LLVM 20.0.0git
HexagonMCCompound.cpp
Go to the documentation of this file.
1//=== HexagonMCCompound.cpp - Hexagon Compound checker -------------------===//
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 file is looks at a packet and tries to form compound insns
10//
11//===----------------------------------------------------------------------===//
12
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/Support/Debug.h"
22#include <cassert>
23#include <cstdint>
24
25using namespace llvm;
26using namespace Hexagon;
27
28#define DEBUG_TYPE "hexagon-mccompound"
29
39};
40
41static const unsigned tstBitOpcode[8] = {
42 J4_tstbit0_fp0_jump_nt, J4_tstbit0_fp0_jump_t, J4_tstbit0_fp1_jump_nt,
43 J4_tstbit0_fp1_jump_t, J4_tstbit0_tp0_jump_nt, J4_tstbit0_tp0_jump_t,
44 J4_tstbit0_tp1_jump_nt, J4_tstbit0_tp1_jump_t};
45static const unsigned cmpeqBitOpcode[8] = {
46 J4_cmpeq_fp0_jump_nt, J4_cmpeq_fp0_jump_t, J4_cmpeq_fp1_jump_nt,
47 J4_cmpeq_fp1_jump_t, J4_cmpeq_tp0_jump_nt, J4_cmpeq_tp0_jump_t,
48 J4_cmpeq_tp1_jump_nt, J4_cmpeq_tp1_jump_t};
49static const unsigned cmpgtBitOpcode[8] = {
50 J4_cmpgt_fp0_jump_nt, J4_cmpgt_fp0_jump_t, J4_cmpgt_fp1_jump_nt,
51 J4_cmpgt_fp1_jump_t, J4_cmpgt_tp0_jump_nt, J4_cmpgt_tp0_jump_t,
52 J4_cmpgt_tp1_jump_nt, J4_cmpgt_tp1_jump_t};
53static const unsigned cmpgtuBitOpcode[8] = {
54 J4_cmpgtu_fp0_jump_nt, J4_cmpgtu_fp0_jump_t, J4_cmpgtu_fp1_jump_nt,
55 J4_cmpgtu_fp1_jump_t, J4_cmpgtu_tp0_jump_nt, J4_cmpgtu_tp0_jump_t,
56 J4_cmpgtu_tp1_jump_nt, J4_cmpgtu_tp1_jump_t};
57static const unsigned cmpeqiBitOpcode[8] = {
58 J4_cmpeqi_fp0_jump_nt, J4_cmpeqi_fp0_jump_t, J4_cmpeqi_fp1_jump_nt,
59 J4_cmpeqi_fp1_jump_t, J4_cmpeqi_tp0_jump_nt, J4_cmpeqi_tp0_jump_t,
60 J4_cmpeqi_tp1_jump_nt, J4_cmpeqi_tp1_jump_t};
61static const unsigned cmpgtiBitOpcode[8] = {
62 J4_cmpgti_fp0_jump_nt, J4_cmpgti_fp0_jump_t, J4_cmpgti_fp1_jump_nt,
63 J4_cmpgti_fp1_jump_t, J4_cmpgti_tp0_jump_nt, J4_cmpgti_tp0_jump_t,
64 J4_cmpgti_tp1_jump_nt, J4_cmpgti_tp1_jump_t};
65static const unsigned cmpgtuiBitOpcode[8] = {
66 J4_cmpgtui_fp0_jump_nt, J4_cmpgtui_fp0_jump_t, J4_cmpgtui_fp1_jump_nt,
67 J4_cmpgtui_fp1_jump_t, J4_cmpgtui_tp0_jump_nt, J4_cmpgtui_tp0_jump_t,
68 J4_cmpgtui_tp1_jump_nt, J4_cmpgtui_tp1_jump_t};
69static const unsigned cmpeqn1BitOpcode[8] = {
70 J4_cmpeqn1_fp0_jump_nt, J4_cmpeqn1_fp0_jump_t, J4_cmpeqn1_fp1_jump_nt,
71 J4_cmpeqn1_fp1_jump_t, J4_cmpeqn1_tp0_jump_nt, J4_cmpeqn1_tp0_jump_t,
72 J4_cmpeqn1_tp1_jump_nt, J4_cmpeqn1_tp1_jump_t};
73static const unsigned cmpgtn1BitOpcode[8] = {
74 J4_cmpgtn1_fp0_jump_nt, J4_cmpgtn1_fp0_jump_t, J4_cmpgtn1_fp1_jump_nt,
75 J4_cmpgtn1_fp1_jump_t, J4_cmpgtn1_tp0_jump_nt, J4_cmpgtn1_tp0_jump_t,
76 J4_cmpgtn1_tp1_jump_nt, J4_cmpgtn1_tp1_jump_t,
77};
78
79// enum HexagonII::CompoundGroup
80static unsigned getCompoundCandidateGroup(MCInst const &MI, bool IsExtended) {
81 MCRegister DstReg, SrcReg, Src1Reg, Src2Reg;
82
83 switch (MI.getOpcode()) {
84 default:
86 //
87 // Compound pairs.
88 // "p0=cmp.eq(Rs16,Rt16); if (p0.new) jump:nt #r9:2"
89 // "Rd16=#U6 ; jump #r9:2"
90 // "Rd16=Rs16 ; jump #r9:2"
91 //
92 case Hexagon::C2_cmpeq:
93 case Hexagon::C2_cmpgt:
94 case Hexagon::C2_cmpgtu:
95 if (IsExtended)
97 DstReg = MI.getOperand(0).getReg();
98 Src1Reg = MI.getOperand(1).getReg();
99 Src2Reg = MI.getOperand(2).getReg();
100 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
103 return HexagonII::HCG_A;
104 break;
105 case Hexagon::C2_cmpeqi:
106 case Hexagon::C2_cmpgti:
107 case Hexagon::C2_cmpgtui:
108 if (IsExtended)
109 return HexagonII::HCG_None;
110 // P0 = cmp.eq(Rs,#u2)
111 DstReg = MI.getOperand(0).getReg();
112 SrcReg = MI.getOperand(1).getReg();
113 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
115 (HexagonMCInstrInfo::inRange<5>(MI, 2) ||
117 return HexagonII::HCG_A;
118 break;
119 case Hexagon::A2_tfr:
120 if (IsExtended)
121 return HexagonII::HCG_None;
122 // Rd = Rs
123 DstReg = MI.getOperand(0).getReg();
124 SrcReg = MI.getOperand(1).getReg();
127 return HexagonII::HCG_A;
128 break;
129 case Hexagon::A2_tfrsi:
130 if (IsExtended)
131 return HexagonII::HCG_None;
132 // Rd = #u6
133 DstReg = MI.getOperand(0).getReg();
134 if (HexagonMCInstrInfo::minConstant(MI, 1) <= 63 &&
137 return HexagonII::HCG_A;
138 break;
139 case Hexagon::S2_tstbit_i:
140 if (IsExtended)
141 return HexagonII::HCG_None;
142 DstReg = MI.getOperand(0).getReg();
143 Src1Reg = MI.getOperand(1).getReg();
144 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
147 return HexagonII::HCG_A;
148 break;
149 // The fact that .new form is used pretty much guarantees
150 // that predicate register will match. Nevertheless,
151 // there could be some false positives without additional
152 // checking.
153 case Hexagon::J2_jumptnew:
154 case Hexagon::J2_jumpfnew:
155 case Hexagon::J2_jumptnewpt:
156 case Hexagon::J2_jumpfnewpt:
157 Src1Reg = MI.getOperand(0).getReg();
158 if (Hexagon::P0 == Src1Reg || Hexagon::P1 == Src1Reg)
159 return HexagonII::HCG_B;
160 break;
161 // Transfer and jump:
162 // Rd=#U6 ; jump #r9:2
163 // Rd=Rs ; jump #r9:2
164 // Do not test for jump range here.
165 case Hexagon::J2_jump:
166 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:
167 return HexagonII::HCG_C;
168 break;
169 }
170
171 return HexagonII::HCG_None;
172}
173
174/// getCompoundOp - Return the index from 0-7 into the above opcode lists.
175static unsigned getCompoundOp(MCInst const &HMCI) {
176 const MCOperand &Predicate = HMCI.getOperand(0);
177 MCRegister PredReg = Predicate.getReg();
178
179 assert((PredReg == Hexagon::P0) || (PredReg == Hexagon::P1) ||
180 (PredReg == Hexagon::P2) || (PredReg == Hexagon::P3));
181
182 switch (HMCI.getOpcode()) {
183 default:
184 llvm_unreachable("Expected match not found.\n");
185 break;
186 case Hexagon::J2_jumpfnew:
187 return (PredReg == Hexagon::P0) ? fp0_jump_nt : fp1_jump_nt;
188 case Hexagon::J2_jumpfnewpt:
189 return (PredReg == Hexagon::P0) ? fp0_jump_t : fp1_jump_t;
190 case Hexagon::J2_jumptnew:
191 return (PredReg == Hexagon::P0) ? tp0_jump_nt : tp1_jump_nt;
192 case Hexagon::J2_jumptnewpt:
193 return (PredReg == Hexagon::P0) ? tp0_jump_t : tp1_jump_t;
194 }
195}
196
197static MCInst *getCompoundInsn(MCContext &Context, MCInst const &L,
198 MCInst const &R) {
199 MCInst *CompoundInsn = nullptr;
200 unsigned compoundOpcode;
201 MCOperand Rs, Rt;
202 int64_t Value;
203 bool Success;
204
205 switch (L.getOpcode()) {
206 default:
207 LLVM_DEBUG(dbgs() << "Possible compound ignored\n");
208 return CompoundInsn;
209
210 case Hexagon::A2_tfrsi:
211 Rt = L.getOperand(0);
212 compoundOpcode = J4_jumpseti;
213 CompoundInsn = Context.createMCInst();
214 CompoundInsn->setOpcode(compoundOpcode);
215
216 CompoundInsn->addOperand(Rt);
217 CompoundInsn->addOperand(L.getOperand(1)); // Immediate
218 CompoundInsn->addOperand(R.getOperand(0)); // Jump target
219 break;
220
221 case Hexagon::A2_tfr:
222 Rt = L.getOperand(0);
223 Rs = L.getOperand(1);
224
225 compoundOpcode = J4_jumpsetr;
226 CompoundInsn = Context.createMCInst();
227 CompoundInsn->setOpcode(compoundOpcode);
228 CompoundInsn->addOperand(Rt);
229 CompoundInsn->addOperand(Rs);
230 CompoundInsn->addOperand(R.getOperand(0)); // Jump target.
231
232 break;
233
234 case Hexagon::C2_cmpeq:
235 LLVM_DEBUG(dbgs() << "CX: C2_cmpeq\n");
236 Rs = L.getOperand(1);
237 Rt = L.getOperand(2);
238
239 compoundOpcode = cmpeqBitOpcode[getCompoundOp(R)];
240 CompoundInsn = Context.createMCInst();
241 CompoundInsn->setOpcode(compoundOpcode);
242 CompoundInsn->addOperand(Rs);
243 CompoundInsn->addOperand(Rt);
244 CompoundInsn->addOperand(R.getOperand(1));
245 break;
246
247 case Hexagon::C2_cmpgt:
248 LLVM_DEBUG(dbgs() << "CX: C2_cmpgt\n");
249 Rs = L.getOperand(1);
250 Rt = L.getOperand(2);
251
252 compoundOpcode = cmpgtBitOpcode[getCompoundOp(R)];
253 CompoundInsn = Context.createMCInst();
254 CompoundInsn->setOpcode(compoundOpcode);
255 CompoundInsn->addOperand(Rs);
256 CompoundInsn->addOperand(Rt);
257 CompoundInsn->addOperand(R.getOperand(1));
258 break;
259
260 case Hexagon::C2_cmpgtu:
261 LLVM_DEBUG(dbgs() << "CX: C2_cmpgtu\n");
262 Rs = L.getOperand(1);
263 Rt = L.getOperand(2);
264
265 compoundOpcode = cmpgtuBitOpcode[getCompoundOp(R)];
266 CompoundInsn = Context.createMCInst();
267 CompoundInsn->setOpcode(compoundOpcode);
268 CompoundInsn->addOperand(Rs);
269 CompoundInsn->addOperand(Rt);
270 CompoundInsn->addOperand(R.getOperand(1));
271 break;
272
273 case Hexagon::C2_cmpeqi:
274 LLVM_DEBUG(dbgs() << "CX: C2_cmpeqi\n");
275 Success = L.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
276 (void)Success;
278 if (Value == -1)
279 compoundOpcode = cmpeqn1BitOpcode[getCompoundOp(R)];
280 else
281 compoundOpcode = cmpeqiBitOpcode[getCompoundOp(R)];
282
283 Rs = L.getOperand(1);
284 CompoundInsn = Context.createMCInst();
285 CompoundInsn->setOpcode(compoundOpcode);
286 CompoundInsn->addOperand(Rs);
287 CompoundInsn->addOperand(L.getOperand(2));
288 CompoundInsn->addOperand(R.getOperand(1));
289 break;
290
291 case Hexagon::C2_cmpgti:
292 LLVM_DEBUG(dbgs() << "CX: C2_cmpgti\n");
293 Success = L.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
294 (void)Success;
296 if (Value == -1)
297 compoundOpcode = cmpgtn1BitOpcode[getCompoundOp(R)];
298 else
299 compoundOpcode = cmpgtiBitOpcode[getCompoundOp(R)];
300
301 Rs = L.getOperand(1);
302 CompoundInsn = Context.createMCInst();
303 CompoundInsn->setOpcode(compoundOpcode);
304 CompoundInsn->addOperand(Rs);
305 CompoundInsn->addOperand(L.getOperand(2));
306 CompoundInsn->addOperand(R.getOperand(1));
307 break;
308
309 case Hexagon::C2_cmpgtui:
310 LLVM_DEBUG(dbgs() << "CX: C2_cmpgtui\n");
311 Rs = L.getOperand(1);
312 compoundOpcode = cmpgtuiBitOpcode[getCompoundOp(R)];
313 CompoundInsn = Context.createMCInst();
314 CompoundInsn->setOpcode(compoundOpcode);
315 CompoundInsn->addOperand(Rs);
316 CompoundInsn->addOperand(L.getOperand(2));
317 CompoundInsn->addOperand(R.getOperand(1));
318 break;
319
320 case Hexagon::S2_tstbit_i:
321 LLVM_DEBUG(dbgs() << "CX: S2_tstbit_i\n");
322 Rs = L.getOperand(1);
323 compoundOpcode = tstBitOpcode[getCompoundOp(R)];
324 CompoundInsn = Context.createMCInst();
325 CompoundInsn->setOpcode(compoundOpcode);
326 CompoundInsn->addOperand(Rs);
327 CompoundInsn->addOperand(R.getOperand(1));
328 break;
329 }
330
331 return CompoundInsn;
332}
333
334/// Non-Symmetrical. See if these two instructions are fit for compound pair.
335static bool isOrderedCompoundPair(MCInst const &MIa, bool IsExtendedA,
336 MCInst const &MIb, bool IsExtendedB) {
337 unsigned MIaG = getCompoundCandidateGroup(MIa, IsExtendedA);
338 unsigned MIbG = getCompoundCandidateGroup(MIb, IsExtendedB);
339 // We have two candidates - check that this is the same register
340 // we are talking about.
341 unsigned Opca = MIa.getOpcode();
342 if (MIaG == HexagonII::HCG_A && MIbG == HexagonII::HCG_C &&
343 (Opca == Hexagon::A2_tfr || Opca == Hexagon::A2_tfrsi))
344 return true;
345 return ((MIaG == HexagonII::HCG_A && MIbG == HexagonII::HCG_B) &&
346 (MIa.getOperand(0).getReg() == MIb.getOperand(0).getReg()));
347}
348
349static bool lookForCompound(MCInstrInfo const &MCII, MCContext &Context,
350 MCInst &MCI) {
352 bool JExtended = false;
353 for (MCInst::iterator J =
355 J != MCI.end(); ++J) {
356 MCInst const *JumpInst = J->getInst();
357 if (HexagonMCInstrInfo::isImmext(*JumpInst)) {
358 JExtended = true;
359 continue;
360 }
361 if (HexagonMCInstrInfo::getType(MCII, *JumpInst) == HexagonII::TypeJ) {
362 // Try to pair with another insn (B)undled with jump.
363 bool BExtended = false;
364 for (MCInst::iterator B =
366 B != MCI.end(); ++B) {
367 MCInst const *Inst = B->getInst();
368 if (JumpInst == Inst) {
369 BExtended = false;
370 continue;
371 }
372 if (HexagonMCInstrInfo::isImmext(*Inst)) {
373 BExtended = true;
374 continue;
375 }
376 LLVM_DEBUG(dbgs() << "J,B: " << JumpInst->getOpcode() << ","
377 << Inst->getOpcode() << "\n");
378 if (isOrderedCompoundPair(*Inst, BExtended, *JumpInst, JExtended)) {
379 MCInst *CompoundInsn = getCompoundInsn(Context, *Inst, *JumpInst);
380 if (CompoundInsn) {
381 LLVM_DEBUG(dbgs() << "B: " << Inst->getOpcode() << ","
382 << JumpInst->getOpcode() << " Compounds to "
383 << CompoundInsn->getOpcode() << "\n");
384 J->setInst(CompoundInsn);
385 MCI.erase(B);
386 return true;
387 }
388 }
389 BExtended = false;
390 }
391 }
392 JExtended = false;
393 }
394 return false;
395}
396
397/// tryCompound - Given a bundle check for compound insns when one
398/// is found update the contents fo the bundle with the compound insn.
399/// If a compound instruction is found then the bundle will have one
400/// additional slot.
402 MCContext &Context, MCInst &MCI) {
404 "Non-Bundle where Bundle expected");
405
406 // By definition a compound must have 2 insn.
407 if (MCI.size() < 2)
408 return;
409
410 // Create a vector, needed to keep the order of jump instructions.
411 MCInst CheckList(MCI);
412
413 // Keep the last known good bundle around in case the shuffle fails.
414 MCInst LastValidBundle(MCI);
415
416 bool PreviouslyValid = llvm::HexagonMCShuffle(Context, false, MCII, STI, MCI);
417
418 // Look for compounds until none are found, only update the bundle when
419 // a compound is found.
420 while (lookForCompound(MCII, Context, CheckList)) {
421 // Need to update the bundle.
422 MCI = CheckList;
423
424 const bool IsValid = llvm::HexagonMCShuffle(Context, false, MCII, STI, MCI);
425 if (PreviouslyValid && !IsValid) {
426 LLVM_DEBUG(dbgs() << "Found ERROR\n");
427 MCI = LastValidBundle;
428 } else if (IsValid) {
429 LastValidBundle = MCI;
430 PreviouslyValid = true;
431 }
432 }
433}
#define Success
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DEBUG(...)
Definition: Debug.h:106
static bool lookForCompound(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI)
static const unsigned cmpgtBitOpcode[8]
static unsigned getCompoundCandidateGroup(MCInst const &MI, bool IsExtended)
static const unsigned cmpeqiBitOpcode[8]
static const unsigned cmpgtuBitOpcode[8]
static const unsigned cmpeqn1BitOpcode[8]
static const unsigned cmpgtn1BitOpcode[8]
static unsigned getCompoundOp(MCInst const &HMCI)
getCompoundOp - Return the index from 0-7 into the above opcode lists.
static const unsigned cmpgtuiBitOpcode[8]
static bool isOrderedCompoundPair(MCInst const &MIa, bool IsExtendedA, MCInst const &MIb, bool IsExtendedB)
Non-Symmetrical. See if these two instructions are fit for compound pair.
@ tp1_jump_nt
@ fp0_jump_nt
@ fp0_jump_t
@ tp1_jump_t
@ fp1_jump_t
@ fp1_jump_nt
@ tp0_jump_nt
@ tp0_jump_t
static const unsigned cmpeqBitOpcode[8]
static const unsigned cmpgtiBitOpcode[8]
static MCInst * getCompoundInsn(MCContext &Context, MCInst const &L, MCInst const &R)
static const unsigned tstBitOpcode[8]
IRTranslator LLVM IR MI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Context object for machine code objects.
Definition: MCContext.h:83
MCInst * createMCInst()
Create and return a new MC instruction.
Definition: MCContext.cpp:194
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
void erase(iterator I)
Definition: MCInst.h:217
SmallVectorImpl< MCOperand >::iterator iterator
Definition: MCInst.h:213
unsigned getOpcode() const
Definition: MCInst.h:199
void addOperand(const MCOperand Op)
Definition: MCInst.h:211
iterator begin()
Definition: MCInst.h:220
iterator end()
Definition: MCInst.h:222
size_t size() const
Definition: MCInst.h:219
void setOpcode(unsigned Op)
Definition: MCInst.h:198
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:207
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:37
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:70
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Generic base class for all target subtargets.
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCContext &Context, MCInst &MCI)
tryCompound - Given a bundle check for compound insns when one is found update the contents fo the bu...
bool isBundle(MCInst const &MCI)
int64_t minConstant(MCInst const &MCI, size_t Index)
bool isIntRegForSubInst(MCRegister Reg)
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI)
Return the Hexagon ISA class for the insn.
bool isImmext(MCInst const &MCI)
constexpr size_t bundleInstructionsOffset
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool HexagonMCShuffle(MCContext &Context, bool ReportErrors, MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &MCB)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163