/// impliesPoison returns true.
bool impliesPoison(const Value *ValAssumedPoison, const Value *V);
-/// Return true if V is poison given that ValAssumedPoison is already poison.
-/// Poison generating flags or metadata are ignored in the process of implying.
-/// And the ignored instructions will be recorded in IgnoredInsts.
-bool impliesPoisonIgnoreFlagsOrMetadata(
- Value *ValAssumedPoison, const Value *V,
- SmallVectorImpl<Instruction *> &IgnoredInsts);
-
/// Return true if this function can prove that V does not have undef bits
/// and is never poison. If V is an aggregate value or vector, check whether
/// all elements (except padding) are not undef or poison.
return false;
}
-static bool
-impliesPoison(Value *ValAssumedPoison, const Value *V, unsigned Depth,
- SmallVectorImpl<Instruction *> *IgnoredInsts = nullptr) {
+static bool impliesPoison(const Value *ValAssumedPoison, const Value *V,
+ unsigned Depth) {
if (isGuaranteedNotToBePoison(ValAssumedPoison))
return true;
if (Depth >= MaxDepth)
return false;
- auto *I = dyn_cast<Instruction>(ValAssumedPoison);
- if (!I || canCreatePoison(cast<Operator>(I),
- /*ConsiderFlagsAndMetadata*/ !IgnoredInsts))
- return false;
-
- for (Value *Op : I->operands())
- if (!impliesPoison(Op, V, Depth + 1, IgnoredInsts))
- return false;
-
- if (IgnoredInsts && I->hasPoisonGeneratingFlagsOrMetadata())
- IgnoredInsts->push_back(I);
-
- return true;
+ const auto *I = dyn_cast<Instruction>(ValAssumedPoison);
+ if (I && !canCreatePoison(cast<Operator>(I))) {
+ return all_of(I->operands(), [=](const Value *Op) {
+ return impliesPoison(Op, V, Depth + 1);
+ });
+ }
+ return false;
}
bool llvm::impliesPoison(const Value *ValAssumedPoison, const Value *V) {
- return ::impliesPoison(const_cast<Value *>(ValAssumedPoison), V,
- /* Depth */ 0);
-}
-
-bool llvm::impliesPoisonIgnoreFlagsOrMetadata(
- Value *ValAssumedPoison, const Value *V,
- SmallVectorImpl<Instruction *> &IgnoredInsts) {
- return ::impliesPoison(ValAssumedPoison, V, /* Depth */ 0, &IgnoredInsts);
+ return ::impliesPoison(ValAssumedPoison, V, /* Depth */ 0);
}
static bool programUndefinedIfUndefOrPoison(const Value *V,
auto *Zero = ConstantInt::getFalse(SelType);
Value *A, *B, *C, *D;
- auto dropPoisonGeneratingFlagsAndMetadata =
- [](ArrayRef<Instruction *> Insts) {
- for (auto *I : Insts)
- I->dropPoisonGeneratingFlagsAndMetadata();
- };
// Folding select to and/or i1 isn't poison safe in general. impliesPoison
// checks whether folding it does not convert a well-defined value into
// poison.
if (match(TrueVal, m_One())) {
+ if (impliesPoison(FalseVal, CondVal)) {
+ // Change: A = select B, true, C --> A = or B, C
+ return BinaryOperator::CreateOr(CondVal, FalseVal);
+ }
+
if (auto *LHS = dyn_cast<FCmpInst>(CondVal))
if (auto *RHS = dyn_cast<FCmpInst>(FalseVal))
if (Value *V = foldLogicOfFCmps(LHS, RHS, /*IsAnd*/ false,
/*IsSelectLogical*/ true))
return replaceInstUsesWith(SI, V);
- // Some patterns can be matched by both of the above and following
- // combinations. Because we need to drop poison generating
- // flags and metadatas for the following combination, it has less priority
- // than the above combination.
- SmallVector<Instruction *> IgnoredInsts;
- if (impliesPoisonIgnoreFlagsOrMetadata(FalseVal, CondVal, IgnoredInsts)) {
- dropPoisonGeneratingFlagsAndMetadata(IgnoredInsts);
- // Change: A = select B, true, C --> A = or B, C
- return BinaryOperator::CreateOr(CondVal, FalseVal);
- }
-
// (A && B) || (C && B) --> (A || C) && B
if (match(CondVal, m_LogicalAnd(m_Value(A), m_Value(B))) &&
match(FalseVal, m_LogicalAnd(m_Value(C), m_Value(D))) &&
}
if (match(FalseVal, m_Zero())) {
+ if (impliesPoison(TrueVal, CondVal)) {
+ // Change: A = select B, C, false --> A = and B, C
+ return BinaryOperator::CreateAnd(CondVal, TrueVal);
+ }
+
if (auto *LHS = dyn_cast<FCmpInst>(CondVal))
if (auto *RHS = dyn_cast<FCmpInst>(TrueVal))
if (Value *V = foldLogicOfFCmps(LHS, RHS, /*IsAnd*/ true,
/*IsSelectLogical*/ true))
return replaceInstUsesWith(SI, V);
- // Some patterns can be matched by both of the above and following
- // combinations. Because we need to drop poison generating
- // flags and metadatas for the following combination, it has less priority
- // than the above combination.
- SmallVector<Instruction *> IgnoredInsts;
- if (impliesPoisonIgnoreFlagsOrMetadata(TrueVal, CondVal, IgnoredInsts)) {
- dropPoisonGeneratingFlagsAndMetadata(IgnoredInsts);
- // Change: A = select B, C, false --> A = and B, C
- return BinaryOperator::CreateAnd(CondVal, TrueVal);
- }
-
// (A || B) && (C || B) --> (A && C) || B
if (match(CondVal, m_LogicalOr(m_Value(A), m_Value(B))) &&
match(TrueVal, m_LogicalOr(m_Value(C), m_Value(D))) &&
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 3
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1
-; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP2]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i1 [[CMP]], i1 false
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2
; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1
-; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP2]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP]]
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 3
; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
define i1 @is_pow2or0_ctpop_wrong_pred2_logical(i32 %x) {
; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred2_logical(
-; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1
-; CHECK-NEXT: [[ISZERO:%.*]] = icmp ne i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 true
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
%cmp = icmp ne i32 %t0, 1
; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 5
; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
define i1 @isnot_pow2nor0_ctpop_wrong_pred2_logical(i32 %x) {
; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred2_logical(
-; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1
-; CHECK-NEXT: [[NOTZERO:%.*]] = icmp eq i32 [[X]], 0
-; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%t0 = tail call i32 @llvm.ctpop.i32(i32 %x)
%cmp = icmp eq i32 %t0, 1
define zeroext i1 @test3_logical(i32 %lhs, i32 %rhs) {
; CHECK-LABEL: @test3_logical(
-; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[LHS:%.*]], [[RHS:%.*]]
+; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[LHS:%.*]], [[RHS:%.*]]
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[LHS]], [[RHS]]
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[SUB]], 31
-; CHECK-NEXT: [[SEL:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
; CHECK-NEXT: ret i1 [[SEL]]
;
; CHECK-NEXT: [[ELEMS_COERCE_FCA_0_EXTRACT:%.*]] = extractvalue [2 x i64] [[ELEMS_COERCE]], 0
; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[ELEMS_COERCE_FCA_0_EXTRACT]] to ptr
; CHECK-NEXT: [[ELEMS_COERCE_FCA_1_EXTRACT:%.*]] = extractvalue [2 x i64] [[ELEMS_COERCE]], 1
-; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[ELEMS_COERCE_FCA_1_EXTRACT]]
+; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[ELEMS_COERCE_FCA_1_EXTRACT]]
; CHECK-NEXT: [[CMP_NOT_I_I_I_I:%.*]] = icmp slt i64 [[ELEMS_COERCE_FCA_1_EXTRACT]], 0
; CHECK-NEXT: br i1 [[CMP_NOT_I_I_I_I]], label [[ERROR:%.*]], label [[FOR_COND_PREHEADER:%.*]]
; CHECK: for.cond.preheader:
-; CHECK-NEXT: [[ADD_PTR_I_IDX_MASK:%.*]] = and i64 [[ELEMS_COERCE_FCA_1_EXTRACT]], 4611686018427387903
-; CHECK-NEXT: [[CMP_I_NOT2:%.*]] = icmp eq i64 [[ADD_PTR_I_IDX_MASK]], 0
+; CHECK-NEXT: [[CMP_I_NOT2:%.*]] = icmp eq i64 [[ELEMS_COERCE_FCA_1_EXTRACT]], 0
; CHECK-NEXT: br i1 [[CMP_I_NOT2]], label [[COMMON_RET:%.*]], label [[FOR_BODY:%.*]]
; CHECK: common.ret:
; CHECK-NEXT: ret void