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, @@ -391,8 +400,10 @@ } while (0) -/// Set function attributes of function \p F based on CPU, Features, and command -/// line flags. +/// Add function attributes to function \p F based on CPU, Features, and command +/// line flags. If there is a pre-existing attribute, leave it as-is. This only +/// sets the corresponding attribute if the function does not already have the +/// attribute. LLVM_ATTRIBUTE_UNUSED static void setFunctionAttributes(StringRef CPU, StringRef Features, Function &F) { auto &Ctx = F.getContext(); @@ -441,6 +452,14 @@ 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/NVPTX/NVPTXISelLowering.cpp =================================================================== --- llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -88,11 +88,6 @@ cl::desc("NVPTX Specific: 0 use sqrt.approx, 1 use sqrt.rn."), cl::init(true)); -static cl::opt FtzEnabled( - "nvptx-f32ftz", cl::ZeroOrMore, cl::Hidden, - cl::desc("NVPTX Specific: Flush f32 subnormals to sign-preserving zero."), - cl::init(false)); - int NVPTXTargetLowering::getDivF32Level() const { if (UsePrecDivF32.getNumOccurrences() > 0) { // If nvptx-prec-div32=N is used on the command-line, always honor it @@ -117,12 +112,6 @@ } bool NVPTXTargetLowering::useF32FTZ(const MachineFunction &MF) const { - // TODO: Get rid of this flag; there can be only one way to do this. - if (FtzEnabled.getNumOccurrences() > 0) { - // If nvptx-f32ftz is used on the command-line, always honor it - return FtzEnabled; - } - DenormalMode Denorm = getTargetMachine().Options.getDenormalMode(APFloat::IEEEsingle()); return Denorm.Output == DenormalMode::PreserveSign; 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.setFP32DenormalMode( parseDenormalFPAttribute( F.getFnAttribute("denormal-fp-math-f32").getValueAsString())); - } + } else + Options.setFP32DenormalMode(DefaultOptions.getRawFP32DenormalMode()); if (F.hasFnAttribute("denormal-fp-math")) { Options.setFPDenormalMode( Index: llvm/test/CodeGen/NVPTX/f16-instructions.ll =================================================================== --- llvm/test/CodeGen/NVPTX/f16-instructions.ll +++ llvm/test/CodeGen/NVPTX/f16-instructions.ll @@ -5,7 +5,7 @@ ; ## Full FP16 with FTZ ; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -mcpu=sm_53 -asm-verbose=false \ ; RUN: -O0 -disable-post-ra -frame-pointer=all -verify-machineinstrs \ -; RUN: -nvptx-f32ftz \ +; RUN: -denormal-fp-math-f32=preserve-sign \ ; RUN: | FileCheck -check-prefixes CHECK,CHECK-F16,CHECK-F16-FTZ %s ; ## FP16 support explicitly disabled. ; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -mcpu=sm_53 -asm-verbose=false \ 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-mixed.ll =================================================================== --- /dev/null +++ llvm/test/Other/opt-override-denormal-fp-math-mixed.ll @@ -0,0 +1,42 @@ +; 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 + +; RUN: opt -S -denormal-fp-math-f32=ieee %s | FileCheck -check-prefixes=IEEEF32,ALL %s +; RUN: opt -S -denormal-fp-math-f32=preserve-sign %s | FileCheck -check-prefixes=PRESERVESIGNF32,ALL %s +; RUN: opt -S -denormal-fp-math-f32=positive-zero %s | FileCheck -check-prefixes=POSZEROF32,ALL %s + +; RUN: opt -S -denormal-fp-math=ieee -denormal-fp-math-f32=ieee %s | FileCheck -check-prefixes=IEEE-BOTH,ALL %s +; RUN: opt -S -denormal-fp-math=preserve-sign -denormal-fp-math-f32=preserve-sign %s | FileCheck -check-prefixes=PRESERVESIGN-BOTH,ALL %s +; RUN: opt -S -denormal-fp-math=positive-zero -denormal-fp-math-f32=positive-zero %s | FileCheck -check-prefixes=POSZERO-BOTH,ALL %s + + + +; ALL: @no_denormal_fp_math_attrs() [[NOATTR:#[0-9]+]] { +define i32 @no_denormal_fp_math_attrs() #0 { +entry: + ret i32 0 +} + +; ALL: both_denormal_fp_math_attrs_preserve_sign_ieee() [[ATTR:#[0-9]+]] { +define i32 @both_denormal_fp_math_attrs_preserve_sign_ieee() #1 { +entry: + ret i32 0 +} + +; ALL-DAG: attributes [[ATTR]] = { nounwind "denormal-fp-math"="preserve-sign,ieee" "denormal-fp-math-f32"="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" } + +; IEEEF32-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math-f32"="ieee,ieee" } +; PRESERVESIGNF32-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math-f32"="preserve-sign,preserve-sign" } +; POSITIVEZEROF32-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math-f32"="positive-zero,positive-zero" } + +; IEEE-BOTH-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math"="ieee,ieee" "denormal-fp-math-f32"="ieee,ieee" } +; PRESERVESIGN-BOTH-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math"="preserve-sign,preserve-sign" "denormal-fp-math-f32"="preserve-sign,preserve-sign" } +; POSITIVEZERO-BOTH-DAG: attributes [[NOATTR]] = { nounwind "denormal-fp-math"="positive-zero,positive-zero" "denormal-fp-math-f32"="positive-zero,positive-zero" } + +attributes #0 = { nounwind } +attributes #1 = { nounwind "denormal-fp-math"="preserve-sign,ieee" "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" }