Subzero: Implement switch lowering for i64.
BUG= none
R=jvoung@chromium.org
Review URL: https://codereview.chromium.org/701673002
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index f06c2e4..17bc8cc 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -4030,14 +4030,38 @@
// cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default
Operand *Src0 = Inst->getComparison();
SizeT NumCases = Inst->getNumCases();
+ if (Src0->getType() == IceType_i64) {
+ Src0 = legalize(Src0); // get Base/Index into physical registers
+ Operand *Src0Lo = loOperand(Src0);
+ Operand *Src0Hi = hiOperand(Src0);
+ if (NumCases >= 2) {
+ Src0Lo = legalizeToVar(Src0Lo);
+ Src0Hi = legalizeToVar(Src0Hi);
+ } else {
+ Src0Lo = legalize(Src0Lo, Legal_Reg | Legal_Mem);
+ Src0Hi = legalize(Src0Hi, Legal_Reg | Legal_Mem);
+ }
+ for (SizeT I = 0; I < NumCases; ++I) {
+ Constant *ValueLo = Ctx->getConstantInt32(IceType_i32, Inst->getValue(I));
+ Constant *ValueHi =
+ Ctx->getConstantInt32(IceType_i32, Inst->getValue(I) >> 32);
+ InstX8632Label *Label = InstX8632Label::create(Func, this);
+ _cmp(Src0Lo, ValueLo);
+ _br(CondX86::Br_ne, Label);
+ _cmp(Src0Hi, ValueHi);
+ _br(CondX86::Br_e, Inst->getLabel(I));
+ Context.insert(Label);
+ }
+ _br(Inst->getLabelDefault());
+ return;
+ }
// OK, we'll be slightly less naive by forcing Src into a physical
// register if there are 2 or more uses.
if (NumCases >= 2)
- Src0 = legalizeToVar(Src0, true);
+ Src0 = legalizeToVar(Src0);
else
Src0 = legalize(Src0, Legal_Reg | Legal_Mem);
for (SizeT I = 0; I < NumCases; ++I) {
- // TODO(stichnot): Correct lowering for IceType_i64.
Constant *Value = Ctx->getConstantInt32(IceType_i32, Inst->getValue(I));
_cmp(Src0, Value);
_br(CondX86::Br_e, Inst->getLabel(I));
diff --git a/tests_lit/llvm2ice_tests/switch-opt.ll b/tests_lit/llvm2ice_tests/switch-opt.ll
index 6b9616f..53a6b27 100644
--- a/tests_lit/llvm2ice_tests/switch-opt.ll
+++ b/tests_lit/llvm2ice_tests/switch-opt.ll
@@ -2,7 +2,9 @@
; same label which also results in phi instructions with multiple
; entries for the same incoming edge.
-; RUN: %p2i -i %s -a --verbose inst | FileCheck %s
+; RUN: %p2i -i %s --args -O2 --verbose none \
+; RUN: | llvm-mc -triple=i686-none-nacl -filetype=obj \
+; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
; RUN: %p2i -i %s -a --verbose none | FileCheck --check-prefix=ERRORS %s
; RUN: %p2i -i %s --insts | %szdiff %s | FileCheck --check-prefix=DUMP %s
@@ -51,6 +53,68 @@
; CHECK-LABEL: testSwitchImm
; CHECK-NOT: cmp {{[0-9]*}},
+; Test for correct 64-bit lowering.
+define internal i32 @testSwitch64(i64 %a) {
+entry:
+ switch i64 %a, label %sw.default [
+ i64 123, label %return
+ i64 234, label %sw.bb1
+ i64 345, label %sw.bb2
+ i64 78187493520, label %sw.bb3
+ ]
+
+sw.bb1: ; preds = %entry
+ br label %return
+
+sw.bb2: ; preds = %entry
+ br label %return
+
+sw.bb3: ; preds = %entry
+ br label %return
+
+sw.default: ; preds = %entry
+ br label %return
+
+return: ; preds = %sw.default, %sw.bb3, %sw.bb2, %sw.bb1, %entry
+ %retval.0 = phi i32 [ 5, %sw.default ], [ 4, %sw.bb3 ], [ 3, %sw.bb2 ], [ 2, %sw.bb1 ], [ 1, %entry ]
+ ret i32 %retval.0
+}
+; CHECK-LABEL: testSwitch64
+; CHECK: cmp {{.*}}, 123
+; CHECK-NEXT: jne
+; CHECK-NEXT: cmp {{.*}}, 0
+; CHECK-NEXT: je
+; CHECK: cmp {{.*}}, 234
+; CHECK-NEXT: jne
+; CHECK-NEXT: cmp {{.*}}, 0
+; CHECK-NEXT: je
+; CHECK: cmp {{.*}}, 345
+; CHECK-NEXT: jne
+; CHECK-NEXT: cmp {{.*}}, 0
+; CHECK-NEXT: je
+; CHECK: cmp {{.*}}, 878082192
+; CHECK-NEXT: jne
+; CHECK-NEXT: cmp {{.*}}, 18
+; CHECK-NEXT: je
+
+; Similar to testSwitchImm, make sure proper addressing modes are
+; used. In reality, this is tested by running the output through the
+; assembler.
+define i32 @testSwitchImm64() {
+entry:
+ switch i64 10, label %sw.default [
+ i64 1, label %sw.default
+ ]
+
+sw.default:
+ ret i32 20
+}
+; CHECK-LABEL: testSwitchImm64
+; CHECK: cmp {{.*}}, 1
+; CHECK-NEXT: jne
+; CHECK-NEXT: cmp {{.*}}, 0
+; CHECK-NEXT: je
+
; CHECK-NOT: ICE translation error
; ERRORS-NOT: ICE translation error
; DUMP-NOT: SZ