Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1394,39 +1394,47 @@ // integer add followed by a promotion. if (SIToFPInst *LHSConv = dyn_cast(LHS)) { Value *LHSIntVal = LHSConv->getOperand(0); - - // (fadd double (sitofp x), fpcst) --> (sitofp (add int x, intcst)) - // ... if the constant fits in the integer value. This is useful for things - // like (double)(x & 1234) + 4.0 -> (double)((X & 1234)+4) which no longer - // requires a constant pool load, and generally allows the add to be better - // instcombined. - if (ConstantFP *CFP = dyn_cast(RHS)) { - Constant *CI = - ConstantExpr::getFPToSI(CFP, LHSIntVal->getType()); - if (LHSConv->hasOneUse() && - ConstantExpr::getSIToFP(CI, I.getType()) == CFP && - WillNotOverflowSignedAdd(LHSIntVal, CI, I)) { - // Insert the new integer add. - Value *NewAdd = Builder->CreateNSWAdd(LHSIntVal, - CI, "addconv"); - return new SIToFPInst(NewAdd, I.getType()); + Type *FPType = LHSConv->getType(); + + // Do we have enough bits in the mantissa to represent the result of the + // integer addition? semanticsPrecision returns the number of mantissa + // bits plus one for the sign bit. + unsigned MaxRepresentableBits + = APFloat::semanticsPrecision(FPType->getFltSemantics()); + if (LHSIntVal->getType()->getIntegerBitWidth() <= MaxRepresentableBits) { + // (fadd double (sitofp x), fpcst) --> (sitofp (add int x, intcst)) + // ... if the constant fits in the integer value. This is useful for things + // like (double)(x & 1234) + 4.0 -> (double)((X & 1234)+4) which no longer + // requires a constant pool load, and generally allows the add to be better + // instcombined. + if (ConstantFP *CFP = dyn_cast(RHS)) { + Constant *CI = + ConstantExpr::getFPToSI(CFP, LHSIntVal->getType()); + if (LHSConv->hasOneUse() && + ConstantExpr::getSIToFP(CI, I.getType()) == CFP && + WillNotOverflowSignedAdd(LHSIntVal, CI, I)) { + // Insert the new integer add. + Value *NewAdd = Builder->CreateNSWAdd(LHSIntVal, + CI, "addconv"); + return new SIToFPInst(NewAdd, I.getType()); + } } - } - // (fadd double (sitofp x), (sitofp y)) --> (sitofp (add int x, y)) - if (SIToFPInst *RHSConv = dyn_cast(RHS)) { - Value *RHSIntVal = RHSConv->getOperand(0); - - // Only do this if x/y have the same type, if at last one of them has a - // single use (so we don't increase the number of int->fp conversions), - // and if the integer add will not overflow. - if (LHSIntVal->getType() == RHSIntVal->getType() && - (LHSConv->hasOneUse() || RHSConv->hasOneUse()) && - WillNotOverflowSignedAdd(LHSIntVal, RHSIntVal, I)) { - // Insert the new integer add. - Value *NewAdd = Builder->CreateNSWAdd(LHSIntVal, - RHSIntVal, "addconv"); - return new SIToFPInst(NewAdd, I.getType()); + // (fadd double (sitofp x), (sitofp y)) --> (sitofp (add int x, y)) + if (SIToFPInst *RHSConv = dyn_cast(RHS)) { + Value *RHSIntVal = RHSConv->getOperand(0); + + // Only do this if x/y have the same type, if at last one of them has a + // single use (so we don't increase the number of int->fp conversions), + // and if the integer add will not overflow. + if (LHSIntVal->getType() == RHSIntVal->getType() && + (LHSConv->hasOneUse() || RHSConv->hasOneUse()) && + WillNotOverflowSignedAdd(LHSIntVal, RHSIntVal, I)) { + // Insert the new integer add. + Value *NewAdd = Builder->CreateNSWAdd(LHSIntVal, + RHSIntVal, "addconv"); + return new SIToFPInst(NewAdd, I.getType()); + } } } } Index: test/Transforms/InstCombine/add-sitofp.ll =================================================================== --- test/Transforms/InstCombine/add-sitofp.ll +++ test/Transforms/InstCombine/add-sitofp.ll @@ -1,9 +1,21 @@ -; RUN: opt < %s -instcombine -S | grep "add nuw nsw i32" +; RUN: opt < %s -instcombine -S | FileCheck %s define double @x(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: @x +; CHECK: add nuw nsw i32 %m = lshr i32 %a, 24 %n = and i32 %m, %b %o = sitofp i32 %n to double %p = fadd double %o, 1.0 ret double %p } + +define float @neg(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: @neg +; CHECK: fadd float + %m = lshr i32 %a, 24 + %n = and i32 %m, %b + %o = sitofp i32 %n to float + %p = fadd float %o, 1.0 + ret float %p +}