Value *X, *Y;
if (match(TI, m_FNeg(m_Value(X))) && match(FI, m_FNeg(m_Value(Y))) &&
(TI->hasOneUse() || FI->hasOneUse())) {
+ // Intersect FMF from the fneg instructions and union those with the select.
+ FastMathFlags FMF = TI->getFastMathFlags();
+ FMF &= FI->getFastMathFlags();
+ FMF |= SI.getFastMathFlags();
Value *NewSel = Builder.CreateSelect(Cond, X, Y, SI.getName() + ".v", &SI);
- return UnaryOperator::CreateFNegFMF(NewSel, TI);
+ if (auto *NewSelI = dyn_cast<Instruction>(NewSel))
+ NewSelI->setFastMathFlags(FMF);
+ Instruction *NewFNeg = UnaryOperator::CreateFNeg(NewSel);
+ NewFNeg->setFastMathFlags(FMF);
+ return NewFNeg;
}
// Min/max intrinsic with a common operand can have the common operand pulled
define double @fneg_fneg_sel_fmf1(double %x, double %y, i1 %cond) {
; CHECK-LABEL: @fneg_fneg_sel_fmf1(
; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]
-; CHECK-NEXT: [[SEL:%.*]] = fneg nnan double [[SEL_V]]
+; CHECK-NEXT: [[SEL:%.*]] = fneg double [[SEL_V]]
; CHECK-NEXT: ret double [[SEL]]
;
%n1 = fneg nnan double %x
define double @fneg_fneg_sel_fmf2(double %x, double %y, i1 %cond) {
; CHECK-LABEL: @fneg_fneg_sel_fmf2(
-; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]
-; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf double [[SEL_V]]
+; CHECK-NEXT: [[SEL_V:%.*]] = select ninf i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]
+; CHECK-NEXT: [[SEL:%.*]] = fneg ninf double [[SEL_V]]
; CHECK-NEXT: ret double [[SEL]]
;
%n1 = fneg nnan ninf double %x
define double @fneg_fneg_sel_fmf3(double %x, double %y, i1 %cond) {
; CHECK-LABEL: @fneg_fneg_sel_fmf3(
-; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]
-; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf double [[SEL_V]]
+; CHECK-NEXT: [[SEL_V:%.*]] = select ninf i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]
+; CHECK-NEXT: [[SEL:%.*]] = fneg ninf double [[SEL_V]]
; CHECK-NEXT: ret double [[SEL]]
;
%n1 = fneg nnan ninf double %x
define double @fneg_fneg_sel_fmf4(double %x, double %y, i1 %cond) {
; CHECK-LABEL: @fneg_fneg_sel_fmf4(
-; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]
-; CHECK-NEXT: [[SEL:%.*]] = fneg nnan double [[SEL_V]]
+; CHECK-NEXT: [[SEL_V:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]
+; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[SEL_V]]
; CHECK-NEXT: ret double [[SEL]]
;
%n1 = fneg nnan double %x