Fix all the remaining lost-fast-math-flags bugs I've been able to find. The most important of these are cases in the generic logic for combining BinaryOperators.

This logic hadn't been updated to handle FastMathFlags, and it took me a while to detect it because it doesn't show up in a simple search for CreateFAdd.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199629 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2014-01-20 07:44:53 +00:00
parent f55ec9ac18
commit 1e1446bf84
6 changed files with 87 additions and 10 deletions

View File

@ -175,7 +175,7 @@ namespace {
Value *createFDiv(Value *Opnd0, Value *Opnd1);
Value *createFNeg(Value *V);
Value *createNaryFAdd(const AddendVect& Opnds, unsigned InstrQuota);
void createInstPostProc(Instruction *NewInst);
void createInstPostProc(Instruction *NewInst, bool NoNumber = false);
InstCombiner::BuilderTy *Builder;
Instruction *Instr;
@ -483,6 +483,11 @@ Value *FAddCombine::performFactorization(Instruction *I) {
if (!Factor)
return 0;
FastMathFlags Flags;
Flags.setUnsafeAlgebra();
if (I0) Flags &= I->getFastMathFlags();
if (I1) Flags &= I->getFastMathFlags();
// Create expression "NewAddSub = AddSub0 +/- AddsSub1"
Value *NewAddSub = (I->getOpcode() == Instruction::FAdd) ?
createFAdd(AddSub0, AddSub1) :
@ -491,12 +496,20 @@ Value *FAddCombine::performFactorization(Instruction *I) {
const APFloat &F = CFP->getValueAPF();
if (!F.isNormal())
return 0;
} else if (Instruction *II = dyn_cast<Instruction>(NewAddSub))
II->setFastMathFlags(Flags);
if (isMpy) {
Value *RI = createFMul(Factor, NewAddSub);
if (Instruction *II = dyn_cast<Instruction>(RI))
II->setFastMathFlags(Flags);
return RI;
}
if (isMpy)
return createFMul(Factor, NewAddSub);
return createFDiv(NewAddSub, Factor);
Value *RI = createFDiv(NewAddSub, Factor);
if (Instruction *II = dyn_cast<Instruction>(RI))
II->setFastMathFlags(Flags);
return RI;
}
Value *FAddCombine::simplify(Instruction *I) {
@ -746,7 +759,10 @@ Value *FAddCombine::createFSub
Value *FAddCombine::createFNeg(Value *V) {
Value *Zero = cast<Value>(ConstantFP::get(V->getType(), 0.0));
return createFSub(Zero, V);
Value *NewV = createFSub(Zero, V);
if (Instruction *I = dyn_cast<Instruction>(NewV))
createInstPostProc(I, true); // fneg's don't receive instruction numbers.
return NewV;
}
Value *FAddCombine::createFAdd
@ -771,11 +787,13 @@ Value *FAddCombine::createFDiv(Value *Opnd0, Value *Opnd1) {
return V;
}
void FAddCombine::createInstPostProc(Instruction *NewInstr) {
void FAddCombine::createInstPostProc(Instruction *NewInstr,
bool NoNumber) {
NewInstr->setDebugLoc(Instr->getDebugLoc());
// Keep track of the number of instruction created.
incCreateInstNum();
if (!NoNumber)
incCreateInstNum();
// Propagate fast-math flags
NewInstr->setFastMathFlags(Instr->getFastMathFlags());

View File

@ -1111,6 +1111,11 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
//
if (!isa<Constant>(Y) || !isa<Constant>(Op1)) {
NewInst = Builder->CreateFMul(Y, Op1);
if (Instruction *RI = dyn_cast<Instruction>(NewInst)) {
FastMathFlags Flags = I.getFastMathFlags();
Flags &= cast<Instruction>(Op0)->getFastMathFlags();
RI->setFastMathFlags(Flags);
}
SimpR = BinaryOperator::CreateFDiv(X, NewInst);
}
} else if (Op1->hasOneUse() && match(Op1, m_FDiv(m_Value(X), m_Value(Y)))) {
@ -1118,6 +1123,11 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
//
if (!isa<Constant>(Y) || !isa<Constant>(Op0)) {
NewInst = Builder->CreateFMul(Op0, Y);
if (Instruction *RI = dyn_cast<Instruction>(NewInst)) {
FastMathFlags Flags = I.getFastMathFlags();
Flags &= cast<Instruction>(Op1)->getFastMathFlags();
RI->setFastMathFlags(Flags);
}
SimpR = BinaryOperator::CreateFDiv(NewInst, X);
}
}

View File

@ -319,6 +319,12 @@ bool InstCombiner::SimplifyAssociativeOrCommutative(BinaryOperator &I) {
Constant *Folded = ConstantExpr::get(Opcode, C1, C2);
BinaryOperator *New = BinaryOperator::Create(Opcode, A, B);
if (isa<FPMathOperator>(New)) {
FastMathFlags Flags = I.getFastMathFlags();
Flags &= Op0->getFastMathFlags();
Flags &= Op1->getFastMathFlags();
New->setFastMathFlags(Flags);
}
InsertNewInstWith(New, I);
New->takeName(Op1);
I.setOperand(0, New);
@ -566,9 +572,14 @@ static Value *FoldOperationIntoSelectOperand(Instruction &I, Value *SO,
if (!ConstIsRHS)
std::swap(Op0, Op1);
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&I))
return IC->Builder->CreateBinOp(BO->getOpcode(), Op0, Op1,
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&I)) {
Value *RI = IC->Builder->CreateBinOp(BO->getOpcode(), Op0, Op1,
SO->getName()+".op");
Instruction *FPInst = dyn_cast<Instruction>(RI);
if (FPInst && isa<FPMathOperator>(FPInst))
FPInst->copyFastMathFlags(BO);
return RI;
}
if (ICmpInst *CI = dyn_cast<ICmpInst>(&I))
return IC->Builder->CreateICmp(CI->getPredicate(), Op0, Op1,
SO->getName()+".cmp");

View File

@ -31,3 +31,21 @@ define float @test4(float %x) nounwind readnone ssp {
; CHECK-LABEL: @test4(
; CHECK-NEXT: fmul fast float %x, 1.250000e-01
}
define float @test5(float %x, float %y, float %z) nounwind readnone ssp {
%div1 = fdiv fast float %x, %y
%div2 = fdiv fast float %div1, %z
ret float %div2
; CHECK-LABEL: @test5(
; CHECK-NEXT: fmul fast
; CHECK-NEXT: fdiv fast
}
define float @test6(float %x, float %y, float %z) nounwind readnone ssp {
%div1 = fdiv fast float %x, %y
%div2 = fdiv fast float %z, %div1
ret float %div2
; CHECK-LABEL: @test6(
; CHECK-NEXT: fmul fast
; CHECK-NEXT: fdiv fast
}

View File

@ -113,3 +113,13 @@ define <4 x float> @test10(<4 x float> %x) {
; CHECK-NOT: fmul
; CHECK: fsub
}
define float @test11(float %x, float %y) {
%a = fadd fast float %x, 1.0
%b = fadd fast float %y, 2.0
%c = fadd fast float %a, %b
ret float %c
; CHECK-LABEL: @test11(
; CHECK-NOT: fadd float
; CHECK: fadd fast float
}

View File

@ -19,3 +19,13 @@ define i32 @t2(i32 %c, i32 %x) nounwind {
%t3 = select i1 %t1, i32 %t2, i32 %x
ret i32 %t3
}
define float @t3(float %x, float %y) nounwind {
%t1 = fcmp ogt float %x, %y
%t2 = select i1 %t1, float %x, float 1.0
%t3 = fadd fast float %t2, 1.0
ret float %t3
; CHECK-LABEL: @t3(
; CHECK: fadd fast
; CHECK: select
}