[llvm] r267139 - [InstCombine] Preserve fast math flags when combining PHIs

Silviu Baranga via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 22 04:21:36 PDT 2016


Author: sbaranga
Date: Fri Apr 22 06:21:36 2016
New Revision: 267139

URL: http://llvm.org/viewvc/llvm-project?rev=267139&view=rev
Log:
[InstCombine] Preserve fast math flags when combining PHIs

Summary:
When optimizing PHIs which have inputs floating point binary
operators, we preserve all IR flags except the fast math
flags.

This change removes the logic which tracked some of the IR flags
(no wrap, exact) and replaces it by doing an and on the IR flags of
all inputs to the PHI - which will also handle the fast math
flags.

Reviewers: majnemer

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D19370

Added:
    llvm/trunk/test/Transforms/InstCombine/phi-preserve-ir-flags.ll
Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp?rev=267139&r1=267138&r2=267139&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp Fri Apr 22 06:21:36 2016
@@ -35,15 +35,6 @@ Instruction *InstCombiner::FoldPHIArgBin
   Type *LHSType = LHSVal->getType();
   Type *RHSType = RHSVal->getType();
 
-  bool isNUW = false, isNSW = false, isExact = false;
-  if (OverflowingBinaryOperator *BO =
-        dyn_cast<OverflowingBinaryOperator>(FirstInst)) {
-    isNUW = BO->hasNoUnsignedWrap();
-    isNSW = BO->hasNoSignedWrap();
-  } else if (PossiblyExactOperator *PEO =
-               dyn_cast<PossiblyExactOperator>(FirstInst))
-    isExact = PEO->isExact();
-
   // Scan to see if all operands are the same opcode, and all have one use.
   for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
     Instruction *I = dyn_cast<Instruction>(PN.getIncomingValue(i));
@@ -59,13 +50,6 @@ Instruction *InstCombiner::FoldPHIArgBin
       if (CI->getPredicate() != cast<CmpInst>(FirstInst)->getPredicate())
         return nullptr;
 
-    if (isNUW)
-      isNUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
-    if (isNSW)
-      isNSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
-    if (isExact)
-      isExact = cast<PossiblyExactOperator>(I)->isExact();
-
     // Keep track of which operand needs a phi node.
     if (I->getOperand(0) != LHSVal) LHSVal = nullptr;
     if (I->getOperand(1) != RHSVal) RHSVal = nullptr;
@@ -124,9 +108,12 @@ Instruction *InstCombiner::FoldPHIArgBin
   BinaryOperator *BinOp = cast<BinaryOperator>(FirstInst);
   BinaryOperator *NewBinOp =
     BinaryOperator::Create(BinOp->getOpcode(), LHSVal, RHSVal);
-  if (isNUW) NewBinOp->setHasNoUnsignedWrap();
-  if (isNSW) NewBinOp->setHasNoSignedWrap();
-  if (isExact) NewBinOp->setIsExact();
+
+  NewBinOp->copyIRFlags(PN.getIncomingValue(0));
+
+  for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i)
+    NewBinOp->andIRFlags(PN.getIncomingValue(i));
+
   NewBinOp->setDebugLoc(FirstInst->getDebugLoc());
   return NewBinOp;
 }
@@ -497,7 +484,6 @@ Instruction *InstCombiner::FoldPHIArgOpI
   // code size and simplifying code.
   Constant *ConstantOp = nullptr;
   Type *CastSrcTy = nullptr;
-  bool isNUW = false, isNSW = false, isExact = false;
 
   if (isa<CastInst>(FirstInst)) {
     CastSrcTy = FirstInst->getOperand(0)->getType();
@@ -514,14 +500,6 @@ Instruction *InstCombiner::FoldPHIArgOpI
     ConstantOp = dyn_cast<Constant>(FirstInst->getOperand(1));
     if (!ConstantOp)
       return FoldPHIArgBinOpIntoPHI(PN);
-
-    if (OverflowingBinaryOperator *BO =
-        dyn_cast<OverflowingBinaryOperator>(FirstInst)) {
-      isNUW = BO->hasNoUnsignedWrap();
-      isNSW = BO->hasNoSignedWrap();
-    } else if (PossiblyExactOperator *PEO =
-               dyn_cast<PossiblyExactOperator>(FirstInst))
-      isExact = PEO->isExact();
   } else {
     return nullptr;  // Cannot fold this operation.
   }
@@ -537,13 +515,6 @@ Instruction *InstCombiner::FoldPHIArgOpI
     } else if (I->getOperand(1) != ConstantOp) {
       return nullptr;
     }
