Value *Cond;
if (match(Op, m_OneUse(m_Select(m_Value(Cond), m_Value(X), m_Value(Y))))) {
// Unlike most transforms, this one is not safe to propagate nsz unless
- // it is present on the original select. (We are conservatively intersecting
- // the nsz flags from the select and root fneg instruction.)
+ // it is present on the original select. We union the flags from the select
+ // and fneg and then remove nsz if needed.
auto propagateSelectFMF = [&](SelectInst *S, bool CommonOperand) {
S->copyFastMathFlags(&I);
- if (auto *OldSel = dyn_cast<SelectInst>(Op))
+ if (auto *OldSel = dyn_cast<SelectInst>(Op)) {
+ FastMathFlags FMF = I.getFastMathFlags();
+ FMF |= OldSel->getFastMathFlags();
+ S->setFastMathFlags(FMF);
if (!OldSel->hasNoSignedZeros() && !CommonOperand &&
!isGuaranteedNotToBeUndefOrPoison(OldSel->getCondition()))
S->setHasNoSignedZeros(false);
+ }
};
// -(Cond ? -P : Y) --> Cond ? P : -Y
Value *P;
define <2 x float> @select_fneg_false(<2 x float> %x, <2 x float> %y, <2 x i1> %b) {
; CHECK-LABEL: @select_fneg_false(
; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan nsz <2 x float> [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select nnan <2 x i1> [[B:%.*]], <2 x float> [[X_NEG]], <2 x float> [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = select nnan ninf <2 x i1> [[B:%.*]], <2 x float> [[X_NEG]], <2 x float> [[Y:%.*]]
; CHECK-NEXT: ret <2 x float> [[R]]
;
%ny = fneg nnan <2 x float> %y
; CHECK-NEXT: [[NX:%.*]] = fneg ninf float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[NX]])
; CHECK-NEXT: [[Y_NEG:%.*]] = fneg float [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], float [[X]], float [[Y_NEG]]
+; CHECK-NEXT: [[R:%.*]] = select fast i1 [[B:%.*]], float [[X]], float [[Y_NEG]]
; CHECK-NEXT: ret float [[R]]
;
%nx = fneg ninf float %x