]> granicus.if.org Git - llvm/commitdiff
[InstCombine] Fix constexpr issue in select combining
authorSimon Pilgrim <llvm-dev@redking.me.uk>
Wed, 12 Oct 2016 10:20:15 +0000 (10:20 +0000)
committerSimon Pilgrim <llvm-dev@redking.me.uk>
Wed, 12 Oct 2016 10:20:15 +0000 (10:20 +0000)
As discussed by Andrea on PR30486, we have an unsafe cast to an Instruction type in the select combine which doesn't take into account that it could be a ConstantExpr instead.

Differential Revision: https://reviews.llvm.org/D25466

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

lib/Transforms/InstCombine/InstructionCombining.cpp
test/Transforms/InstCombine/switch-constant-expr.ll [new file with mode: 0644]

index 54f8b722b7e95250802a1b2fc4381d311960e792..6b31a5449f74dcce8c656422c3b18a5541138660 100644 (file)
@@ -2271,9 +2271,9 @@ Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) {
           SI.getContext(), C.getCaseValue()->getValue().trunc(NewWidth)));
   }
 
+  Value *Op0 = nullptr;
   ConstantInt *AddRHS = nullptr;
-  if (match(Cond, m_Add(m_Value(), m_ConstantInt(AddRHS)))) {
-    Instruction *I = cast<Instruction>(Cond);
+  if (match(Cond, m_Add(m_Value(Op0), m_ConstantInt(AddRHS)))) {
     // Change 'switch (X+4) case 1:' into 'switch (X) case -3'.
     for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e;
          ++i) {
@@ -2289,8 +2289,9 @@ Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) {
              "Result of expression should be constant");
       i.setValue(cast<ConstantInt>(NewCaseVal));
     }
-    SI.setCondition(I->getOperand(0));
-    Worklist.Add(I);
+    SI.setCondition(Op0);
+    if (auto *CondI = dyn_cast<Instruction>(Cond))
+      Worklist.Add(CondI);
     return &SI;
   }
 
diff --git a/test/Transforms/InstCombine/switch-constant-expr.ll b/test/Transforms/InstCombine/switch-constant-expr.ll
new file mode 100644 (file)
index 0000000..c2ea83b
--- /dev/null
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+@g = global i32 0
+
+; PR30486
+define i32 @single_case() {
+; CHECK-LABEL: @single_case(
+; CHECK-NEXT:    switch i32 ptrtoint (i32* @g to i32), label %x [
+; CHECK-NEXT:    ]
+; CHECK:       x:
+; CHECK-NEXT:    ret i32 0
+;
+  switch i32 add (i32 ptrtoint (i32* @g to i32), i32 -1), label %x []
+x:
+  ret i32 0
+}
+
+define i32 @multiple_cases() {
+; CHECK-LABEL: @multiple_cases(
+; CHECK-NEXT:    switch i32 ptrtoint (i32* @g to i32), label %x [
+; CHECK-NEXT:    i32 2, label %one
+; CHECK-NEXT:    i32 3, label %two
+; CHECK-NEXT:    ]
+; CHECK:       x:
+; CHECK-NEXT:    ret i32 0
+; CHECK:       one:
+; CHECK-NEXT:    ret i32 1
+; CHECK:       two:
+; CHECK-NEXT:    ret i32 2
+;
+  switch i32 add (i32 ptrtoint (i32* @g to i32), i32 -1), label %x [
+  i32 1, label %one
+  i32 2, label %two
+  ]
+x:
+  ret i32 0
+
+one:
+  ret i32 1
+
+two:
+  ret i32 2
+}