Skip to content

Commit

Permalink
[InstCombine] Preserve fast math flags when combining PHIs
Browse files Browse the repository at this point in the history
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@267139 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
sbaranga-arm committed Apr 22, 2016
1 parent fed867f commit 883a09c
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 38 deletions.
49 changes: 11 additions & 38 deletions lib/Transforms/InstCombine/InstCombinePHI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<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));
Expand All @@ -59,13 +50,6 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
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;
Expand Down Expand Up @@ -124,9 +108,12 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
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;
}
Expand Down Expand Up @@ -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<CastInst>(FirstInst)) {
CastSrcTy = FirstInst->getOperand(0)->getType();
Expand All @@ -514,14 +500,6 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
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.
}
Expand All @@ -537,13 +515,6 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
} 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
Expand Down Expand Up @@ -584,9 +555,11 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {

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;
}
Expand Down
89 changes: 89 additions & 0 deletions test/Transforms/InstCombine/phi-preserve-ir-flags.ll
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 883a09c

Please sign in to comment.