Index: llvm/lib/Analysis/ConstantFolding.cpp =================================================================== --- llvm/lib/Analysis/ConstantFolding.cpp +++ llvm/lib/Analysis/ConstantFolding.cpp @@ -1001,8 +1001,32 @@ if (Instruction::isUnaryOp(Opcode)) return ConstantFoldUnaryOpOperand(Opcode, Ops[0], DL); - if (Instruction::isBinaryOp(Opcode)) + if (Instruction::isBinaryOp(Opcode)) { + switch (Opcode) { + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + case Instruction::FRem: + // If folding produces a denormal constant from a fast instruction, + // flush it to zero. + if (auto *I = dyn_cast(InstOrCE)) { + if (I->isFast()) { + Constant *C = + ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL); + if (ConstantFP *CFP = dyn_cast(C)) { + if (CFP->getValueAPF().isDenormal()) { + return Constant::getNullValue(C->getType()); + } + } + return C; + } + } + default: + break; + } return ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL); + } if (Instruction::isCast(Opcode)) return ConstantFoldCastOperand(Opcode, Ops[0], DestTy, DL); Index: llvm/test/Transforms/InstCombine/constant-fold-denormals.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/InstCombine/constant-fold-denormals.ll @@ -0,0 +1,29 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +define float @test_float() { +; CHECK-LABEL: @test_float( +; CHECK-NEXT: ret float 0x3800000000000000 + %mul = fmul float 0x3810000000000000, 5.000000e-01 + ret float %mul +} + +define double @test_double() { +; CHECK-LABEL: @test_double( +; CHECK-NEXT: ret double 0x8000000000000 + %mul = fmul double 0x10000000000000, 5.000000e-01 + ret double %mul +} + +define float @test_float_fast() { +; CHECK-LABEL: @test_float_fast( +; CHECK-NEXT: ret float 0.000000e+00 + %mul = fmul fast float 0x3810000000000000, 5.000000e-01 + ret float %mul +} + +define double @test_double_fast() { +; CHECK-LABEL: @test_double_fast( +; CHECK-NEXT: ret double 0.000000e+00 + %mul = fmul fast double 0x10000000000000, 5.000000e-01 + ret double %mul +}