-
-    if (isNUW)
-      isNUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
-    if (isNSW)
-      isNSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
-    if (isExact)
-      isExact = cast<PossiblyExactOperator>(I)->isExact();
   }
 
   // Okay, they are all the same operation.  Create a new PHI node of the
@@ -584,9 +555,11 @@ Instruction *InstCombiner::FoldPHIArgOpI
 
   if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst)) {
     BinOp = BinaryOperator::Create(BinOp->getOpcode(), PhiVal, ConstantOp);
-    if (isNUW) BinOp->setHasNoUnsignedWrap();
-    if (isNSW) BinOp->setHasNoSignedWrap();
-    if (isExact) BinOp->setIsExact();
+    BinOp->copyIRFlags(PN.getIncomingValue(0));
+
+    for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i)
+      BinOp->andIRFlags(PN.getIncomingValue(i));
+
     BinOp->setDebugLoc(FirstInst->getDebugLoc());
     return BinOp;
   }

Added: llvm/trunk/test/Transforms/InstCombine/phi-preserve-ir-flags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/phi-preserve-ir-flags.ll?rev=267139&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/phi-preserve-ir-flags.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/phi-preserve-ir-flags.ll Fri Apr 22 06:21:36 2016
@@ -0,0 +1,89 @@
+; RUN: opt < %s -instcombine -S -o - | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+
+; CHECK-LABEL: define float @func1(
+define float @func1(float %a, float %b, float %c, i1 %cond) {
+entry:
+  br i1 %cond, label %cond.true, label %cond.false
+
+cond.true:
+  %sub0 = fsub fast float %a, %b
+  br label %cond.end
+
+cond.false:
+  %sub1 = fsub fast float %a, %c
+  br label %cond.end
+
+; The fast-math flags should always be transfered if possible.
+; CHECK-LABEL: cond.end
+; CHECK  [[PHI:%[^ ]*]] = phi float [ %b, %cond.true ], [ %c, %cond.false ]
+; CHECK  fsub fast float %a, [[PHI]]
+cond.end:
+  %e = phi float [ %sub0, %cond.true ], [ %sub1, %cond.false ]
+  ret float %e
+}
+
+; CHECK-LABEL: define float @func2(
+define float @func2(float %a, float %b, float %c, i1 %cond) {
+entry:
+  br i1 %cond, label %cond.true, label %cond.false
+
+cond.true:
+  %sub0 = fsub fast float %a, %b
+  br label %cond.end
+
+cond.false:
+  %sub1 = fsub float %a, %c
+  br label %cond.end
+
+; The fast-math flags should always be transfered if possible.
+; CHECK-LABEL: cond.end
+; CHECK  [[PHI:%[^ ]*]] = phi float [ %b, %cond.true ], [ %c, %cond.false ]
+; CHECK  fsub float %a, [[PHI]]
+cond.end:
+  %e = phi float [ %sub0, %cond.true ], [ %sub1, %cond.false ]
+  ret float %e
+}
+
+; CHECK-LABEL: define float @func3(
+define float @func3(float %a, float %b, float %c, i1 %cond) {
+entry:
+  br i1 %cond, label %cond.true, label %cond.false
+
+cond.true:
+  %sub0 = fsub fast float %a, 2.0
+  br label %cond.end
+
+cond.false:
+  %sub1 = fsub fast float %b, 2.0
+  br label %cond.end
+
+; CHECK-LABEL: cond.end
+; CHECK  [[PHI:%[^ ]*]] = phi float [ %a, %cond.true ], [ %b, %cond.false ]
+; CHECK  fadd fast float %a, [[PHI]]
+cond.end:
+  %e = phi float [ %sub0, %cond.true ], [ %sub1, %cond.false ]
+  ret float %e
+}
+
+; CHECK-LABEL: define float @func4(
+define float @func4(float %a, float %b, float %c, i1 %cond) {
+entry:
+  br i1 %cond, label %cond.true, label %cond.false
+
+cond.true:
+  %sub0 = fsub fast float %a, 2.0
+  br label %cond.end
+
+cond.false:
+  %sub1 = fsub float %b, 2.0
+  br label %cond.end
+
+; CHECK-LABEL: cond.end
+; CHECK  [[PHI:%[^ ]*]] = phi float [ %a, %cond.true ], [ %b, %cond.false ]
+; CHECK  fadd float %a, [[PHI]]
+cond.end:
+  %e = phi float [ %sub0, %cond.true ], [ %sub1, %cond.false ]
+  ret float %e
+}




More information about the llvm-commits mailing list