[GlobalISel][IRTranslator] Fix switch table lowering to use signed LE not unsigned.
authorAmara Emerson <aemerson@apple.com>
Tue, 24 Sep 2019 00:09:23 +0000 (00:09 +0000)
committerAmara Emerson <aemerson@apple.com>
Tue, 24 Sep 2019 00:09:23 +0000 (00:09 +0000)
We were miscompiling switch value comparisons with the wrong signedness, which
shows up when we have things like switch case values with i1 types, which end up
being legalized incorrectly.

Fixes PR43383

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@372675 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/GlobalISel/IRTranslator.cpp
test/CodeGen/AArch64/GlobalISel/arm64-irtranslator-switch.ll

index 1e34739cb03548afbdfa63266f109d51caf47651..2ce05ec39680d7a5adb526a0570956bc9652d8ba 100644 (file)
@@ -589,8 +589,8 @@ void IRTranslator::emitSwitchCase(SwitchCG::CaseBlock &CB,
     Register CondRHS = getOrCreateVReg(*CB.CmpRHS);
     Cond = MIB.buildICmp(CB.PredInfo.Pred, i1Ty, CondLHS, CondRHS).getReg(0);
   } else {
-    assert(CB.PredInfo.Pred == CmpInst::ICMP_ULE &&
-           "Can only handle ULE ranges");
+    assert(CB.PredInfo.Pred == CmpInst::ICMP_SLE &&
+           "Can only handle SLE ranges");
 
     const APInt& Low = cast<ConstantInt>(CB.CmpLHS)->getValue();
     const APInt& High = cast<ConstantInt>(CB.CmpRHS)->getValue();
@@ -599,7 +599,7 @@ void IRTranslator::emitSwitchCase(SwitchCG::CaseBlock &CB,
     if (cast<ConstantInt>(CB.CmpLHS)->isMinValue(true)) {
       Register CondRHS = getOrCreateVReg(*CB.CmpRHS);
       Cond =
-          MIB.buildICmp(CmpInst::ICMP_ULE, i1Ty, CmpOpReg, CondRHS).getReg(0);
+          MIB.buildICmp(CmpInst::ICMP_SLE, i1Ty, CmpOpReg, CondRHS).getReg(0);
     } else {
       const LLT &CmpTy = MRI->getType(CmpOpReg);
       auto Sub = MIB.buildSub({CmpTy}, CmpOpReg, CondLHS);
@@ -729,7 +729,7 @@ bool IRTranslator::lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I,
     MHS = nullptr;
   } else {
     // Check I->Low <= Cond <= I->High.
-    Pred = CmpInst::ICMP_ULE;
+    Pred = CmpInst::ICMP_SLE;
     LHS = I->Low;
     MHS = Cond;
     RHS = I->High;
index f5075216352fb7a847b79d4e40151838c007ce71..969cacb89d10e0e3ec0d0265277041cf7c5e43d1 100644 (file)
@@ -1412,3 +1412,45 @@ bb4:                                              ; preds = %bb1
 
 declare i64* @ham(i32)
 
+define internal void @bar() unnamed_addr #1 {
+  ; CHECK-LABEL: name: bar
+  ; CHECK: bb.1 (%ir-block.0):
+    unreachable
+}
+
+define i1 @i1_value_cmp_is_signed(i1) {
+  ; CHECK-LABEL: name: i1_value_cmp_is_signed
+  ; CHECK: bb.1.Entry:
+  ; CHECK:   successors: %bb.3(0x40000000), %bb.2(0x40000000)
+  ; CHECK:   liveins: $w0
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[COPY]](s32)
+  ; CHECK:   [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
+  ; CHECK:   [[C1:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
+  ; CHECK:   [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(sle), [[TRUNC]](s1), [[C1]]
+  ; CHECK:   G_BRCOND [[ICMP]](s1), %bb.3
+  ; CHECK:   G_BR %bb.2
+  ; CHECK: bb.2.BadValue:
+  ; CHECK:   successors:
+  ; CHECK:   ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
+  ; CHECK:   BL @bar, csr_aarch64_aapcs, implicit-def $lr, implicit $sp
+  ; CHECK:   ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
+  ; CHECK: bb.3.OkValue:
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s8) = G_ZEXT [[TRUNC]](s1)
+  ; CHECK:   [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[ZEXT]](s8)
+  ; CHECK:   $w0 = COPY [[ANYEXT]](s32)
+  ; CHECK:   RET_ReallyLR implicit $w0
+Entry:
+  switch i1 %0, label %BadValue [
+    i1 false, label %OkValue
+    i1 true, label %OkValue
+  ]
+
+BadValue:
+  call fastcc void @bar()
+  unreachable
+
+OkValue:
+  ret i1 %0
+}
+