diff --git a/llvm/include/llvm/Analysis/InstructionSimplify.h b/llvm/include/llvm/Analysis/InstructionSimplify.h --- a/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -128,9 +128,11 @@ return Copy; } - /// If CanUseUndef is true, returns whether \p V is undef. - /// Otherwise always return false. - bool isUndefValue(Value *V) const { + /// If CanUseUndef is true, returns true if \p V is undef or poison. + /// Otherwise, return true if V is poison. + bool isUndefOrPoison(Value *V) const { + if (isa(V)) + return true; if (!CanUseUndef) return false; return isa(V); diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -415,9 +415,9 @@ return TV; // If one branch simplified to undef, return the other one. - if (TV && Q.isUndefValue(TV)) + if (TV && Q.isUndefOrPoison(TV)) return FV; - if (FV && Q.isUndefValue(FV)) + if (FV && Q.isUndefOrPoison(FV)) return TV; // If applying the operation did not change the true and false select values, @@ -612,7 +612,7 @@ return C; // X + undef -> undef - if (Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op1)) return Op1; // X + 0 -> X @@ -732,7 +732,7 @@ // X - undef -> undef // undef - X -> undef - if (Q.isUndefValue(Op0) || Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op0) || Q.isUndefOrPoison(Op1)) return UndefValue::get(Op0->getType()); // X - 0 -> X @@ -867,7 +867,7 @@ // X * undef -> 0 // X * 0 -> 0 - if (Q.isUndefValue(Op1) || match(Op1, m_Zero())) + if (Q.isUndefOrPoison(Op1) || match(Op1, m_Zero())) return Constant::getNullValue(Op0->getType()); // X * 1 -> X @@ -926,7 +926,7 @@ // X / undef -> undef // X % undef -> undef - if (Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op1)) return Op1; // X / 0 -> undef @@ -943,14 +943,14 @@ unsigned NumElts = VTy->getNumElements(); for (unsigned i = 0; i != NumElts; ++i) { Constant *Elt = Op1C->getAggregateElement(i); - if (Elt && (Elt->isNullValue() || Q.isUndefValue(Elt))) + if (Elt && (Elt->isNullValue() || Q.isUndefOrPoison(Elt))) return UndefValue::get(Ty); } } // undef / X -> 0 // undef % X -> 0 - if (Q.isUndefValue(Op0)) + if (Q.isUndefOrPoison(Op0)) return Constant::getNullValue(Ty); // 0 / X -> 0 @@ -1204,7 +1204,7 @@ return false; // X shift by undef -> undef because it may shift by the bitwidth. - if (Q.isUndefValue(C)) + if (Q.isUndefOrPoison(C)) return true; // Shifting by the bitwidth or more is undefined. @@ -1290,7 +1290,7 @@ // undef >> X -> 0 // undef >> X -> undef (if it's exact) - if (Q.isUndefValue(Op0)) + if (Q.isUndefOrPoison(Op0)) return isExact ? Op0 : Constant::getNullValue(Op0->getType()); // The low bit cannot be shifted out of an exact shift if it is set. @@ -1312,7 +1312,7 @@ // undef << X -> 0 // undef << X -> undef if (if it's NSW/NUW) - if (Q.isUndefValue(Op0)) + if (Q.isUndefOrPoison(Op0)) return isNSW || isNUW ? Op0 : Constant::getNullValue(Op0->getType()); // (X >> A) << A -> X @@ -2007,7 +2007,7 @@ return C; // X & undef -> 0 - if (Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op1)) return Constant::getNullValue(Op0->getType()); // X & X = X @@ -2165,7 +2165,7 @@ // X | undef -> -1 // X | -1 = -1 // Do not return Op1 because it may contain undef elements if it's a vector. - if (Q.isUndefValue(Op1) || match(Op1, m_AllOnes())) + if (Q.isUndefOrPoison(Op1) || match(Op1, m_AllOnes())) return Constant::getAllOnesValue(Op0->getType()); // X | X = X @@ -2307,7 +2307,7 @@ return C; // A ^ undef -> undef - if (Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op1)) return Op1; // A ^ 0 = A @@ -3305,12 +3305,12 @@ // For EQ and NE, we can always pick a value for the undef to make the // predicate pass or fail, so we can return undef. // Matches behavior in llvm::ConstantFoldCompareInstruction. - if (Q.isUndefValue(RHS) && ICmpInst::isEquality(Pred)) + if (Q.isUndefOrPoison(RHS) && ICmpInst::isEquality(Pred)) return UndefValue::get(ITy); // icmp X, X -> true/false // icmp X, undef -> true/false because undef could be X. - if (LHS == RHS || Q.isUndefValue(RHS)) + if (LHS == RHS || Q.isUndefOrPoison(RHS)) return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred)); if (Value *V = simplifyICmpOfBools(Pred, LHS, RHS, Q)) @@ -3637,7 +3637,7 @@ // fcmp pred x, undef and fcmp pred undef, x // fold to true if unordered, false if ordered - if (Q.isUndefValue(LHS) || Q.isUndefValue(RHS)) { + if (Q.isUndefOrPoison(LHS) || Q.isUndefOrPoison(RHS)) { // Choosing NaN for the undef will always make unordered comparison succeed // and ordered comparison fail. return ConstantInt::get(RetTy, CmpInst::isUnordered(Pred)); @@ -4097,7 +4097,7 @@ return ConstantFoldSelectInstruction(CondC, TrueC, FalseC); // select undef, X, Y -> X or Y - if (Q.isUndefValue(CondC)) + if (Q.isUndefOrPoison(CondC)) return isa(FalseVal) ? FalseVal : TrueVal; // TODO: Vector constants with undef elements don't simplify. @@ -4126,11 +4126,11 @@ // If the true or false value is undef, we can fold to the other value as // long as the other value isn't poison. // select ?, undef, X -> X - if (Q.isUndefValue(TrueVal) && + if (Q.isUndefOrPoison(TrueVal) && isGuaranteedNotToBeUndefOrPoison(FalseVal, Q.AC, Q.CxtI, Q.DT)) return FalseVal; // select ?, X, undef -> X - if (Q.isUndefValue(FalseVal) && + if (Q.isUndefOrPoison(FalseVal) && isGuaranteedNotToBeUndefOrPoison(TrueVal, Q.AC, Q.CxtI, Q.DT)) return TrueVal; @@ -4153,10 +4153,10 @@ // one element is undef, choose the defined element as the safe result. if (TEltC == FEltC) NewC.push_back(TEltC); - else if (Q.isUndefValue(TEltC) && + else if (Q.isUndefOrPoison(TEltC) && isGuaranteedNotToBeUndefOrPoison(FEltC)) NewC.push_back(FEltC); - else if (Q.isUndefValue(FEltC) && + else if (Q.isUndefOrPoison(FEltC) && isGuaranteedNotToBeUndefOrPoison(TEltC)) NewC.push_back(TEltC); else @@ -4208,7 +4208,7 @@ else if (VectorType *VT = dyn_cast(Ops[1]->getType())) GEPTy = VectorType::get(GEPTy, VT->getElementCount()); - if (Q.isUndefValue(Ops[0])) + if (Q.isUndefOrPoison(Ops[0])) return UndefValue::get(GEPTy); bool IsScalableVec = isa(SrcTy); @@ -4317,7 +4317,7 @@ return ConstantFoldInsertValueInstruction(CAgg, CVal, Idxs); // insertvalue x, undef, n -> x - if (Q.isUndefValue(Val)) + if (Q.isUndefOrPoison(Val)) return Agg; // insertvalue x, (extractvalue y, n), n @@ -4325,7 +4325,7 @@ if (EV->getAggregateOperand()->getType() == Agg->getType() && EV->getIndices() == Idxs) { // insertvalue undef, (extractvalue y, n), n -> y - if (Q.isUndefValue(Agg)) + if (Q.isUndefOrPoison(Agg)) return EV->getAggregateOperand(); // insertvalue y, (extractvalue y, n), n -> y @@ -4359,12 +4359,12 @@ } // If index is undef, it might be out of bounds (see above case) - if (Q.isUndefValue(Idx)) + if (Q.isUndefOrPoison(Idx)) return UndefValue::get(Vec->getType()); // If the scalar is undef, and there is no risk of propagating poison from the // vector value, simplify to the vector value. - if (Q.isUndefValue(Val) && + if (Q.isUndefOrPoison(Val) && isGuaranteedNotToBeUndefOrPoison(Vec)) return Vec; @@ -4420,7 +4420,7 @@ if (auto *Splat = CVec->getSplatValue()) return Splat; - if (Q.isUndefValue(Vec)) + if (Q.isUndefOrPoison(Vec)) return UndefValue::get(VecVTy->getElementType()); } @@ -4437,7 +4437,7 @@ // An undef extract index can be arbitrarily chosen to be an out-of-range // index value, which would result in the instruction being undef. - if (Q.isUndefValue(Idx)) + if (Q.isUndefOrPoison(Idx)) return UndefValue::get(VecVTy->getElementType()); return nullptr; @@ -4461,7 +4461,7 @@ for (Value *Incoming : PN->incoming_values()) { // If the incoming value is the phi node itself, it can safely be skipped. if (Incoming == PN) continue; - if (Q.isUndefValue(Incoming)) { + if (Q.isUndefOrPoison(Incoming)) { // Remember that we saw an undef value, but otherwise ignore them. HasUndefInput = true; continue; @@ -4657,7 +4657,7 @@ // A shuffle of a splat is always the splat itself. Legal if the shuffle's // value type is same as the input vectors' type. if (auto *OpShuf = dyn_cast(Op0)) - if (Q.isUndefValue(Op1) && RetTy == InVecTy && + if (Q.isUndefOrPoison(Op1) && RetTy == InVecTy && is_splat(OpShuf->getShuffleMask())) return Op0; @@ -4743,7 +4743,7 @@ for (Value *V : Ops) { bool IsNan = match(V, m_NaN()); bool IsInf = match(V, m_Inf()); - bool IsUndef = Q.isUndefValue(V); + bool IsUndef = Q.isUndefOrPoison(V); // If this operation has 'nnan' or 'ninf' and at least 1 disallowed operand // (an undef operand can be chosen to be Nan/Inf), then the result of @@ -5346,7 +5346,7 @@ std::swap(Op0, Op1); // Assume undef is the limit value. - if (Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op1)) return ConstantInt::get(ReturnType, getMaxMinLimit(IID, BitWidth)); const APInt *C; @@ -5410,7 +5410,7 @@ // undef - X -> { undef, false } // X + undef -> { undef, false } // undef + x -> { undef, false } - if (Q.isUndefValue(Op0) || Q.isUndefValue(Op1)) { + if (Q.isUndefOrPoison(Op0) || Q.isUndefOrPoison(Op1)) { return ConstantStruct::get( cast(ReturnType), {UndefValue::get(ReturnType->getStructElementType(0)), @@ -5425,7 +5425,7 @@ return Constant::getNullValue(ReturnType); // undef * X -> { 0, false } // X * undef -> { 0, false } - if (Q.isUndefValue(Op0) || Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op0) || Q.isUndefOrPoison(Op1)) return Constant::getNullValue(ReturnType); break; case Intrinsic::uadd_sat: @@ -5439,7 +5439,7 @@ // sat(undef + X) -> -1 // For unsigned: Assume undef is MAX, thus we saturate to MAX (-1). // For signed: Assume undef is ~X, in which case X + ~X = -1. - if (Q.isUndefValue(Op0) || Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op0) || Q.isUndefOrPoison(Op1)) return Constant::getAllOnesValue(ReturnType); // X + 0 -> X @@ -5456,7 +5456,7 @@ LLVM_FALLTHROUGH; case Intrinsic::ssub_sat: // X - X -> 0, X - undef -> 0, undef - X -> 0 - if (Op0 == Op1 || Q.isUndefValue(Op0) || Q.isUndefValue(Op1)) + if (Op0 == Op1 || Q.isUndefOrPoison(Op0) || Q.isUndefOrPoison(Op1)) return Constant::getNullValue(ReturnType); // X - 0 -> X if (match(Op1, m_Zero())) @@ -5499,7 +5499,7 @@ std::swap(Op0, Op1); // If an argument is undef, return the other argument. - if (Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op1)) return Op0; bool PropagateNaN = IID == Intrinsic::minimum || IID == Intrinsic::maximum; @@ -5585,11 +5585,11 @@ *ShAmtArg = Call->getArgOperand(2); // If both operands are undef, the result is undef. - if (Q.isUndefValue(Op0) && Q.isUndefValue(Op1)) + if (Q.isUndefOrPoison(Op0) && Q.isUndefOrPoison(Op1)) return UndefValue::get(F->getReturnType()); // If shift amount is undef, assume it is zero. - if (Q.isUndefValue(ShAmtArg)) + if (Q.isUndefOrPoison(ShAmtArg)) return Call->getArgOperand(IID == Intrinsic::fshl ? 0 : 1); const APInt *ShAmtC; diff --git a/llvm/test/Transforms/InstSimplify/select.ll b/llvm/test/Transforms/InstSimplify/select.ll --- a/llvm/test/Transforms/InstSimplify/select.ll +++ b/llvm/test/Transforms/InstSimplify/select.ll @@ -942,6 +942,21 @@ ret i1 %spec.select } +define i1 @expand_binop_poison(i32 %x, i32 %y) { +; CHECK-LABEL: @expand_binop_poison( +; CHECK-NEXT: [[CMP9_NOT_1:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMP15:%.*]] = icmp slt i32 [[X]], [[Y]] +; CHECK-NEXT: [[SPEC_SELECT39:%.*]] = select i1 [[CMP9_NOT_1]], i1 poison, i1 [[CMP15]] +; CHECK-NEXT: ret i1 [[SPEC_SELECT39]] +; + %cmp9.not.1 = icmp eq i32 %x, %y + %cmp15 = icmp slt i32 %x, %y + %spec.select39 = select i1 %cmp9.not.1, i1 poison, i1 %cmp15 + %spec.select40 = xor i1 %cmp9.not.1, 1 + %spec.select = and i1 %spec.select39, %spec.select40 + ret i1 %spec.select +} + define i32 @pr47322_more_poisonous_replacement(i32 %arg) { ; CHECK-LABEL: @pr47322_more_poisonous_replacement( ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARG:%.*]], 0