xref: /llvm-project/llvm/lib/Target/AMDGPU/AMDGPUCombinerHelper.cpp (revision bbb53d1a8cd37cbb31ec5ec7938a0f24f628c821)
1 //=== lib/CodeGen/GlobalISel/AMDGPUCombinerHelper.cpp ---------------------===//
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 #include "AMDGPUCombinerHelper.h"
10 #include "GCNSubtarget.h"
11 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
12 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
13 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
14 #include "llvm/IR/IntrinsicsAMDGPU.h"
15 #include "llvm/Target/TargetMachine.h"
16 
17 using namespace llvm;
18 using namespace MIPatternMatch;
19 
20 AMDGPUCombinerHelper::AMDGPUCombinerHelper(
21     GISelChangeObserver &Observer, MachineIRBuilder &B, bool IsPreLegalize,
22     GISelKnownBits *KB, MachineDominatorTree *MDT, const LegalizerInfo *LI,
23     const GCNSubtarget &STI)
24     : CombinerHelper(Observer, B, IsPreLegalize, KB, MDT, LI), STI(STI),
25       TII(*STI.getInstrInfo()) {}
26 
27 LLVM_READNONE
28 static bool fnegFoldsIntoMI(const MachineInstr &MI) {
29   switch (MI.getOpcode()) {
30   case AMDGPU::G_FADD:
31   case AMDGPU::G_FSUB:
32   case AMDGPU::G_FMUL:
33   case AMDGPU::G_FMA:
34   case AMDGPU::G_FMAD:
35   case AMDGPU::G_FMINNUM:
36   case AMDGPU::G_FMAXNUM:
37   case AMDGPU::G_FMINNUM_IEEE:
38   case AMDGPU::G_FMAXNUM_IEEE:
39   case AMDGPU::G_FMINIMUM:
40   case AMDGPU::G_FMAXIMUM:
41   case AMDGPU::G_FSIN:
42   case AMDGPU::G_FPEXT:
43   case AMDGPU::G_INTRINSIC_TRUNC:
44   case AMDGPU::G_FPTRUNC:
45   case AMDGPU::G_FRINT:
46   case AMDGPU::G_FNEARBYINT:
47   case AMDGPU::G_INTRINSIC_ROUND:
48   case AMDGPU::G_INTRINSIC_ROUNDEVEN:
49   case AMDGPU::G_FCANONICALIZE:
50   case AMDGPU::G_AMDGPU_RCP_IFLAG:
51   case AMDGPU::G_AMDGPU_FMIN_LEGACY:
52   case AMDGPU::G_AMDGPU_FMAX_LEGACY:
53     return true;
54   case AMDGPU::G_INTRINSIC: {
55     Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
56     switch (IntrinsicID) {
57     case Intrinsic::amdgcn_rcp:
58     case Intrinsic::amdgcn_rcp_legacy:
59     case Intrinsic::amdgcn_sin:
60     case Intrinsic::amdgcn_fmul_legacy:
61     case Intrinsic::amdgcn_fmed3:
62     case Intrinsic::amdgcn_fma_legacy:
63       return true;
64     default:
65       return false;
66     }
67   }
68   default:
69     return false;
70   }
71 }
72 
73 /// \p returns true if the operation will definitely need to use a 64-bit
74 /// encoding, and thus will use a VOP3 encoding regardless of the source
75 /// modifiers.
76 LLVM_READONLY
77 static bool opMustUseVOP3Encoding(const MachineInstr &MI,
78                                   const MachineRegisterInfo &MRI) {
79   return MI.getNumOperands() > (isa<GIntrinsic>(MI) ? 4u : 3u) ||
80          MRI.getType(MI.getOperand(0).getReg()).getScalarSizeInBits() == 64;
81 }
82 
83 // Most FP instructions support source modifiers.
84 LLVM_READONLY
85 static bool hasSourceMods(const MachineInstr &MI) {
86   if (!MI.memoperands().empty())
87     return false;
88 
89   switch (MI.getOpcode()) {
90   case AMDGPU::COPY:
91   case AMDGPU::G_SELECT:
92   case AMDGPU::G_FDIV:
93   case AMDGPU::G_FREM:
94   case TargetOpcode::INLINEASM:
95   case TargetOpcode::INLINEASM_BR:
96   case AMDGPU::G_INTRINSIC_W_SIDE_EFFECTS:
97   case AMDGPU::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
98   case AMDGPU::G_BITCAST:
99   case AMDGPU::G_ANYEXT:
100   case AMDGPU::G_BUILD_VECTOR:
101   case AMDGPU::G_BUILD_VECTOR_TRUNC:
102   case AMDGPU::G_PHI:
103     return false;
104   case AMDGPU::G_INTRINSIC:
105   case AMDGPU::G_INTRINSIC_CONVERGENT: {
106     Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
107     switch (IntrinsicID) {
108     case Intrinsic::amdgcn_interp_p1:
109     case Intrinsic::amdgcn_interp_p2:
110     case Intrinsic::amdgcn_interp_mov:
111     case Intrinsic::amdgcn_interp_p1_f16:
112     case Intrinsic::amdgcn_interp_p2_f16:
113     case Intrinsic::amdgcn_div_scale:
114       return false;
115     default:
116       return true;
117     }
118   }
119   default:
120     return true;
121   }
122 }
123 
124 static bool allUsesHaveSourceMods(MachineInstr &MI, MachineRegisterInfo &MRI,
125                                   unsigned CostThreshold = 4) {
126   // Some users (such as 3-operand FMA/MAD) must use a VOP3 encoding, and thus
127   // it is truly free to use a source modifier in all cases. If there are
128   // multiple users but for each one will necessitate using VOP3, there will be
129   // a code size increase. Try to avoid increasing code size unless we know it
130   // will save on the instruction count.
131   unsigned NumMayIncreaseSize = 0;
132   Register Dst = MI.getOperand(0).getReg();
133   for (const MachineInstr &Use : MRI.use_nodbg_instructions(Dst)) {
134     if (!hasSourceMods(Use))
135       return false;
136 
137     if (!opMustUseVOP3Encoding(Use, MRI)) {
138       if (++NumMayIncreaseSize > CostThreshold)
139         return false;
140     }
141   }
142   return true;
143 }
144 
145 static bool mayIgnoreSignedZero(MachineInstr &MI) {
146   const TargetOptions &Options = MI.getMF()->getTarget().Options;
147   return Options.NoSignedZerosFPMath || MI.getFlag(MachineInstr::MIFlag::FmNsz);
148 }
149 
150 static bool isInv2Pi(const APFloat &APF) {
151   static const APFloat KF16(APFloat::IEEEhalf(), APInt(16, 0x3118));
152   static const APFloat KF32(APFloat::IEEEsingle(), APInt(32, 0x3e22f983));
153   static const APFloat KF64(APFloat::IEEEdouble(),
154                             APInt(64, 0x3fc45f306dc9c882));
155 
156   return APF.bitwiseIsEqual(KF16) || APF.bitwiseIsEqual(KF32) ||
157          APF.bitwiseIsEqual(KF64);
158 }
159 
160 // 0 and 1.0 / (0.5 * pi) do not have inline immmediates, so there is an
161 // additional cost to negate them.
162 static bool isConstantCostlierToNegate(MachineInstr &MI, Register Reg,
163                                        MachineRegisterInfo &MRI) {
164   std::optional<FPValueAndVReg> FPValReg;
165   if (mi_match(Reg, MRI, m_GFCstOrSplat(FPValReg))) {
166     if (FPValReg->Value.isZero() && !FPValReg->Value.isNegative())
167       return true;
168 
169     const GCNSubtarget &ST = MI.getMF()->getSubtarget<GCNSubtarget>();
170     if (ST.hasInv2PiInlineImm() && isInv2Pi(FPValReg->Value))
171       return true;
172   }
173   return false;
174 }
175 
176 static unsigned inverseMinMax(unsigned Opc) {
177   switch (Opc) {
178   case AMDGPU::G_FMAXNUM:
179     return AMDGPU::G_FMINNUM;
180   case AMDGPU::G_FMINNUM:
181     return AMDGPU::G_FMAXNUM;
182   case AMDGPU::G_FMAXNUM_IEEE:
183     return AMDGPU::G_FMINNUM_IEEE;
184   case AMDGPU::G_FMINNUM_IEEE:
185     return AMDGPU::G_FMAXNUM_IEEE;
186   case AMDGPU::G_FMAXIMUM:
187     return AMDGPU::G_FMINIMUM;
188   case AMDGPU::G_FMINIMUM:
189     return AMDGPU::G_FMAXIMUM;
190   case AMDGPU::G_AMDGPU_FMAX_LEGACY:
191     return AMDGPU::G_AMDGPU_FMIN_LEGACY;
192   case AMDGPU::G_AMDGPU_FMIN_LEGACY:
193     return AMDGPU::G_AMDGPU_FMAX_LEGACY;
194   default:
195     llvm_unreachable("invalid min/max opcode");
196   }
197 }
198 
199 bool AMDGPUCombinerHelper::matchFoldableFneg(MachineInstr &MI,
200                                              MachineInstr *&MatchInfo) const {
201   Register Src = MI.getOperand(1).getReg();
202   MatchInfo = MRI.getVRegDef(Src);
203 
204   // If the input has multiple uses and we can either fold the negate down, or
205   // the other uses cannot, give up. This both prevents unprofitable
206   // transformations and infinite loops: we won't repeatedly try to fold around
207   // a negate that has no 'good' form.
208   if (MRI.hasOneNonDBGUse(Src)) {
209     if (allUsesHaveSourceMods(MI, MRI, 0))
210       return false;
211   } else {
212     if (fnegFoldsIntoMI(*MatchInfo) &&
213         (allUsesHaveSourceMods(MI, MRI) ||
214          !allUsesHaveSourceMods(*MatchInfo, MRI)))
215       return false;
216   }
217 
218   switch (MatchInfo->getOpcode()) {
219   case AMDGPU::G_FMINNUM:
220   case AMDGPU::G_FMAXNUM:
221   case AMDGPU::G_FMINNUM_IEEE:
222   case AMDGPU::G_FMAXNUM_IEEE:
223   case AMDGPU::G_FMINIMUM:
224   case AMDGPU::G_FMAXIMUM:
225   case AMDGPU::G_AMDGPU_FMIN_LEGACY:
226   case AMDGPU::G_AMDGPU_FMAX_LEGACY:
227     // 0 doesn't have a negated inline immediate.
228     return !isConstantCostlierToNegate(*MatchInfo,
229                                        MatchInfo->getOperand(2).getReg(), MRI);
230   case AMDGPU::G_FADD:
231   case AMDGPU::G_FSUB:
232   case AMDGPU::G_FMA:
233   case AMDGPU::G_FMAD:
234     return mayIgnoreSignedZero(*MatchInfo);
235   case AMDGPU::G_FMUL:
236   case AMDGPU::G_FPEXT:
237   case AMDGPU::G_INTRINSIC_TRUNC:
238   case AMDGPU::G_FPTRUNC:
239   case AMDGPU::G_FRINT:
240   case AMDGPU::G_FNEARBYINT:
241   case AMDGPU::G_INTRINSIC_ROUND:
242   case AMDGPU::G_INTRINSIC_ROUNDEVEN:
243   case AMDGPU::G_FSIN:
244   case AMDGPU::G_FCANONICALIZE:
245   case AMDGPU::G_AMDGPU_RCP_IFLAG:
246     return true;
247   case AMDGPU::G_INTRINSIC:
248   case AMDGPU::G_INTRINSIC_CONVERGENT: {
249     Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MatchInfo)->getIntrinsicID();
250     switch (IntrinsicID) {
251     case Intrinsic::amdgcn_rcp:
252     case Intrinsic::amdgcn_rcp_legacy:
253     case Intrinsic::amdgcn_sin:
254     case Intrinsic::amdgcn_fmul_legacy:
255     case Intrinsic::amdgcn_fmed3:
256       return true;
257     case Intrinsic::amdgcn_fma_legacy:
258       return mayIgnoreSignedZero(*MatchInfo);
259     default:
260       return false;
261     }
262   }
263   default:
264     return false;
265   }
266 }
267 
268 void AMDGPUCombinerHelper::applyFoldableFneg(MachineInstr &MI,
269                                              MachineInstr *&MatchInfo) const {
270   // Transform:
271   // %A = inst %Op1, ...
272   // %B = fneg %A
273   //
274   // into:
275   //
276   // (if %A has one use, specifically fneg above)
277   // %B = inst (maybe fneg %Op1), ...
278   //
279   // (if %A has multiple uses)
280   // %B = inst (maybe fneg %Op1), ...
281   // %A = fneg %B
282 
283   // Replace register in operand with a register holding negated value.
284   auto NegateOperand = [&](MachineOperand &Op) {
285     Register Reg = Op.getReg();
286     if (!mi_match(Reg, MRI, m_GFNeg(m_Reg(Reg))))
287       Reg = Builder.buildFNeg(MRI.getType(Reg), Reg).getReg(0);
288     replaceRegOpWith(MRI, Op, Reg);
289   };
290 
291   // Replace either register in operands with a register holding negated value.
292   auto NegateEitherOperand = [&](MachineOperand &X, MachineOperand &Y) {
293     Register XReg = X.getReg();
294     Register YReg = Y.getReg();
295     if (mi_match(XReg, MRI, m_GFNeg(m_Reg(XReg))))
296       replaceRegOpWith(MRI, X, XReg);
297     else if (mi_match(YReg, MRI, m_GFNeg(m_Reg(YReg))))
298       replaceRegOpWith(MRI, Y, YReg);
299     else {
300       YReg = Builder.buildFNeg(MRI.getType(YReg), YReg).getReg(0);
301       replaceRegOpWith(MRI, Y, YReg);
302     }
303   };
304 
305   Builder.setInstrAndDebugLoc(*MatchInfo);
306 
307   // Negate appropriate operands so that resulting value of MatchInfo is
308   // negated.
309   switch (MatchInfo->getOpcode()) {
310   case AMDGPU::G_FADD:
311   case AMDGPU::G_FSUB:
312     NegateOperand(MatchInfo->getOperand(1));
313     NegateOperand(MatchInfo->getOperand(2));
314     break;
315   case AMDGPU::G_FMUL:
316     NegateEitherOperand(MatchInfo->getOperand(1), MatchInfo->getOperand(2));
317     break;
318   case AMDGPU::G_FMINNUM:
319   case AMDGPU::G_FMAXNUM:
320   case AMDGPU::G_FMINNUM_IEEE:
321   case AMDGPU::G_FMAXNUM_IEEE:
322   case AMDGPU::G_FMINIMUM:
323   case AMDGPU::G_FMAXIMUM:
324   case AMDGPU::G_AMDGPU_FMIN_LEGACY:
325   case AMDGPU::G_AMDGPU_FMAX_LEGACY: {
326     NegateOperand(MatchInfo->getOperand(1));
327     NegateOperand(MatchInfo->getOperand(2));
328     unsigned Opposite = inverseMinMax(MatchInfo->getOpcode());
329     replaceOpcodeWith(*MatchInfo, Opposite);
330     break;
331   }
332   case AMDGPU::G_FMA:
333   case AMDGPU::G_FMAD:
334     NegateEitherOperand(MatchInfo->getOperand(1), MatchInfo->getOperand(2));
335     NegateOperand(MatchInfo->getOperand(3));
336     break;
337   case AMDGPU::G_FPEXT:
338   case AMDGPU::G_INTRINSIC_TRUNC:
339   case AMDGPU::G_FRINT:
340   case AMDGPU::G_FNEARBYINT:
341   case AMDGPU::G_INTRINSIC_ROUND:
342   case AMDGPU::G_INTRINSIC_ROUNDEVEN:
343   case AMDGPU::G_FSIN:
344   case AMDGPU::G_FCANONICALIZE:
345   case AMDGPU::G_AMDGPU_RCP_IFLAG:
346   case AMDGPU::G_FPTRUNC:
347     NegateOperand(MatchInfo->getOperand(1));
348     break;
349   case AMDGPU::G_INTRINSIC:
350   case AMDGPU::G_INTRINSIC_CONVERGENT: {
351     Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MatchInfo)->getIntrinsicID();
352     switch (IntrinsicID) {
353     case Intrinsic::amdgcn_rcp:
354     case Intrinsic::amdgcn_rcp_legacy:
355     case Intrinsic::amdgcn_sin:
356       NegateOperand(MatchInfo->getOperand(2));
357       break;
358     case Intrinsic::amdgcn_fmul_legacy:
359       NegateEitherOperand(MatchInfo->getOperand(2), MatchInfo->getOperand(3));
360       break;
361     case Intrinsic::amdgcn_fmed3:
362       NegateOperand(MatchInfo->getOperand(2));
363       NegateOperand(MatchInfo->getOperand(3));
364       NegateOperand(MatchInfo->getOperand(4));
365       break;
366     case Intrinsic::amdgcn_fma_legacy:
367       NegateEitherOperand(MatchInfo->getOperand(2), MatchInfo->getOperand(3));
368       NegateOperand(MatchInfo->getOperand(4));
369       break;
370     default:
371       llvm_unreachable("folding fneg not supported for this intrinsic");
372     }
373     break;
374   }
375   default:
376     llvm_unreachable("folding fneg not supported for this instruction");
377   }
378 
379   Register Dst = MI.getOperand(0).getReg();
380   Register MatchInfoDst = MatchInfo->getOperand(0).getReg();
381 
382   if (MRI.hasOneNonDBGUse(MatchInfoDst)) {
383     // MatchInfo now has negated value so use that instead of old Dst.
384     replaceRegWith(MRI, Dst, MatchInfoDst);
385   } else {
386     // We want to swap all uses of Dst with uses of MatchInfoDst and vice versa
387     // but replaceRegWith will replace defs as well. It is easier to replace one
388     // def with a new register.
389     LLT Type = MRI.getType(Dst);
390     Register NegatedMatchInfo = MRI.createGenericVirtualRegister(Type);
391     replaceRegOpWith(MRI, MatchInfo->getOperand(0), NegatedMatchInfo);
392 
393     // MatchInfo now has negated value so use that instead of old Dst.
394     replaceRegWith(MRI, Dst, NegatedMatchInfo);
395 
396     // Recreate non negated value for other uses of old MatchInfoDst
397     auto NextInst = ++MatchInfo->getIterator();
398     Builder.setInstrAndDebugLoc(*NextInst);
399     Builder.buildFNeg(MatchInfoDst, NegatedMatchInfo, MI.getFlags());
400   }
401 
402   MI.eraseFromParent();
403 }
404 
405 // TODO: Should return converted value / extension source and avoid introducing
406 // intermediate fptruncs in the apply function.
407 static bool isFPExtFromF16OrConst(const MachineRegisterInfo &MRI,
408                                   Register Reg) {
409   const MachineInstr *Def = MRI.getVRegDef(Reg);
410   if (Def->getOpcode() == TargetOpcode::G_FPEXT) {
411     Register SrcReg = Def->getOperand(1).getReg();
412     return MRI.getType(SrcReg) == LLT::scalar(16);
413   }
414 
415   if (Def->getOpcode() == TargetOpcode::G_FCONSTANT) {
416     APFloat Val = Def->getOperand(1).getFPImm()->getValueAPF();
417     bool LosesInfo = true;
418     Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &LosesInfo);
419     return !LosesInfo;
420   }
421 
422   return false;
423 }
424 
425 bool AMDGPUCombinerHelper::matchExpandPromotedF16FMed3(MachineInstr &MI,
426                                                        Register Src0,
427                                                        Register Src1,
428                                                        Register Src2) const {
429   assert(MI.getOpcode() == TargetOpcode::G_FPTRUNC);
430   Register SrcReg = MI.getOperand(1).getReg();
431   if (!MRI.hasOneNonDBGUse(SrcReg) || MRI.getType(SrcReg) != LLT::scalar(32))
432     return false;
433 
434   return isFPExtFromF16OrConst(MRI, Src0) && isFPExtFromF16OrConst(MRI, Src1) &&
435          isFPExtFromF16OrConst(MRI, Src2);
436 }
437 
438 void AMDGPUCombinerHelper::applyExpandPromotedF16FMed3(MachineInstr &MI,
439                                                        Register Src0,
440                                                        Register Src1,
441                                                        Register Src2) const {
442   // We expect fptrunc (fpext x) to fold out, and to constant fold any constant
443   // sources.
444   Src0 = Builder.buildFPTrunc(LLT::scalar(16), Src0).getReg(0);
445   Src1 = Builder.buildFPTrunc(LLT::scalar(16), Src1).getReg(0);
446   Src2 = Builder.buildFPTrunc(LLT::scalar(16), Src2).getReg(0);
447 
448   LLT Ty = MRI.getType(Src0);
449   auto A1 = Builder.buildFMinNumIEEE(Ty, Src0, Src1);
450   auto B1 = Builder.buildFMaxNumIEEE(Ty, Src0, Src1);
451   auto C1 = Builder.buildFMaxNumIEEE(Ty, A1, Src2);
452   Builder.buildFMinNumIEEE(MI.getOperand(0), B1, C1);
453   MI.eraseFromParent();
454 }
455 
456 bool AMDGPUCombinerHelper::matchCombineFmulWithSelectToFldexp(
457     MachineInstr &MI, MachineInstr &Sel,
458     std::function<void(MachineIRBuilder &)> &MatchInfo) const {
459   assert(MI.getOpcode() == TargetOpcode::G_FMUL);
460   assert(Sel.getOpcode() == TargetOpcode::G_SELECT);
461   assert(MI.getOperand(2).getReg() == Sel.getOperand(0).getReg());
462 
463   Register Dst = MI.getOperand(0).getReg();
464   LLT DestTy = MRI.getType(Dst);
465   LLT ScalarDestTy = DestTy.getScalarType();
466 
467   if ((ScalarDestTy != LLT::float64() && ScalarDestTy != LLT::float32() &&
468        ScalarDestTy != LLT::float16()) ||
469       !MRI.hasOneNonDBGUse(Sel.getOperand(0).getReg()))
470     return false;
471 
472   Register SelectCondReg = Sel.getOperand(1).getReg();
473   MachineInstr *SelectTrue = MRI.getVRegDef(Sel.getOperand(2).getReg());
474   MachineInstr *SelectFalse = MRI.getVRegDef(Sel.getOperand(3).getReg());
475 
476   const auto SelectTrueVal =
477       isConstantOrConstantSplatVectorFP(*SelectTrue, MRI);
478   if (!SelectTrueVal)
479     return false;
480   const auto SelectFalseVal =
481       isConstantOrConstantSplatVectorFP(*SelectFalse, MRI);
482   if (!SelectFalseVal)
483     return false;
484 
485   if (SelectTrueVal->isNegative() != SelectFalseVal->isNegative())
486     return false;
487 
488   // For f32, only non-inline constants should be transformed.
489   if (ScalarDestTy == LLT::float32() && TII.isInlineConstant(*SelectTrueVal) &&
490       TII.isInlineConstant(*SelectFalseVal))
491     return false;
492 
493   int SelectTrueLog2Val = SelectTrueVal->getExactLog2Abs();
494   if (SelectTrueLog2Val == INT_MIN)
495     return false;
496   int SelectFalseLog2Val = SelectFalseVal->getExactLog2Abs();
497   if (SelectFalseLog2Val == INT_MIN)
498     return false;
499 
500   MatchInfo = [=, &MI](MachineIRBuilder &Builder) {
501     LLT IntDestTy = DestTy.changeElementType(LLT::scalar(32));
502     auto NewSel = Builder.buildSelect(
503         IntDestTy, SelectCondReg,
504         Builder.buildConstant(IntDestTy, SelectTrueLog2Val),
505         Builder.buildConstant(IntDestTy, SelectFalseLog2Val));
506 
507     Register XReg = MI.getOperand(1).getReg();
508     if (SelectTrueVal->isNegative()) {
509       auto NegX =
510           Builder.buildFNeg(DestTy, XReg, MRI.getVRegDef(XReg)->getFlags());
511       Builder.buildFLdexp(Dst, NegX, NewSel, MI.getFlags());
512     } else {
513       Builder.buildFLdexp(Dst, XReg, NewSel, MI.getFlags());
514     }
515   };
516 
517   return true;
518 }
519