This enables more simplifications and gets us closer to removing undef.
ping @alinas
Value *NewGVN::lookupOperandLeader(Value *V) const {
CongruenceClass *CC = ValueToClass.lookup(V);
if (CC) {
- // Everything in TOP is represented by undef, as it can be any value.
+ // Everything in TOP is represented by poison, as it can be any value.
// We do have to make sure we get the type right though, so we can't set the
- // RepLeader to undef.
+ // RepLeader to poison.
if (CC == TOPClass)
- return UndefValue::get(V->getType());
+ return PoisonValue::get(V->getType());
return CC->getStoredValue() ? CC->getStoredValue() : CC->getLeader();
}
return nullptr;
Value *LoadAddressLeader = lookupOperandLeader(LI->getPointerOperand());
- // Load of undef is undef.
+ // Load of undef is UB.
if (isa<UndefValue>(LoadAddressLeader))
- return createConstantExpression(UndefValue::get(LI->getType()));
+ return createConstantExpression(PoisonValue::get(LI->getType()));
MemoryAccess *OriginalAccess = getMemoryAccess(I);
MemoryAccess *DefiningAccess =
MSSAWalker->getClobberingMemoryAccess(OriginalAccess);
if (!MSSA->isLiveOnEntryDef(DefiningAccess)) {
if (auto *MD = dyn_cast<MemoryDef>(DefiningAccess)) {
Instruction *DefiningInst = MD->getMemoryInst();
- // If the defining instruction is not reachable, replace with undef.
+ // If the defining instruction is not reachable, replace with poison.
if (!ReachableBlocks.count(DefiningInst->getParent()))
- return createConstantExpression(UndefValue::get(LI->getType()));
+ return createConstantExpression(PoisonValue::get(LI->getType()));
// This will handle stores and memory insts. We only do if it the
// defining access has a different type, or it is a pointer produced by
// certain memory operations that cause the memory to have a fixed value
// We match the semantics of SimplifyPhiNode from InstructionSimplify here.
// See if all arguments are the same.
// We track if any were undef because they need special handling.
- bool HasUndef = false;
+ bool HasUndef = false, HasPoison = false;
auto Filtered = make_filter_range(E->operands(), [&](Value *Arg) {
+ if (isa<PoisonValue>(Arg)) {
+ HasPoison = true;
+ return false;
+ }
if (isa<UndefValue>(Arg)) {
HasUndef = true;
return false;
});
// If we are left with no operands, it's dead.
if (Filtered.empty()) {
- // If it has undef at this point, it means there are no-non-undef arguments,
- // and thus, the value of the phi node must be undef.
+ // If it has undef or poison at this point, it means there are no-non-undef
+ // arguments, and thus, the value of the phi node must be undef.
+ if (HasPoison && !HasUndef) {
+ LLVM_DEBUG(
+ dbgs() << "PHI Node " << *I
+ << " has no non-poison arguments, valuing it as poison\n");
+ return createConstantExpression(PoisonValue::get(I->getType()));
+ }
if (HasUndef) {
LLVM_DEBUG(
dbgs() << "PHI Node " << *I
// expression to say if one is equivalent to the other.
// We also special case undef, so that if we have an undef, we can't use the
// common value unless it dominates the phi block.
- if (HasUndef) {
+ if (HasPoison || HasUndef) {
// If we have undef and at least one other value, this is really a
// multivalued phi, and we need to know if it's cycle free in order to
// evaluate whether we can ignore the undef. The other parts of this are
LLVM_DEBUG(dbgs() << "Skipping phi of ops operand for incoming block "
<< getBlockName(PredBB)
<< " because the block is unreachable\n");
- FoundVal = UndefValue::get(I->getType());
+ FoundVal = PoisonValue::get(I->getType());
RevisitOnReachabilityChange[PHIBlock].set(InstrToDFSNum(I));
}
// Delete all instructions marked for deletion.
for (Instruction *ToErase : InstructionsToErase) {
if (!ToErase->use_empty())
- ToErase->replaceAllUsesWith(UndefValue::get(ToErase->getType()));
+ ToErase->replaceAllUsesWith(PoisonValue::get(ToErase->getType()));
assert(ToErase->getParent() &&
"BB containing ToErase deleted unexpectedly!");
for (BasicBlock::reverse_iterator I(StartPoint); I != BB->rend();) {
Instruction &Inst = *I++;
if (!Inst.use_empty())
- Inst.replaceAllUsesWith(UndefValue::get(Inst.getType()));
+ Inst.replaceAllUsesWith(PoisonValue::get(Inst.getType()));
if (isa<LandingPadInst>(Inst))
continue;
salvageKnowledge(&Inst, AC);
}
// Now insert something that simplifycfg will turn into an unreachable.
Type *Int8Ty = Type::getInt8Ty(BB->getContext());
- new StoreInst(UndefValue::get(Int8Ty),
+ new StoreInst(PoisonValue::get(Int8Ty),
Constant::getNullValue(Int8Ty->getPointerTo()),
BB->getTerminator());
}
LLVM_DEBUG(dbgs() << "Replacing incoming value of " << PHI
<< " for block "
<< getBlockName(PHI->getIncomingBlock(Operand))
- << " with undef due to it being unreachable\n");
- Operand.set(UndefValue::get(PHI->getType()));
+ << " with poison due to it being unreachable\n");
+ Operand.set(PoisonValue::get(PHI->getType()));
}
};
// Replace unreachable phi arguments.
; CHECK: cond_next2943:
; CHECK-NEXT: br i1 false, label [[BB2982_PREHEADER:%.*]], label [[BB2928]]
; CHECK: bb2982.preheader:
-; CHECK-NEXT: store i8 undef, i8* null
-; CHECK-NEXT: ret i32 undef
+; CHECK-NEXT: store i8 poison, i8* null
+; CHECK-NEXT: ret i32 poison
;
cond_next2835.1: ; preds = %cond_next2861
%tmp2922 = load i32, i32* @n_spills, align 4 ; <i32> [#uses=0]
; CHECK: bb2:
; CHECK-NEXT: br i1 true, label [[BB2]], label [[BB2]]
; CHECK: 0:
-; CHECK-NEXT: store i8 undef, i8* null, align 1
+; CHECK-NEXT: store i8 poison, i8* null, align 1
; CHECK-NEXT: ret i32 [[P]]
;
entry:
; CHECK-NEXT: call void @llvm.assume(i1 false)
; CHECK-NEXT: ret i32 15
; CHECK: bb3:
-; CHECK-NEXT: store i8 undef, i8* null, align 1
+; CHECK-NEXT: store i8 poison, i8* null, align 1
; CHECK-NEXT: ret i32 17
;
entry:
; CHECK: bb14:
; CHECK-NEXT: br label [[BB16]]
; CHECK: bb15:
-; CHECK-NEXT: store i8 undef, i8* null, align 1
+; CHECK-NEXT: store i8 poison, i8* null, align 1
; CHECK-NEXT: br label [[BB16]]
; CHECK: bb16:
-; CHECK-NEXT: [[TMP17:%.*]] = phi i32 [ undef, [[BB15]] ], [ 1, [[BB14]] ], [ 9, [[BB7]] ]
+; CHECK-NEXT: [[TMP17:%.*]] = phi i32 [ poison, [[BB15]] ], [ 1, [[BB14]] ], [ 9, [[BB7]] ]
; CHECK-NEXT: switch i32 [[TMP17]], label [[BB19]] [
; CHECK-NEXT: i32 0, label [[BB6]]
; CHECK-NEXT: i32 9, label [[BB18:%.*]]
; CHECK-NEXT: i8 6, label [[BB8:%.*]]
; CHECK-NEXT: ]
; CHECK: bb8:
-; CHECK-NEXT: store i8 undef, i8* null, align 1
+; CHECK-NEXT: store i8 poison, i8* null, align 1
; CHECK-NEXT: br label [[BB4]]
; CHECK: bb9:
; CHECK-NEXT: store i8 0, i8* [[ARG]], align 1, !g !0
; CHECK: bb90:
; CHECK-NEXT: br label [[BB90]]
; CHECK: bb138:
-; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: store i8 poison, i8* null
; CHECK-NEXT: br label [[BB138:%.*]]
;
bb:
; CHECK-NEXT: top:
; CHECK-NEXT: br label [[IF:%.*]]
; CHECK: if:
-; CHECK-NEXT: [[TMP0:%.*]] = phi double [ [[TMP1:%.*]], [[IF]] ], [ undef, [[TOP:%.*]] ]
-; CHECK-NEXT: [[TMP1]] = fadd double [[TMP0]], 1.000000e+00
; CHECK-NEXT: br i1 false, label [[L50:%.*]], label [[IF]]
; CHECK: L50:
-; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: store i8 poison, i8* null
; CHECK-NEXT: ret void
;
top:
; CHECK: if.then:
; CHECK-NEXT: br i1 false, label [[FIRSTPHIBLOCK:%.*]], label [[TEMP:%.*]]
; CHECK: firstphiblock:
-; CHECK-NEXT: [[FIRSTPHI:%.*]] = phi i64 [ undef, [[IF_THEN]] ], [ [[SECONDPHI:%.*]], [[SECONDPHIBLOCK:%.*]] ]
+; CHECK-NEXT: [[FIRSTPHI:%.*]] = phi i64 [ poison, [[IF_THEN]] ], [ [[SECONDPHI:%.*]], [[SECONDPHIBLOCK:%.*]] ]
; CHECK-NEXT: br i1 undef, label %for.cond17thread-pre-split, label [[SECONDPHIBLOCK]]
; CHECK: secondphiblock:
; CHECK-NEXT: [[SECONDPHI]] = phi i64 [ [[THIRDPHI:%.*]], [[THIRDPHIBLOCK:%.*]] ], [ [[FIRSTPHI]], [[FIRSTPHIBLOCK]] ]
; CHECK-NEXT: [[F_0:%.*]] = phi i32* [ @b, [[ENTRY:%.*]] ], [ @a, [[L1_LOOPEXIT:%.*]] ]
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond.loopexit:
-; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: store i8 poison, i8* null
; CHECK-NEXT: br label [[FOR_COND]]
; CHECK: for.cond:
; CHECK-NEXT: br i1 undef, label [[FOR_END14:%.*]], label [[FOR_COND1_PREHEADER:%.*]]
; CHECK-NEXT: [[F_0:%.*]] = phi i32* [ @b, [[ENTRY:%.*]] ], [ @a, [[L1_LOOPEXIT:%.*]] ]
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond.loopexit:
-; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: store i8 poison, i8* null
; CHECK-NEXT: br label [[FOR_COND]]
; CHECK: for.cond:
; CHECK-NEXT: br i1 undef, label [[FOR_END14:%.*]], label [[FOR_COND1_PREHEADER:%.*]]
; CHECK-NEXT: %dipsy = load i64, i64* @c
; CHECK-NEXT: br label %ph
; CHECK: back: ; preds = %l2
-; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: store i8 poison, i8* null
; CHECK-NEXT: br label %ph
; CHECK: end: ; preds = %l2
; CHECK-NEXT: ret void
; CHECK: while.body12:
; CHECK-NEXT: br i1 undef, label [[IF_END18]], label [[L]]
; CHECK: L.loopexit:
-; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: store i8 poison, i8* null
; CHECK-NEXT: br label [[L]]
; CHECK: L:
-; CHECK-NEXT: [[H_125]] = phi i32 [ [[H_127]], [[WHILE_BODY12]] ], [ undef, [[L_LOOPEXIT]] ]
+; CHECK-NEXT: [[H_125]] = phi i32 [ [[H_127]], [[WHILE_BODY12]] ], [ poison, [[L_LOOPEXIT]] ]
; CHECK-NEXT: br i1 undef, label [[WHILE_COND10]], label [[IF_END18]]
; CHECK: if.end18:
; CHECK-NEXT: [[H_126]] = phi i32 [ [[H_125]], [[L]] ], [ [[H_127]], [[WHILE_BODY12]] ]
; CHECK: bb8:
; CHECK-NEXT: br i1 false, label [[BB9:%.*]], label [[BB3:%.*]]
; CHECK: bb9:
-; CHECK-NEXT: store i8 undef, i8* null, align 1
+; CHECK-NEXT: store i8 poison, i8* null, align 1
; CHECK-NEXT: br label [[BB3]]
; CHECK: bb10:
; CHECK-NEXT: store i32 0, i32* @global, align 4, !h !0
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 false, label [[FOR_COND1:%.*]], label [[FOR_INC:%.*]]
; CHECK: for.cond1:
-; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i16 [ undef, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC]] ]
+; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i16 [ poison, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC]] ]
; CHECK-NEXT: store i16 [[PHIOFOPS]], i16* @b, align 2
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
; CHECK-NEXT: store i64 7, i64* [[J_3:%.*]], align 4
; CHECK-NEXT: br label [[FOR_BODY]]
; CHECK: for.cond16:
-; CHECK-NEXT: [[J_0:%.*]] = phi i64* [ @f, [[ENTRY:%.*]] ], [ undef, [[FOR_COND20:%.*]] ], [ @e, [[FOR_COND16]] ]
+; CHECK-NEXT: [[J_0:%.*]] = phi i64* [ @f, [[ENTRY:%.*]] ], [ poison, [[FOR_COND20:%.*]] ], [ @e, [[FOR_COND16]] ]
; CHECK-NEXT: br i1 undef, label [[FOR_COND20]], label [[FOR_COND16]]
; CHECK: for.cond20:
-; CHECK-NEXT: [[J_2:%.*]] = phi i64* [ [[J_0]], [[FOR_COND16]] ], [ undef, [[IF_END24]] ]
+; CHECK-NEXT: [[J_2:%.*]] = phi i64* [ [[J_0]], [[FOR_COND16]] ], [ poison, [[IF_END24]] ]
; CHECK-NEXT: br i1 true, label [[IF_END24]], label [[FOR_COND16]]
; CHECK: if.end24:
; CHECK-NEXT: [[J_3]] = phi i64* [ [[J_2]], [[FOR_COND20]] ], [ undef, [[ENTRY]] ]
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 false, label %body, label %end
; CHECK: body:
-; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: store i8 poison, i8* null
; CHECK-NEXT: br label %end
; CHECK: end:
; CHECK-NEXT: ret void