diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index 25e0ff5599d43..5bcdf636ca1d7 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -7823,23 +7823,46 @@ struct AAPotentialValuesFloating : AAPotentialValuesImpl { if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy()) return indicatePessimisticFixpoint(); - // TODO: Use assumed simplified condition value - auto &LHSAA = A.getAAFor(*this, IRPosition::value(*LHS), - DepClassTy::REQUIRED); - if (!LHSAA.isValidState()) - return indicatePessimisticFixpoint(); + bool UsedAssumedInformation = false; + Optional C = A.getAssumedConstant(*SI->getCondition(), *this, + UsedAssumedInformation); + + // Check if we only need one operand. + bool OnlyLeft = false, OnlyRight = false; + if (C.hasValue() && *C && (*C)->isOneValue()) + OnlyLeft = true; + else if (C.hasValue() && *C && (*C)->isZeroValue()) + OnlyRight = true; + + const AAPotentialValues *LHSAA = nullptr, *RHSAA = nullptr; + if (!OnlyRight) { + LHSAA = &A.getAAFor(*this, IRPosition::value(*LHS), + DepClassTy::REQUIRED); + if (!LHSAA->isValidState()) + return indicatePessimisticFixpoint(); + } + if (!OnlyLeft) { + RHSAA = &A.getAAFor(*this, IRPosition::value(*RHS), + DepClassTy::REQUIRED); + if (!RHSAA->isValidState()) + return indicatePessimisticFixpoint(); + } - auto &RHSAA = A.getAAFor(*this, IRPosition::value(*RHS), - DepClassTy::REQUIRED); - if (!RHSAA.isValidState()) - return indicatePessimisticFixpoint(); + if (!LHSAA || !RHSAA) { + // select (true/false), lhs, rhs + auto *OpAA = LHSAA ? LHSAA : RHSAA; - if (LHSAA.undefIsContained() && RHSAA.undefIsContained()) + if (OpAA->undefIsContained()) + unionAssumedWithUndef(); + else + unionAssumed(*OpAA); + + } else if (LHSAA->undefIsContained() && RHSAA->undefIsContained()) { // select i1 *, undef , undef => undef unionAssumedWithUndef(); - else { - unionAssumed(LHSAA); - unionAssumed(RHSAA); + } else { + unionAssumed(*LHSAA); + unionAssumed(*RHSAA); } return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED : ChangeStatus::CHANGED; diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll index db4b8b6ef88f3..1d8b468e43133 100644 --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -1073,6 +1073,37 @@ b: ret i1 %cmp2 } +define i32 @test_select(i32 %c) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_select +; IS__TUNIT____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @select() #[[ATTR1]] +; IS__TUNIT____-NEXT: ret i32 [[CALL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_select +; IS__CGSCC____-SAME: (i32 [[C:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret i32 42 +; + %call = call i32 @select(i1 1, i32 42, i32 %c) + ret i32 %call +} + +define internal i32 @select(i1 %a, i32 %b, i32 %c) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@select +; IS__TUNIT____-SAME: () #[[ATTR1]] { +; IS__TUNIT____-NEXT: ret i32 42 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@select +; IS__CGSCC____-SAME: () #[[ATTR1]] { +; IS__CGSCC____-NEXT: ret i32 undef +; + %s = select i1 %a, i32 %b, i32 %c + ret i32 %s +} + define i1 @icmp() { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@icmp