[llvm] 5d7d689 - [InstCombine] fix propagation of FMF through select-of-fnegs

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 31 06:52:23 PDT 2021


Author: Sanjay Patel
Date: 2021-08-31T09:52:17-04:00
New Revision: 5d7d689edf01e41d908ced188efcc6405627fd2b

URL: https://github.com/llvm/llvm-project/commit/5d7d689edf01e41d908ced188efcc6405627fd2b
DIFF: https://github.com/llvm/llvm-project/commit/5d7d689edf01e41d908ced188efcc6405627fd2b.diff

LOG: [InstCombine] fix propagation of FMF through select-of-fnegs

The existing code was unquestionably wrong - it looked at one
fneg and ignored the other 2 instructions.

It was also untested, so it didn't make the list of bugs
flagged by Alive2.

This is an unusual propagation, but Alive2 agress that we
can intersect the fnegs and union that with the select,
then apply the results to both new instructions:
https://alive2.llvm.org/ce/z/SF8_dt

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/test/Transforms/InstCombine/fneg.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index ff4611e163ae..b9242f4fb8bc 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -319,8 +319,16 @@ Instruction *InstCombinerImpl::foldSelectOpOp(SelectInst &SI, Instruction *TI,
   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

diff  --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index 9caa620ffa17..3e1d58149151 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -441,7 +441,7 @@ define float @fneg_fneg_sel_extra_use3(float %x, float %y, i1 %cond) {
 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
@@ -452,8 +452,8 @@ define double @fneg_fneg_sel_fmf1(double %x, double %y, i1 %cond) {
 
 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
@@ -464,8 +464,8 @@ define double @fneg_fneg_sel_fmf2(double %x, double %y, i1 %cond) {
 
 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
@@ -476,8 +476,8 @@ define double @fneg_fneg_sel_fmf3(double %x, double %y, i1 %cond) {
 
 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


        


More information about the llvm-commits mailing list