From e0205fdcd8b82be03774fe897b2f13bcfbc207c4 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Mon, 20 Jan 2014 07:44:53 +0000 Subject: [PATCH] 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. llvm-svn: 199629 --- .../InstCombine/InstCombineAddSub.cpp | 34 ++++++++++++++----- .../InstCombine/InstCombineMulDivRem.cpp | 10 ++++++ .../InstCombine/InstructionCombining.cpp | 15 ++++++-- test/Transforms/InstCombine/fdiv.ll | 18 ++++++++++ test/Transforms/InstCombine/fmul.ll | 10 ++++++ test/Transforms/InstCombine/select-2.ll | 10 ++++++ 6 files changed, 87 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 45db2468810..c56a31ce350 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -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(NewAddSub)) + II->setFastMathFlags(Flags); + + if (isMpy) { + Value *RI = createFMul(Factor, NewAddSub); + if (Instruction *II = dyn_cast(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(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(ConstantFP::get(V->getType(), 0.0)); - return createFSub(Zero, V); + Value *NewV = createFSub(Zero, V); + if (Instruction *I = dyn_cast(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()); diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 738756a5a28..dd2089f3b72 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1111,6 +1111,11 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { // if (!isa(Y) || !isa(Op1)) { NewInst = Builder->CreateFMul(Y, Op1); + if (Instruction *RI = dyn_cast(NewInst)) { + FastMathFlags Flags = I.getFastMathFlags(); + Flags &= cast(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(Y) || !isa(Op0)) { NewInst = Builder->CreateFMul(Op0, Y); + if (Instruction *RI = dyn_cast(NewInst)) { + FastMathFlags Flags = I.getFastMathFlags(); + Flags &= cast(Op1)->getFastMathFlags(); + RI->setFastMathFlags(Flags); + } SimpR = BinaryOperator::CreateFDiv(NewInst, X); } } diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index 191a101e0a3..6a7252fc41e 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -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(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(&I)) - return IC->Builder->CreateBinOp(BO->getOpcode(), Op0, Op1, + if (BinaryOperator *BO = dyn_cast(&I)) { + Value *RI = IC->Builder->CreateBinOp(BO->getOpcode(), Op0, Op1, SO->getName()+".op"); + Instruction *FPInst = dyn_cast(RI); + if (FPInst && isa(FPInst)) + FPInst->copyFastMathFlags(BO); + return RI; + } if (ICmpInst *CI = dyn_cast(&I)) return IC->Builder->CreateICmp(CI->getPredicate(), Op0, Op1, SO->getName()+".cmp"); diff --git a/test/Transforms/InstCombine/fdiv.ll b/test/Transforms/InstCombine/fdiv.ll index c3aabd78666..af6a2401a8f 100644 --- a/test/Transforms/InstCombine/fdiv.ll +++ b/test/Transforms/InstCombine/fdiv.ll @@ -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 +} diff --git a/test/Transforms/InstCombine/fmul.ll b/test/Transforms/InstCombine/fmul.ll index fdfc8df0a21..18cbf9da536 100644 --- a/test/Transforms/InstCombine/fmul.ll +++ b/test/Transforms/InstCombine/fmul.ll @@ -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 +} diff --git a/test/Transforms/InstCombine/select-2.ll b/test/Transforms/InstCombine/select-2.ll index 5b9deb4515a..832d958c5f3 100644 --- a/test/Transforms/InstCombine/select-2.ll +++ b/test/Transforms/InstCombine/select-2.ll @@ -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 +}