summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2011-07-01 00:42:17 +0000
committerDan Gohman <gohman@apple.com>2011-07-01 00:42:17 +0000
commit30cb6dda5ae441f27edef302cbb33936fbafba6d (patch)
tree5dcd699fdb5bb1c806988ebb7e419ccbce56d93b
parentd5dc9eca2beece0faa85e7cbf17182fe7fcd0b36 (diff)
downloadllvm-30cb6dda5ae441f27edef302cbb33936fbafba6d.tar.gz
llvm-30cb6dda5ae441f27edef302cbb33936fbafba6d.tar.bz2
llvm-30cb6dda5ae441f27edef302cbb33936fbafba6d.tar.xz
Improve constant folding of undef for binary operators.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134221 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/VMCore/ConstantFold.cpp28
-rw-r--r--test/Transforms/InstSimplify/binop.ll99
2 files changed, 123 insertions, 4 deletions
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp
index 579d356b1d..8cca06fdda 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -1014,20 +1014,38 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
case Instruction::Add:
case Instruction::Sub:
return UndefValue::get(C1->getType());
- case Instruction::Mul:
case Instruction::And:
+ if (isa<UndefValue>(C1) && isa<UndefValue>(C2)) // undef & undef -> undef
+ return C1;
+ return Constant::getNullValue(C1->getType()); // undef & X -> 0
+ case Instruction::Mul: {
+ ConstantInt *CI;
+ // X * undef -> undef if X is odd or undef
+ if (((CI = dyn_cast<ConstantInt>(C1)) && CI->getValue()[0]) ||
+ ((CI = dyn_cast<ConstantInt>(C2)) && CI->getValue()[0]) ||
+ (isa<UndefValue>(C1) && isa<UndefValue>(C2)))
+ return UndefValue::get(C1->getType());
+
+ // X * undef -> 0 otherwise
return Constant::getNullValue(C1->getType());
+ }
case Instruction::UDiv:
case Instruction::SDiv:
+ // undef / 1 -> undef
+ if (Opcode == Instruction::UDiv || Opcode == Instruction::SDiv)
+ if (ConstantInt *CI2 = dyn_cast<ConstantInt>(C2))
+ if (CI2->isOne())
+ return C1;
+ // FALL THROUGH
case Instruction::URem:
case Instruction::SRem:
if (!isa<UndefValue>(C2)) // undef / X -> 0
return Constant::getNullValue(C1->getType());
return C2; // X / undef -> undef
case Instruction::Or: // X | undef -> -1
- if (const VectorType *PTy = dyn_cast<VectorType>(C1->getType()))
- return Constant::getAllOnesValue(PTy);
- return Constant::getAllOnesValue(C1->getType());
+ if (isa<UndefValue>(C1) && isa<UndefValue>(C2)) // undef | undef -> undef
+ return C1;
+ return Constant::getAllOnesValue(C1->getType()); // undef | X -> ~0
case Instruction::LShr:
if (isa<UndefValue>(C2) && isa<UndefValue>(C1))
return C1; // undef lshr undef -> undef
@@ -1041,6 +1059,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
else
return C1; // X ashr undef --> X
case Instruction::Shl:
+ if (isa<UndefValue>(C2) && isa<UndefValue>(C1))
+ return C1; // undef shl undef -> undef
// undef << X -> 0 or X << undef -> 0
return Constant::getNullValue(C1->getType());
}
diff --git a/test/Transforms/InstSimplify/binop.ll b/test/Transforms/InstSimplify/binop.ll
new file mode 100644
index 0000000000..f4bc55753a
--- /dev/null
+++ b/test/Transforms/InstSimplify/binop.ll
@@ -0,0 +1,99 @@
+; RUN: opt -instsimplify -S < %s | FileCheck %s
+
+; @test0
+; CHECK: ret i64 undef
+define i64 @test0() {
+ %r = mul i64 undef, undef
+ ret i64 %r
+}
+
+; @test1
+; CHECK: ret i64 undef
+define i64 @test1() {
+ %r = mul i64 3, undef
+ ret i64 %r
+}
+
+; @test2
+; CHECK: ret i64 undef
+define i64 @test2() {
+ %r = mul i64 undef, 3
+ ret i64 %r
+}
+
+; @test3
+; CHECK: ret i64 0
+define i64 @test3() {
+ %r = mul i64 undef, 6
+ ret i64 %r
+}
+
+; @test4
+; CHECK: ret i64 0
+define i64 @test4() {
+ %r = mul i64 6, undef
+ ret i64 %r
+}
+
+; @test5
+; CHECK: ret i64 undef
+define i64 @test5() {
+ %r = and i64 undef, undef
+ ret i64 %r
+}
+
+; @test6
+; CHECK: ret i64 undef
+define i64 @test6() {
+ %r = or i64 undef, undef
+ ret i64 %r
+}
+
+; @test7
+; CHECK: ret i64 undef
+define i64 @test7() {
+ %r = udiv i64 undef, 1
+ ret i64 %r
+}
+
+; @test8
+; CHECK: ret i64 undef
+define i64 @test8() {
+ %r = sdiv i64 undef, 1
+ ret i64 %r
+}
+
+; @test9
+; CHECK: ret i64 0
+define i64 @test9() {
+ %r = urem i64 undef, 1
+ ret i64 %r
+}
+
+; @test10
+; CHECK: ret i64 0
+define i64 @test10() {
+ %r = srem i64 undef, 1
+ ret i64 %r
+}
+
+; @test11
+; CHECK: ret i64 undef
+define i64 @test11() {
+ %r = shl i64 undef, undef
+ ret i64 %r
+}
+
+; @test12
+; CHECK: ret i64 undef
+define i64 @test12() {
+ %r = ashr i64 undef, undef
+ ret i64 %r
+}
+
+; @test13
+; CHECK: ret i64 undef
+define i64 @test13() {
+ %r = lshr i64 undef, undef
+ ret i64 %r
+}