Teach the constant folder how to handle a few simple i1 cases.
authorNick Lewycky <nicholas@mxc.ca>
Sun, 20 Sep 2009 00:04:02 +0000 (00:04 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Sun, 20 Sep 2009 00:04:02 +0000 (00:04 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82340 91177308-0d34-0410-b5e6-96231b3b80d8

lib/VMCore/ConstantFold.cpp
test/Transforms/ConstProp/2009-09-19-ConstFold-i1-ConstExpr.ll [new file with mode: 0644]

index 15b6df90a44da6121ecba074fe2e3c9511e29371..f2b8ad5d92c4fbffcd1127a27eb4dda12710a830 100644 (file)
@@ -1010,6 +1010,37 @@ Constant *llvm::ConstantFoldBinaryInstruction(LLVMContext &Context,
     }
   }
 
+  // i1 can be simplified in many cases.
+  if (C1->getType() == Type::getInt1Ty(Context)) {
+    switch (Opcode) {
+    case Instruction::Add:
+    case Instruction::Sub:
+      return ConstantExpr::getXor(const_cast<Constant*>(C1),
+                                  const_cast<Constant*>(C2));
+    case Instruction::Mul:
+      return ConstantExpr::getAnd(const_cast<Constant*>(C1),
+                                  const_cast<Constant*>(C2));
+    case Instruction::Shl:
+    case Instruction::LShr:
+    case Instruction::AShr:
+      // We can assume that C2 == 0.  If it were one the result would be
+      // undefined because the shift value is as large as the bitwidth.
+      return const_cast<Constant*>(C1);
+    case Instruction::SDiv:
+    case Instruction::UDiv:
+      // We can assume that C2 == 1.  If it were zero the result would be
+      // undefined through division by zero.
+      return const_cast<Constant*>(C1);
+    case Instruction::URem:
+    case Instruction::SRem:
+      // We can assume that C2 == 1.  If it were zero the result would be
+      // undefined through division by zero.
+      return ConstantInt::getFalse(Context);
+    default:
+      break;
+    }
+  }
+
   // We don't know how to fold this.
   return 0;
 }
diff --git a/test/Transforms/ConstProp/2009-09-19-ConstFold-i1-ConstExpr.ll b/test/Transforms/ConstProp/2009-09-19-ConstFold-i1-ConstExpr.ll
new file mode 100644 (file)
index 0000000..debf9a8
--- /dev/null
@@ -0,0 +1,25 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+@X = external global i8
+@Y = external global i8
+@Z = external global i8
+
+global i1 add (i1 icmp ult (i8* @X, i8* @Y), i1 icmp ult (i8* @X, i8* @Z))
+; CHECK: xor
+global i1 sub (i1 icmp ult (i8* @X, i8* @Y), i1 icmp ult (i8* @X, i8* @Z))
+; CHECK: xor
+global i1 mul (i1 icmp ult (i8* @X, i8* @Y), i1 icmp ult (i8* @X, i8* @Z))
+; CHECK: and
+
+global i1 sdiv (i1 icmp ult (i8* @X, i8* @Y), i1 icmp ult (i8* @X, i8* @Z))
+; CHECK-NOT: @Z
+; CHECK: i1 icmp ult (i8* @X, i8* @Y)
+global i1 udiv (i1 icmp ult (i8* @X, i8* @Y), i1 icmp ult (i8* @X, i8* @Z))
+; CHECK-NOT: @Z
+; CHECK: i1 icmp ult (i8* @X, i8* @Y)
+global i1 srem (i1 icmp ult (i8* @X, i8* @Y), i1 icmp ult (i8* @X, i8* @Z))
+; CHECK-NOT: icmp
+; CHECK: i1 false
+global i1 urem (i1 icmp ult (i8* @X, i8* @Y), i1 icmp ult (i8* @X, i8* @Z))
+; CHECK-NOT: icmp
+; CHECK: i1 false