LLVM 24.0.0git
HexagonXQFloatGenerator.cpp
Go to the documentation of this file.
1//===-------------------- HexagonXQFloatGenerator.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// This pass enables generation of XQFloat instructions. XQF instructions
10// are more efficient, but can be less precise in comparison to IEEE ones.
11// Based on the accuracy preservation of the generated code, we enabled four
12// modes - Strict IEEE-754 compliant, IEEE-754 compliant, Lossy subnormals and
13// legacy mode.
14//
15// Strict IEEE mode adheres to similar accuracy and precision as of IEEE-754.
16//
17// IEEE-754 compliant mode excludes IEEE-754 overflows and lower precision
18// subnormals due to larger dynamic range than IEEE-754.
19// All subnormals have extra precision.
20//
21// Lossy subnormals mode without normalization result in a loss of accuracy.
22// This provides greater precision than a clamp of subnormals to 0.
23// If dataset excludes subnormals, it behavas as IEEE-754 compliant mode.
24//
25// The direct mode has a loss of 1 bit of accuracy compared to IEEE-754.
26//
27// V79 replaces the prior internal HVX floating point format for floating-point
28// arithmetic. The new internal HVX floating-point format yields results
29// identical to IEEE-754 round-to-even mode. The new format contains more bits
30// than IEEE-754, which optionally produces results with greater range and
31// accuracy. Only the HVX vector registers use the HVX floating-point format.
32// Memory maintains all floating-point data in IEEE-754 format,
33// and all loads/stores use the IEEE-754 format. A subset of HVX floating-point
34// operations transform IEEE-754 floating-point data to HVX floating-point data.
35// Subsequent HVX floating-point instructions may consume operands in the HVX
36// floating-point without conversion to IEEE-754, which allows for performant
37// & energy efficient code. The program does not need to switch between formats
38// continuously. The program must convert the HVX floating-point results to
39// IEEE-754 prior to storing to memory.
40
41// HVX floating-point achieves IEEE-754 compliance through normalization.
42// The program may skip normalization when faster calculation is desired, and
43// IEEE-754 compliance isn’t required. HVX floating-point contains two input
44// types: qf32, single precision floating point, and qf16, half precision
45// floating point. In Hexagon, IEEE-754 contains two input types: sf, single
46// precision floating point, and hf, half precision floating point.
47//
48// Only HVX floating-point source and destination instructions use HVX
49// floating-point values. Instructions specify the HVX floating-point format
50// with the qf16 and qf32 identifier. A source vector register will drop the
51// extended state of a HVX floating-point value when an instruction reads the
52// source vector register without the qf16 or qf32 identifier. A destination
53// vector register will reset its extended state when an instruction writes to
54// a vector register without the qf16 or qf32 identifier. When dropping the
55// extended state, the floating-point value loses accuracy. The program may
56// preserve the floating-point value by converting HVX floating-point values
57// to IEEE-754 values. Compiler must convert HVX floating-point values to
58// IEEE-754 values before using as an input to stores, permutes, shifts, and
59// any other operations that do not source the HVX floating-point format.
60//
61// Depending on the desired results, HVX floating-point operations may have
62// some requirements on the input sources. The HVX floating-point values
63// require normalization to achieve IEEE-754 compliance, while faster operations
64// may skip normalization. The program normalizes HVX floating-point values
65// before subsequent HVX floating-point operations, so the floating-point value
66// does not lose precision. The program also obtains results identical to
67// IEEE-754 by converting all HVX floating-point results to IEEE-754 format
68// before consumed in any subsequent operation. There are however cases where
69// this conversion is redundant, or the differences between IEEE-754 and HVX
70// floating-point may not be a concern.
71//
72// The conversion logic can be understood by the table below:
73//
74// ================================================================================================================================================
75// | | | |
76// | Inputs to add/subtarct | Inputs to
77// multiplication instuctions | Non-HVX floating
78// point | | instructions | | instruction
79// | | | | |
80// ===============================================================================================================================================|
81// Sources | IEEE- | HVX | HVX | sf | qf32 | qf32 | hf
82// | qf16 | qf16 | IEE-754 | HVX | HVX |
83// | 754 | floating | floating | | from | from | |
84// from | from | | floating | floating | | |
85// point | point | | mult | adder | | mult
86// | adder | | point | point | | | from |
87// from | | | | | | | |
88// from | from | | | multi | adder | |
89// | | | | | | mult |
90// adder | | | | | | | | | | |
91// | | |
92// ===============================================================================================================================================|
93// Strict | Direct | Convert | Convert | Normalize | Convert | Convert
94// | widening | Convert | Convert | Direct | Convert | Convert | IEEE-754
95// | Use | to | to | | to IEEE | to IEEE | multiply
96// | to IEEE, | to IEEE, | use | to | to | compliance | |
97// IEEE | IEEE | | then | then | then | widening
98// | widening | | IEEE | IEEE |
99// | | | | | normalize | normalize
100// | convert | multiply,| multiply,| | | |
101// | | | | | | | to IEEE
102// | convert | convert | | | | | |
103// | | | | | | to
104// IEEE | to IEEE | | | |
105// -----------------------------------------------------------------------------------------------------------------------------------------------|
106// IEEE-754 | Direct | Direct | Direct | Normalize | Direct | Normalize
107// | Widening | Direct | Widening | Direct | Convert | Convert | compliance
108// | Use | Use | Use | | use | | multiply
109// | use | multiply | use | to IEEE | to IEEE |
110// -----------------------------------------------------------------------------------------------------------------------------------------------|
111// Lossy | Direct | Direct | Direct | Direct | Direct | Normalize
112// | Direct | Direct | Widening | Direct | Convert | Convert | Subnormals
113// | Use | Use | Use | Use | use | | use |
114// use | multiply | use | to IEEE | to IEEE |
115// -----------------------------------------------------------------------------------------------------------------------------------------------|
116// Direct | Direct | Direct | Direct | Direct | Direct | Direct |
117// Direct | Direct | Direct | Direct | Direct | Direct | Lossy |
118// Use | Use | Use | Use | use | use | use |
119// use | use | use | use | use |
120// -----------------------------------------------------------------------------------------------------------------------------------------------|
121//
122// For v81, the normalization sequence changes. Instead of multiplying 0
123// and -0, a simple copy operation normalizes the unnormal value. Both
124// qf and IEEE-754 value can be unnormal.
125// Additionally for v81, we have two new vsub instructions which are handled.
126
127#define HEXAGON_XQFLOAT_GENERATOR "XQFloat Generator pass"
128
129#include "Hexagon.h"
130#include "HexagonInstrInfo.h"
131#include "HexagonSubtarget.h"
132#include "HexagonTargetMachine.h"
133#include "llvm/ADT/SmallPtrSet.h"
134#include "llvm/ADT/SmallVector.h"
135#include "llvm/ADT/Statistic.h"
141#include "llvm/CodeGen/Passes.h"
142#include "llvm/IR/DebugLoc.h"
143#include "llvm/Pass.h"
145#include "llvm/Support/Debug.h"
147#include <vector>
148
149#define DEBUG_TYPE "hexagon-xqf-gen"
150
151using namespace llvm;
152
154
155// Master flag to enable XQF generations
156cl::opt<bool> EnableHVXXQFloat("enable-xqf-gen", cl::init(false),
157 cl::desc("Enable XQFloat generations"));
158// Master flag to remove extraneous qf to sf/hf conversions
160 EnableConversionsRemoval("enable-rem-conv", cl::init(false),
161 cl::desc("Enable extraneous conversions removal"));
162
163// Diagnostic flags
164cl::opt<bool> PrintDebug("debug-print", cl::init(false),
165 cl::desc("Print function mir after transformation"));
166// This vector contains the opcodes which generate qf32 from add/subtract
167static constexpr unsigned XQFPAdd32[] = {
168 // vector add instructions
169 Hexagon::V6_vadd_sf, Hexagon::V6_vadd_qf32, Hexagon::V6_vadd_qf32_mix,
170
171 // vector subtract instructions
172 Hexagon::V6_vsub_qf32, Hexagon::V6_vsub_qf32_mix, Hexagon::V6_vsub_sf,
173 Hexagon::V6_vsub_sf_mix};
174
175// This vector contains the opcodes which generate qf16 from add/subtract
176static constexpr unsigned XQFPAdd16[] = {
177 // vector add instructions
178 Hexagon::V6_vadd_hf, Hexagon::V6_vadd_qf16, Hexagon::V6_vadd_qf16_mix,
179
180 // vector subtract intrutions
181 Hexagon::V6_vsub_hf, Hexagon::V6_vsub_qf16, Hexagon::V6_vsub_qf16_mix,
182 Hexagon::V6_vsub_hf_mix};
183
184// This vector contains the opcodes which generate qf32 from multiplication
185static constexpr unsigned XQFPMult32[] = {
186 Hexagon::V6_vmpy_qf32, Hexagon::V6_vmpy_qf32_qf16, Hexagon::V6_vmpy_qf32_hf,
187 Hexagon::V6_vmpy_qf32_sf, Hexagon::V6_vmpy_qf32_mix_hf};
188// This vector contains the opcodes which generate qf16 from multiplication
189static constexpr unsigned XQFPMult16[] = {Hexagon::V6_vmpy_qf16,
190 Hexagon::V6_vmpy_qf16_hf,
191 Hexagon::V6_vmpy_qf16_mix_hf};
192
193namespace llvm {
196} // namespace llvm
197
198namespace {
199
200struct HexagonXQFloatGenerator : public MachineFunctionPass {
201public:
202 static char ID;
203 HexagonXQFloatGenerator() : MachineFunctionPass(ID) {}
204
205 bool runOnMachineFunction(MachineFunction &MF) override;
206
207 StringRef getPassName() const override { return HEXAGON_XQFLOAT_GENERATOR; }
208
209 void getAnalysisUsage(AnalysisUsage &AU) const override {
211 }
212
213private:
214 // Handle each XQF optimization level
215 bool HandleStrictIEEE(MachineFunction &);
216 bool HandleCompliantIEEE(MachineFunction &);
217 bool HandleLossySubnormals(MachineFunction &);
218 bool HandleLossyLegacy(MachineFunction &);
219
220 // Checkers functions for input operands
221 bool checkIfInputFromAdder32(Register Reg);
222 bool checkIfInputFromAdder16(Register Reg);
223 bool checkIfInputFromMult32(Register Reg);
224 bool checkIfInputFromMult16(Register Reg);
225 bool deleteList();
226
227 // Helper functions for conversion/normalization/widening
228 bool widenMultiplicationInputF16(MachineInstr &, Register &, Register &,
229 Register &, bool);
230 bool widenMultiplicationInputF16Rt(MachineInstr &, Register &, Register &,
231 Register &);
232 void widenMultiplyInputHF(MachineInstr &, Register &, Register &, Register &);
233 bool normalizeMultiplicationInputF32(MachineInstr &, Register &, Register &,
234 Register &, Register &, bool &);
235 void normalizeMultiplicationInputSF(MachineInstr &, Register &, Register &,
236 Register &, Register &, bool &);
237 bool convertNormalizeMultOp32(MachineInstr &, Register &, Register &,
238 Register &, Register &, bool &);
239 bool convertWidenMultOp16(MachineInstr &, Register &, Register &, Register &,
240 bool);
241 bool convertWidenMultOp32(MachineInstr &, Register &, Register &, Register &,
242 bool);
243 void createPrologInstructions(MachineInstr &, Register &);
244 bool convertAddOpToIEEE16(MachineInstr &, Register &, Register &, Register &,
245 bool, bool, bool);
246 bool convertAddOpToIEEE32(MachineInstr &, Register &, Register &, Register &,
247 bool, bool, bool);
248 void generateQF16FromQF32(MachineInstr &, Register &, Register &);
249 bool convertIfInputToNonHVX(MachineInstr &, bool);
250 void createConvertInstr(MachineInstr *, Register &, Register &, bool);
251
252 // V81 specific normalization function
253 bool V81normalizeMultF32(MachineInstr &, Register &, Register &, Register &,
254 bool, bool, bool);
255
256 const HexagonSubtarget *HST = nullptr;
257 const HexagonInstrInfo *HII = nullptr;
258 MachineRegisterInfo *MRI = nullptr;
259
261 OriginalMI; // Hold the instructions to be deleted
262};
263
264// Print machine function
265static void debug_print([[maybe_unused]] MachineFunction &MF) {
266 dbgs() << "\n=== Printing function ===\n";
267#ifndef NDEBUG
268 for (MachineBasicBlock &MBB : MF)
269 MBB.dump();
270#endif // NDEBUG
271}
272
273// This class removes redundant vector convert instructions from qf to hf/sf.
274// Additionally, it relaces use of sf/hf registers with qf types.
275// The resulting code is complete without dangling instructions.
276// FIXME: Liveness is not preserved.
277class VectorConvertRemove {
278
279public:
280 VectorConvertRemove(MachineFunction &_MF, MachineRegisterInfo *_MRI,
281 const HexagonSubtarget *_HST)
282 : MF(_MF), MRI(_MRI), HST(_HST) {
283 HII = HST->getInstrInfo();
284 }
285
286 void run();
287
288private:
289 MachineFunction &MF;
290 MachineRegisterInfo *MRI;
291 const HexagonSubtarget *HST;
292 const HexagonInstrInfo *HII;
293
294 enum Operation { Add16, Add32, Sub16, Sub32, Mul16, Mul32 };
295 // Helper functions
296 void handle_addsub_sf_sf(MachineInstr &, Register &, Register &, Register &,
297 bool);
298 void handle_addsub_qf_sf(MachineInstr &, Register &, Register &, Register &,
299 bool);
300 void handle_addsubmul_hf_hf(MachineInstr &, Register &, Register &,
301 Register &, Operation);
302 void handle_addsubmul_qf_hf(MachineInstr &, Register &, Register &,
303 Register &, Operation);
304 void handle_qf32_mul_sf_sf(MachineInstr &, Register &, Register &,
305 Register &);
306 bool checkHVXUses32(MachineInstr *, MachineInstr *);
307 bool checkHVXUses16(MachineInstr *, MachineInstr *);
308 unsigned getOperation(Operation, bool, bool);
309
310 // List which holds conversion instructions
311 SmallPtrSet<MachineInstr *, 16> ConvInstrList;
312 // List which holds qf handling instructions
313 std::vector<MachineInstr *> SfHfInstrList;
314};
315
316// both : both operands are replaced
317unsigned VectorConvertRemove::getOperation(Operation Op, bool firstOpQf,
318 bool secOpQf) {
319 if (firstOpQf && secOpQf) {
320 switch (Op) {
321 case Add16:
322 return Hexagon::V6_vadd_qf16;
323 case Add32:
324 return Hexagon::V6_vadd_qf32;
325 case Sub16:
326 return Hexagon::V6_vsub_qf16;
327 case Sub32:
328 return Hexagon::V6_vsub_qf32;
329 case Mul16:
330 return Hexagon::V6_vmpy_qf16;
331 case Mul32:
332 return Hexagon::V6_vmpy_qf32_qf16;
333 }
334 } else if (firstOpQf) {
335 switch (Op) {
336 case Add16:
337 return Hexagon::V6_vadd_qf16_mix;
338 case Add32:
339 return Hexagon::V6_vadd_qf32_mix;
340 case Sub16:
341 return Hexagon::V6_vsub_qf16_mix;
342 case Sub32:
343 return Hexagon::V6_vsub_qf32_mix;
344 case Mul16:
345 return Hexagon::V6_vmpy_qf16_mix_hf;
346 case Mul32:
347 return Hexagon::V6_vmpy_qf32_mix_hf;
348 }
349 } else if (secOpQf) {
350 switch (Op) {
351 case Sub16:
352 return Hexagon::V6_vsub_hf_mix;
353 case Sub32:
354 return Hexagon::V6_vsub_sf_mix;
355 default:
356 break;
357 }
358 } else {
359 }
360 llvm_unreachable("Unknown opcode and operand combination!");
361}
362
363// Return false if there are multiple instructions where the qf32 is used
364// other than the instruction for which it is called
365bool VectorConvertRemove::checkHVXUses32(MachineInstr *MI,
366 MachineInstr *UseMI) {
367 Register convReg = MI->getOperand(0).getReg();
368 // Iterate over all uses of the Def we are analyzing
369 for (MachineInstr &UMI : MRI->use_instructions(convReg)) {
370 if (&UMI == UseMI)
371 continue;
372 // Since the convert cannot be deleted, we set the operand as NOT kill
373 MI->getOperand(1).setIsKill(false);
374 return false;
375 }
376 return true;
377}
378
379// Return false if there are multiple instructions where the qf16 is used
380// other than the instruction for which it is called
381bool VectorConvertRemove::checkHVXUses16(MachineInstr *MI,
382 MachineInstr *UseMI) {
383 Register convReg = MI->getOperand(0).getReg();
384 // Iterate over all uses of the Def we are analyzing
385 for (MachineInstr &UMI : MRI->use_instructions(convReg)) {
386 if (&UMI == UseMI)
387 continue;
388 // Since the convert cannot be deleted, we set the operand as NOT kill
389 MI->getOperand(1).setIsKill(false);
390 return false;
391 }
392 return true;
393}
394
395// Removes converts feeding to op(sf,sf), and replaces its sf operands with qf
396void VectorConvertRemove::handle_addsub_sf_sf(MachineInstr &MI, Register &Reg1,
397 Register &Reg2, Register &Dest,
398 bool isAdd) {
399
400 MachineBasicBlock &MBB = *MI.getParent();
401 const DebugLoc &DL = MI.getDebugLoc();
402
403 bool firstConv = false, secConv = false;
404 bool DefOp1_del = false, DefOp2_del = false;
405 Register Src1, Src2;
406
407 MachineInstr *DefOp1 = MRI->getVRegDef(Reg1);
408 MachineInstr *DefOp2 = MRI->getVRegDef(Reg2);
409 // check if the first operand is from a convert operation
410 if (DefOp1->getOpcode() == Hexagon::V6_vconv_sf_qf32) {
411 if (checkHVXUses32(DefOp1, &MI))
412 DefOp1_del = true;
413 Src1 = DefOp1->getOperand(1).getReg();
414 firstConv = true;
415 }
416
417 // check if the second operand is from a convert operation
418 if (DefOp2->getOpcode() == Hexagon::V6_vconv_sf_qf32) {
419 if (checkHVXUses32(DefOp2, &MI))
420 DefOp2_del = true;
421 Src2 = DefOp2->getOperand(1).getReg();
422 secConv = true;
423 }
424
425 if (firstConv && secConv) {
426 BuildMI(MBB, MI, DL,
427 HII->get(getOperation(isAdd ? Operation::Add32 : Operation::Sub32,
428 true, true)),
429 Dest)
430 .addReg(Src1)
431 .addReg(Src2);
432 SfHfInstrList.push_back(&MI);
433 } else if (firstConv) {
434 BuildMI(MBB, MI, DL,
435 HII->get(getOperation(isAdd ? Operation::Add32 : Operation::Sub32,
436 true, false)),
437 Dest)
438 .addReg(Src1)
439 .addReg(Reg2);
440 SfHfInstrList.push_back(&MI);
441 } else if (secConv) {
442 // For v79, there is no provision for 2nd op being qf for add/sub
443 if (HST->useHVXV81Ops()) {
444 if (isAdd)
445 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), Dest)
446 .addReg(Src2)
447 .addReg(Reg1);
448 else
449 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vsub_sf_mix), Dest)
450 .addReg(Reg1)
451 .addReg(Src2);
452 SfHfInstrList.push_back(&MI);
453 // For v79, there is no provision for 2nd op being qf for add/sub. Since
454 // add is commutative, the ops can be rotated.
455 } else if (HST->useHVXV79Ops()) {
456 // for vadd we interchange the ops, for vsub we ignore
457 if (isAdd) {
458 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), Dest)
459 .addReg(Src2)
460 .addReg(Reg1);
461 SfHfInstrList.push_back(&MI);
462 } else // don't delete the convert instruction for vsub
463 DefOp2_del = false;
464 }
465 }
466
467 if (DefOp1_del)
468 ConvInstrList.insert(DefOp1);
469 if (DefOp2_del)
470 ConvInstrList.insert(DefOp2);
471}
472
473// Removes converts feeding to op(hf,hf), and replaces its hf operands with qf
474void VectorConvertRemove::handle_addsubmul_hf_hf(MachineInstr &MI,
475 Register &Reg1, Register &Reg2,
476 Register &Dest, Operation Op) {
477
478 MachineBasicBlock &MBB = *MI.getParent();
479 const DebugLoc &DL = MI.getDebugLoc();
480
481 bool firstConv = false, secConv = false;
482 bool DefOp1_del = false, DefOp2_del = false;
483 bool isSub = Op == Operation::Sub16;
484 Register Src1, Src2;
485
486 MachineInstr *DefOp1 = MRI->getVRegDef(Reg1);
487 MachineInstr *DefOp2 = MRI->getVRegDef(Reg2);
488 // check if the first operand is from a convert operation
489 if (DefOp1->getOpcode() == Hexagon::V6_vconv_hf_qf16) {
490 if (checkHVXUses16(DefOp1, &MI))
491 DefOp1_del = true;
492 Src1 = DefOp1->getOperand(1).getReg();
493 firstConv = true;
494 }
495
496 // check if the second operand is from a convert operation
497 if (DefOp2->getOpcode() == Hexagon::V6_vconv_hf_qf16) {
498 if (checkHVXUses16(DefOp2, &MI))
499 DefOp2_del = true;
500 Src2 = DefOp2->getOperand(1).getReg();
501 secConv = true;
502 }
503
504 if (firstConv && secConv) {
505 BuildMI(MBB, MI, DL, HII->get(getOperation(Op, true, true)), Dest)
506 .addReg(Src1)
507 .addReg(Src2);
508 SfHfInstrList.push_back(&MI);
509 } else if (firstConv) {
510 BuildMI(MBB, MI, DL, HII->get(getOperation(Op, true, false)), Dest)
511 .addReg(Src1)
512 .addReg(Reg2);
513 SfHfInstrList.push_back(&MI);
514 } else if (secConv) {
515 // For v81, we interchange the ops for vadd/vmul
516 // for vsub we use qf as second operand
517 if (HST->useHVXV81Ops()) {
518 if (!isSub)
519 BuildMI(MBB, MI, DL, HII->get(getOperation(Op, true, false)), Dest)
520 .addReg(Src2)
521 .addReg(Reg1);
522 else
523 BuildMI(MBB, MI, DL, HII->get(getOperation(Op, false, true)), Dest)
524 .addReg(Reg1)
525 .addReg(Src2);
526 SfHfInstrList.push_back(&MI);
527 } else if (HST->useHVXV79Ops()) {
528 // for vadd/vmul we interchange the ops, for vsub we ignore
529 if (!isSub) {
530 BuildMI(MBB, MI, DL, HII->get(getOperation(Op, true, false)), Dest)
531 .addReg(Src2)
532 .addReg(Reg1);
533 SfHfInstrList.push_back(&MI);
534 } else // don't delete the convert instruction for vsub
535 DefOp2_del = false;
536 }
537 }
538
539 if (DefOp1_del)
540 ConvInstrList.insert(DefOp1);
541 if (DefOp2_del)
542 ConvInstrList.insert(DefOp2);
543}
544
545// Removes converts feeding to op(qf,sf), and replaces its sf operands with qf
546void VectorConvertRemove::handle_addsub_qf_sf(MachineInstr &MI, Register &Reg1,
547 Register &Reg2, Register &Dest,
548 bool isAdd) {
549 MachineBasicBlock &MBB = *MI.getParent();
550 const DebugLoc &DL = MI.getDebugLoc();
551 Register Src;
552 bool conv = false;
553
554 MachineInstr *DefOp = MRI->getVRegDef(Reg2);
555 // check if the second operand is from a convert operation
556 if (DefOp->getOpcode() == Hexagon::V6_vconv_sf_qf32) {
557 if (checkHVXUses32(DefOp, &MI))
558 ConvInstrList.insert(DefOp);
559 Src = DefOp->getOperand(1).getReg();
560 conv = true;
561 }
562
563 if (conv) {
564 BuildMI(MBB, MI, DL,
565 HII->get(isAdd ? Hexagon::V6_vadd_qf32 : Hexagon::V6_vsub_qf32),
566 Dest)
567 .addReg(Reg1)
568 .addReg(Src);
569 SfHfInstrList.push_back(&MI);
570 }
571}
572
573// Removes converts feeding to op(qf,hf), and replaces its hf operands with qf
574void VectorConvertRemove::handle_addsubmul_qf_hf(MachineInstr &MI,
575 Register &Reg1, Register &Reg2,
576 Register &Dest, Operation Op) {
577 MachineBasicBlock &MBB = *MI.getParent();
578 const DebugLoc &DL = MI.getDebugLoc();
579 Register Src;
580 bool conv = false;
581
582 MachineInstr *DefOp = MRI->getVRegDef(Reg2);
583 // check if the second operand is from a convert operation
584 if (DefOp->getOpcode() == Hexagon::V6_vconv_hf_qf16) {
585 if (checkHVXUses16(DefOp, &MI))
586 ConvInstrList.insert(DefOp);
587 Src = DefOp->getOperand(1).getReg();
588 conv = true;
589 }
590
591 if (conv) {
592 BuildMI(MBB, MI, DL, HII->get(getOperation(Op, true, true)), Dest)
593 .addReg(Reg1)
594 .addReg(Src);
595 SfHfInstrList.push_back(&MI);
596 }
597}
598
599// Removes converts feeding to op(sf,sf), and replaces its sf operands with qf
600void VectorConvertRemove::handle_qf32_mul_sf_sf(MachineInstr &MI,
601 Register &Reg1, Register &Reg2,
602 Register &Dest) {
603 MachineBasicBlock &MBB = *MI.getParent();
604 const DebugLoc &DL = MI.getDebugLoc();
605 Register Src1, Src2;
606 bool firstConv = false, secConv = false;
607
608 MachineInstr *DefOp1 = MRI->getVRegDef(Reg1);
609 MachineInstr *DefOp2 = MRI->getVRegDef(Reg2);
610
611 if (DefOp1->getOpcode() == Hexagon::V6_vconv_sf_qf32 &&
612 DefOp2->getOpcode() == Hexagon::V6_vconv_sf_qf32) {
613 // If yes, we can remove the convert
614 if (checkHVXUses32(DefOp1, &MI) && checkHVXUses32(DefOp2, &MI)) {
615 ConvInstrList.insert(DefOp1);
616 ConvInstrList.insert(DefOp2);
617 }
618 Src1 = DefOp1->getOperand(1).getReg();
619 Src2 = DefOp2->getOperand(1).getReg();
620 firstConv = true;
621 secConv = true;
622 }
623
624 // If both are true, then only replace with qf32 = vmpy(qf32, qf32)
625 if (firstConv && secConv) {
626 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
627 .addReg(Src1)
628 .addReg(Src2);
629 SfHfInstrList.push_back(&MI);
630 }
631}
632
633void VectorConvertRemove::run() {
634 for (auto &MBB : MF) {
635 for (auto &MI : MBB) {
636 // Skip if the instruction does not have two operands,
637 // or is a bundle instruction
638 // or is a debug instruction
639 if (MI.getNumOperands() != 3 || MI.isDebugInstr())
640 continue;
641
642 auto Op1 = MI.getOperand(1);
643 if (!Op1.isReg())
644 continue;
645 auto Op2 = MI.getOperand(2);
646 if (!Op2.isReg())
647 continue;
648 auto Op0 = MI.getOperand(0);
649 if (!Op0.isReg())
650 continue;
651 Register Reg1 = Op1.getReg();
652 Register Reg2 = Op2.getReg();
653 Register Dest = Op0.getReg();
654
655 switch (MI.getOpcode()) {
656 // TODO Handle the new vsub instructions
657 // qf32 = vadd(sf, sf)
658 case Hexagon::V6_vadd_sf:
659 handle_addsub_sf_sf(MI, Reg1, Reg2, Dest, true);
660 break;
661 // qf32 = vsub(sf, sf)
662 case Hexagon::V6_vsub_sf:
663 handle_addsub_sf_sf(MI, Reg1, Reg2, Dest, false);
664 break;
665 // qf32 = vadd(qf32, sf)
666 case Hexagon::V6_vadd_qf32_mix:
667 handle_addsub_qf_sf(MI, Reg1, Reg2, Dest, true);
668 break;
669 // qf32 = vsub(qf32, sf)
670 case Hexagon::V6_vsub_qf32_mix:
671 handle_addsub_qf_sf(MI, Reg1, Reg2, Dest, false);
672 break;
673 // qf16 = vadd(hf, hf)
674 case Hexagon::V6_vadd_hf:
675 handle_addsubmul_hf_hf(MI, Reg1, Reg2, Dest, Operation::Add16);
676 break;
677 // qf16 = vsub(hf, hf)
678 case Hexagon::V6_vsub_hf:
679 handle_addsubmul_hf_hf(MI, Reg1, Reg2, Dest, Operation::Sub16);
680 break;
681 // qf16 = vadd(qf16, hf)
682 case Hexagon::V6_vadd_qf16_mix:
683 handle_addsubmul_qf_hf(MI, Reg1, Reg2, Dest, Operation::Add16);
684 break;
685 // qf16 = vsub(qf16, hf)
686 case Hexagon::V6_vsub_qf16_mix:
687 handle_addsubmul_qf_hf(MI, Reg1, Reg2, Dest, Operation::Sub16);
688 break;
689 // qf32 = vmpy(sf, sf)
690 case Hexagon::V6_vmpy_qf32_sf:
691 handle_qf32_mul_sf_sf(MI, Reg1, Reg2, Dest);
692 break;
693 // qf32 = vmpy(hf, hf)
694 case Hexagon::V6_vmpy_qf32_hf:
695 handle_addsubmul_hf_hf(MI, Reg1, Reg2, Dest, Operation::Mul32);
696 break;
697 // qf32 = vmpy(qf16, hf)
698 case Hexagon::V6_vmpy_qf32_mix_hf:
699 handle_addsubmul_qf_hf(MI, Reg1, Reg2, Dest, Operation::Mul32);
700 break;
701 // qf16 = vmpy(hf, hf)
702 case Hexagon::V6_vmpy_qf16_hf:
703 handle_addsubmul_hf_hf(MI, Reg1, Reg2, Dest, Operation::Mul16);
704 break;
705 // qf16 = vmpy(qf16, hf)
706 case Hexagon::V6_vmpy_qf16_mix_hf:
707 handle_addsubmul_qf_hf(MI, Reg1, Reg2, Dest, Operation::Mul16);
708 break;
709 default:
710 break;
711 }
712 }
713 }
714
715 // Delete the vadd/vsub/vmpy instructions
716 for (MachineInstr *sfhfMI : SfHfInstrList) {
717 LLVM_DEBUG(dbgs() << "deleting sf/hf instruction ");
718 LLVM_DEBUG(sfhfMI->dump());
719 sfhfMI->eraseFromParent();
720 }
721 // Delete conversion instructions
722 for (MachineInstr *convMI : ConvInstrList) {
723 LLVM_DEBUG(dbgs() << "deleting conversion instruction");
724 LLVM_DEBUG(convMI->dump());
725 convMI->eraseFromParent();
726 }
727}
728
729char HexagonXQFloatGenerator::ID = 0;
730
731} // namespace
732
733INITIALIZE_PASS(HexagonXQFloatGenerator, "hexagon-xqfloat-generator",
734 HEXAGON_XQFLOAT_GENERATOR, false, false)
735
737 return new HexagonXQFloatGenerator();
738}
739
740// Returns true if qf32 input is from an adder/subtract unit
741bool HexagonXQFloatGenerator::checkIfInputFromAdder32(Register Reg) {
742 MachineInstr *Def = MRI->getVRegDef(Reg);
743 if (!Def)
744 return false;
745
746 // If the definition is a copy, we need to analyze its def again
747 if (Def->getOpcode() == TargetOpcode::COPY) {
748 Register SrcReg = Def->getOperand(1).getReg();
749 if (SrcReg.isValid())
750 return checkIfInputFromAdder32(SrcReg);
751 return false;
752 } else if (Def->getOpcode() == TargetOpcode::REG_SEQUENCE) {
753 Register SrcReg1 = Def->getOperand(1).getReg();
754 Register SrcReg2 = Def->getOperand(2).getReg();
755 bool isTrue = false;
756 if (SrcReg1.isValid())
757 isTrue = checkIfInputFromAdder32(SrcReg1);
758 if (SrcReg2.isValid())
759 isTrue |= checkIfInputFromAdder32(SrcReg2);
760 return isTrue;
761 } else
762 return llvm::is_contained(XQFPAdd32, Def->getOpcode());
763}
764
765// Returns true if qf16 input is from an adder/subtract unit
766bool HexagonXQFloatGenerator::checkIfInputFromAdder16(Register Reg) {
767 MachineInstr *Def = MRI->getVRegDef(Reg);
768 if (!Def)
769 return false;
770
771 // if the definition is a copy, we need to analyze its def again
772 if (Def->getOpcode() == TargetOpcode::COPY) {
773 Register SrcReg = Def->getOperand(1).getReg();
774 if (SrcReg.isValid())
775 return checkIfInputFromAdder16(SrcReg);
776 return false;
777 } else
778 return llvm::is_contained(XQFPAdd16, Def->getOpcode());
779}
780
781// Returns true if qf32 input is from a multiplier unit
782bool HexagonXQFloatGenerator::checkIfInputFromMult32(Register Reg) {
783 MachineInstr *Def = MRI->getVRegDef(Reg);
784 if (!Def)
785 return false;
786
787 // if the definition is a copy, we need to analyze its def again
788 if (Def->getOpcode() == TargetOpcode::COPY) {
789 Register SrcReg = Def->getOperand(1).getReg();
790 if (SrcReg.isValid())
791 return checkIfInputFromMult32(SrcReg);
792 return false;
793 } else if (Def->getOpcode() == TargetOpcode::REG_SEQUENCE) {
794 Register SrcReg1 = Def->getOperand(1).getReg();
795 Register SrcReg2 = Def->getOperand(2).getReg();
796 bool isTrue = false;
797 if (SrcReg1.isValid())
798 isTrue |= checkIfInputFromMult32(SrcReg1);
799 if (SrcReg2.isValid())
800 isTrue |= checkIfInputFromMult32(SrcReg2);
801 return isTrue;
802 } else
803 return llvm::is_contained(XQFPMult32, Def->getOpcode());
804}
805
806// Returns true if qf16 input is from a multiplier unit
807bool HexagonXQFloatGenerator::checkIfInputFromMult16(Register Reg) {
808 MachineInstr *Def = MRI->getVRegDef(Reg);
809 if (!Def)
810 return false;
811
812 // if the definition is a copy, we need to analyze its def again
813 if (Def->getOpcode() == TargetOpcode::COPY) {
814 Register SrcReg = Def->getOperand(1).getReg();
815 if (SrcReg.isValid())
816 return checkIfInputFromMult16(SrcReg);
817 return false;
818 } else
819 return llvm::is_contained(XQFPMult16, Def->getOpcode());
820}
821
822// Generates sf = qf32 instruction or hf = qf16 intruction
823void HexagonXQFloatGenerator::createConvertInstr(MachineInstr *UseMI,
824 Register &NewR, Register &OldR,
825 bool is32bit) {
826 const DebugLoc &DL = UseMI->getDebugLoc();
827 MachineBasicBlock *MBB = UseMI->getParent();
828 NewR = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
829 if (is32bit)
830 BuildMI(*MBB, *UseMI, DL, HII->get(Hexagon::V6_vconv_sf_qf32), NewR)
831 .addReg(OldR);
832 else
833 BuildMI(*MBB, *UseMI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), NewR)
834 .addReg(OldR);
835}
836
837// Generate HVX to IEEE conversion instruction for all non-HVX uses
838bool HexagonXQFloatGenerator::convertIfInputToNonHVX(MachineInstr &MI,
839 bool is32bit) {
840 Register NewR;
841 bool Changed = false;
842 ;
843 Register Dest = MI.getOperand(0).getReg();
844
845 // Iterate over all uses of the Def we are analyzing
846 for (auto &MO : make_range(MRI->use_begin(Dest), MRI->use_end())) {
847 MachineInstr *UseMI = MO.getParent();
848 // Omit if the use is a REG_SEQUENCE instruction, since the only
849 // use of REG_SEQUENCE in qf context is transforming to IEEE.
850 // Omit for use in DBG instructions.
851 // Omit for use in PHI instructions since PHI result can be used as a qf
852 // operand.
853 if (UseMI->getOpcode() == TargetOpcode::REG_SEQUENCE ||
854 UseMI->getOpcode() == TargetOpcode::DBG_VALUE ||
855 UseMI->getOpcode() == TargetOpcode::DBG_LABEL ||
856 UseMI->getOpcode() == TargetOpcode::PHI)
857 continue;
858
859 // If 32-bit operand
860 if (is32bit) {
861 // If it is a copy instruction, we need to analyze it uses
862 if (UseMI->getOpcode() == TargetOpcode::COPY)
863 return convertIfInputToNonHVX(*UseMI, /* 32 bit */ true);
864 if (!HII->usesQFOperand(UseMI)) {
865 createConvertInstr(UseMI, NewR, Dest, /*32 bit*/ true);
866 MO.setReg(NewR);
867 Changed = true;
868 }
869 // If 16-bit operand
870 } else {
871 // If it is a copy instruction, we need to analyze it uses
872 if (UseMI->getOpcode() == TargetOpcode::COPY)
873 return convertIfInputToNonHVX(*UseMI, /* 16 bit */ false);
874 if (!HII->usesQFOperand(UseMI)) {
875 createConvertInstr(UseMI, NewR, Dest, /*16 bit*/ false);
876 MO.setReg(NewR);
877 Changed = true;
878 }
879 }
880 }
881 return Changed;
882}
883
884// generate qf16 = qf32 via:
885// hf = qf32
886// V0 = #0
887// qf16 = vsub(hf,V0)
888void HexagonXQFloatGenerator::generateQF16FromQF32(MachineInstr &MI,
889 Register &Dest,
890 Register &SrcReg) {
891
892 MachineBasicBlock &MBB = *MI.getParent();
893 const DebugLoc &DL = MI.getDebugLoc();
894
895 Register convertReg = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
896 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf32), convertReg)
897 .addReg(SrcReg);
898 Register VR0 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
899 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vd0), VR0);
900
901 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vsub_hf), Dest)
902 .addReg(convertReg)
903 .addReg(VR0);
904}
905
906// Widen qf16 = vmpy(hf, hf) result unconditionally
907void HexagonXQFloatGenerator::widenMultiplyInputHF(MachineInstr &MI,
908 Register &Reg1,
909 Register &Reg2,
910 Register &Dest) {
911 Register output_mpy = MRI->createVirtualRegister(&Hexagon::HvxWRRegClass);
912 MachineBasicBlock &MBB = *MI.getParent();
913 const DebugLoc &DL = MI.getDebugLoc();
914
915 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
916 .addReg(Reg1)
917 .addReg(Reg2);
918 generateQF16FromQF32(MI, Dest, output_mpy);
919}
920
921// Widen vmpy(qf16, qf16/hf) result conditionally
922bool HexagonXQFloatGenerator::widenMultiplicationInputF16(MachineInstr &MI,
923 Register &Reg1,
924 Register &Reg2,
925 Register &Dest,
926 bool twoOps) {
927 bool firstconvert = false, secondconvert = false;
928 MachineBasicBlock &MBB = *MI.getParent();
929 const DebugLoc &DL = MI.getDebugLoc();
930
931 // We widen only that operand which comes from add/subtract unit.
932 if (checkIfInputFromAdder16(Reg1))
933 firstconvert = true;
934 // twoOps == true suggest 2nd operand is qf16, else it is hf
935 if (twoOps && checkIfInputFromAdder16(Reg2))
936 secondconvert = true;
937
938 Register widenReg;
939 // if either operands from add/subtract unit, we widen
940 if (twoOps) {
941 if (firstconvert || secondconvert) {
942 widenReg = MRI->createVirtualRegister(&Hexagon::HvxWRRegClass);
943 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_qf16), widenReg)
944 .addReg(Reg1)
945 .addReg(Reg2);
946 } else {
947 return false;
948 }
949 } else {
950 if (firstconvert) {
951 widenReg = MRI->createVirtualRegister(&Hexagon::HvxWRRegClass);
952 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), widenReg)
953 .addReg(Reg1)
954 .addReg(Reg2);
955 } else {
956 return false;
957 }
958 }
959
960 // generate qf16 = qf32
961 generateQF16FromQF32(MI, Dest, widenReg);
962
963 return true;
964}
965
966// Handle qf16 = vmpy(qf16, Rt)
967// For strict IEEE mode, convert the qf16 to IEEE before widening
968bool HexagonXQFloatGenerator::widenMultiplicationInputF16Rt(MachineInstr &MI,
969 Register &Reg1,
970 Register &Reg2,
971 Register &Dest) {
972 // If the first input is not from an adder, for strict-ieee check if
973 // input from mult, else return false.
974 if (!checkIfInputFromAdder16(Reg1)) {
975 if (QFloatModeValue == QFloatMode::StrictIEEE) {
976 if (!checkIfInputFromMult16(Reg1))
977 return false;
978 } else
979 return false;
980 }
981
982 MachineBasicBlock &MBB = *MI.getParent();
983 const DebugLoc &DL = MI.getDebugLoc();
984
985 Register VSplatReg = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
986 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_lvsplatw), VSplatReg).addReg(Reg2);
987
988 Register widenReg = MRI->createVirtualRegister(&Hexagon::HvxWRRegClass);
989 if (QFloatModeValue == QFloatMode::StrictIEEE) {
990 Register VHf = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
991 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), VHf).addReg(Reg1);
992 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_hf), widenReg)
993 .addReg(VHf)
994 .addReg(VSplatReg);
995 } else {
996 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), widenReg)
997 .addReg(Reg1)
998 .addReg(VSplatReg);
999 }
1000
1001 // generate qf16 = qf32
1002 generateQF16FromQF32(MI, Dest, widenReg);
1003 return true;
1004}
1005
1006// Handle qf32 = vadd/vsub(qf32/sf, qf32/sf)
1007// Handle vadd/vsub instructions with qf32 operands conditionally
1008// isAdd: true if an add instruction is analyzed, false for subtract
1009// isFirstOpQf: true if 1st operand is qf32 type, false if sf type
1010// isSecOpQf: true if 2nd operand is qf32 type, false if sf type
1011bool HexagonXQFloatGenerator::convertAddOpToIEEE32(
1012 MachineInstr &MI, Register &Reg1, Register &Reg2, Register &Dest,
1013 bool isAdd, bool isFirstOpQf, bool isSecOpQf) {
1014
1015 Register VR1;
1016 Register VR2;
1017 bool firstconvert = false, secondconvert = false;
1018 MachineBasicBlock &MBB = *MI.getParent();
1019 const DebugLoc &DL = MI.getDebugLoc();
1020
1021 // If the first operand is qf32 type
1022 if (isFirstOpQf) {
1023 // If the first operand is from add/sub/mul unit,
1024 // generate IEEE conversion instruction sf = qf32
1025 if (checkIfInputFromAdder32(Reg1) || checkIfInputFromMult32(Reg1)) {
1026 VR1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1027 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_sf_qf32), VR1)
1028 .addReg(Reg1);
1029 firstconvert = true;
1030 }
1031 }
1032
1033 // If 2nd operand is of qf32 type
1034 if (isSecOpQf) {
1035 // If the second operand is from add/sub/mul unit,
1036 // generate IEEE conversion instruction
1037 if (checkIfInputFromAdder32(Reg2) || checkIfInputFromMult32(Reg2)) {
1038 VR2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1039 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_sf_qf32), VR2)
1040 .addReg(Reg2);
1041 secondconvert = true;
1042 }
1043 }
1044
1045 // If both operands are qf32 type, use V6_v[add/sub]_sf instruction
1046 // If one of them is of sf type, use V6_v[add/sub]_qf32_mix instruction
1047 // Output is qf32
1048 if (isFirstOpQf && isSecOpQf) {
1049 if (firstconvert && secondconvert) {
1050 BuildMI(MBB, MI, DL,
1051 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1052 .addReg(VR1)
1053 .addReg(VR2);
1054 } else if (firstconvert) {
1055 if (isAdd)
1056 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), Dest)
1057 .addReg(Reg2)
1058 .addReg(VR1);
1059 // For vsub type, for v81 we use a different opcode,
1060 // for v79, we convert the 2nd op to IEEE too.
1061 else {
1062 if (HST->useHVXV81Ops())
1063 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vsub_sf_mix), Dest)
1064 .addReg(VR1)
1065 .addReg(Reg2);
1066 else {
1067 VR2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1068 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_sf_qf32), VR2)
1069 .addReg(Reg2);
1070 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vsub_sf), Dest)
1071 .addReg(VR1)
1072 .addReg(VR2);
1073 }
1074 }
1075 } else if (secondconvert) {
1076 BuildMI(MBB, MI, DL,
1077 HII->get(isAdd ? Hexagon::V6_vadd_qf32_mix
1078 : Hexagon::V6_vsub_qf32_mix),
1079 Dest)
1080 .addReg(Reg1)
1081 .addReg(VR2);
1082 } else { // none of the inputs is from an add/sub/mul unit
1083 return false;
1084 }
1085 // handle vadd/vsub when the 1st op of original instruction is qf type
1086 } else if (isFirstOpQf) {
1087 if (firstconvert)
1088 BuildMI(MBB, MI, DL,
1089 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1090 .addReg(VR1)
1091 .addReg(Reg2);
1092 else
1093 return false;
1094 // handle vadd/vsub when the 2nd op of original instruction is qf type
1095 } else if (isSecOpQf) {
1096 if (secondconvert)
1097 BuildMI(MBB, MI, DL,
1098 HII->get(isAdd ? Hexagon::V6_vadd_sf : Hexagon::V6_vsub_sf), Dest)
1099 .addReg(Reg1)
1100 .addReg(VR2);
1101 else
1102 return false;
1103 } else
1104 return false;
1105 return true;
1106}
1107
1108// Handle qf16 = vadd/vsub(qf16, qf16/hf)
1109// Handle vadd/vsub instructions with qf16 operands conditionally
1110// isAdd: true if an add instruction is analyzed, false for subtract
1111// isFirstOpQf: true if 1st operand is qf16 type, false if hf type
1112// isSecOpQf: true if 2nd operand is qf16 type, false if hf type
1113bool HexagonXQFloatGenerator::convertAddOpToIEEE16(
1114 MachineInstr &MI, Register &Reg1, Register &Reg2, Register &Dest,
1115 bool isAdd, bool isFirstOpQf, bool isSecOpQf) {
1116
1117 MachineBasicBlock &MBB = *MI.getParent();
1118 const DebugLoc &DL = MI.getDebugLoc();
1119 Register VR1;
1120 Register VR2;
1121 bool firstconvert = false, secondconvert = false;
1122
1123 // If the first qf16 operand is from add/sub/mul unit,
1124 // generate IEEE conversion instruction
1125 if (isFirstOpQf) {
1126 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1127 VR1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1128 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), VR1)
1129 .addReg(Reg1);
1130 firstconvert = true;
1131 }
1132 }
1133 if (isSecOpQf) {
1134 // If the second operand is from add/sub/mul unit,
1135 // generate IEEE conversion instruction
1136 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1137 VR2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1138 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), VR2)
1139 .addReg(Reg2);
1140 secondconvert = true;
1141 }
1142 }
1143
1144 // If both operands are qf16 type, use V6_v[add/sub]_hf instruction
1145 // If one of them is of hf type, use V6_v[add/sub]_qf16_mix instruction
1146 // Output is qf16
1147 if (isFirstOpQf && isSecOpQf) {
1148 if (firstconvert && secondconvert) {
1149 BuildMI(MBB, MI, DL,
1150 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1151 .addReg(VR1)
1152 .addReg(VR2);
1153 } else if (firstconvert) {
1154 if (isAdd)
1155 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf16_mix), Dest)
1156 .addReg(Reg2)
1157 .addReg(VR1);
1158 // For vsub type, for v81 we use a different opcode,
1159 // for v79, we convert the 2nd op to IEEE too.
1160 else {
1161 if (HST->useHVXV81Ops())
1162 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vsub_hf_mix), Dest)
1163 .addReg(VR1)
1164 .addReg(Reg2);
1165 else {
1166 VR2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1167 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), VR2)
1168 .addReg(Reg2);
1169 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vsub_hf), Dest)
1170 .addReg(VR1)
1171 .addReg(VR2);
1172 }
1173 }
1174 } else if (secondconvert) {
1175 BuildMI(MBB, MI, DL,
1176 HII->get(isAdd ? Hexagon::V6_vadd_qf16_mix
1177 : Hexagon::V6_vsub_qf16_mix),
1178 Dest)
1179 .addReg(Reg1)
1180 .addReg(VR2);
1181 } else { // none of the inputs is from an add/sub/mul unit
1182 return false;
1183 }
1184 // handle vadd/vsub when the 1st op of original instruction is qf type
1185 } else if (isFirstOpQf) {
1186 if (firstconvert)
1187 BuildMI(MBB, MI, DL,
1188 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1189 .addReg(VR1)
1190 .addReg(Reg2);
1191 else
1192 return false;
1193 // handle vadd/vsub when the 2nd op of original instruction is qf type
1194 } else if (isSecOpQf) {
1195 if (secondconvert)
1196 BuildMI(MBB, MI, DL,
1197 HII->get(isAdd ? Hexagon::V6_vadd_hf : Hexagon::V6_vsub_hf), Dest)
1198 .addReg(Reg1)
1199 .addReg(VR2);
1200 else
1201 return false;
1202 } else
1203 return false;
1204 return true;
1205}
1206
1207// Create the prolog
1208// v0 = #0
1209// R1 = #0x80000000
1210// v1.sf = vsplat(R1)
1211// v2.sf = vmpy(v0.sf, v1.sf)
1212void HexagonXQFloatGenerator::createPrologInstructions(MachineInstr &MI,
1213 Register &R_mpy) {
1214
1215 MachineBasicBlock &MBB = *MI.getParent();
1216 const DebugLoc &DL = MI.getDebugLoc();
1217
1218 Register VR0 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1219 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vd0), VR0);
1220
1221 Register R_0 = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1222 BuildMI(MBB, MI, DL, HII->get(Hexagon::A2_tfrsi), R_0).addImm(0x80000000);
1223
1224 Register VR_0 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1225 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_lvsplatw), VR_0).addReg(R_0);
1226
1227 R_mpy = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1228 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_sf), R_mpy)
1229 .addReg(VR0)
1230 .addReg(VR_0);
1231}
1232
1233bool HexagonXQFloatGenerator::V81normalizeMultF32(
1234 MachineInstr &MI, Register &Reg1, Register &Reg2, Register &Dest,
1235 bool firstconvert, bool secondconvert, bool strictieee) {
1236 MachineBasicBlock &MBB = *MI.getParent();
1237 const DebugLoc &DL = MI.getDebugLoc();
1238 Register input_mpy1, input_mpy2;
1239
1240 auto Op =
1241 strictieee ? Hexagon::V6_vconv_qf32_sf : Hexagon::V6_vconv_qf32_qf32;
1242
1243 // Normalize both input operands
1244 if (firstconvert && secondconvert) {
1245 input_mpy1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1246 input_mpy2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1247
1248 BuildMI(MBB, MI, DL, HII->get(Op), input_mpy1).addReg(Reg1);
1249 BuildMI(MBB, MI, DL, HII->get(Op), input_mpy2).addReg(Reg2);
1250 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1251 .addReg(input_mpy1)
1252 .addReg(input_mpy2);
1253 }
1254 // Normalize only first operand
1255 else if (firstconvert) {
1256 input_mpy1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1257 BuildMI(MBB, MI, DL, HII->get(Op), input_mpy1).addReg(Reg1);
1258 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1259 .addReg(input_mpy1)
1260 .addReg(Reg2);
1261 }
1262 // Normalize only second operand
1263 else if (secondconvert) {
1264 input_mpy2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1265 BuildMI(MBB, MI, DL, HII->get(Op), input_mpy2).addReg(Reg2);
1266 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1267 .addReg(Reg1)
1268 .addReg(input_mpy2);
1269 } else
1270 // we do nothing if the inputs are not from adder/sub/mult unit
1271 return false;
1272
1273 return true;
1274}
1275
1276// Normalize qf32 = vmpy(sf, sf) instruction unconditionally
1277void HexagonXQFloatGenerator::normalizeMultiplicationInputSF(
1278 MachineInstr &MI, Register &Src1, Register &Src2, Register &Dest,
1279 Register &R_mpy, bool &PrologCreated) {
1280
1281 MachineBasicBlock &MBB = *MI.getParent();
1282 const DebugLoc &DL = MI.getDebugLoc();
1283
1284 if (HST->useHVXV81Ops()) {
1285 Register input_mpy1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1286 Register input_mpy2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1287
1288 // Normalize both inputs
1289 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_qf32_sf), input_mpy1)
1290 .addReg(Src1);
1291 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_qf32_sf), input_mpy2)
1292 .addReg(Src2);
1293 // Add the new vmpy
1294 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1295 .addReg(input_mpy1)
1296 .addReg(input_mpy2);
1297 return;
1298 }
1299
1300 if (!PrologCreated) {
1301 createPrologInstructions(MI, R_mpy);
1302 PrologCreated = true;
1303 }
1304
1305 Register input_mpy1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1306 Register input_mpy2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1307 // Normalize both inputs
1308 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1309 .addReg(R_mpy)
1310 .addReg(Src1);
1311 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1312 .addReg(R_mpy)
1313 .addReg(Src2);
1314 // Add the new vmpy
1315 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1316 .addReg(input_mpy1)
1317 .addReg(input_mpy2);
1318}
1319
1320// Convert and normalize qf32 = vmpy(qf32, qf32) instructions conditionally
1321bool HexagonXQFloatGenerator::convertNormalizeMultOp32(
1322 MachineInstr &MI, Register &Reg1, Register &Reg2, Register &Dest,
1323 Register &R_mpy, bool &PrologCreated) {
1324
1325 Register VR1, VR2;
1326 bool firstconvert = false, secondconvert = false;
1327 MachineBasicBlock &MBB = *MI.getParent();
1328 const DebugLoc &DL = MI.getDebugLoc();
1329
1330 // If the first operand is from add/subtract/multiply unit, generate IEEE
1331 // conversion instruction
1332 if (checkIfInputFromAdder32(Reg1) || checkIfInputFromMult32(Reg1)) {
1333 VR1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1334 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_sf_qf32), VR1).addReg(Reg1);
1335 firstconvert = true;
1336 }
1337
1338 if (checkIfInputFromAdder32(Reg2) || checkIfInputFromMult32(Reg2)) {
1339 VR2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1340 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_sf_qf32), VR2).addReg(Reg2);
1341 secondconvert = true;
1342 }
1343
1344 if (HST->useHVXV81Ops()) {
1345 if (firstconvert && secondconvert)
1346 return V81normalizeMultF32(MI, VR1, VR2, Dest, true, true, true);
1347 else if (firstconvert)
1348 return V81normalizeMultF32(MI, VR1, Reg2, Dest, true, false, true);
1349 else if (secondconvert)
1350 return V81normalizeMultF32(MI, Reg1, VR2, Dest, false, true, true);
1351 else
1352 return false;
1353 }
1354
1355 // create prolog if not already created
1356 if (!PrologCreated && (firstconvert || secondconvert)) {
1357 createPrologInstructions(MI, R_mpy);
1358 PrologCreated = true;
1359 }
1360
1361 Register input_mpy1, input_mpy2;
1362
1363 // Normalize both IEEE converts
1364 if (firstconvert && secondconvert) {
1365 input_mpy2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1366 input_mpy1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1367
1368 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1369 .addReg(R_mpy)
1370 .addReg(VR1);
1371 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1372 .addReg(R_mpy)
1373 .addReg(VR2);
1374 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1375 .addReg(input_mpy1)
1376 .addReg(input_mpy2);
1377 // Normalize only first operand
1378 } else if (firstconvert) {
1379 input_mpy1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1380
1381 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy1)
1382 .addReg(R_mpy)
1383 .addReg(VR1);
1384 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1385 .addReg(input_mpy1)
1386 .addReg(Reg2);
1387 // Normalize only second operand
1388 } else if (secondconvert) {
1389 input_mpy2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1390
1391 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32_mix), input_mpy2)
1392 .addReg(R_mpy)
1393 .addReg(VR2);
1394 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1395 .addReg(Reg1)
1396 .addReg(input_mpy2);
1397 } else {
1398 // we do nothing if the inputs are not fromadder/subtracter/multiplier unit
1399 return false;
1400 }
1401 return true;
1402}
1403
1404// Convert to IEEE and widen qf16 = vmpy(qf16/hf, qf16) conditionally
1405// Then convert qf32 to qf16
1406// twoOps: true if the first operand is qf type, false if hf type
1407bool HexagonXQFloatGenerator::convertWidenMultOp16(MachineInstr &MI,
1408 Register &Reg1,
1409 Register &Reg2,
1410 Register &Dest,
1411 bool twoOps) {
1412
1413 Register VR1, VR2, output_mpy;
1414 bool firstconvert = false,
1415 secondconvert = false; // normalize with hf or qf16 operands
1416 MachineBasicBlock &MBB = *MI.getParent();
1417 const DebugLoc &DL = MI.getDebugLoc();
1418
1419 // If the first operand is from add/sub/mul unit,
1420 // generate IEEE conversion instruction
1421 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1422 VR1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1423 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), VR1).addReg(Reg1);
1424 firstconvert = true;
1425 }
1426
1427 if (twoOps) {
1428 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1429 VR2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1430 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), VR2)
1431 .addReg(Reg2);
1432 secondconvert = true;
1433 }
1434 }
1435
1436 if (twoOps) {
1437 // Both operands have been converted to IEEE
1438 if (firstconvert && secondconvert) {
1439 output_mpy = MRI->createVirtualRegister(&Hexagon::HvxWRRegClass);
1440 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
1441 .addReg(VR1)
1442 .addReg(VR2);
1443 // Only one operand has been converted to IEEE
1444 } else if (firstconvert) {
1445 output_mpy = MRI->createVirtualRegister(&Hexagon::HvxWRRegClass);
1446 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), output_mpy)
1447 .addReg(Reg2)
1448 .addReg(VR1);
1449 } else if (secondconvert) {
1450 output_mpy = MRI->createVirtualRegister(&Hexagon::HvxWRRegClass);
1451 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), output_mpy)
1452 .addReg(Reg1)
1453 .addReg(VR2);
1454 } else {
1455 // Neither have to be transformed
1456 return false;
1457 }
1458 } else {
1459 if (firstconvert) {
1460 output_mpy = MRI->createVirtualRegister(&Hexagon::HvxWRRegClass);
1461 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_hf), output_mpy)
1462 .addReg(VR1)
1463 .addReg(Reg2);
1464 } else
1465 return false;
1466 }
1467
1468 // convert qf32 to qf16
1469 generateQF16FromQF32(MI, Dest, output_mpy);
1470
1471 return true;
1472}
1473
1474// Convert to IEEE and perform qf32 = vmpy(qf16/hf, qf16) conditionally
1475// Final output is qf32 type
1476bool HexagonXQFloatGenerator::convertWidenMultOp32(MachineInstr &MI,
1477 Register &Reg1,
1478 Register &Reg2,
1479 Register &Dest,
1480 bool twoOps) {
1481 Register VR1, VR2;
1482 bool firstconvert = false,
1483 secondconvert = false; // normalize with hf or qf16 operands
1484 MachineBasicBlock &MBB = *MI.getParent();
1485 const DebugLoc &DL = MI.getDebugLoc();
1486
1487 // If the first operand is from add/subtract/multiply unit, generate IEEE
1488 // conversion instruction
1489 if (checkIfInputFromAdder16(Reg1) || checkIfInputFromMult16(Reg1)) {
1490 VR1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1491 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), VR1).addReg(Reg1);
1492 firstconvert = true;
1493 }
1494
1495 if (twoOps) {
1496 if (checkIfInputFromAdder16(Reg2) || checkIfInputFromMult16(Reg2)) {
1497 VR2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1498 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vconv_hf_qf16), VR2)
1499 .addReg(Reg2);
1500 secondconvert = true;
1501 }
1502 }
1503
1504 if (twoOps) {
1505 // Both operands have been converted to IEEE
1506 if (firstconvert && secondconvert) {
1507 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_hf), Dest)
1508 .addReg(VR1)
1509 .addReg(VR2);
1510 // Only one operand has been converted to IEEE
1511 } else if (firstconvert) {
1512 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), Dest)
1513 .addReg(Reg2)
1514 .addReg(VR1);
1515 } else if (secondconvert) {
1516 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_mix_hf), Dest)
1517 .addReg(Reg1)
1518 .addReg(VR2);
1519 } else
1520 // Neither have to be transformed
1521 return false;
1522 } else {
1523 if (firstconvert)
1524 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32_hf), Dest)
1525 .addReg(VR1)
1526 .addReg(Reg2);
1527 else
1528 return false;
1529 }
1530
1531 return true;
1532}
1533
1534// Normalize instructions of type qf32 = vmpy(qf32, qf32)
1535bool HexagonXQFloatGenerator::normalizeMultiplicationInputF32(
1536 MachineInstr &MI, Register &Reg1, Register &Reg2, Register &Dest,
1537 Register &R_mpy, bool &PrologCreated) {
1538 bool firstconvert = false, secondconvert = false;
1539 MachineBasicBlock &MBB = *MI.getParent();
1540 const DebugLoc &DL = MI.getDebugLoc();
1541
1542 // We normalize only that operand which comes from add/subtract unit.
1543 if (checkIfInputFromAdder32(Reg1))
1544 firstconvert = true;
1545 if (checkIfInputFromAdder32(Reg2))
1546 secondconvert = true;
1547
1548 // v81 normalization
1549 if (HST->useHVXV81Ops())
1550 return V81normalizeMultF32(MI, Reg1, Reg2, Dest, firstconvert,
1551 secondconvert, false);
1552
1553 // create normalization operand conditionally for v79
1554 if ((!PrologCreated && (firstconvert || secondconvert))) {
1555 createPrologInstructions(MI, R_mpy);
1556 PrologCreated = true;
1557 }
1558
1559 Register input_mpy1, input_mpy2;
1560
1561 // Normalize both input operands
1562 if (firstconvert && secondconvert) {
1563 input_mpy2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1564 input_mpy1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1565
1566 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy1)
1567 .addReg(R_mpy)
1568 .addReg(Reg1);
1569 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy2)
1570 .addReg(R_mpy)
1571 .addReg(Reg2);
1572 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1573 .addReg(input_mpy1)
1574 .addReg(input_mpy2);
1575 // Normalize only first operand
1576 } else if (firstconvert) {
1577 input_mpy1 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1578
1579 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy1)
1580 .addReg(R_mpy)
1581 .addReg(Reg1);
1582 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1583 .addReg(input_mpy1)
1584 .addReg(Reg2);
1585 // Normalize only second operand
1586 } else if (secondconvert) {
1587 input_mpy2 = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1588
1589 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vadd_qf32), input_mpy2)
1590 .addReg(R_mpy)
1591 .addReg(Reg2);
1592 BuildMI(MBB, MI, DL, HII->get(Hexagon::V6_vmpy_qf32), Dest)
1593 .addReg(input_mpy2)
1594 .addReg(Reg1);
1595 } else {
1596 // we do nothing if the inputs are not from adder/subtracter/multiplier unit
1597 return false;
1598 }
1599
1600 return true;
1601}
1602
1603bool HexagonXQFloatGenerator::deleteList() {
1604 if (OriginalMI.empty())
1605 return false;
1606 bool Changed = false;
1607 for (MachineInstr *origMI : OriginalMI) {
1608 LLVM_DEBUG(dbgs() << "deleting redundant instruction");
1609 LLVM_DEBUG(origMI->dump());
1610 origMI->eraseFromParent();
1611 Changed = true;
1612 }
1613 OriginalMI.clear();
1614 return Changed;
1615}
1616
1617// Parent function to handle Loosy subnormal transformations
1618bool HexagonXQFloatGenerator::HandleLossySubnormals(MachineFunction &MF) {
1619 bool Changed = false;
1620 Register R_mpy;
1621 for (auto &MBB : MF) {
1622 bool PrologCreated = false;
1623 for (auto &MI : MBB) {
1624 Changed |= deleteList();
1625 // Skip if the instruction does not have two operands,
1626 // or is a bundle instruction
1627 // or is a debug instruction
1628 if (MI.getNumOperands() != 3 || MI.isDebugInstr())
1629 continue;
1630 auto Op1 = MI.getOperand(1);
1631 if (!Op1.isReg())
1632 continue;
1633 auto Op2 = MI.getOperand(2);
1634 if (!Op2.isReg())
1635 continue;
1636 auto Op0 = MI.getOperand(0);
1637 if (!Op0.isReg())
1638 continue;
1639 Register Reg1 = Op1.getReg();
1640 Register Reg2 = Op2.getReg();
1641 Register Dest = Op0.getReg();
1642
1643 // FIXME Do not process physical registers as operands
1644 if (!Reg1.isVirtual() || !Reg2.isVirtual() || !Dest.isVirtual())
1645 continue;
1646
1647 switch (MI.getOpcode()) {
1648 // qf32 = vmpy(qf32, qf32)
1649 // Normalize one or both input operands
1650 // if from add/sub unit
1651 case Hexagon::V6_vmpy_qf32:
1652 if (normalizeMultiplicationInputF32(MI, Reg1, Reg2, Dest, R_mpy,
1653 PrologCreated))
1654 OriginalMI.push_back(&MI);
1655 Changed |= convertIfInputToNonHVX(MI, true);
1656 break;
1657
1658 // qf16 = vmpy(qf16, qf16)
1659 // Widening multiply to qf32 and convert back to qf16
1660 // if any of the operands are from add/sub unit
1661 case Hexagon::V6_vmpy_qf16:
1662 if (widenMultiplicationInputF16(MI, Reg1, Reg2, Dest, true))
1663 OriginalMI.push_back(&MI);
1664 Changed |= convertIfInputToNonHVX(MI, false);
1665 break;
1666
1667 // qf16 = vmpy(qf16, Rt.hf)
1668 // Splat Rt to vector and then widening multiply
1669 // and then convert back to qf16
1670 // if first operand is from add/sub unit
1671 case Hexagon::V6_vmpy_rt_qf16:
1672 if (widenMultiplicationInputF16Rt(MI, Reg1, Reg2, Dest))
1673 OriginalMI.push_back(&MI);
1674 Changed |= convertIfInputToNonHVX(MI, false);
1675 break;
1676
1677 // qf16 = vmpy(qf16, hf)
1678 // Widening multiply to qf32 and convert back to qf16
1679 // if first operand is from add/sub unit
1680 case Hexagon::V6_vmpy_qf16_mix_hf:
1681 if (widenMultiplicationInputF16(MI, Reg1, Reg2, Dest, false))
1682 OriginalMI.push_back(&MI);
1683 Changed |= convertIfInputToNonHVX(MI, false);
1684 break;
1685 // Check if use of qf32 generating add/sub/mul instructions
1686 // are used as non-HVX operands.
1687 // If yes, convert the use to IEEE
1688 case Hexagon::V6_vadd_sf:
1689 case Hexagon::V6_vadd_qf32:
1690 case Hexagon::V6_vadd_qf32_mix:
1691 case Hexagon::V6_vsub_sf:
1692 case Hexagon::V6_vsub_qf32:
1693 case Hexagon::V6_vsub_qf32_mix:
1694 case Hexagon::V6_vsub_sf_mix:
1695 case Hexagon::V6_vmpy_qf32_qf16:
1696 case Hexagon::V6_vmpy_qf32_hf:
1697 case Hexagon::V6_vmpy_qf32_mix_hf:
1698 case Hexagon::V6_vmpy_rt_sf:
1699 case Hexagon::V6_vmpy_qf32_sf:
1700 Changed |= convertIfInputToNonHVX(MI, true);
1701 break;
1702 // Check if use of qf16 generating add/sub/mul instructions
1703 // are used as non-HVX operands.
1704 // If yes, convert the use to IEEE
1705 case Hexagon::V6_vadd_hf:
1706 case Hexagon::V6_vsub_hf:
1707 case Hexagon::V6_vadd_qf16:
1708 case Hexagon::V6_vsub_qf16:
1709 case Hexagon::V6_vadd_qf16_mix:
1710 case Hexagon::V6_vsub_qf16_mix:
1711 case Hexagon::V6_vsub_hf_mix:
1712 case Hexagon::V6_vmpy_qf16_hf:
1713 case Hexagon::V6_vmpy_rt_hf:
1714 Changed |= convertIfInputToNonHVX(MI, false);
1715 break;
1716 default:
1717 break;
1718 }
1719 }
1720 }
1721 if (OriginalMI.empty() || !Changed)
1722 return false;
1723 return true;
1724}
1725
1726// Parent function to handle all IEEE-754 compliant transformations
1727bool HexagonXQFloatGenerator::HandleCompliantIEEE(MachineFunction &MF) {
1728 bool Changed = false;
1729 Register R_mpy;
1730 for (auto &MBB : MF) {
1731 bool PrologCreated = false;
1732 for (auto &MI : MBB) {
1733 Changed |= deleteList();
1734 // Skip if the instruction does not have two operands,
1735 // or is a bundle instruction
1736 // or is a debug instruction
1737 if (MI.getNumOperands() != 3 || MI.isDebugInstr())
1738 continue;
1739
1740 auto Op1 = MI.getOperand(1);
1741 if (!Op1.isReg())
1742 continue;
1743 auto Op2 = MI.getOperand(2);
1744 if (!Op2.isReg())
1745 continue;
1746 auto Op0 = MI.getOperand(0);
1747 if (!Op0.isReg())
1748 continue;
1749 Register Reg1 = Op1.getReg();
1750 Register Reg2 = Op2.getReg();
1751 Register Dest = Op0.getReg();
1752 Register VRtSplat;
1753
1754 // FIXME Do not process physical registers as operands
1755 if (!Reg1.isVirtual() || !Reg2.isVirtual() || !Dest.isVirtual())
1756 continue;
1757
1758 switch (MI.getOpcode()) {
1759
1760 // ==== Handle multiplication instructions ====
1761
1762 // qf32 = vmpy(sf, Rt.sf)
1763 // Splat Rt to a vector
1764 // Normalize both input operands unconditionally
1765 case Hexagon::V6_vmpy_rt_sf:
1766 VRtSplat = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1767 BuildMI(MBB, MI, MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1768 VRtSplat)
1769 .addReg(Reg2);
1770 normalizeMultiplicationInputSF(MI, Reg1, VRtSplat, Dest, R_mpy,
1771 PrologCreated);
1772 OriginalMI.push_back(&MI);
1773 Changed |= convertIfInputToNonHVX(MI, true);
1774 break;
1775
1776 // qf32 = vmpy(sf, sf)
1777 // Normalize both operands unconditionally
1778 case Hexagon::V6_vmpy_qf32_sf:
1779 normalizeMultiplicationInputSF(MI, Reg1, Reg2, Dest, R_mpy,
1780 PrologCreated);
1781 OriginalMI.push_back(&MI);
1782 Changed |= convertIfInputToNonHVX(MI, true);
1783 break;
1784
1785 // qf32 = vmpy(qf32, qf32)
1786 // Normalize one or both input operands
1787 // if from add/sub unit
1788 case Hexagon::V6_vmpy_qf32:
1789 if (normalizeMultiplicationInputF32(MI, Reg1, Reg2, Dest, R_mpy,
1790 PrologCreated))
1791 OriginalMI.push_back(&MI);
1792 Changed |= convertIfInputToNonHVX(MI, true);
1793 break;
1794
1795 // qf16 = vmpy(hf, rt)
1796 // Splat Rt to vector and then widening multiply
1797 case Hexagon::V6_vmpy_rt_hf:
1798 VRtSplat = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1799 BuildMI(MBB, MI, MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1800 VRtSplat)
1801 .addReg(Reg2);
1802 widenMultiplyInputHF(MI, Reg1, VRtSplat, Dest);
1803 OriginalMI.push_back(&MI);
1804 Changed |= convertIfInputToNonHVX(MI, false);
1805 break;
1806
1807 // Widening multiply
1808 // qf16 = vmpy(hf, hf)
1809 case Hexagon::V6_vmpy_qf16_hf:
1810 widenMultiplyInputHF(MI, Reg1, Reg2, Dest);
1811 OriginalMI.push_back(&MI);
1812 Changed |= convertIfInputToNonHVX(MI, false);
1813 break;
1814
1815 // qf16 = vmpy(qf16, qf16)
1816 // Widening multiply to qf32 and convert back to qf16
1817 // if any of the operands are from add/sub unit
1818 case Hexagon::V6_vmpy_qf16:
1819 if (widenMultiplicationInputF16(MI, Reg1, Reg2, Dest, true))
1820 OriginalMI.push_back(&MI);
1821 Changed |= convertIfInputToNonHVX(MI, false);
1822 break;
1823
1824 // qf16 = vmpy(qf16, Rt.hf)
1825 // Splat Rt to vector and then widening multiply
1826 // and then convert back to qf16
1827 // if first operand is from add/sub unit
1828 case Hexagon::V6_vmpy_rt_qf16:
1829 if (widenMultiplicationInputF16Rt(MI, Reg1, Reg2, Dest))
1830 OriginalMI.push_back(&MI);
1831 Changed |= convertIfInputToNonHVX(MI, false);
1832 break;
1833
1834 // qf16 = vmpy(qf16, hf)
1835 // Widening multiply to qf32 and convert back to qf16
1836 // if first operand is from add/sub unit
1837 case Hexagon::V6_vmpy_qf16_mix_hf:
1838 if (widenMultiplicationInputF16(MI, Reg1, Reg2, Dest, false))
1839 OriginalMI.push_back(&MI);
1840 Changed |= convertIfInputToNonHVX(MI, false);
1841 break;
1842
1843 // Check if use of qf32/qf16 generating add/sub/mul
1844 // instructions are used as non-HVX operands.
1845 // If yes, convert the use to IEEE
1846 case Hexagon::V6_vadd_sf:
1847 case Hexagon::V6_vadd_qf32:
1848 case Hexagon::V6_vadd_qf32_mix:
1849 case Hexagon::V6_vsub_sf:
1850 case Hexagon::V6_vsub_qf32:
1851 case Hexagon::V6_vsub_qf32_mix:
1852 case Hexagon::V6_vsub_sf_mix:
1853 case Hexagon::V6_vmpy_qf32_qf16:
1854 case Hexagon::V6_vmpy_qf32_hf:
1855 case Hexagon::V6_vmpy_qf32_mix_hf:
1856 Changed |= convertIfInputToNonHVX(MI, true);
1857 break;
1858 case Hexagon::V6_vadd_hf:
1859 case Hexagon::V6_vsub_hf:
1860 case Hexagon::V6_vadd_qf16:
1861 case Hexagon::V6_vsub_qf16:
1862 case Hexagon::V6_vadd_qf16_mix:
1863 case Hexagon::V6_vsub_qf16_mix:
1864 case Hexagon::V6_vsub_hf_mix:
1865 Changed |= convertIfInputToNonHVX(MI, false);
1866 break;
1867 default:
1868 break;
1869 }
1870 }
1871 }
1872 if (OriginalMI.empty() || !Changed)
1873 return false;
1874 return true;
1875}
1876
1877// Parent function to do strict IEEE transformations
1878bool HexagonXQFloatGenerator::HandleStrictIEEE(MachineFunction &MF) {
1879
1880 bool Changed = false;
1881 Register R_mpy;
1882 for (auto &MBB : MF) {
1883 bool PrologCreated = false;
1884 for (auto &MI : MBB) {
1885 Changed |= deleteList();
1886 // Skip if the instruction does not have two operands,
1887 // or is a bundle instruction
1888 // or is a debug instruction
1889 if (MI.getNumOperands() != 3 || MI.isDebugInstr())
1890 continue;
1891
1892 auto Op1 = MI.getOperand(1);
1893 if (!Op1.isReg())
1894 continue;
1895 auto Op2 = MI.getOperand(2);
1896 if (!Op2.isReg())
1897 continue;
1898 auto Op0 = MI.getOperand(0);
1899 if (!Op0.isReg())
1900 continue;
1901 Register Reg1 = Op1.getReg();
1902 Register Reg2 = Op2.getReg();
1903 Register Dest = Op0.getReg();
1904 Register VRtSplat;
1905
1906 // FIXME Do not process physical registers as operands
1907 if (!Reg1.isVirtual() || !Reg2.isVirtual() || !Dest.isVirtual())
1908 continue;
1909
1910 switch (MI.getOpcode()) {
1911 // ==== Handle add/subtract instructions ====
1912 // Convert one or both the input operands to IEEE 32-bit
1913 // if from add/sub/mult unit(s)
1914 // qf32 = vadd(qf32, qf32)
1915 case Hexagon::V6_vadd_qf32:
1916 if (convertAddOpToIEEE32(MI, Reg1, Reg2, Dest, true, true, true))
1917 OriginalMI.push_back(&MI);
1918 Changed |= convertIfInputToNonHVX(MI, true);
1919 break;
1920 // qf32 = vsub(qf32, qf32)
1921 case Hexagon::V6_vsub_qf32:
1922 if (convertAddOpToIEEE32(MI, Reg1, Reg2, Dest, false, true, true))
1923 OriginalMI.push_back(&MI);
1924 Changed |= convertIfInputToNonHVX(MI, true);
1925 break;
1926 // Convert only the first input operand to IEEE 32-bit
1927 // if it is from add/sub/mult unit
1928 // qf32 = vadd(qf32, sf)
1929 case Hexagon::V6_vadd_qf32_mix:
1930 if (convertAddOpToIEEE32(MI, Reg1, Reg2, Dest, true, true, false))
1931 OriginalMI.push_back(&MI);
1932 Changed |= convertIfInputToNonHVX(MI, true);
1933 break;
1934 // qf32 = vsub(qf32, sf)
1935 case Hexagon::V6_vsub_qf32_mix:
1936 if (convertAddOpToIEEE32(MI, Reg1, Reg2, Dest, false, true, false))
1937 OriginalMI.push_back(&MI);
1938 Changed |= convertIfInputToNonHVX(MI, true);
1939 break;
1940 // qf32 = vsub(sf, qf32)
1941 case Hexagon::V6_vsub_sf_mix:
1942 if (convertAddOpToIEEE32(MI, Reg1, Reg2, Dest, false, false, true))
1943 OriginalMI.push_back(&MI);
1944 Changed |= convertIfInputToNonHVX(MI, true);
1945 break;
1946 break;
1947
1948 // Convert one or both the input operands to IEEE 16-bit
1949 // if from add/sub/mult unit(s)
1950 // qf16 = vadd(qf16, qf16)
1951 case Hexagon::V6_vadd_qf16:
1952 if (convertAddOpToIEEE16(MI, Reg1, Reg2, Dest, true, true, true))
1953 OriginalMI.push_back(&MI);
1954 Changed |= convertIfInputToNonHVX(MI, false);
1955 break;
1956 // qf16 = vsub(qf16, qf16)
1957 case Hexagon::V6_vsub_qf16:
1958 if (convertAddOpToIEEE16(MI, Reg1, Reg2, Dest, false, true, true))
1959 OriginalMI.push_back(&MI);
1960 Changed |= convertIfInputToNonHVX(MI, false);
1961 break;
1962 // Convert only the first input operand IEEE 16-bit
1963 // if it is from add/sub/mul unit
1964 // qf16 = vadd(qf16, hf)
1965 case Hexagon::V6_vadd_qf16_mix:
1966 if (convertAddOpToIEEE16(MI, Reg1, Reg2, Dest, true, true, false))
1967 OriginalMI.push_back(&MI);
1968 Changed |= convertIfInputToNonHVX(MI, false);
1969 break;
1970 // qf16 = vsub(qf16, hf)
1971 case Hexagon::V6_vsub_qf16_mix:
1972 if (convertAddOpToIEEE16(MI, Reg1, Reg2, Dest, false, true, false))
1973 OriginalMI.push_back(&MI);
1974 Changed |= convertIfInputToNonHVX(MI, false);
1975 break;
1976 // qf16 = vsub(hf, qf16)
1977 case Hexagon::V6_vsub_hf_mix:
1978 if (convertAddOpToIEEE16(MI, Reg1, Reg2, Dest, false, false, true))
1979 OriginalMI.push_back(&MI);
1980 Changed |= convertIfInputToNonHVX(MI, false);
1981 break;
1982
1983 // ==== Handle multiplication instructions ====
1984
1985 // qf32 = vmpy(sf, Rt.sf)
1986 // Splat Rt to a vector
1987 // Normalize both input operands unconditionally
1988 case Hexagon::V6_vmpy_rt_sf:
1989 VRtSplat = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
1990 BuildMI(MBB, MI, MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
1991 VRtSplat)
1992 .addReg(Reg2);
1993 normalizeMultiplicationInputSF(MI, Reg1, VRtSplat, Dest, R_mpy,
1994 PrologCreated);
1995 OriginalMI.push_back(&MI);
1996 Changed |= convertIfInputToNonHVX(MI, true);
1997 break;
1998
1999 // Normalize both operands unconditionally
2000 // qf32 = vmpy(sf, sf)
2001 case Hexagon::V6_vmpy_qf32_sf:
2002 normalizeMultiplicationInputSF(MI, Reg1, Reg2, Dest, R_mpy,
2003 PrologCreated);
2004 Changed |= convertIfInputToNonHVX(MI, true);
2005 OriginalMI.push_back(&MI);
2006 break;
2007
2008 // Convert one or both input operands to IEEE 32-bit
2009 // if from add/sub/mult unit and normalize
2010 // qf32 = vmpy(qf32, qf32)
2011 case Hexagon::V6_vmpy_qf32:
2012 if (convertNormalizeMultOp32(MI, Reg1, Reg2, Dest, R_mpy,
2013 PrologCreated))
2014 OriginalMI.push_back(&MI);
2015 Changed |= convertIfInputToNonHVX(MI, true);
2016 break;
2017
2018 // Convert one or both input operands to IEEE 16-bit
2019 // if from mul/add/sub unit;
2020 // then widening multiply to generate qf32
2021 // then convert to qf16
2022 // qf16 = vmpy(qf16, qf16)
2023 case Hexagon::V6_vmpy_qf16:
2024 if (convertWidenMultOp16(MI, Reg1, Reg2, Dest, true))
2025 OriginalMI.push_back(&MI);
2026 Changed |= convertIfInputToNonHVX(MI, false);
2027 break;
2028
2029 // Convert one or both input operands to IEEE 16-bit
2030 // if from mul/add/sub unit;
2031 // then widening multiply to generate qf32
2032 // qf32 = vmpy(qf16, qf16)
2033 case Hexagon::V6_vmpy_qf32_qf16:
2034 if (convertWidenMultOp32(MI, Reg1, Reg2, Dest, true))
2035 OriginalMI.push_back(&MI);
2036 Changed |= convertIfInputToNonHVX(MI, true);
2037 break;
2038
2039 // qf16 = vmpy(hf, rt)
2040 // Splat Rt to vector and then widening multiply
2041 case Hexagon::V6_vmpy_rt_hf:
2042 VRtSplat = MRI->createVirtualRegister(&Hexagon::HvxVRRegClass);
2043 BuildMI(MBB, MI, MI.getDebugLoc(), HII->get(Hexagon::V6_lvsplatw),
2044 VRtSplat)
2045 .addReg(Reg2);
2046 widenMultiplyInputHF(MI, Reg1, VRtSplat, Dest);
2047 OriginalMI.push_back(&MI);
2048 Changed |= convertIfInputToNonHVX(MI, false);
2049 break;
2050
2051 // Widening multiply, then convert to IEEE
2052 // qf16 = vmpy(hf, hf)
2053 case Hexagon::V6_vmpy_qf16_hf:
2054 widenMultiplyInputHF(MI, Reg1, Reg2, Dest);
2055 OriginalMI.push_back(&MI);
2056 Changed |= convertIfInputToNonHVX(MI, false);
2057 break;
2058
2059 // qf16 = vmpy(qf16, Rt.hf)
2060 // Splat Rt to vector and then widening multiply
2061 // and then convert back to qf16
2062 // if first operand is from add/sub unit
2063 case Hexagon::V6_vmpy_rt_qf16:
2064 if (widenMultiplicationInputF16Rt(MI, Reg1, Reg2, Dest))
2065 OriginalMI.push_back(&MI);
2066 Changed |= convertIfInputToNonHVX(MI, false);
2067 break;
2068
2069 // qf16 = vmpy(qf16, hf)
2070 // Convert only the first input operans to IEEE 16-bit
2071 // if from mul/add/sub unit;
2072 // then widening multiply to generate qf32
2073 // then convert back to qf16
2074 case Hexagon::V6_vmpy_qf16_mix_hf:
2075 if (convertWidenMultOp16(MI, Reg1, Reg2, Dest, false))
2076 OriginalMI.push_back(&MI);
2077 Changed |= convertIfInputToNonHVX(MI, false);
2078 break;
2079
2080 // qf32 = vmpy(qf16, hf)
2081 // Convert only the first input operans to IEEE 16-bit
2082 // if from mul/add/sub unit;
2083 // then widening multiply to generate qf32
2084 case Hexagon::V6_vmpy_qf32_mix_hf:
2085 if (convertWidenMultOp32(MI, Reg1, Reg2, Dest, false))
2086 OriginalMI.push_back(&MI);
2087 Changed |= convertIfInputToNonHVX(MI, true);
2088 break;
2089 // Check if use of qf32/qf16 generating add/sub/mul
2090 // instructions are used as non-HVX operands.
2091 // If yes, convert the use to IEEE
2092 case Hexagon::V6_vadd_sf:
2093 case Hexagon::V6_vsub_sf:
2094 Changed |= convertIfInputToNonHVX(MI, true);
2095 break;
2096 case Hexagon::V6_vadd_hf:
2097 case Hexagon::V6_vsub_hf:
2098 Changed |= convertIfInputToNonHVX(MI, false);
2099 break;
2100 default:
2101 break;
2102 }
2103 }
2104 }
2105 if (OriginalMI.empty() || !Changed)
2106 return false;
2107 return true;
2108}
2109
2110// There is no conversions in lossy mode
2111bool HexagonXQFloatGenerator::HandleLossyLegacy(MachineFunction &MF) {
2112 return false;
2113}
2114
2115bool HexagonXQFloatGenerator::runOnMachineFunction(MachineFunction &MF) {
2116 if (!EnableHVXXQFloat || (QFloatModeValue == QFloatMode::Legacy))
2117 return false;
2118
2119 bool Changed = false;
2120 HST = &MF.getSubtarget<HexagonSubtarget>();
2121 HII = HST->getInstrInfo();
2122 MRI = &MF.getRegInfo();
2123
2125 !(QFloatModeValue == QFloatMode::StrictIEEE)) {
2126 VectorConvertRemove VCR(MF, MRI, HST);
2127 VCR.run();
2128 LLVM_DEBUG(dbgs() << "\nExtraneous conversion instructions removed for "
2129 << MF.getName());
2130 if (PrintDebug)
2131 debug_print(MF);
2132 }
2133
2134 switch (QFloatModeValue) {
2135 case QFloatMode::StrictIEEE:
2136 LLVM_DEBUG(dbgs() << "\nGenerating code for STRICT-IEEE mode.\n");
2137 Changed = HandleStrictIEEE(MF);
2138 break;
2139 case QFloatMode::IEEE:
2140 LLVM_DEBUG(dbgs() << "\nGenerating code for IEEE mode.\n");
2141 Changed = HandleCompliantIEEE(MF);
2142 break;
2143 case QFloatMode::Lossy:
2144 LLVM_DEBUG(dbgs() << "\nGenerating code for LOSSY mode.\n");
2145 Changed = HandleLossySubnormals(MF);
2146 break;
2147 case QFloatMode::Legacy:
2148 LLVM_DEBUG(dbgs() << "\nGenerating code for LEGACY mode.\n");
2149 Changed = HandleLossyLegacy(MF);
2150 break;
2151 }
2152 LLVM_DEBUG(dbgs() << "...fine");
2153
2154 // Delete the original instructions
2155 for (MachineInstr *origMI : OriginalMI) {
2156 LLVM_DEBUG(origMI->dump());
2157 origMI->eraseFromParent();
2158 }
2159 OriginalMI.clear();
2160
2161 return Changed;
2162}
MachineInstrBuilder & UseMI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
cl::opt< QFloatMode > QFloatModeValue
static constexpr unsigned XQFPMult32[]
cl::opt< bool > EnableHVXXQFloat("enable-xqf-gen", cl::init(false), cl::desc("Enable XQFloat generations"))
cl::opt< bool > EnableConversionsRemoval("enable-rem-conv", cl::init(false), cl::desc("Enable extraneous conversions removal"))
cl::opt< bool > PrintDebug("debug-print", cl::init(false), cl::desc("Print function mir after transformation"))
static constexpr unsigned XQFPAdd16[]
static constexpr unsigned XQFPAdd32[]
#define HEXAGON_XQFLOAT_GENERATOR
static constexpr unsigned XQFPMult16[]
IRTranslator LLVM IR MI
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
PowerPC Reduce CR logical Operation
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define LLVM_DEBUG(...)
Definition Debug.h:119
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool usesQFOperand(MachineInstr *MI, unsigned Index=0) const
const HexagonInstrInfo * getInstrInfo() const override
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
use_iterator use_begin(Register RegNo) const
static use_iterator use_end()
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createHexagonXQFloatGenerator()
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
void initializeHexagonXQFloatGeneratorPass(PassRegistry &)
DWARFExpression::Operation Op
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947