98 enum FtzRequirementTy {
108 SCP_FunnelShiftClamp,
113 struct SimplifyAction {
115 std::optional<Intrinsic::ID> IID;
116 std::optional<Instruction::CastOps> CastOp;
117 std::optional<Instruction::BinaryOps> BinaryOp;
118 std::optional<SpecialCase> Special;
120 FtzRequirementTy FtzRequirement = FTZ_Any;
123 bool IsHalfTy =
false;
125 SimplifyAction() =
default;
128 bool IsHalfTy =
false)
129 : IID(IID), FtzRequirement(FtzReq), IsHalfTy(IsHalfTy) {}
136 : BinaryOp(BinaryOp), FtzRequirement(FtzReq) {}
138 SimplifyAction(SpecialCase Special, FtzRequirementTy FtzReq)
139 : Special(Special), FtzRequirement(FtzReq) {}
144 const SimplifyAction Action = [
II]() -> SimplifyAction {
145 switch (
II->getIntrinsicID()) {
147 case Intrinsic::nvvm_ceil_d:
148 return {Intrinsic::ceil, FTZ_Any};
149 case Intrinsic::nvvm_ceil_f:
150 return {Intrinsic::ceil, FTZ_MustBeOff};
151 case Intrinsic::nvvm_ceil_ftz_f:
152 return {Intrinsic::ceil, FTZ_MustBeOn};
153 case Intrinsic::nvvm_floor_d:
154 return {Intrinsic::floor, FTZ_Any};
155 case Intrinsic::nvvm_floor_f:
156 return {Intrinsic::floor, FTZ_MustBeOff};
157 case Intrinsic::nvvm_floor_ftz_f:
158 return {Intrinsic::floor, FTZ_MustBeOn};
159 case Intrinsic::nvvm_fma_rn_d:
160 return {Intrinsic::fma, FTZ_Any};
161 case Intrinsic::nvvm_fma_rn_f:
162 return {Intrinsic::fma, FTZ_MustBeOff};
163 case Intrinsic::nvvm_fma_rn_ftz_f:
164 return {Intrinsic::fma, FTZ_MustBeOn};
165 case Intrinsic::nvvm_fma_rn_f16:
166 return {Intrinsic::fma, FTZ_MustBeOff,
true};
167 case Intrinsic::nvvm_fma_rn_ftz_f16:
168 return {Intrinsic::fma, FTZ_MustBeOn,
true};
169 case Intrinsic::nvvm_fma_rn_f16x2:
170 return {Intrinsic::fma, FTZ_MustBeOff,
true};
171 case Intrinsic::nvvm_fma_rn_ftz_f16x2:
172 return {Intrinsic::fma, FTZ_MustBeOn,
true};
173 case Intrinsic::nvvm_fma_rn_bf16:
174 return {Intrinsic::fma, FTZ_MustBeOff,
true};
175 case Intrinsic::nvvm_fma_rn_bf16x2:
176 return {Intrinsic::fma, FTZ_MustBeOff,
true};
177 case Intrinsic::nvvm_fmax_d:
178 return {Intrinsic::maximumnum, FTZ_Any};
179 case Intrinsic::nvvm_fmax_f:
180 return {Intrinsic::maximumnum, FTZ_MustBeOff};
181 case Intrinsic::nvvm_fmax_ftz_f:
182 return {Intrinsic::maximumnum, FTZ_MustBeOn};
183 case Intrinsic::nvvm_fmax_nan_f:
184 return {Intrinsic::maximum, FTZ_MustBeOff};
185 case Intrinsic::nvvm_fmax_ftz_nan_f:
186 return {Intrinsic::maximum, FTZ_MustBeOn};
187 case Intrinsic::nvvm_fmax_f16:
188 return {Intrinsic::maximumnum, FTZ_MustBeOff,
true};
189 case Intrinsic::nvvm_fmax_ftz_f16:
190 return {Intrinsic::maximumnum, FTZ_MustBeOn,
true};
191 case Intrinsic::nvvm_fmax_f16x2:
192 return {Intrinsic::maximumnum, FTZ_MustBeOff,
true};
193 case Intrinsic::nvvm_fmax_ftz_f16x2:
194 return {Intrinsic::maximumnum, FTZ_MustBeOn,
true};
195 case Intrinsic::nvvm_fmax_nan_f16:
196 return {Intrinsic::maximum, FTZ_MustBeOff,
true};
197 case Intrinsic::nvvm_fmax_ftz_nan_f16:
198 return {Intrinsic::maximum, FTZ_MustBeOn,
true};
199 case Intrinsic::nvvm_fmax_nan_f16x2:
200 return {Intrinsic::maximum, FTZ_MustBeOff,
true};
201 case Intrinsic::nvvm_fmax_ftz_nan_f16x2:
202 return {Intrinsic::maximum, FTZ_MustBeOn,
true};
203 case Intrinsic::nvvm_fmin_d:
204 return {Intrinsic::minimumnum, FTZ_Any};
205 case Intrinsic::nvvm_fmin_f:
206 return {Intrinsic::minimumnum, FTZ_MustBeOff};
207 case Intrinsic::nvvm_fmin_ftz_f:
208 return {Intrinsic::minimumnum, FTZ_MustBeOn};
209 case Intrinsic::nvvm_fmin_nan_f:
210 return {Intrinsic::minimum, FTZ_MustBeOff};
211 case Intrinsic::nvvm_fmin_ftz_nan_f:
212 return {Intrinsic::minimum, FTZ_MustBeOn};
213 case Intrinsic::nvvm_fmin_f16:
214 return {Intrinsic::minimumnum, FTZ_MustBeOff,
true};
215 case Intrinsic::nvvm_fmin_ftz_f16:
216 return {Intrinsic::minimumnum, FTZ_MustBeOn,
true};
217 case Intrinsic::nvvm_fmin_f16x2:
218 return {Intrinsic::minimumnum, FTZ_MustBeOff,
true};
219 case Intrinsic::nvvm_fmin_ftz_f16x2:
220 return {Intrinsic::minimumnum, FTZ_MustBeOn,
true};
221 case Intrinsic::nvvm_fmin_nan_f16:
222 return {Intrinsic::minimum, FTZ_MustBeOff,
true};
223 case Intrinsic::nvvm_fmin_ftz_nan_f16:
224 return {Intrinsic::minimum, FTZ_MustBeOn,
true};
225 case Intrinsic::nvvm_fmin_nan_f16x2:
226 return {Intrinsic::minimum, FTZ_MustBeOff,
true};
227 case Intrinsic::nvvm_fmin_ftz_nan_f16x2:
228 return {Intrinsic::minimum, FTZ_MustBeOn,
true};
229 case Intrinsic::nvvm_sqrt_rn_d:
230 return {Intrinsic::sqrt, FTZ_Any};
231 case Intrinsic::nvvm_sqrt_f:
236 return {Intrinsic::sqrt, FTZ_Any};
237 case Intrinsic::nvvm_trunc_d:
238 return {Intrinsic::trunc, FTZ_Any};
239 case Intrinsic::nvvm_trunc_f:
240 return {Intrinsic::trunc, FTZ_MustBeOff};
241 case Intrinsic::nvvm_trunc_ftz_f:
242 return {Intrinsic::trunc, FTZ_MustBeOn};
251 case Intrinsic::nvvm_i2d_rn:
252 case Intrinsic::nvvm_i2f_rn:
253 case Intrinsic::nvvm_ll2d_rn:
254 case Intrinsic::nvvm_ll2f_rn:
255 return {Instruction::SIToFP};
256 case Intrinsic::nvvm_ui2d_rn:
257 case Intrinsic::nvvm_ui2f_rn:
258 case Intrinsic::nvvm_ull2d_rn:
259 case Intrinsic::nvvm_ull2f_rn:
260 return {Instruction::UIToFP};
263 case Intrinsic::nvvm_div_rn_d:
264 return {Instruction::FDiv, FTZ_Any};
271 case Intrinsic::nvvm_rcp_rn_d:
272 return {SPC_Reciprocal, FTZ_Any};
274 case Intrinsic::nvvm_fshl_clamp:
275 case Intrinsic::nvvm_fshr_clamp:
276 return {SCP_FunnelShiftClamp, FTZ_Any};
307 if (Action.FtzRequirement != FTZ_Any) {
313 if (FtzEnabled != (Action.FtzRequirement == FTZ_MustBeOn))
322 Type *Tys[] = {
II->getArgOperand(0)->getType()};
331 II->getArgOperand(1),
II->getName());
342 switch (*Action.Special) {
346 Instruction::FDiv, ConstantFP::get(
II->getArgOperand(0)->getType(), 1),
347 II->getArgOperand(0),
II->getName());
349 case SCP_FunnelShiftClamp: {
353 const bool IsLeft =
II->getIntrinsicID() == Intrinsic::nvvm_fshl_clamp;
354 if (ShiftConst->getZExtValue() >=
II->getType()->getIntegerBitWidth())
357 const unsigned FshIID = IsLeft ? Intrinsic::fshl : Intrinsic::fshr;
359 II->getModule(), FshIID,
II->getType()),
365 llvm_unreachable(
"All SpecialCase enumerators should be handled in switch.");