ConstantFolding: Add a missing folding that leads to a miscompile.
authorBenjamin Kramer <benny.kra@googlemail.com>
Thu, 24 Jan 2013 16:28:28 +0000 (16:28 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Thu, 24 Jan 2013 16:28:28 +0000 (16:28 +0000)
We use constant folding to see if an intrinsic evaluates to the same value as a
constant that we know. If we don't take the undefinedness into account we get a
value that doesn't match the actual implementation, and miscompiled code.

This was uncovered by Chandler's simplifycfg changes.

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

lib/Analysis/ConstantFolding.cpp
test/Transforms/ConstProp/2007-11-23-cttz.ll
test/Transforms/InstCombine/intrinsics.ll

index 9246e26422e4aa1c358f9df328bb6474da7f9ea6..4b4fa5cd4ea9c94dfc1eacca0d7f32d43e9ce0ef 100644 (file)
@@ -1474,12 +1474,12 @@ llvm::ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
           return ConstantStruct::get(cast<StructType>(F->getReturnType()), Ops);
         }
         case Intrinsic::cttz:
-          // FIXME: This should check for Op2 == 1, and become unreachable if
-          // Op1 == 0.
+          if (Op2->isOne() && Op1->isZero()) // cttz(0, 1) is undef.
+            return UndefValue::get(Ty);
           return ConstantInt::get(Ty, Op1->getValue().countTrailingZeros());
         case Intrinsic::ctlz:
-          // FIXME: This should check for Op2 == 1, and become unreachable if
-          // Op1 == 0.
+          if (Op2->isOne() && Op1->isZero()) // ctlz(0, 1) is undef.
+            return UndefValue::get(Ty);
           return ConstantInt::get(Ty, Op1->getValue().countLeadingZeros());
         }
       }
index 6d34cb17fffd910833e55318a28bbcc732d76f02..c5ee70c2ff1208ce17a4c63f10d3d8efbe94f42a 100644 (file)
@@ -3,6 +3,6 @@
 declare i13 @llvm.cttz.i13(i13, i1)
 
 define i13 @test() {
-       %X = call i13 @llvm.cttz.i13(i13 0, i1 true)
+       %X = call i13 @llvm.cttz.i13(i13 0, i1 false)
        ret i13 %X
 }
index 93f0a953fd336f7574fe5b515bbb7304e6609ae1..f334b3b1e93533bc4d2f3446f69afa73de8cd664 100644 (file)
@@ -220,3 +220,39 @@ define i32 @cttz_simplify1b(i32 %x) nounwind readnone ssp {
 ; CHECK: @cttz_simplify1b
 ; CHECK-NEXT: ret i32 0
 }
+
+define i32 @ctlz_undef(i32 %Value) nounwind {
+  %ctlz = call i32 @llvm.ctlz.i32(i32 0, i1 true)
+  ret i32 %ctlz
+
+; CHECK: @ctlz_undef
+; CHECK-NEXT: ret i32 undef
+}
+
+define i32 @cttz_undef(i32 %Value) nounwind {
+  %cttz = call i32 @llvm.cttz.i32(i32 0, i1 true)
+  ret i32 %cttz
+
+; CHECK: @cttz_undef
+; CHECK-NEXT: ret i32 undef
+}
+
+define i32 @ctlz_select(i32 %Value) nounwind {
+  %tobool = icmp ne i32 %Value, 0
+  %ctlz = call i32 @llvm.ctlz.i32(i32 %Value, i1 true)
+  %s = select i1 %tobool, i32 %ctlz, i32 32
+  ret i32 %s
+
+; CHECK: @ctlz_select
+; CHECK: select i1 %tobool, i32 %ctlz, i32 32
+}
+
+define i32 @cttz_select(i32 %Value) nounwind {
+  %tobool = icmp ne i32 %Value, 0
+  %cttz = call i32 @llvm.cttz.i32(i32 %Value, i1 true)
+  %s = select i1 %tobool, i32 %cttz, i32 32
+  ret i32 %s
+
+; CHECK: @cttz_select
+; CHECK: select i1 %tobool, i32 %cttz, i32 32
+}