diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 0aa301bc7a8..8d4677b0ec6 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1528,9 +1528,21 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) { if (Instruction *NV = FoldOpIntoSelect(I, SI)) return NV; - // If this is a 'B = x-(-A)', change to B = x+A... + // If this is a 'B = x-(-A)', change to B = x+A, potentially looking + // through FP extensions/truncations along the way. if (Value *V = dyn_castFNegVal(Op1)) return BinaryOperator::CreateFAdd(Op0, V); + if (FPTruncInst *FPTI = dyn_cast(Op1)) { + if (Value *V = dyn_castFNegVal(FPTI->getOperand(0))) { + Value *NewTrunc = Builder->CreateFPTrunc(V, I.getType()); + return BinaryOperator::CreateFAdd(Op0, NewTrunc); + } + } else if (FPExtInst *FPEI = dyn_cast(Op1)) { + if (Value *V = dyn_castFNegVal(FPEI->getOperand(0))) { + Value *NewTrunc = Builder->CreateFPExt(V, I.getType()); + return BinaryOperator::CreateFAdd(Op0, NewTrunc); + } + } if (I.hasUnsafeAlgebra()) { if (Value *V = FAddCombine(Builder).simplify(&I)) diff --git a/test/Transforms/InstCombine/fneg-ext.ll b/test/Transforms/InstCombine/fneg-ext.ll new file mode 100644 index 00000000000..49ad2325261 --- /dev/null +++ b/test/Transforms/InstCombine/fneg-ext.ll @@ -0,0 +1,12 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +; CHECK: test1 +define double @test1(float %a, double %b) nounwind readnone ssp uwtable { +; CHECK-NOT: fsub +; CHECK: fpext +; CHECK: fadd + %1 = fsub float -0.000000e+00, %a + %2 = fpext float %1 to double + %3 = fsub double %b, %2 + ret double %3 +}