if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
return indicatePessimisticFixpoint();
- // TODO: Use assumed simplified condition value
- auto &LHSAA = A.getAAFor<AAPotentialValues>(*this, IRPosition::value(*LHS),
- DepClassTy::REQUIRED);
- if (!LHSAA.isValidState())
- return indicatePessimisticFixpoint();
+ bool UsedAssumedInformation = false;
+ Optional<Constant *> 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<AAPotentialValues>(*this, IRPosition::value(*LHS),
+ DepClassTy::REQUIRED);
+ if (!LHSAA->isValidState())
+ return indicatePessimisticFixpoint();
+ }
+ if (!OnlyLeft) {
+ RHSAA = &A.getAAFor<AAPotentialValues>(*this, IRPosition::value(*RHS),
+ DepClassTy::REQUIRED);
+ if (!RHSAA->isValidState())
+ return indicatePessimisticFixpoint();
+ }
- auto &RHSAA = A.getAAFor<AAPotentialValues>(*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;
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