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