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 instructions | 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 instruction
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;
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;
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();
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 instruction
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
MachineRegisterInfo & MRI
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:312
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the 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:1963