LLVM 22.0.0git
HexagonGenPredicate.cpp
Go to the documentation of this file.
1//===- HexagonGenPredicate.cpp --------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Hexagon.h"
10#include "HexagonInstrInfo.h"
11#include "HexagonSubtarget.h"
12#include "llvm/ADT/SetVector.h"
13#include "llvm/ADT/StringRef.h"
23#include "llvm/IR/DebugLoc.h"
25#include "llvm/Pass.h"
27#include "llvm/Support/Debug.h"
30#include <cassert>
31#include <iterator>
32#include <queue>
33
34#define DEBUG_TYPE "gen-pred"
35
36using namespace llvm;
37
38namespace {
39
41
42struct PrintRegister {
43 friend raw_ostream &operator<<(raw_ostream &OS, const PrintRegister &PR);
44
45 PrintRegister(RegSubRegPair R, const TargetRegisterInfo &I)
46 : Reg(R), TRI(I) {}
47
48private:
51};
52
53[[maybe_unused]] raw_ostream &operator<<(raw_ostream &OS,
54 const PrintRegister &PR);
55raw_ostream &operator<<(raw_ostream &OS, const PrintRegister &PR) {
56 return OS << printReg(PR.Reg.Reg, &PR.TRI, PR.Reg.SubReg);
57}
58
59 class HexagonGenPredicate : public MachineFunctionPass {
60 public:
61 static char ID;
62
63 HexagonGenPredicate() : MachineFunctionPass(ID) {}
64
65 StringRef getPassName() const override {
66 return "Hexagon generate predicate operations";
67 }
68
69 void getAnalysisUsage(AnalysisUsage &AU) const override {
73 }
74
75 bool runOnMachineFunction(MachineFunction &MF) override;
76
77 private:
78 using VectOfInst = SetVector<MachineInstr *>;
79 using SetOfReg = SetVector<RegSubRegPair>;
81
82 const HexagonInstrInfo *TII = nullptr;
83 const HexagonRegisterInfo *TRI = nullptr;
84 MachineRegisterInfo *MRI = nullptr;
85 SetOfReg PredGPRs;
86 VectOfInst PUsers;
87 RegToRegMap G2P;
88
89 bool isPredReg(Register R);
90 void collectPredicateGPR(MachineFunction &MF);
91 void processPredicateGPR(const RegSubRegPair &Reg);
92 unsigned getPredForm(unsigned Opc);
93 bool isConvertibleToPredForm(const MachineInstr *MI);
94 bool isScalarCmp(unsigned Opc);
95 bool isScalarPred(RegSubRegPair PredReg);
96 RegSubRegPair getPredRegFor(const RegSubRegPair &Reg);
97 bool convertToPredForm(MachineInstr *MI);
98 bool eliminatePredCopies(MachineFunction &MF);
99 };
100
101} // end anonymous namespace
102
103char HexagonGenPredicate::ID = 0;
104
105INITIALIZE_PASS_BEGIN(HexagonGenPredicate, "hexagon-gen-pred-pass",
106 "Hexagon generate predicate operations", false, false)
108INITIALIZE_PASS_END(HexagonGenPredicate, "hexagon-gen-pred-pass",
109 "Hexagon generate predicate operations", false, false)
110
111bool HexagonGenPredicate::isPredReg(Register R) {
112 if (!R.isVirtual())
113 return false;
114 const TargetRegisterClass *RC = MRI->getRegClass(R);
115 return RC == &Hexagon::PredRegsRegClass;
116}
117
118unsigned HexagonGenPredicate::getPredForm(unsigned Opc) {
119 using namespace Hexagon;
120
121 switch (Opc) {
122 case A2_and:
123 case A2_andp:
124 return C2_and;
125 case A4_andn:
126 case A4_andnp:
127 return C2_andn;
128 case M4_and_and:
129 return C4_and_and;
130 case M4_and_andn:
131 return C4_and_andn;
132 case M4_and_or:
133 return C4_and_or;
134
135 case A2_or:
136 case A2_orp:
137 return C2_or;
138 case A4_orn:
139 case A4_ornp:
140 return C2_orn;
141 case M4_or_and:
142 return C4_or_and;
143 case M4_or_andn:
144 return C4_or_andn;
145 case M4_or_or:
146 return C4_or_or;
147
148 case A2_xor:
149 case A2_xorp:
150 return C2_xor;
151
152 case C2_tfrrp:
153 return COPY;
154 }
155 // The opcode corresponding to 0 is TargetOpcode::PHI. We can use 0 here
156 // to denote "none", but we need to make sure that none of the valid opcodes
157 // that we return will ever be 0.
158 static_assert(PHI == 0, "Use different value for <none>");
159 return 0;
160}
161
162bool HexagonGenPredicate::isConvertibleToPredForm(const MachineInstr *MI) {
163 unsigned Opc = MI->getOpcode();
164 if (getPredForm(Opc) != 0)
165 return true;
166
167 // Comparisons against 0 are also convertible. This does not apply to
168 // A4_rcmpeqi or A4_rcmpneqi, since they produce values 0 or 1, which
169 // may not match the value that the predicate register would have if
170 // it was converted to a predicate form.
171 switch (Opc) {
172 case Hexagon::C2_cmpeqi:
173 case Hexagon::C4_cmpneqi:
174 if (MI->getOperand(2).isImm() && MI->getOperand(2).getImm() == 0)
175 return true;
176 break;
177 }
178 return false;
179}
180
181void HexagonGenPredicate::collectPredicateGPR(MachineFunction &MF) {
182 for (MachineBasicBlock &B : MF) {
183 for (MachineInstr &MI : B) {
184 unsigned Opc = MI.getOpcode();
185 switch (Opc) {
186 case Hexagon::C2_tfrpr:
187 case TargetOpcode::COPY:
188 if (isPredReg(MI.getOperand(1).getReg())) {
189 RegSubRegPair RD = getRegSubRegPair(MI.getOperand(0));
190 if (RD.Reg.isVirtual())
191 PredGPRs.insert(RD);
192 }
193 break;
194 }
195 }
196 }
197}
198
199void HexagonGenPredicate::processPredicateGPR(const RegSubRegPair &Reg) {
200 LLVM_DEBUG(dbgs() << __func__ << ": " << printReg(Reg.Reg, TRI, Reg.SubReg)
201 << "\n");
202 using use_iterator = MachineRegisterInfo::use_iterator;
203
204 use_iterator I = MRI->use_begin(Reg.Reg), E = MRI->use_end();
205 if (I == E) {
206 LLVM_DEBUG(dbgs() << "Dead reg: " << printReg(Reg.Reg, TRI, Reg.SubReg)
207 << '\n');
208 MachineInstr *DefI = MRI->getVRegDef(Reg.Reg);
209 DefI->eraseFromParent();
210 return;
211 }
212
213 for (; I != E; ++I) {
214 MachineInstr *UseI = I->getParent();
215 if (isConvertibleToPredForm(UseI))
216 PUsers.insert(UseI);
217 }
218}
219
220RegSubRegPair HexagonGenPredicate::getPredRegFor(const RegSubRegPair &Reg) {
221 // Create a predicate register for a given Reg. The newly created register
222 // will have its value copied from Reg, so that it can be later used as
223 // an operand in other instructions.
224 assert(Reg.Reg.isVirtual());
225 RegToRegMap::iterator F = G2P.find(Reg);
226 if (F != G2P.end())
227 return F->second;
228
229 LLVM_DEBUG(dbgs() << __func__ << ": " << PrintRegister(Reg, *TRI));
230 MachineInstr *DefI = MRI->getVRegDef(Reg.Reg);
231 assert(DefI);
232 unsigned Opc = DefI->getOpcode();
233 if (Opc == Hexagon::C2_tfrpr || Opc == TargetOpcode::COPY) {
234 assert(DefI->getOperand(0).isDef() && DefI->getOperand(1).isUse());
236 G2P.insert(std::make_pair(Reg, PR));
237 LLVM_DEBUG(dbgs() << " -> " << PrintRegister(PR, *TRI) << '\n');
238 return PR;
239 }
240
241 MachineBasicBlock &B = *DefI->getParent();
242 DebugLoc DL = DefI->getDebugLoc();
243 const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
244 Register NewPR = MRI->createVirtualRegister(PredRC);
245
246 // For convertible instructions, do not modify them, so that they can
247 // be converted later. Generate a copy from Reg to NewPR.
248 if (isConvertibleToPredForm(DefI)) {
249 MachineBasicBlock::iterator DefIt = DefI;
250 BuildMI(B, std::next(DefIt), DL, TII->get(TargetOpcode::COPY), NewPR)
251 .addReg(Reg.Reg, 0, Reg.SubReg);
252 G2P.insert(std::make_pair(Reg, RegSubRegPair(NewPR)));
253 LLVM_DEBUG(dbgs() << " -> !" << PrintRegister(RegSubRegPair(NewPR), *TRI)
254 << '\n');
255 return RegSubRegPair(NewPR);
256 }
257
258 llvm_unreachable("Invalid argument");
259}
260
261bool HexagonGenPredicate::isScalarCmp(unsigned Opc) {
262 switch (Opc) {
263 case Hexagon::C2_cmpeq:
264 case Hexagon::C2_cmpgt:
265 case Hexagon::C2_cmpgtu:
266 case Hexagon::C2_cmpeqp:
267 case Hexagon::C2_cmpgtp:
268 case Hexagon::C2_cmpgtup:
269 case Hexagon::C2_cmpeqi:
270 case Hexagon::C2_cmpgti:
271 case Hexagon::C2_cmpgtui:
272 case Hexagon::C2_cmpgei:
273 case Hexagon::C2_cmpgeui:
274 case Hexagon::C4_cmpneqi:
275 case Hexagon::C4_cmpltei:
276 case Hexagon::C4_cmplteui:
277 case Hexagon::C4_cmpneq:
278 case Hexagon::C4_cmplte:
279 case Hexagon::C4_cmplteu:
280 case Hexagon::A4_cmpbeq:
281 case Hexagon::A4_cmpbeqi:
282 case Hexagon::A4_cmpbgtu:
283 case Hexagon::A4_cmpbgtui:
284 case Hexagon::A4_cmpbgt:
285 case Hexagon::A4_cmpbgti:
286 case Hexagon::A4_cmpheq:
287 case Hexagon::A4_cmphgt:
288 case Hexagon::A4_cmphgtu:
289 case Hexagon::A4_cmpheqi:
290 case Hexagon::A4_cmphgti:
291 case Hexagon::A4_cmphgtui:
292 return true;
293 }
294 return false;
295}
296
297bool HexagonGenPredicate::isScalarPred(RegSubRegPair PredReg) {
298 std::queue<RegSubRegPair> WorkQ;
299 WorkQ.push(PredReg);
300
301 while (!WorkQ.empty()) {
302 RegSubRegPair PR = WorkQ.front();
303 WorkQ.pop();
304 const MachineInstr *DefI = MRI->getVRegDef(PR.Reg);
305 if (!DefI)
306 return false;
307 unsigned DefOpc = DefI->getOpcode();
308 switch (DefOpc) {
309 case TargetOpcode::COPY: {
310 const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
311 if (MRI->getRegClass(PR.Reg) != PredRC)
312 return false;
313 // If it is a copy between two predicate registers, fall through.
314 [[fallthrough]];
315 }
316 case Hexagon::C2_and:
317 case Hexagon::C2_andn:
318 case Hexagon::C4_and_and:
319 case Hexagon::C4_and_andn:
320 case Hexagon::C4_and_or:
321 case Hexagon::C2_or:
322 case Hexagon::C2_orn:
323 case Hexagon::C4_or_and:
324 case Hexagon::C4_or_andn:
325 case Hexagon::C4_or_or:
326 case Hexagon::C4_or_orn:
327 case Hexagon::C2_xor:
328 // Add operands to the queue.
329 for (const MachineOperand &MO : DefI->operands())
330 if (MO.isReg() && MO.isUse())
331 WorkQ.push(RegSubRegPair(MO.getReg()));
332 break;
333
334 // All non-vector compares are ok, everything else is bad.
335 default:
336 return isScalarCmp(DefOpc);
337 }
338 }
339
340 return true;
341}
342
343bool HexagonGenPredicate::convertToPredForm(MachineInstr *MI) {
344 LLVM_DEBUG(dbgs() << __func__ << ": " << MI << " " << *MI);
345
346 unsigned Opc = MI->getOpcode();
347 assert(isConvertibleToPredForm(MI));
348 unsigned NumOps = MI->getNumOperands();
349 for (unsigned i = 0; i < NumOps; ++i) {
350 MachineOperand &MO = MI->getOperand(i);
351 if (!MO.isReg() || !MO.isUse())
352 continue;
354 if (Reg.SubReg && Reg.SubReg != Hexagon::isub_lo)
355 return false;
356 if (!PredGPRs.count(Reg))
357 return false;
358 }
359
360 MachineBasicBlock &B = *MI->getParent();
361 DebugLoc DL = MI->getDebugLoc();
362
363 unsigned NewOpc = getPredForm(Opc);
364 // Special case for comparisons against 0.
365 if (NewOpc == 0) {
366 switch (Opc) {
367 case Hexagon::C2_cmpeqi:
368 NewOpc = Hexagon::C2_not;
369 break;
370 case Hexagon::C4_cmpneqi:
371 NewOpc = TargetOpcode::COPY;
372 break;
373 default:
374 return false;
375 }
376
377 // If it's a scalar predicate register, then all bits in it are
378 // the same. Otherwise, to determine whether all bits are 0 or not
379 // we would need to use any8.
380 RegSubRegPair PR = getPredRegFor(getRegSubRegPair(MI->getOperand(1)));
381 if (!isScalarPred(PR))
382 return false;
383 // This will skip the immediate argument when creating the predicate
384 // version instruction.
385 NumOps = 2;
386 }
387
388 // Check that def is in operand #0.
389 MachineOperand &Op0 = MI->getOperand(0);
390 assert(Op0.isDef());
392
393 // Don't use getPredRegFor, since it will create an association between
394 // the argument and a created predicate register (i.e. it will insert a
395 // copy if a new predicate register is created).
396 const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
397 RegSubRegPair NewPR = MRI->createVirtualRegister(PredRC);
398 MachineInstrBuilder MIB = BuildMI(B, MI, DL, TII->get(NewOpc), NewPR.Reg);
399
400 // Add predicate counterparts of the GPRs.
401 for (unsigned i = 1; i < NumOps; ++i) {
402 RegSubRegPair GPR = getRegSubRegPair(MI->getOperand(i));
403 RegSubRegPair Pred = getPredRegFor(GPR);
404 MIB.addReg(Pred.Reg, 0, Pred.SubReg);
405 }
406 LLVM_DEBUG(dbgs() << "generated: " << *MIB);
407
408 // Generate a copy-out: NewGPR = NewPR, and replace all uses of OutR
409 // with NewGPR.
410 const TargetRegisterClass *RC = MRI->getRegClass(OutR.Reg);
411 Register NewOutR = MRI->createVirtualRegister(RC);
412 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), NewOutR)
413 .addReg(NewPR.Reg, 0, NewPR.SubReg);
414 MRI->replaceRegWith(OutR.Reg, NewOutR);
415 MI->eraseFromParent();
416
417 // If the processed instruction was C2_tfrrp (i.e. Rn = Pm; Pk = Rn),
418 // then the output will be a predicate register. Do not visit the
419 // users of it.
420 if (!isPredReg(NewOutR)) {
421 RegSubRegPair R(NewOutR);
422 PredGPRs.insert(R);
423 processPredicateGPR(R);
424 }
425 return true;
426}
427
428bool HexagonGenPredicate::eliminatePredCopies(MachineFunction &MF) {
429 LLVM_DEBUG(dbgs() << __func__ << "\n");
430 const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
431 bool Changed = false;
432 VectOfInst Erase;
433
434 // First, replace copies
435 // IntR = PredR1
436 // PredR2 = IntR
437 // with
438 // PredR2 = PredR1
439 // Such sequences can be generated when a copy-into-pred is generated from
440 // a gpr register holding a result of a convertible instruction. After
441 // the convertible instruction is converted, its predicate result will be
442 // copied back into the original gpr.
443
444 for (MachineBasicBlock &MBB : MF) {
445 for (MachineInstr &MI : MBB) {
446 if (MI.getOpcode() != TargetOpcode::COPY)
447 continue;
448 RegSubRegPair DR = getRegSubRegPair(MI.getOperand(0));
449 RegSubRegPair SR = getRegSubRegPair(MI.getOperand(1));
450 if (!DR.Reg.isVirtual())
451 continue;
452 if (!SR.Reg.isVirtual())
453 continue;
454 if (MRI->getRegClass(DR.Reg) != PredRC)
455 continue;
456 if (MRI->getRegClass(SR.Reg) != PredRC)
457 continue;
458 assert(!DR.SubReg && !SR.SubReg && "Unexpected subregister");
459 MRI->replaceRegWith(DR.Reg, SR.Reg);
460 Erase.insert(&MI);
461 Changed = true;
462 }
463 }
464
465 for (MachineInstr *MI : Erase)
466 MI->eraseFromParent();
467
468 return Changed;
469}
470
471bool HexagonGenPredicate::runOnMachineFunction(MachineFunction &MF) {
472 if (skipFunction(MF.getFunction()))
473 return false;
474
475 TII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
476 TRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
477 MRI = &MF.getRegInfo();
478 PredGPRs.clear();
479 PUsers.clear();
480 G2P.clear();
481
482 bool Changed = false;
483 collectPredicateGPR(MF);
484 for (const RegSubRegPair &R : PredGPRs)
485 processPredicateGPR(R);
486
487 bool Again;
488 do {
489 Again = false;
490 VectOfInst Processed, Copy;
491
492 Copy = PUsers;
493 for (MachineInstr *MI : Copy) {
494 bool Done = convertToPredForm(MI);
495 if (Done) {
496 Processed.insert(MI);
497 Again = true;
498 }
499 }
500 Changed |= Again;
501
502 auto Done = [Processed] (MachineInstr *MI) -> bool {
503 return Processed.count(MI);
504 };
505 PUsers.remove_if(Done);
506 } while (Again);
507
508 Changed |= eliminatePredCopies(MF);
509 return Changed;
510}
511
513 return new HexagonGenPredicate();
514}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Rewrite undef for PHI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file implements a set that has insertion order iteration characteristics.
#define LLVM_DEBUG(...)
Definition Debug.h:114
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
iterator end()
Definition DenseMap.h:81
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:241
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
mop_range operands()
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_iterator< true, false, false, true, false > use_iterator
use_iterator/use_begin/use_end - Walk all uses of the specified register.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
A vector that has set insertion semantics.
Definition SetVector.h:58
bool remove_if(UnaryPredicate P)
Remove items from the set vector based on a predicate function.
Definition SetVector.h:228
void clear()
Completely clear the SetVector.
Definition SetVector.h:265
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
Definition SetVector.h:260
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:149
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
bool isPredReg(MCRegisterInfo const &MRI, MCRegister Reg)
This is an optimization pass for GlobalISel generic memory operations.
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Done
Definition Threading.h:60
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
FunctionPass * createHexagonGenPredicate()
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
A pair composed of a register and a sub-register index.