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