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
13#include "MCTargetDesc/HexagonBaseInfo.h"
14#include "MCTargetDesc/HexagonMCInstrInfo.h"
15#include "MCTargetDesc/HexagonMCShuffler.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/Support/Debug.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/raw_ostream.h"
22#include <cassert>
23#include <cstdint>
24
25using namespace llvm;
26using namespace Hexagon;
27
28#define DEBUG_TYPE "hexagon-mccompound"
29
30enum OpcodeIndex {
31 fp0_jump_nt = 0,
32 fp0_jump_t,
33 fp1_jump_nt,
34 fp1_jump_t,
35 tp0_jump_nt,
36 tp0_jump_t,
37 tp1_jump_nt,
38 tp1_jump_t
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 unsigned DstReg, SrcReg, Src1Reg, Src2Reg;
82
83 switch (MI.getOpcode()) {
84 default:
85 return HexagonII::HCG_None;
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)
96 return HexagonII::HCG_None;
97 DstReg = MI.getOperand(i: 0).getReg();
98 Src1Reg = MI.getOperand(i: 1).getReg();
99 Src2Reg = MI.getOperand(i: 2).getReg();
100 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
101 HexagonMCInstrInfo::isIntRegForSubInst(Reg: Src1Reg) &&
102 HexagonMCInstrInfo::isIntRegForSubInst(Reg: Src2Reg))
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(i: 0).getReg();
112 SrcReg = MI.getOperand(i: 1).getReg();
113 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
114 HexagonMCInstrInfo::isIntRegForSubInst(Reg: SrcReg) &&
115 (HexagonMCInstrInfo::inRange<5>(MCI: MI, Index: 2) ||
116 HexagonMCInstrInfo::minConstant(MCI: MI, Index: 2) == -1))
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(i: 0).getReg();
124 SrcReg = MI.getOperand(i: 1).getReg();
125 if (HexagonMCInstrInfo::isIntRegForSubInst(Reg: DstReg) &&
126 HexagonMCInstrInfo::isIntRegForSubInst(Reg: SrcReg))
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(i: 0).getReg();
134 if (HexagonMCInstrInfo::minConstant(MCI: MI, Index: 1) <= 63 &&
135 HexagonMCInstrInfo::minConstant(MCI: MI, Index: 1) >= 0 &&
136 HexagonMCInstrInfo::isIntRegForSubInst(Reg: DstReg))
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(i: 0).getReg();
143 Src1Reg = MI.getOperand(i: 1).getReg();
144 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
145 HexagonMCInstrInfo::isIntRegForSubInst(Reg: Src1Reg) &&
146 HexagonMCInstrInfo::minConstant(MCI: MI, Index: 2) == 0)
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(i: 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(i: 0);
177 unsigned 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(i: 0);
212 compoundOpcode = J4_jumpseti;
213 CompoundInsn = Context.createMCInst();
214 CompoundInsn->setOpcode(compoundOpcode);
215
216 CompoundInsn->addOperand(Op: Rt);
217 CompoundInsn->addOperand(Op: L.getOperand(i: 1)); // Immediate
218 CompoundInsn->addOperand(Op: R.getOperand(i: 0)); // Jump target
219 break;
220
221 case Hexagon::A2_tfr:
222 Rt = L.getOperand(i: 0);
223 Rs = L.getOperand(i: 1);
224
225 compoundOpcode = J4_jumpsetr;
226 CompoundInsn = Context.createMCInst();
227 CompoundInsn->setOpcode(compoundOpcode);
228 CompoundInsn->addOperand(Op: Rt);
229 CompoundInsn->addOperand(Op: Rs);
230 CompoundInsn->addOperand(Op: R.getOperand(i: 0)); // Jump target.
231
232 break;
233
234 case Hexagon::C2_cmpeq:
235 LLVM_DEBUG(dbgs() << "CX: C2_cmpeq\n");
236 Rs = L.getOperand(i: 1);
237 Rt = L.getOperand(i: 2);
238
239 compoundOpcode = cmpeqBitOpcode[getCompoundOp(HMCI: R)];
240 CompoundInsn = Context.createMCInst();
241 CompoundInsn->setOpcode(compoundOpcode);
242 CompoundInsn->addOperand(Op: Rs);
243 CompoundInsn->addOperand(Op: Rt);
244 CompoundInsn->addOperand(Op: R.getOperand(i: 1));
245 break;
246
247 case Hexagon::C2_cmpgt:
248 LLVM_DEBUG(dbgs() << "CX: C2_cmpgt\n");
249 Rs = L.getOperand(i: 1);
250 Rt = L.getOperand(i: 2);
251
252 compoundOpcode = cmpgtBitOpcode[getCompoundOp(HMCI: R)];
253 CompoundInsn = Context.createMCInst();
254 CompoundInsn->setOpcode(compoundOpcode);
255 CompoundInsn->addOperand(Op: Rs);
256 CompoundInsn->addOperand(Op: Rt);
257 CompoundInsn->addOperand(Op: R.getOperand(i: 1));
258 break;
259
260 case Hexagon::C2_cmpgtu:
261 LLVM_DEBUG(dbgs() << "CX: C2_cmpgtu\n");
262 Rs = L.getOperand(i: 1);
263 Rt = L.getOperand(i: 2);
264
265 compoundOpcode = cmpgtuBitOpcode[getCompoundOp(HMCI: R)];
266 CompoundInsn = Context.createMCInst();
267 CompoundInsn->setOpcode(compoundOpcode);
268 CompoundInsn->addOperand(Op: Rs);
269 CompoundInsn->addOperand(Op: Rt);
270 CompoundInsn->addOperand(Op: R.getOperand(i: 1));
271 break;
272
273 case Hexagon::C2_cmpeqi:
274 LLVM_DEBUG(dbgs() << "CX: C2_cmpeqi\n");
275 Success = L.getOperand(i: 2).getExpr()->evaluateAsAbsolute(Res&: Value);
276 (void)Success;
277 assert(Success);
278 if (Value == -1)
279 compoundOpcode = cmpeqn1BitOpcode[getCompoundOp(HMCI: R)];
280 else
281 compoundOpcode = cmpeqiBitOpcode[getCompoundOp(HMCI: R)];
282
283 Rs = L.getOperand(i: 1);
284 CompoundInsn = Context.createMCInst();
285 CompoundInsn->setOpcode(compoundOpcode);
286 CompoundInsn->addOperand(Op: Rs);
287 CompoundInsn->addOperand(Op: L.getOperand(i: 2));
288 CompoundInsn->addOperand(Op: R.getOperand(i: 1));
289 break;
290
291 case Hexagon::C2_cmpgti:
292 LLVM_DEBUG(dbgs() << "CX: C2_cmpgti\n");
293 Success = L.getOperand(i: 2).getExpr()->evaluateAsAbsolute(Res&: Value);
294 (void)Success;
295 assert(Success);
296 if (Value == -1)
297 compoundOpcode = cmpgtn1BitOpcode[getCompoundOp(HMCI: R)];
298 else
299 compoundOpcode = cmpgtiBitOpcode[getCompoundOp(HMCI: R)];
300
301 Rs = L.getOperand(i: 1);
302 CompoundInsn = Context.createMCInst();
303 CompoundInsn->setOpcode(compoundOpcode);
304 CompoundInsn->addOperand(Op: Rs);
305 CompoundInsn->addOperand(Op: L.getOperand(i: 2));
306 CompoundInsn->addOperand(Op: R.getOperand(i: 1));
307 break;
308
309 case Hexagon::C2_cmpgtui:
310 LLVM_DEBUG(dbgs() << "CX: C2_cmpgtui\n");
311 Rs = L.getOperand(i: 1);
312 compoundOpcode = cmpgtuiBitOpcode[getCompoundOp(HMCI: R)];
313 CompoundInsn = Context.createMCInst();
314 CompoundInsn->setOpcode(compoundOpcode);
315 CompoundInsn->addOperand(Op: Rs);
316 CompoundInsn->addOperand(Op: L.getOperand(i: 2));
317 CompoundInsn->addOperand(Op: R.getOperand(i: 1));
318 break;
319
320 case Hexagon::S2_tstbit_i:
321 LLVM_DEBUG(dbgs() << "CX: S2_tstbit_i\n");
322 Rs = L.getOperand(i: 1);
323 compoundOpcode = tstBitOpcode[getCompoundOp(HMCI: R)];
324 CompoundInsn = Context.createMCInst();
325 CompoundInsn->setOpcode(compoundOpcode);
326 CompoundInsn->addOperand(Op: Rs);
327 CompoundInsn->addOperand(Op: R.getOperand(i: 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(MI: MIa, IsExtended: IsExtendedA);
338 unsigned MIbG = getCompoundCandidateGroup(MI: MIb, IsExtended: 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(i: 0).getReg() == MIb.getOperand(i: 0).getReg()));
347}
348
349static bool lookForCompound(MCInstrInfo const &MCII, MCContext &Context,
350 MCInst &MCI) {
351 assert(HexagonMCInstrInfo::isBundle(MCI));
352 bool JExtended = false;
353 for (MCInst::iterator J =
354 MCI.begin() + HexagonMCInstrInfo::bundleInstructionsOffset;
355 J != MCI.end(); ++J) {
356 MCInst const *JumpInst = J->getInst();
357 if (HexagonMCInstrInfo::isImmext(MCI: *JumpInst)) {
358 JExtended = true;
359 continue;
360 }
361 if (HexagonMCInstrInfo::getType(MCII, MCI: *JumpInst) == HexagonII::TypeJ) {
362 // Try to pair with another insn (B)undled with jump.
363 bool BExtended = false;
364 for (MCInst::iterator B =
365 MCI.begin() + HexagonMCInstrInfo::bundleInstructionsOffset;
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(MCI: *Inst)) {
373 BExtended = true;
374 continue;
375 }
376 LLVM_DEBUG(dbgs() << "J,B: " << JumpInst->getOpcode() << ","
377 << Inst->getOpcode() << "\n");
378 if (isOrderedCompoundPair(MIa: *Inst, IsExtendedA: BExtended, MIb: *JumpInst, IsExtendedB: JExtended)) {
379 MCInst *CompoundInsn = getCompoundInsn(Context, L: *Inst, R: *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(I: 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.
401void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
402 MCContext &Context, MCInst &MCI) {
403 assert(HexagonMCInstrInfo::isBundle(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, ReportErrors: false, MCII, STI, MCB&: 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, MCI&: CheckList)) {
421 // Need to update the bundle.
422 MCI = CheckList;
423
424 const bool IsValid = llvm::HexagonMCShuffle(Context, ReportErrors: false, MCII, STI, MCB&: 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}
434