1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[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
This commit is contained in:
Silviu Baranga 2016-04-22 11:21:36 +00:00
parent 0102a446f7
commit 52b925e4c9
2 changed files with 100 additions and 38 deletions

View File

@ -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));
@ -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;
@ -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;
}
@ -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();
@ -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.
}
@ -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
@ -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;
}

View File

@ -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
}