assuem(X) handling in GVN bugfix
authorPiotr Padlewski <prazek@google.com>
Wed, 2 Sep 2015 20:00:03 +0000 (20:00 +0000)
committerPiotr Padlewski <prazek@google.com>
Wed, 2 Sep 2015 20:00:03 +0000 (20:00 +0000)
There was infinite loop because it was trying to change assume(true) into
assume(true)
Also added handling when assume(false) appear

http://reviews.llvm.org/D12516

llvm-svn: 246697

llvm/lib/Transforms/Scalar/GVN.cpp
llvm/test/Transforms/GVN/assume-equal.ll

index 092cb69..cf90fbf 100644 (file)
@@ -1771,8 +1771,24 @@ bool GVN::processAssumeIntrinsic(IntrinsicInst *IntrinsicI) {
   assert(IntrinsicI->getIntrinsicID() == Intrinsic::assume &&
          "This function can only be called with llvm.assume intrinsic");
   Value *V = IntrinsicI->getArgOperand(0);
+
+  if (ConstantInt *Cond = dyn_cast<ConstantInt>(V)) {
+    if (Cond->isZero()) {
+      Type *Int8Ty = Type::getInt8Ty(V->getContext());
+      // Insert a new store to null instruction before the load to indicate that
+      // this code is not reachable.  FIXME: We could insert unreachable
+      // instruction directly because we can modify the CFG.
+      new StoreInst(UndefValue::get(Int8Ty),
+                    Constant::getNullValue(Int8Ty->getPointerTo()),
+                    IntrinsicI);
+    }
+    markInstructionForDeletion(IntrinsicI);
+    return false;
+  }
+
   Constant *True = ConstantInt::getTrue(V->getContext());
   bool Changed = false;
+
   for (BasicBlock *Successor : successors(IntrinsicI->getParent())) {
     BasicBlockEdge Edge(IntrinsicI->getParent(), Successor);
 
@@ -1780,6 +1796,7 @@ bool GVN::processAssumeIntrinsic(IntrinsicInst *IntrinsicI) {
     // will check dominance for us.
     Changed |= propagateEquality(V, True, Edge, false);
   }
+
   // We can replace assume value with true, which covers cases like this:
   // call void @llvm.assume(i1 %cmp)
   // br i1 %cmp, label %bb1, label %bb2 ; will change %cmp to true
@@ -2087,6 +2104,8 @@ bool GVN::replaceOperandsWithConsts(Instruction *Instr) const {
     Value *Operand = Instr->getOperand(OpNum);
     auto it = ReplaceWithConstMap.find(Operand);
     if (it != ReplaceWithConstMap.end()) {
+      assert(!isa<Constant>(Operand) &&
+             "Replacing constants with constants is invalid");
       Instr->setOperand(OpNum, it->second);
       Changed = true;
     }
@@ -2459,8 +2478,8 @@ bool GVN::processBlock(BasicBlock *BB) {
        BI != BE;) {
     if (!ReplaceWithConstMap.empty())
       ChangedFunction |= replaceOperandsWithConsts(BI);
-
     ChangedFunction |= processInstruction(BI);
+
     if (InstrsToErase.empty()) {
       ++BI;
       continue;
index 0e4df96..2f9c394 100644 (file)
@@ -122,6 +122,7 @@ entry:
   ; CHECK: br i1 true, label %bb2, label %bb2
   br i1 %cmp, label %bb2, label %bb2
 bb2:
+  call void @llvm.assume(i1 true)
   ; CHECK: br i1 true, label %bb2, label %bb2
   br i1 %cmp, label %bb2, label %bb2
   
@@ -129,6 +130,45 @@ bb2:
   ret i32 %p
 }
 
+; CHECK-LABEL: define i32 @_Z1ij(i32 %p)
+define i32 @_Z1ij(i32 %p) {
+entry:
+  %cmp = icmp eq i32 %p, 42
+  call void @llvm.assume(i1 %cmp)
+  
+  ; CHECK: br i1 true, label %bb2, label %bb2
+  br i1 %cmp, label %bb2, label %bb2
+bb2:
+   ; CHECK-NOT: %cmp2 = 
+  %cmp2 = icmp eq i32 %p, 42
+  ; CHECK-NOT: call void @llvm.assume(
+  call void @llvm.assume(i1 %cmp2)
+  
+  ; CHECK: br i1 true, label %bb2, label %bb2
+  br i1 %cmp, label %bb2, label %bb2
+  
+  ; CHECK: ret i32 42
+  ret i32 %p
+}
+
+; CHECK-LABEL: define i32 @_Z1ik(i32 %p)
+define i32 @_Z1ik(i32 %p) {
+entry:
+  %cmp = icmp eq i32 %p, 42
+  call void @llvm.assume(i1 %cmp)
+  
+  ; CHECK: br i1 true, label %bb2, label %bb3
+  br i1 %cmp, label %bb2, label %bb3
+bb2:
+  ; CHECK-NOT: %cmp3 = 
+  %cmp3 = icmp eq i32 %p, 43
+  ; CHECK: store i8 undef, i8* null
+  call void @llvm.assume(i1 %cmp3)
+  ret i32 15
+bb3:
+  ret i32 17
+}
+
 declare noalias i8* @_Znwm(i64)
 declare void @_ZN1AC1Ev(%struct.A*)
 declare void @llvm.assume(i1)