Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -1771,8 +1771,24 @@ 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(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 cound 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 @@ // 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 @@ Value *Operand = Instr->getOperand(OpNum); auto it = ReplaceWithConstMap.find(Operand); if (it != ReplaceWithConstMap.end()) { + assert(!isa(Operand) && + "Replacing constants with constants is invalid"); Instr->setOperand(OpNum, it->second); Changed = true; } @@ -2459,8 +2478,8 @@ BI != BE;) { if (!ReplaceWithConstMap.empty()) ChangedFunction |= replaceOperandsWithConsts(BI); - ChangedFunction |= processInstruction(BI); + if (InstrsToErase.empty()) { ++BI; continue; Index: test/Transforms/GVN/assume-equal.ll =================================================================== --- test/Transforms/GVN/assume-equal.ll +++ test/Transforms/GVN/assume-equal.ll @@ -122,6 +122,7 @@ ; 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 @@ 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)