diff --git a/llvm/include/llvm/Analysis/ValueLattice.h b/llvm/include/llvm/Analysis/ValueLattice.h --- a/llvm/include/llvm/Analysis/ValueLattice.h +++ b/llvm/include/llvm/Analysis/ValueLattice.h @@ -44,6 +44,10 @@ /// overdefined undef, + /// The same as undef state except it is an PoisonValue constant or produces + /// poison. + poison, + /// This Value has a specific constant value. The constant cannot be undef. /// (For constant integers, constantrange is used instead. Integer typed /// constantexprs can appear as constant.) Note that the constant state @@ -96,6 +100,7 @@ case overdefined: case unknown: case undef: + case poison: case constant: case notconstant: break; @@ -164,6 +169,7 @@ case overdefined: case unknown: case undef: + case poison: break; } } @@ -183,6 +189,7 @@ case overdefined: case unknown: case undef: + case poison: break; } Other.Tag = unknown; @@ -238,8 +245,11 @@ } bool isUndef() const { return Tag == undef; } + bool isPoison() const { return Tag == poison; } bool isUnknown() const { return Tag == unknown; } - bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; } + bool isUnknownOrUndefOrPoison() const { + return Tag == unknown || Tag == undef || Tag == poison; + } bool isConstant() const { return Tag == constant; } bool isNotConstant() const { return Tag == notconstant; } bool isConstantRangeIncludingUndef() const { @@ -292,6 +302,15 @@ return true; } + bool markPoison() { + if (isPoison()) + return false; + + assert(isUnknown()); + Tag = poison; + return true; + } + bool markUndef() { if (isUndef()) return false; @@ -302,6 +321,9 @@ } bool markConstant(Constant *V, bool MayIncludeUndef = false) { + if (isa(V)) + return markPoison(); + if (isa(V)) return markUndef(); @@ -375,7 +397,7 @@ return true; } - assert(isUnknown() || isUndef()); + assert(isUnknownOrUndefOrPoison()); NumRangeExtensions = 0; Tag = NewTag; @@ -394,9 +416,11 @@ return true; } - if (isUndef()) { + if (isUndef() || isPoison()) { assert(!RHS.isUnknown()); - if (RHS.isUndef()) + if (isPoison() && RHS.isUndef()) + return markUndef(); + if (RHS.isUndef() || RHS.isPoison()) return false; if (RHS.isConstant()) return markConstant(RHS.getConstant(), true); diff --git a/llvm/lib/Analysis/ValueLattice.cpp b/llvm/lib/Analysis/ValueLattice.cpp --- a/llvm/lib/Analysis/ValueLattice.cpp +++ b/llvm/lib/Analysis/ValueLattice.cpp @@ -57,6 +57,8 @@ return OS << "unknown"; if (Val.isUndef()) return OS << "undef"; + if (Val.isPoison()) + return OS << "poison"; if (Val.isOverdefined()) return OS << "overdefined"; diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -310,7 +310,7 @@ } if (F->getReturnType()->isVoidTy()) continue; - if (SCCPSolver::isConstant(ReturnValue) || ReturnValue.isUnknownOrUndef()) + if (SCCPSolver::isConstant(ReturnValue) || ReturnValue.isUnknownOrUndefOrPoison()) findReturnsToZap(*F, ReturnsToZap, Solver); } diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp --- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp +++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp @@ -58,7 +58,7 @@ } bool SCCPSolver::isOverdefined(const ValueLatticeElement &LV) { - return !LV.isUnknownOrUndef() && !SCCPSolver::isConstant(LV); + return !LV.isUnknownOrUndefOrPoison() && !SCCPSolver::isConstant(LV); } static bool canRemoveInstruction(Instruction *I) { @@ -912,8 +912,12 @@ const ValueLatticeElement &LV = getLatticeValueFor(V); if (SCCPSolver::isOverdefined(LV)) return nullptr; - Const = SCCPSolver::isConstant(LV) ? getConstant(LV) - : UndefValue::get(V->getType()); + if (SCCPSolver::isConstant(LV)) + Const = getConstant(LV); + else if (LV.isPoison()) + Const = PoisonValue::get(V->getType()); + else + Const = UndefValue::get(V->getType()); } assert(Const && "Constant is nullptr here!"); return Const; @@ -1011,7 +1015,7 @@ if (!CI) { // Overdefined condition variables, and branches on unfoldable constant // conditions, mean the branch could go either way. - if (!BCValue.isUnknownOrUndef()) + if (!BCValue.isUnknownOrUndefOrPoison()) Succs[0] = Succs[1] = true; return; } @@ -1054,7 +1058,7 @@ } // Overdefined or unknown condition? All destinations are executable! - if (!SCValue.isUnknownOrUndef()) + if (!SCValue.isUnknownOrUndefOrPoison()) Succs.assign(TI.getNumSuccessors(), true); return; } @@ -1067,7 +1071,7 @@ BlockAddress *Addr = dyn_cast_or_null(getConstant(IBRValue)); if (!Addr) { // Overdefined or unknown condition? // All destinations are executable! - if (!IBRValue.isUnknownOrUndef()) + if (!IBRValue.isUnknownOrUndefOrPoison()) Succs.assign(TI.getNumSuccessors(), true); return; } @@ -1216,7 +1220,7 @@ return; ValueLatticeElement OpSt = getValueState(I.getOperand(0)); - if (OpSt.isUnknownOrUndef()) + if (OpSt.isUnknownOrUndefOrPoison()) return; if (Constant *OpC = getConstant(OpSt)) { @@ -1254,7 +1258,7 @@ ValueLatticeElement R = getValueState(RHS); addAdditionalUser(LHS, &EVI); addAdditionalUser(RHS, &EVI); - if (L.isUnknownOrUndef() || R.isUnknownOrUndef()) + if (L.isUnknownOrUndefOrPoison() || R.isUnknownOrUndefOrPoison()) return; // Wait to resolve. Type *Ty = LHS->getType(); @@ -1351,7 +1355,7 @@ return (void)markOverdefined(&I); ValueLatticeElement CondValue = getValueState(I.getCondition()); - if (CondValue.isUnknownOrUndef()) + if (CondValue.isUnknownOrUndefOrPoison()) return; if (ConstantInt *CondCB = getConstantInt(CondValue)) { @@ -1383,7 +1387,7 @@ return (void)markOverdefined(&I); // If something is unknown/undef, wait for it to resolve. - if (V0State.isUnknownOrUndef()) + if (V0State.isUnknownOrUndefOrPoison()) return; if (SCCPSolver::isConstant(V0State)) @@ -1408,7 +1412,7 @@ return (void)markOverdefined(&I); // If something is unknown/undef, wait for it to resolve. - if (V0State.isUnknownOrUndef()) + if (V0State.isUnknownOrUndefOrPoison()) return; if (SCCPSolver::isConstant(V0State) && @@ -1428,7 +1432,7 @@ return; // If something is undef, wait for it to resolve. - if (V1State.isUnknownOrUndef() || V2State.isUnknownOrUndef()) + if (V1State.isUnknownOrUndefOrPoison() || V2State.isUnknownOrUndefOrPoison()) return; if (V1State.isOverdefined() && V2State.isOverdefined()) @@ -1436,7 +1440,7 @@ // If either of the operands is a constant, try to fold it to a constant. // TODO: Use information from notconstant better. - if ((V1State.isConstant() || V2State.isConstant())) { + if (SCCPSolver::isConstant(V1State) || SCCPSolver::isConstant(V2State)) { Value *V1 = SCCPSolver::isConstant(V1State) ? getConstant(V1State) : I.getOperand(0); Value *V2 = SCCPSolver::isConstant(V2State) ? getConstant(V2State) @@ -1494,7 +1498,7 @@ } // If operands are still unknown, wait for it to resolve. - if ((V1State.isUnknownOrUndef() || V2State.isUnknownOrUndef()) && + if ((V1State.isUnknownOrUndefOrPoison() || V2State.isUnknownOrUndefOrPoison()) && !SCCPSolver::isConstant(ValueState[&I])) return; @@ -1512,7 +1516,7 @@ for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { ValueLatticeElement State = getValueState(I.getOperand(i)); - if (State.isUnknownOrUndef()) + if (State.isUnknownOrUndefOrPoison()) return; // Operands are not resolved yet. if (SCCPSolver::isOverdefined(State)) @@ -1578,7 +1582,7 @@ return (void)markOverdefined(&I); ValueLatticeElement PtrVal = getValueState(I.getOperand(0)); - if (PtrVal.isUnknownOrUndef()) + if (PtrVal.isUnknownOrUndefOrPoison()) return; // The pointer is not resolved yet! ValueLatticeElement &IV = ValueState[&I]; @@ -1642,7 +1646,7 @@ continue; // Carried in CB, not allowed in Operands. ValueLatticeElement State = getValueState(A); - if (State.isUnknownOrUndef()) + if (State.isUnknownOrUndefOrPoison()) return; // Operands are not resolved yet. if (SCCPSolver::isOverdefined(State)) return (void)markOverdefined(&CB); @@ -1779,7 +1783,7 @@ SmallVector OpRanges; for (Value *Op : II->args()) { const ValueLatticeElement &State = getValueState(Op); - if (State.isUnknownOrUndef()) + if (State.isUnknownOrUndefOrPoison()) return; OpRanges.push_back(getConstantRange(State, Op->getType())); } diff --git a/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll b/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll --- a/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll +++ b/llvm/test/Transforms/SCCP/binaryops-range-special-cases.ll @@ -102,8 +102,7 @@ ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) -; CHECK-NEXT: [[UREM_3:%.*]] = urem i16 12704, 0 -; CHECK-NEXT: [[C_5:%.*]] = icmp eq i16 [[UREM_3]], 1 +; CHECK-NEXT: [[C_5:%.*]] = icmp eq i16 poison, 1 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; @@ -130,8 +129,7 @@ ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) -; CHECK-NEXT: [[SREM_3:%.*]] = urem i16 12704, 0 -; CHECK-NEXT: [[C_5:%.*]] = icmp eq i16 [[SREM_3]], 1 +; CHECK-NEXT: [[C_5:%.*]] = icmp eq i16 poison, 1 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SCCP/ip-ranges-phis.ll b/llvm/test/Transforms/SCCP/ip-ranges-phis.ll --- a/llvm/test/Transforms/SCCP/ip-ranges-phis.ll +++ b/llvm/test/Transforms/SCCP/ip-ranges-phis.ll @@ -56,11 +56,11 @@ ; CHECK-NEXT: [[V_2:%.*]] = select i1 [[C_2]], i32 20, i32 200 ; CHECK-NEXT: [[V_3:%.*]] = select i1 [[C_3]], i32 30, i32 300 ; CHECK-NEXT: [[R_1:%.*]] = add nuw nsw i32 [[V_1]], [[V_2]] -; CHECK-NEXT: [[R_2:%.*]] = add nuw nsw i32 [[R_1]], [[V_3]] -; CHECK-NEXT: [[R_3:%.*]] = add nuw nsw i32 [[R_2]], 400 -; CHECK-NEXT: [[R_4:%.*]] = add nuw nsw i32 [[R_3]], 50 -; CHECK-NEXT: [[R_5:%.*]] = add nuw nsw i32 [[R_4]], 60 -; CHECK-NEXT: [[R_6:%.*]] = add nuw nsw i32 [[R_4]], 700 +; CHECK-NEXT: [[R_2:%.*]] = add i32 [[R_1]], [[V_3]] +; CHECK-NEXT: [[R_3:%.*]] = add i32 [[R_2]], 400 +; CHECK-NEXT: [[R_4:%.*]] = add i32 [[R_3]], 50 +; CHECK-NEXT: [[R_5:%.*]] = add i32 [[R_4]], 60 +; CHECK-NEXT: [[R_6:%.*]] = add i32 [[R_4]], 700 ; CHECK-NEXT: ret i32 [[R_6]] ; @@ -204,7 +204,7 @@ ; CHECK-NEXT: br label [[END]] ; CHECK: end: ; CHECK-NEXT: [[P1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 5, [[IF_TRUE]] ] -; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @f3(i32 [[P1]], i32 [[Y]], i1 [[CMP_1]]) +; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @f3(i32 [[P1]], i32 [[Y]], i1 [[CMP_1]]), !range [[RNG0:![0-9]+]] ; CHECK-NEXT: ret i32 [[CALL1]] ; diff --git a/llvm/test/Transforms/SCCP/overdefined-div.ll b/llvm/test/Transforms/SCCP/overdefined-div.ll --- a/llvm/test/Transforms/SCCP/overdefined-div.ll +++ b/llvm/test/Transforms/SCCP/overdefined-div.ll @@ -25,8 +25,7 @@ define i32 @test3(i32 %foo) { ; CHECK-LABEL: define i32 @test3 ; CHECK-SAME: (i32 [[FOO:%.*]]) { -; CHECK-NEXT: [[TINKYWINKY:%.*]] = udiv i32 [[FOO]], 0 -; CHECK-NEXT: ret i32 [[TINKYWINKY]] +; CHECK-NEXT: ret i32 poison ; %tinkywinky = udiv i32 %foo, 0 ret i32 %tinkywinky @@ -35,8 +34,7 @@ define i32 @test4(i32 %foo) { ; CHECK-LABEL: define i32 @test4 ; CHECK-SAME: (i32 [[FOO:%.*]]) { -; CHECK-NEXT: [[TINKYWINKY:%.*]] = sdiv i32 [[FOO]], 0 -; CHECK-NEXT: ret i32 [[TINKYWINKY]] +; CHECK-NEXT: ret i32 poison ; %tinkywinky = sdiv i32 %foo, 0 ret i32 %tinkywinky diff --git a/llvm/test/Transforms/SCCP/ub-shift.ll b/llvm/test/Transforms/SCCP/ub-shift.ll --- a/llvm/test/Transforms/SCCP/ub-shift.ll +++ b/llvm/test/Transforms/SCCP/ub-shift.ll @@ -3,10 +3,9 @@ define void @shift_undef_64(ptr %p) { ; CHECK-LABEL: @shift_undef_64( -; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 4 -; CHECK-NEXT: store i64 -1, ptr [[P]], align 4 -; CHECK-NEXT: [[R3:%.*]] = shl nuw nsw i64 -1, 4294967298 -; CHECK-NEXT: store i64 [[R3]], ptr [[P]], align 4 +; CHECK-NEXT: store i64 poison, ptr [[P:%.*]], align 4 +; CHECK-NEXT: store i64 poison, ptr [[P]], align 4 +; CHECK-NEXT: store i64 poison, ptr [[P]], align 4 ; CHECK-NEXT: ret void ; %r1 = lshr i64 -1, 4294967296 ; 2^32 @@ -23,10 +22,9 @@ define void @shift_undef_65(ptr %p) { ; CHECK-LABEL: @shift_undef_65( -; CHECK-NEXT: store i65 0, ptr [[P:%.*]], align 4 -; CHECK-NEXT: store i65 0, ptr [[P]], align 4 -; CHECK-NEXT: [[R3:%.*]] = shl nuw nsw i65 1, -18446744073709551615 -; CHECK-NEXT: store i65 [[R3]], ptr [[P]], align 4 +; CHECK-NEXT: store i65 poison, ptr [[P:%.*]], align 4 +; CHECK-NEXT: store i65 poison, ptr [[P]], align 4 +; CHECK-NEXT: store i65 poison, ptr [[P]], align 4 ; CHECK-NEXT: ret void ; %r1 = lshr i65 2, 18446744073709551617 @@ -43,10 +41,9 @@ define void @shift_undef_256(ptr %p) { ; CHECK-LABEL: @shift_undef_256( -; CHECK-NEXT: store i256 0, ptr [[P:%.*]], align 4 -; CHECK-NEXT: store i256 0, ptr [[P]], align 4 -; CHECK-NEXT: [[R3:%.*]] = shl nuw nsw i256 1, 18446744073709551619 -; CHECK-NEXT: store i256 [[R3]], ptr [[P]], align 4 +; CHECK-NEXT: store i256 poison, ptr [[P:%.*]], align 4 +; CHECK-NEXT: store i256 poison, ptr [[P]], align 4 +; CHECK-NEXT: store i256 poison, ptr [[P]], align 4 ; CHECK-NEXT: ret void ; %r1 = lshr i256 2, 18446744073709551617 @@ -63,10 +60,9 @@ define void @shift_undef_511(ptr %p) { ; CHECK-LABEL: @shift_undef_511( -; CHECK-NEXT: store i511 0, ptr [[P:%.*]], align 4 -; CHECK-NEXT: store i511 -1, ptr [[P]], align 4 -; CHECK-NEXT: [[R3:%.*]] = shl nuw nsw i511 -3, 1208925819614629174706180 -; CHECK-NEXT: store i511 [[R3]], ptr [[P]], align 4 +; CHECK-NEXT: store i511 poison, ptr [[P:%.*]], align 4 +; CHECK-NEXT: store i511 poison, ptr [[P]], align 4 +; CHECK-NEXT: store i511 poison, ptr [[P]], align 4 ; CHECK-NEXT: ret void ; %r1 = lshr i511 -1, 1208925819614629174706276 ; 2^80 + 100