From e985c76b905129cf083d0894694eaef3362a2555 Mon Sep 17 00:00:00 2001 From: Silviu Baranga Date: Fri, 22 Apr 2016 11:21:36 +0000 Subject: [PATCH] [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 llvm-svn: 267139 --- llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp | 49 +++--------- .../InstCombine/phi-preserve-ir-flags.ll | 89 ++++++++++++++++++++++ 2 files changed, 100 insertions(+), 38 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/phi-preserve-ir-flags.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp index e3b4aea..79a4912 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -35,15 +35,6 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) { Type *LHSType = LHSVal->getType(); Type *RHSType = RHSVal->getType(); - bool isNUW = false, isNSW = false, isExact = false; - if (OverflowingBinaryOperator *BO = - dyn_cast(FirstInst)) { - isNUW = BO->hasNoUnsignedWrap(); - isNSW = BO->hasNoSignedWrap(); - } else if (PossiblyExactOperator *PEO = - dyn_cast(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(PN.getIncomingValue(i)); @@ -59,13 +50,6 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) { if (CI->getPredicate() != cast(FirstInst)->getPredicate()) return nullptr; - if (isNUW) - isNUW = cast(I)->hasNoUnsignedWrap(); - if (isNSW) - isNSW = cast(I)->hasNoSignedWrap(); - if (isExact) - isExact = cast(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::FoldPHIArgBinOpIntoPHI(PHINode &PN) { BinaryOperator *BinOp = cast(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::FoldPHIArgOpIntoPHI(PHINode &PN) { // code size and simplifying code. Constant *ConstantOp = nullptr; Type *CastSrcTy = nullptr; - bool isNUW = false, isNSW = false, isExact = false; if (isa(FirstInst)) { CastSrcTy = FirstInst->getOperand(0)->getType(); @@ -514,14 +500,6 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) { ConstantOp = dyn_cast(FirstInst->getOperand(1)); if (!ConstantOp) return FoldPHIArgBinOpIntoPHI(PN); - - if (OverflowingBinaryOperator *BO = - dyn_cast(FirstInst)) { - isNUW = BO->hasNoUnsignedWrap(); - isNSW = BO->hasNoSignedWrap(); - } else if (PossiblyExactOperator *PEO = - dyn_cast(FirstInst)) - isExact = PEO->isExact(); } else { return nullptr; // Cannot fold this operation. } @@ -537,13 +515,6 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) { } else if (I->getOperand(1) != ConstantOp) { return nullptr; } - - if (isNUW) - isNUW = cast(I)->hasNoUnsignedWrap(); - if (isNSW) - isNSW = cast(I)->hasNoSignedWrap(); - if (isExact) - isExact = cast(I)->isExact(); } // Okay, they are all the same operation. Create a new PHI node of the @@ -584,9 +555,11 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) { if (BinaryOperator *BinOp = dyn_cast(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; } diff --git a/llvm/test/Transforms/InstCombine/phi-preserve-ir-flags.ll b/llvm/test/Transforms/InstCombine/phi-preserve-ir-flags.ll new file mode 100644 index 0000000..6e3ae80 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/phi-preserve-ir-flags.ll @@ -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 +} -- 2.7.4