1 //===-- SIModeRegisterDefaults.h --------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIB_TARGET_AMDGPU_SIMODEREGISTERDEFAULTS_H
10 #define LLVM_LIB_TARGET_AMDGPU_SIMODEREGISTERDEFAULTS_H
11 
12 #include "Utils/AMDGPUBaseInfo.h"
13 #include "llvm/ADT/FloatingPointMode.h"
14 
15 namespace llvm {
16 
17 // Track defaults for fields in the MODE register.
18 struct SIModeRegisterDefaults {
19   /// Floating point opcodes that support exception flag gathering quiet and
20   /// propagate signaling NaN inputs per IEEE 754-2008. Min_dx10 and max_dx10
21   /// become IEEE 754- 2008 compliant due to signaling NaN propagation and
22   /// quieting.
23   bool IEEE : 1;
24 
25   /// Used by the vector ALU to force DX10-style treatment of NaNs: when set,
26   /// clamp NaN to zero; otherwise, pass NaN through.
27   bool DX10Clamp : 1;
28 
29   /// If this is set, neither input or output denormals are flushed for most f32
30   /// instructions.
31   DenormalMode FP32Denormals;
32 
33   /// If this is set, neither input or output denormals are flushed for both f64
34   /// and f16/v2f16 instructions.
35   DenormalMode FP64FP16Denormals;
36 
37   SIModeRegisterDefaults() :
38     IEEE(true),
39     DX10Clamp(true),
40     FP32Denormals(DenormalMode::getIEEE()),
41     FP64FP16Denormals(DenormalMode::getIEEE()) {}
42 
43   SIModeRegisterDefaults(const Function &F);
44 
45   static SIModeRegisterDefaults getDefaultForCallingConv(CallingConv::ID CC) {
46     SIModeRegisterDefaults Mode;
47     Mode.IEEE = !AMDGPU::isShader(CC);
48     return Mode;
49   }
50 
51   bool operator==(const SIModeRegisterDefaults Other) const {
52     return IEEE == Other.IEEE && DX10Clamp == Other.DX10Clamp &&
53            FP32Denormals == Other.FP32Denormals &&
54            FP64FP16Denormals == Other.FP64FP16Denormals;
55   }
56 
57   /// Get the encoding value for the FP_DENORM bits of the mode register for the
58   /// FP32 denormal mode.
59   uint32_t fpDenormModeSPValue() const {
60     if (FP32Denormals == DenormalMode::getPreserveSign())
61       return FP_DENORM_FLUSH_IN_FLUSH_OUT;
62     if (FP32Denormals.Output == DenormalMode::PreserveSign)
63       return FP_DENORM_FLUSH_OUT;
64     if (FP32Denormals.Input == DenormalMode::PreserveSign)
65       return FP_DENORM_FLUSH_IN;
66     return FP_DENORM_FLUSH_NONE;
67   }
68 
69   /// Get the encoding value for the FP_DENORM bits of the mode register for the
70   /// FP64/FP16 denormal mode.
71   uint32_t fpDenormModeDPValue() const {
72     if (FP64FP16Denormals == DenormalMode::getPreserveSign())
73       return FP_DENORM_FLUSH_IN_FLUSH_OUT;
74     if (FP64FP16Denormals.Output == DenormalMode::PreserveSign)
75       return FP_DENORM_FLUSH_OUT;
76     if (FP64FP16Denormals.Input == DenormalMode::PreserveSign)
77       return FP_DENORM_FLUSH_IN;
78     return FP_DENORM_FLUSH_NONE;
79   }
80 
81   // FIXME: Inlining should be OK for dx10-clamp, since the caller's mode should
82   // be able to override.
83   bool isInlineCompatible(SIModeRegisterDefaults CalleeMode) const {
84     return DX10Clamp == CalleeMode.DX10Clamp && IEEE == CalleeMode.IEEE;
85   }
86 };
87 
88 } // end namespace llvm
89 
90 #endif // LLVM_LIB_TARGET_AMDGPU_SIMODEREGISTERDEFAULTS_H
91