diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -65,7 +65,7 @@ // We want to use these instructions, and using fp32 denormals also causes // instructions to run at the double precision rate for the device so it's // probably best to just report no single precision denormals. -static uint32_t getFPMode(AMDGPU::SIModeRegisterDefaults Mode) { +static uint32_t getFPMode(SIModeRegisterDefaults Mode) { return FP_ROUND_MODE_SP(FP_ROUND_ROUND_TO_NEAREST) | FP_ROUND_MODE_DP(FP_ROUND_ROUND_TO_NEAREST) | FP_DENORM_MODE_SP(Mode.fpDenormModeSPValue()) | diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp @@ -14,15 +14,16 @@ #include "AMDGPU.h" #include "AMDGPUTargetMachine.h" +#include "SIModeRegisterDefaults.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/LegacyDivergenceAnalysis.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/Dominators.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/IntrinsicsAMDGPU.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/KnownBits.h" @@ -1425,7 +1426,7 @@ HasUnsafeFPMath = hasUnsafeFPMath(F); - AMDGPU::SIModeRegisterDefaults Mode(F); + SIModeRegisterDefaults Mode(F); HasFP32Denormals = Mode.allFP32Denormals(); bool MadeChange = false; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h --- a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h @@ -16,6 +16,7 @@ #include "GCNSubtarget.h" #include "SIMachineFunctionInfo.h" +#include "SIModeRegisterDefaults.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Target/TargetMachine.h" @@ -82,7 +83,7 @@ const GCNSubtarget *Subtarget; // Default FP mode for the current function. - AMDGPU::SIModeRegisterDefaults Mode; + SIModeRegisterDefaults Mode; bool EnableLateStructurizeCFG; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp @@ -131,7 +131,7 @@ } #endif Subtarget = &MF.getSubtarget(); - Mode = AMDGPU::SIModeRegisterDefaults(MF.getFunction()); + Mode = SIModeRegisterDefaults(MF.getFunction()); return SelectionDAGISel::runOnMachineFunction(MF); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp @@ -547,7 +547,7 @@ #ifndef NDEBUG const SIMachineFunctionInfo *MFI = I.getMF()->getInfo(); - AMDGPU::SIModeRegisterDefaults Mode = MFI->getMode(); + SIModeRegisterDefaults Mode = MFI->getMode(); assert((IsFMA || !Mode.allFP32Denormals()) && "fmad selected with denormals enabled"); #endif diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -3875,10 +3875,9 @@ // Enable or disable FP32 denorm mode. When 'Enable' is true, emit instructions // to enable denorm mode. When 'Enable' is false, disable denorm mode. -static void toggleSPDenormMode(bool Enable, - MachineIRBuilder &B, +static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B, const GCNSubtarget &ST, - AMDGPU::SIModeRegisterDefaults Mode) { + SIModeRegisterDefaults Mode) { // Set SP denorm mode to this value. unsigned SPDenormMode = Enable ? FP_DENORM_FLUSH_NONE : Mode.fpDenormModeSPValue(); @@ -3913,7 +3912,7 @@ Register LHS = MI.getOperand(1).getReg(); Register RHS = MI.getOperand(2).getReg(); const SIMachineFunctionInfo *MFI = B.getMF().getInfo(); - AMDGPU::SIModeRegisterDefaults Mode = MFI->getMode(); + SIModeRegisterDefaults Mode = MFI->getMode(); uint16_t Flags = MI.getFlags(); diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp @@ -75,7 +75,7 @@ void applyClamp(MachineInstr &MI, Register &Reg); private: - AMDGPU::SIModeRegisterDefaults getMode(); + SIModeRegisterDefaults getMode(); bool getIEEE(); bool getDX10Clamp(); bool isFminnumIeee(const MachineInstr &MI); @@ -328,7 +328,7 @@ MI.eraseFromParent(); } -AMDGPU::SIModeRegisterDefaults AMDGPURegBankCombinerHelper::getMode() { +SIModeRegisterDefaults AMDGPURegBankCombinerHelper::getMode() { return MF.getInfo()->getMode(); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp @@ -17,6 +17,7 @@ #include "AMDGPUTargetTransformInfo.h" #include "AMDGPUTargetMachine.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "SIModeRegisterDefaults.h" #include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ValueTracking.h" @@ -293,7 +294,7 @@ ST(static_cast(TM->getSubtargetImpl(F))), TLI(ST->getTargetLowering()), CommonTTI(TM, F), IsGraphics(AMDGPU::isGraphics(F.getCallingConv())) { - AMDGPU::SIModeRegisterDefaults Mode(F); + SIModeRegisterDefaults Mode(F); HasFP32Denormals = Mode.allFP32Denormals(); HasFP64FP16Denormals = Mode.allFP64FP16Denormals(); } @@ -1148,8 +1149,8 @@ // FIXME: dx10_clamp can just take the caller setting, but there seems to be // no way to support merge for backend defined attributes. - AMDGPU::SIModeRegisterDefaults CallerMode(*Caller); - AMDGPU::SIModeRegisterDefaults CalleeMode(*Callee); + SIModeRegisterDefaults CallerMode(*Caller); + SIModeRegisterDefaults CalleeMode(*Callee); if (!CallerMode.isInlineCompatible(CalleeMode)) return false; diff --git a/llvm/lib/Target/AMDGPU/CMakeLists.txt b/llvm/lib/Target/AMDGPU/CMakeLists.txt --- a/llvm/lib/Target/AMDGPU/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/CMakeLists.txt @@ -152,6 +152,7 @@ SIMachineScheduler.cpp SIMemoryLegalizer.cpp SIModeRegister.cpp + SIModeRegisterDefaults.cpp SIOptimizeExecMasking.cpp SIOptimizeExecMaskingPreRA.cpp SIOptimizeVGPRLiveRange.cpp diff --git a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h --- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h +++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h @@ -18,6 +18,7 @@ #include "AMDGPUTargetMachine.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "SIInstrInfo.h" +#include "SIModeRegisterDefaults.h" #include "llvm/ADT/SetVector.h" #include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/CodeGen/PseudoSourceValue.h" @@ -215,7 +216,7 @@ SIMode() = default; - SIMode(const AMDGPU::SIModeRegisterDefaults &Mode) { + SIMode(const SIModeRegisterDefaults &Mode) { IEEE = Mode.IEEE; DX10Clamp = Mode.DX10Clamp; FP32InputDenormals = Mode.FP32Denormals.Input != DenormalMode::PreserveSign; @@ -359,7 +360,7 @@ friend class GCNTargetMachine; // State of MODE register, assumed FP mode. - AMDGPU::SIModeRegisterDefaults Mode; + SIModeRegisterDefaults Mode; // Registers that may be reserved for spilling purposes. These may be the same // as the input registers. @@ -551,9 +552,7 @@ void reserveWWMRegister(Register Reg) { WWMReservedRegs.insert(Reg); } - AMDGPU::SIModeRegisterDefaults getMode() const { - return Mode; - } + SIModeRegisterDefaults getMode() const { return Mode; } ArrayRef getSGPRSpillToVGPRLanes(int FrameIndex) const { diff --git a/llvm/lib/Target/AMDGPU/SIModeRegisterDefaults.h b/llvm/lib/Target/AMDGPU/SIModeRegisterDefaults.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/SIModeRegisterDefaults.h @@ -0,0 +1,121 @@ +//===-- SIModeRegisterDefaults.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AMDGPU_SIMODEREGISTERDEFAULTS_H +#define LLVM_LIB_TARGET_AMDGPU_SIMODEREGISTERDEFAULTS_H + +#include "Utils/AMDGPUBaseInfo.h" +#include "llvm/ADT/FloatingPointMode.h" + +namespace llvm { + +// Track defaults for fields in the MODE register. +struct SIModeRegisterDefaults { + /// Floating point opcodes that support exception flag gathering quiet and + /// propagate signaling NaN inputs per IEEE 754-2008. Min_dx10 and max_dx10 + /// become IEEE 754- 2008 compliant due to signaling NaN propagation and + /// quieting. + bool IEEE : 1; + + /// Used by the vector ALU to force DX10-style treatment of NaNs: when set, + /// clamp NaN to zero; otherwise, pass NaN through. + bool DX10Clamp : 1; + + /// If this is set, neither input or output denormals are flushed for most f32 + /// instructions. + DenormalMode FP32Denormals; + + /// If this is set, neither input or output denormals are flushed for both f64 + /// and f16/v2f16 instructions. + DenormalMode FP64FP16Denormals; + + SIModeRegisterDefaults() + : IEEE(true), DX10Clamp(true), FP32Denormals(DenormalMode::getIEEE()), + FP64FP16Denormals(DenormalMode::getIEEE()) {} + + SIModeRegisterDefaults(const Function &F); + + static SIModeRegisterDefaults getDefaultForCallingConv(CallingConv::ID CC) { + SIModeRegisterDefaults Mode; + Mode.IEEE = !AMDGPU::isShader(CC); + return Mode; + } + + bool operator==(const SIModeRegisterDefaults Other) const { + return IEEE == Other.IEEE && DX10Clamp == Other.DX10Clamp && + FP32Denormals == Other.FP32Denormals && + FP64FP16Denormals == Other.FP64FP16Denormals; + } + + bool allFP32Denormals() const { + return FP32Denormals == DenormalMode::getIEEE(); + } + + bool allFP64FP16Denormals() const { + return FP64FP16Denormals == DenormalMode::getIEEE(); + } + + /// Get the encoding value for the FP_DENORM bits of the mode register for the + /// FP32 denormal mode. + uint32_t fpDenormModeSPValue() const { + if (FP32Denormals == DenormalMode::getPreserveSign()) + return FP_DENORM_FLUSH_IN_FLUSH_OUT; + if (FP32Denormals.Output == DenormalMode::PreserveSign) + return FP_DENORM_FLUSH_OUT; + if (FP32Denormals.Input == DenormalMode::PreserveSign) + return FP_DENORM_FLUSH_IN; + return FP_DENORM_FLUSH_NONE; + } + + /// Get the encoding value for the FP_DENORM bits of the mode register for the + /// FP64/FP16 denormal mode. + uint32_t fpDenormModeDPValue() const { + if (FP64FP16Denormals == DenormalMode::getPreserveSign()) + return FP_DENORM_FLUSH_IN_FLUSH_OUT; + if (FP64FP16Denormals.Output == DenormalMode::PreserveSign) + return FP_DENORM_FLUSH_OUT; + if (FP64FP16Denormals.Input == DenormalMode::PreserveSign) + return FP_DENORM_FLUSH_IN; + return FP_DENORM_FLUSH_NONE; + } + + /// Returns true if a flag is compatible if it's enabled in the callee, but + /// disabled in the caller. + static bool oneWayCompatible(bool CallerMode, bool CalleeMode) { + return CallerMode == CalleeMode || (!CallerMode && CalleeMode); + } + + // FIXME: Inlining should be OK for dx10-clamp, since the caller's mode should + // be able to override. + bool isInlineCompatible(SIModeRegisterDefaults CalleeMode) const { + if (DX10Clamp != CalleeMode.DX10Clamp) + return false; + if (IEEE != CalleeMode.IEEE) + return false; + + // Allow inlining denormals enabled into denormals flushed functions. + return oneWayCompatible(FP64FP16Denormals.Input != + DenormalMode::PreserveSign, + CalleeMode.FP64FP16Denormals.Input != + DenormalMode::PreserveSign) && + oneWayCompatible(FP64FP16Denormals.Output != + DenormalMode::PreserveSign, + CalleeMode.FP64FP16Denormals.Output != + DenormalMode::PreserveSign) && + oneWayCompatible(FP32Denormals.Input != DenormalMode::PreserveSign, + CalleeMode.FP32Denormals.Input != + DenormalMode::PreserveSign) && + oneWayCompatible(FP32Denormals.Output != DenormalMode::PreserveSign, + CalleeMode.FP32Denormals.Output != + DenormalMode::PreserveSign); + } +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_AMDGPU_SIMODEREGISTERDEFAULTS_H diff --git a/llvm/lib/Target/AMDGPU/SIModeRegisterDefaults.cpp b/llvm/lib/Target/AMDGPU/SIModeRegisterDefaults.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/SIModeRegisterDefaults.cpp @@ -0,0 +1,38 @@ +//===-- SIModeRegisterDefaults.cpp ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "SIModeRegisterDefaults.h" + +using namespace llvm; + +SIModeRegisterDefaults::SIModeRegisterDefaults(const Function &F) { + *this = getDefaultForCallingConv(F.getCallingConv()); + + StringRef IEEEAttr = F.getFnAttribute("amdgpu-ieee").getValueAsString(); + if (!IEEEAttr.empty()) + IEEE = IEEEAttr == "true"; + + StringRef DX10ClampAttr = + F.getFnAttribute("amdgpu-dx10-clamp").getValueAsString(); + if (!DX10ClampAttr.empty()) + DX10Clamp = DX10ClampAttr == "true"; + + StringRef DenormF32Attr = + F.getFnAttribute("denormal-fp-math-f32").getValueAsString(); + if (!DenormF32Attr.empty()) + FP32Denormals = parseDenormalFPAttribute(DenormF32Attr); + + StringRef DenormAttr = + F.getFnAttribute("denormal-fp-math").getValueAsString(); + if (!DenormAttr.empty()) { + DenormalMode DenormMode = parseDenormalFPAttribute(DenormAttr); + if (DenormF32Attr.empty()) + FP32Denormals = DenormMode; + FP64FP16Denormals = DenormMode; + } +} diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -10,7 +10,6 @@ #define LLVM_LIB_TARGET_AMDGPU_UTILS_AMDGPUBASEINFO_H #include "SIDefines.h" -#include "llvm/ADT/FloatingPointMode.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Module.h" @@ -1312,110 +1311,6 @@ /// \returns true if the intrinsic is uniform bool isIntrinsicAlwaysUniform(unsigned IntrID); -// Track defaults for fields in the MODE register. -struct SIModeRegisterDefaults { - /// Floating point opcodes that support exception flag gathering quiet and - /// propagate signaling NaN inputs per IEEE 754-2008. Min_dx10 and max_dx10 - /// become IEEE 754- 2008 compliant due to signaling NaN propagation and - /// quieting. - bool IEEE : 1; - - /// Used by the vector ALU to force DX10-style treatment of NaNs: when set, - /// clamp NaN to zero; otherwise, pass NaN through. - bool DX10Clamp : 1; - - /// If this is set, neither input or output denormals are flushed for most f32 - /// instructions. - DenormalMode FP32Denormals; - - /// If this is set, neither input or output denormals are flushed for both f64 - /// and f16/v2f16 instructions. - DenormalMode FP64FP16Denormals; - - SIModeRegisterDefaults() : - IEEE(true), - DX10Clamp(true), - FP32Denormals(DenormalMode::getIEEE()), - FP64FP16Denormals(DenormalMode::getIEEE()) {} - - SIModeRegisterDefaults(const Function &F); - - static SIModeRegisterDefaults getDefaultForCallingConv(CallingConv::ID CC) { - SIModeRegisterDefaults Mode; - Mode.IEEE = !AMDGPU::isShader(CC); - return Mode; - } - - bool operator ==(const SIModeRegisterDefaults Other) const { - return IEEE == Other.IEEE && DX10Clamp == Other.DX10Clamp && - FP32Denormals == Other.FP32Denormals && - FP64FP16Denormals == Other.FP64FP16Denormals; - } - - bool allFP32Denormals() const { - return FP32Denormals == DenormalMode::getIEEE(); - } - - bool allFP64FP16Denormals() const { - return FP64FP16Denormals == DenormalMode::getIEEE(); - } - - /// Get the encoding value for the FP_DENORM bits of the mode register for the - /// FP32 denormal mode. - uint32_t fpDenormModeSPValue() const { - if (FP32Denormals == DenormalMode::getPreserveSign()) - return FP_DENORM_FLUSH_IN_FLUSH_OUT; - if (FP32Denormals.Output == DenormalMode::PreserveSign) - return FP_DENORM_FLUSH_OUT; - if (FP32Denormals.Input == DenormalMode::PreserveSign) - return FP_DENORM_FLUSH_IN; - return FP_DENORM_FLUSH_NONE; - } - - /// Get the encoding value for the FP_DENORM bits of the mode register for the - /// FP64/FP16 denormal mode. - uint32_t fpDenormModeDPValue() const { - if (FP64FP16Denormals == DenormalMode::getPreserveSign()) - return FP_DENORM_FLUSH_IN_FLUSH_OUT; - if (FP64FP16Denormals.Output == DenormalMode::PreserveSign) - return FP_DENORM_FLUSH_OUT; - if (FP64FP16Denormals.Input == DenormalMode::PreserveSign) - return FP_DENORM_FLUSH_IN; - return FP_DENORM_FLUSH_NONE; - } - - /// Returns true if a flag is compatible if it's enabled in the callee, but - /// disabled in the caller. - static bool oneWayCompatible(bool CallerMode, bool CalleeMode) { - return CallerMode == CalleeMode || (!CallerMode && CalleeMode); - } - - // FIXME: Inlining should be OK for dx10-clamp, since the caller's mode should - // be able to override. - bool isInlineCompatible(SIModeRegisterDefaults CalleeMode) const { - if (DX10Clamp != CalleeMode.DX10Clamp) - return false; - if (IEEE != CalleeMode.IEEE) - return false; - - // Allow inlining denormals enabled into denormals flushed functions. - return oneWayCompatible(FP64FP16Denormals.Input != - DenormalMode::PreserveSign, - CalleeMode.FP64FP16Denormals.Input != - DenormalMode::PreserveSign) && - oneWayCompatible(FP64FP16Denormals.Output != - DenormalMode::PreserveSign, - CalleeMode.FP64FP16Denormals.Output != - DenormalMode::PreserveSign) && - oneWayCompatible(FP32Denormals.Input != DenormalMode::PreserveSign, - CalleeMode.FP32Denormals.Input != - DenormalMode::PreserveSign) && - oneWayCompatible(FP32Denormals.Output != DenormalMode::PreserveSign, - CalleeMode.FP32Denormals.Output != - DenormalMode::PreserveSign); - } -}; - } // end namespace AMDGPU raw_ostream &operator<<(raw_ostream &OS, diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -2598,31 +2598,6 @@ return 13; } -SIModeRegisterDefaults::SIModeRegisterDefaults(const Function &F) { - *this = getDefaultForCallingConv(F.getCallingConv()); - - StringRef IEEEAttr = F.getFnAttribute("amdgpu-ieee").getValueAsString(); - if (!IEEEAttr.empty()) - IEEE = IEEEAttr == "true"; - - StringRef DX10ClampAttr - = F.getFnAttribute("amdgpu-dx10-clamp").getValueAsString(); - if (!DX10ClampAttr.empty()) - DX10Clamp = DX10ClampAttr == "true"; - - StringRef DenormF32Attr = F.getFnAttribute("denormal-fp-math-f32").getValueAsString(); - if (!DenormF32Attr.empty()) - FP32Denormals = parseDenormalFPAttribute(DenormF32Attr); - - StringRef DenormAttr = F.getFnAttribute("denormal-fp-math").getValueAsString(); - if (!DenormAttr.empty()) { - DenormalMode DenormMode = parseDenormalFPAttribute(DenormAttr); - if (DenormF32Attr.empty()) - FP32Denormals = DenormMode; - FP64FP16Denormals = DenormMode; - } -} - namespace { struct SourceOfDivergence {