Index: llvm/include/llvm/CodeGen/CommandFlags.inc =================================================================== --- llvm/include/llvm/CodeGen/CommandFlags.inc +++ llvm/include/llvm/CodeGen/CommandFlags.inc @@ -151,18 +151,27 @@ "attribute not to use exceptions"), cl::init(false)); +static const auto DenormFlagEnumOptions = + cl::values(clEnumValN(DenormalMode::IEEE, "ieee", + "IEEE 754 denormal numbers"), + clEnumValN(DenormalMode::PreserveSign, "preserve-sign", + "the sign of a flushed-to-zero number is preserved " + "in the sign of 0"), + clEnumValN(DenormalMode::PositiveZero, "positive-zero", + "denormals are flushed to positive zero")); + // FIXME: Doesn't have way to specify separate input and output modes. static cl::opt DenormalFPMath( "denormal-fp-math", cl::desc("Select which denormal numbers the code is permitted to require"), cl::init(DenormalMode::IEEE), - cl::values(clEnumValN(DenormalMode::IEEE, "ieee", - "IEEE 754 denormal numbers"), - clEnumValN(DenormalMode::PreserveSign, "preserve-sign", - "the sign of a flushed-to-zero number is preserved " - "in the sign of 0"), - clEnumValN(DenormalMode::PositiveZero, "positive-zero", - "denormals are flushed to positive zero"))); + DenormFlagEnumOptions); + +static cl::opt DenormalFP32Math( + "denormal-fp-math-f32", + cl::desc("Select which denormal numbers the code is permitted to require for float"), + cl::init(DenormalMode::Invalid), + DenormFlagEnumOptions); static cl::opt EnableHonorSignDependentRoundingFPMath( "enable-sign-dependent-rounding-fp-math", cl::Hidden, @@ -430,6 +439,21 @@ HANDLE_BOOL_ATTR(EnableNoNaNsFPMath, "no-nans-fp-math"); HANDLE_BOOL_ATTR(EnableNoSignedZerosFPMath, "no-signed-zeros-fp-math"); + if (DenormalFPMath.getNumOccurrences() > 0 && + !F.hasFnAttribute("denormal-fp-math")) { + // FIXME: Command line flag should expose separate input/output modes. + NewAttrs.addAttribute("denormal-fp-math", + DenormalMode(DenormalFPMath, DenormalFPMath).str()); + } + + if (DenormalFP32Math.getNumOccurrences() > 0 && + !F.hasFnAttribute("denormal-fp-math-f32")) { + // FIXME: Command line flag should expose separate input/output modes. + NewAttrs.addAttribute( + "denormal-fp-math-f32", + DenormalMode(DenormalFP32Math, DenormalFP32Math).str()); + } + if (TrapFuncName.getNumOccurrences() > 0) for (auto &B : F) for (auto &I : B) Index: llvm/lib/Target/TargetMachine.cpp =================================================================== --- llvm/lib/Target/TargetMachine.cpp +++ llvm/lib/Target/TargetMachine.cpp @@ -64,12 +64,12 @@ RESET_OPTION(NoNaNsFPMath, "no-nans-fp-math"); RESET_OPTION(NoSignedZerosFPMath, "no-signed-zeros-fp-math"); - Options.setFP32DenormalMode(DenormalMode::getInvalid()); if (F.hasFnAttribute("denormal-fp-math-f32")) { Options.setFPDenormalMode( parseDenormalFPAttribute( F.getFnAttribute("denormal-fp-math-f32").getValueAsString())); - } + } else + Options.setFP32DenormalMode(DefaultOptions.getRawFP32DenormalMode()); if (F.hasFnAttribute("denormal-fp-math")) { Options.setFPDenormalMode( Index: llvm/test/Other/opt-override-denormal-fp-math-f32.ll =================================================================== --- /dev/null +++ llvm/test/Other/opt-override-denormal-fp-math-f32.ll @@ -0,0 +1,23 @@ +; RUN: opt -S -denormal-fp-math-f32=ieee %s | FileCheck -check-prefixes=IEEE,ALL %s +; RUN: opt -S -denormal-fp-math-f32=preserve-sign %s | FileCheck -check-prefixes=PRESERVESIGN,ALL %s +; RUN: opt -S -denormal-fp-math-f32=positive-zero %s | FileCheck -check-prefixes=POSZERO,ALL %s + +; ALL: @no_denormal_fp_math_f32_attr() [[NOATTR:#[0-9]+]] { +define i32 @no_denormal_fp_math_f32_attr() #0 { +entry: + ret i32 0 +} + +; ALL: denormal_fp_math_attr_preserve_sign_ieee() [[ATTR:#[0-9]+]] { +define i32 @denormal_fp_math_attr_preserve_sign_ieee() #1 { +entry: + ret i32 0 +} + +; ALL-DAG: attributes [[ATTR]] = { nounwind "denormal-fp-math-f32"="preserve-sign,ieee" } +; IEEE-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math-f32"="ieee,ieee" } +; PRESERVESIGN-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math-f32"="preserve-sign,preserve-sign" } +; POSITIVEZERO-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math-f32"="positive-zero,positive-zero" } + +attributes #0 = { nounwind } +attributes #1 = { nounwind "denormal-fp-math-f32"="preserve-sign,ieee" } Index: llvm/test/Other/opt-override-denormal-fp-math.ll =================================================================== --- /dev/null +++ llvm/test/Other/opt-override-denormal-fp-math.ll @@ -0,0 +1,23 @@ +; RUN: opt -S -denormal-fp-math=ieee %s | FileCheck -check-prefixes=IEEE,ALL %s +; RUN: opt -S -denormal-fp-math=preserve-sign %s | FileCheck -check-prefixes=PRESERVESIGN,ALL %s +; RUN: opt -S -denormal-fp-math=positive-zero %s | FileCheck -check-prefixes=POSZERO,ALL %s + +; ALL: @no_denormal_fp_math_attr() [[NOATTR:#[0-9]+]] { +define i32 @no_denormal_fp_math_attr() #0 { +entry: + ret i32 0 +} + +; ALL: denormal_fp_math_attr_preserve_sign_ieee() [[ATTR:#[0-9]+]] { +define i32 @denormal_fp_math_attr_preserve_sign_ieee() #1 { +entry: + ret i32 0 +} + +; ALL-DAG: attributes [[ATTR]] = { nounwind "denormal-fp-math"="preserve-sign,ieee" } +; IEEE-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math"="ieee,ieee" } +; PRESERVESIGN-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math"="preserve-sign,preserve-sign" } +; POSITIVEZERO-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math"="positive-zero,positive-zero" } + +attributes #0 = { nounwind } +attributes #1 = { nounwind "denormal-fp-math"="preserve-sign,ieee" }