LLVM 20.0.0git
HexagonMCDuplexInfo.cpp
Go to the documentation of this file.
1//===- HexagonMCDuplexInfo.cpp - Instruction bundle checking --------------===//
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 implements duplexing of instructions to reduce code size
10//
11//===----------------------------------------------------------------------===//
12
13#include "HexagonMCExpr.h"
19#include "llvm/Support/Debug.h"
23#include <cassert>
24#include <cstdint>
25#include <iterator>
26#include <map>
27#include <utility>
28
29using namespace llvm;
30using namespace Hexagon;
31
32#define DEBUG_TYPE "hexagon-mcduplex-info"
33
34// pair table of subInstructions with opcodes
35static const std::pair<unsigned, unsigned> opcodeData[] = {
36 std::make_pair((unsigned)SA1_addi, 0),
37 std::make_pair((unsigned)SA1_addrx, 6144),
38 std::make_pair((unsigned)SA1_addsp, 3072),
39 std::make_pair((unsigned)SA1_and1, 4608),
40 std::make_pair((unsigned)SA1_clrf, 6768),
41 std::make_pair((unsigned)SA1_clrfnew, 6736),
42 std::make_pair((unsigned)SA1_clrt, 6752),
43 std::make_pair((unsigned)SA1_clrtnew, 6720),
44 std::make_pair((unsigned)SA1_cmpeqi, 6400),
45 std::make_pair((unsigned)SA1_combine0i, 7168),
46 std::make_pair((unsigned)SA1_combine1i, 7176),
47 std::make_pair((unsigned)SA1_combine2i, 7184),
48 std::make_pair((unsigned)SA1_combine3i, 7192),
49 std::make_pair((unsigned)SA1_combinerz, 7432),
50 std::make_pair((unsigned)SA1_combinezr, 7424),
51 std::make_pair((unsigned)SA1_dec, 4864),
52 std::make_pair((unsigned)SA1_inc, 4352),
53 std::make_pair((unsigned)SA1_seti, 2048),
54 std::make_pair((unsigned)SA1_setin1, 6656),
55 std::make_pair((unsigned)SA1_sxtb, 5376),
56 std::make_pair((unsigned)SA1_sxth, 5120),
57 std::make_pair((unsigned)SA1_tfr, 4096),
58 std::make_pair((unsigned)SA1_zxtb, 5888),
59 std::make_pair((unsigned)SA1_zxth, 5632),
60 std::make_pair((unsigned)SL1_loadri_io, 0),
61 std::make_pair((unsigned)SL1_loadrub_io, 4096),
62 std::make_pair((unsigned)SL2_deallocframe, 7936),
63 std::make_pair((unsigned)SL2_jumpr31, 8128),
64 std::make_pair((unsigned)SL2_jumpr31_f, 8133),
65 std::make_pair((unsigned)SL2_jumpr31_fnew, 8135),
66 std::make_pair((unsigned)SL2_jumpr31_t, 8132),
67 std::make_pair((unsigned)SL2_jumpr31_tnew, 8134),
68 std::make_pair((unsigned)SL2_loadrb_io, 4096),
69 std::make_pair((unsigned)SL2_loadrd_sp, 7680),
70 std::make_pair((unsigned)SL2_loadrh_io, 0),
71 std::make_pair((unsigned)SL2_loadri_sp, 7168),
72 std::make_pair((unsigned)SL2_loadruh_io, 2048),
73 std::make_pair((unsigned)SL2_return, 8000),
74 std::make_pair((unsigned)SL2_return_f, 8005),
75 std::make_pair((unsigned)SL2_return_fnew, 8007),
76 std::make_pair((unsigned)SL2_return_t, 8004),
77 std::make_pair((unsigned)SL2_return_tnew, 8006),
78 std::make_pair((unsigned)SS1_storeb_io, 4096),
79 std::make_pair((unsigned)SS1_storew_io, 0),
80 std::make_pair((unsigned)SS2_allocframe, 7168),
81 std::make_pair((unsigned)SS2_storebi0, 4608),
82 std::make_pair((unsigned)SS2_storebi1, 4864),
83 std::make_pair((unsigned)SS2_stored_sp, 2560),
84 std::make_pair((unsigned)SS2_storeh_io, 0),
85 std::make_pair((unsigned)SS2_storew_sp, 2048),
86 std::make_pair((unsigned)SS2_storewi0, 4096),
87 std::make_pair((unsigned)SS2_storewi1, 4352)};
88
89bool HexagonMCInstrInfo::isDuplexPairMatch(unsigned Ga, unsigned Gb) {
90 switch (Ga) {
92 default:
93 return false;
95 return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_A);
97 return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
98 Gb == HexagonII::HSIG_A);
100 return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
103 return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
104 Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_S2 ||
105 Gb == HexagonII::HSIG_A);
107 return (Gb == HexagonII::HSIG_A);
109 return (Gb == HexagonII::HSIG_Compound);
110 }
111 return false;
112}
113
114unsigned HexagonMCInstrInfo::iClassOfDuplexPair(unsigned Ga, unsigned Gb) {
115 switch (Ga) {
117 default:
118 break;
120 switch (Gb) {
121 default:
122 break;
124 return 0;
126 return 0x4;
127 }
128 break;
130 switch (Gb) {
131 default:
132 break;
134 return 0x1;
136 return 0x2;
138 return 0x5;
139 }
140 break;
142 switch (Gb) {
143 default:
144 break;
146 return 0x8;
148 return 0x9;
150 return 0xA;
152 return 0x6;
153 }
154 break;
156 switch (Gb) {
157 default:
158 break;
160 return 0xC;
162 return 0xD;
164 return 0xB;
166 return 0xE;
168 return 0x7;
169 }
170 break;
172 switch (Gb) {
173 default:
174 break;
176 return 0x3;
177 }
178 break;
180 switch (Gb) {
182 return 0xFFFFFFFF;
183 }
184 break;
185 }
186 return 0xFFFFFFFF;
187}
188
190 MCRegister DstReg, PredReg, SrcReg, Src1Reg, Src2Reg;
191
192 switch (MCI.getOpcode()) {
193 default:
195 //
196 // Group L1:
197 //
198 // Rd = memw(Rs+#u4:2)
199 // Rd = memub(Rs+#u4:0)
200 case Hexagon::L2_loadri_io:
201 DstReg = MCI.getOperand(0).getReg();
202 SrcReg = MCI.getOperand(1).getReg();
203 // Special case this one from Group L2.
204 // Rd = memw(r29+#u5:2)
206 if (HexagonMCInstrInfo::isIntReg(SrcReg) &&
207 Hexagon::R29 == SrcReg && inRange<5, 2>(MCI, 2)) {
208 return HexagonII::HSIG_L2;
209 }
210 // Rd = memw(Rs+#u4:2)
212 inRange<4, 2>(MCI, 2)) {
213 return HexagonII::HSIG_L1;
214 }
215 }
216 break;
217 case Hexagon::L2_loadrub_io:
218 // Rd = memub(Rs+#u4:0)
219 DstReg = MCI.getOperand(0).getReg();
220 SrcReg = MCI.getOperand(1).getReg();
223 inRange<4>(MCI, 2)) {
224 return HexagonII::HSIG_L1;
225 }
226 break;
227 //
228 // Group L2:
229 //
230 // Rd = memh/memuh(Rs+#u3:1)
231 // Rd = memb(Rs+#u3:0)
232 // Rd = memw(r29+#u5:2) - Handled above.
233 // Rdd = memd(r29+#u5:3)
234 // deallocframe
235 // [if ([!]p0[.new])] dealloc_return
236 // [if ([!]p0[.new])] jumpr r31
237 case Hexagon::L2_loadrh_io:
238 case Hexagon::L2_loadruh_io:
239 // Rd = memh/memuh(Rs+#u3:1)
240 DstReg = MCI.getOperand(0).getReg();
241 SrcReg = MCI.getOperand(1).getReg();
244 inRange<3, 1>(MCI, 2)) {
245 return HexagonII::HSIG_L2;
246 }
247 break;
248 case Hexagon::L2_loadrb_io:
249 // Rd = memb(Rs+#u3:0)
250 DstReg = MCI.getOperand(0).getReg();
251 SrcReg = MCI.getOperand(1).getReg();
254 inRange<3>(MCI, 2)) {
255 return HexagonII::HSIG_L2;
256 }
257 break;
258 case Hexagon::L2_loadrd_io:
259 // Rdd = memd(r29+#u5:3)
260 DstReg = MCI.getOperand(0).getReg();
261 SrcReg = MCI.getOperand(1).getReg();
263 HexagonMCInstrInfo::isIntReg(SrcReg) && Hexagon::R29 == SrcReg &&
264 inRange<5, 3>(MCI, 2)) {
265 return HexagonII::HSIG_L2;
266 }
267 break;
268
269 case Hexagon::L4_return:
270 case Hexagon::L2_deallocframe:
271 return HexagonII::HSIG_L2;
272
273 case Hexagon::EH_RETURN_JMPR:
274 case Hexagon::J2_jumpr:
275 case Hexagon::PS_jmpret:
276 // jumpr r31
277 // Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0.
278 DstReg = MCI.getOperand(0).getReg();
279 if (Hexagon::R31 == DstReg)
280 return HexagonII::HSIG_L2;
281 break;
282
283 case Hexagon::J2_jumprt:
284 case Hexagon::J2_jumprf:
285 case Hexagon::J2_jumprtnew:
286 case Hexagon::J2_jumprfnew:
287 case Hexagon::PS_jmprett:
288 case Hexagon::PS_jmpretf:
289 case Hexagon::PS_jmprettnew:
290 case Hexagon::PS_jmpretfnew:
291 case Hexagon::PS_jmprettnewpt:
292 case Hexagon::PS_jmpretfnewpt:
293 DstReg = MCI.getOperand(1).getReg();
294 SrcReg = MCI.getOperand(0).getReg();
295 // [if ([!]p0[.new])] jumpr r31
296 if ((Hexagon::P0 == SrcReg) && (Hexagon::R31 == DstReg)) {
297 return HexagonII::HSIG_L2;
298 }
299 break;
300 case Hexagon::L4_return_t:
301 case Hexagon::L4_return_f:
302 case Hexagon::L4_return_tnew_pnt:
303 case Hexagon::L4_return_fnew_pnt:
304 // [if ([!]p0[.new])] dealloc_return
305 SrcReg = MCI.getOperand(1).getReg();
306 if (Hexagon::P0 == SrcReg) {
307 return HexagonII::HSIG_L2;
308 }
309 break;
310 //
311 // Group S1:
312 //
313 // memw(Rs+#u4:2) = Rt
314 // memb(Rs+#u4:0) = Rt
315 case Hexagon::S2_storeri_io:
316 // Special case this one from Group S2.
317 // memw(r29+#u5:2) = Rt
318 Src1Reg = MCI.getOperand(0).getReg();
319 Src2Reg = MCI.getOperand(2).getReg();
320 if (HexagonMCInstrInfo::isIntReg(Src1Reg) &&
322 Hexagon::R29 == Src1Reg && inRange<5, 2>(MCI, 1)) {
323 return HexagonII::HSIG_S2;
324 }
325 // memw(Rs+#u4:2) = Rt
328 inRange<4, 2>(MCI, 1)) {
329 return HexagonII::HSIG_S1;
330 }
331 break;
332 case Hexagon::S2_storerb_io:
333 // memb(Rs+#u4:0) = Rt
334 Src1Reg = MCI.getOperand(0).getReg();
335 Src2Reg = MCI.getOperand(2).getReg();
338 inRange<4>(MCI, 1)) {
339 return HexagonII::HSIG_S1;
340 }
341 break;
342 //
343 // Group S2:
344 //
345 // memh(Rs+#u3:1) = Rt
346 // memw(r29+#u5:2) = Rt
347 // memd(r29+#s6:3) = Rtt
348 // memw(Rs+#u4:2) = #U1
349 // memb(Rs+#u4) = #U1
350 // allocframe(#u5:3)
351 case Hexagon::S2_storerh_io:
352 // memh(Rs+#u3:1) = Rt
353 Src1Reg = MCI.getOperand(0).getReg();
354 Src2Reg = MCI.getOperand(2).getReg();
357 inRange<3, 1>(MCI, 1)) {
358 return HexagonII::HSIG_S2;
359 }
360 break;
361 case Hexagon::S2_storerd_io:
362 // memd(r29+#s6:3) = Rtt
363 Src1Reg = MCI.getOperand(0).getReg();
364 Src2Reg = MCI.getOperand(2).getReg();
366 HexagonMCInstrInfo::isIntReg(Src1Reg) && Hexagon::R29 == Src1Reg &&
367 inSRange<6, 3>(MCI, 1)) {
368 return HexagonII::HSIG_S2;
369 }
370 break;
371 case Hexagon::S4_storeiri_io:
372 // memw(Rs+#u4:2) = #U1
373 Src1Reg = MCI.getOperand(0).getReg();
375 inRange<4, 2>(MCI, 1) && inRange<1>(MCI, 2)) {
376 return HexagonII::HSIG_S2;
377 }
378 break;
379 case Hexagon::S4_storeirb_io:
380 // memb(Rs+#u4) = #U1
381 Src1Reg = MCI.getOperand(0).getReg();
383 inRange<4>(MCI, 1) && inRange<1>(MCI, 2)) {
384 return HexagonII::HSIG_S2;
385 }
386 break;
387 case Hexagon::S2_allocframe:
388 if (inRange<5, 3>(MCI, 2))
389 return HexagonII::HSIG_S2;
390 break;
391 //
392 // Group A:
393 //
394 // Rx = add(Rx,#s7)
395 // Rd = Rs
396 // Rd = #u6
397 // Rd = #-1
398 // if ([!]P0[.new]) Rd = #0
399 // Rd = add(r29,#u6:2)
400 // Rx = add(Rx,Rs)
401 // P0 = cmp.eq(Rs,#u2)
402 // Rdd = combine(#0,Rs)
403 // Rdd = combine(Rs,#0)
404 // Rdd = combine(#u2,#U2)
405 // Rd = add(Rs,#1)
406 // Rd = add(Rs,#-1)
407 // Rd = sxth/sxtb/zxtb/zxth(Rs)
408 // Rd = and(Rs,#1)
409 case Hexagon::A2_addi:
410 DstReg = MCI.getOperand(0).getReg();
411 SrcReg = MCI.getOperand(1).getReg();
413 // Rd = add(r29,#u6:2)
414 if (HexagonMCInstrInfo::isIntReg(SrcReg) && Hexagon::R29 == SrcReg &&
415 inRange<6, 2>(MCI, 2)) {
416 return HexagonII::HSIG_A;
417 }
418 // Rx = add(Rx,#s7)
419 if (DstReg == SrcReg) {
420 return HexagonII::HSIG_A;
421 }
422 // Rd = add(Rs,#1)
423 // Rd = add(Rs,#-1)
425 (minConstant(MCI, 2) == 1 || minConstant(MCI, 2) == -1)) {
426 return HexagonII::HSIG_A;
427 }
428 }
429 break;
430 case Hexagon::A2_add:
431 // Rx = add(Rx,Rs)
432 DstReg = MCI.getOperand(0).getReg();
433 Src1Reg = MCI.getOperand(1).getReg();
434 Src2Reg = MCI.getOperand(2).getReg();
435 if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) && (DstReg == Src1Reg) &&
437 return HexagonII::HSIG_A;
438 }
439 break;
440 case Hexagon::A2_andir:
441 DstReg = MCI.getOperand(0).getReg();
442 SrcReg = MCI.getOperand(1).getReg();
445 (minConstant(MCI, 2) == 1 || minConstant(MCI, 2) == 255)) {
446 return HexagonII::HSIG_A;
447 }
448 break;
449 case Hexagon::A2_tfr:
450 // Rd = Rs
451 DstReg = MCI.getOperand(0).getReg();
452 SrcReg = MCI.getOperand(1).getReg();
455 return HexagonII::HSIG_A;
456 }
457 break;
458 case Hexagon::A2_tfrsi:
459 DstReg = MCI.getOperand(0).getReg();
460
462 return HexagonII::HSIG_A;
463 }
464 break;
465 case Hexagon::C2_cmoveit:
466 case Hexagon::C2_cmovenewit:
467 case Hexagon::C2_cmoveif:
468 case Hexagon::C2_cmovenewif:
469 // if ([!]P0[.new]) Rd = #0
470 // Actual form:
471 // %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16;
472 DstReg = MCI.getOperand(0).getReg(); // Rd
473 PredReg = MCI.getOperand(1).getReg(); // P0
475 Hexagon::P0 == PredReg && minConstant(MCI, 2) == 0) {
476 return HexagonII::HSIG_A;
477 }
478 break;
479 case Hexagon::C2_cmpeqi:
480 // P0 = cmp.eq(Rs,#u2)
481 DstReg = MCI.getOperand(0).getReg();
482 SrcReg = MCI.getOperand(1).getReg();
483 if (Hexagon::P0 == DstReg &&
485 inRange<2>(MCI, 2)) {
486 return HexagonII::HSIG_A;
487 }
488 break;
489 case Hexagon::A2_combineii:
490 case Hexagon::A4_combineii:
491 // Rdd = combine(#u2,#U2)
492 DstReg = MCI.getOperand(0).getReg();
494 inRange<2>(MCI, 1) && inRange<2>(MCI, 2)) {
495 return HexagonII::HSIG_A;
496 }
497 break;
498 case Hexagon::A4_combineri:
499 // Rdd = combine(Rs,#0)
500 DstReg = MCI.getOperand(0).getReg();
501 SrcReg = MCI.getOperand(1).getReg();
504 minConstant(MCI, 2) == 0) {
505 return HexagonII::HSIG_A;
506 }
507 break;
508 case Hexagon::A4_combineir:
509 // Rdd = combine(#0,Rs)
510 DstReg = MCI.getOperand(0).getReg();
511 SrcReg = MCI.getOperand(2).getReg();
514 minConstant(MCI, 1) == 0) {
515 return HexagonII::HSIG_A;
516 }
517 break;
518 case Hexagon::A2_sxtb:
519 case Hexagon::A2_sxth:
520 case Hexagon::A2_zxtb:
521 case Hexagon::A2_zxth:
522 // Rd = sxth/sxtb/zxtb/zxth(Rs)
523 DstReg = MCI.getOperand(0).getReg();
524 SrcReg = MCI.getOperand(1).getReg();
527 return HexagonII::HSIG_A;
528 }
529 break;
530 }
531
533}
534
536 MCRegister DstReg, SrcReg;
537 switch (potentialDuplex.getOpcode()) {
538 case Hexagon::A2_addi:
539 // testing for case of: Rx = add(Rx,#s7)
540 DstReg = potentialDuplex.getOperand(0).getReg();
541 SrcReg = potentialDuplex.getOperand(1).getReg();
542 if (DstReg == SrcReg && HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
543 int64_t Value;
544 if (!potentialDuplex.getOperand(2).getExpr()->evaluateAsAbsolute(Value))
545 return true;
546 if (!isShiftedInt<7, 0>(Value))
547 return true;
548 }
549 break;
550 case Hexagon::A2_tfrsi:
551 DstReg = potentialDuplex.getOperand(0).getReg();
552
554 int64_t Value;
555 if (!potentialDuplex.getOperand(1).getExpr()->evaluateAsAbsolute(Value))
556 return true;
557 // Check for case of Rd = #-1.
558 if (Value == -1)
559 return false;
560 // Check for case of Rd = #u6.
561 if (!isShiftedUInt<6, 0>(Value))
562 return true;
563 }
564 break;
565 default:
566 break;
567 }
568 return false;
569}
570
571/// non-Symmetrical. See if these two instructions are fit for duplex pair.
573 MCInst const &MIa, bool ExtendedA,
574 MCInst const &MIb, bool ExtendedB,
575 bool bisReversable,
576 MCSubtargetInfo const &STI) {
577 // Slot 1 cannot be extended in duplexes PRM 10.5
578 if (ExtendedA)
579 return false;
580 // Only A2_addi and A2_tfrsi can be extended in duplex form PRM 10.5
581 if (ExtendedB) {
582 unsigned Opcode = MIb.getOpcode();
583 if ((Opcode != Hexagon::A2_addi) && (Opcode != Hexagon::A2_tfrsi))
584 return false;
585 }
588
589 static std::map<unsigned, unsigned> subinstOpcodeMap(std::begin(opcodeData),
590 std::end(opcodeData));
591
592 // If a duplex contains 2 insns in the same group, the insns must be
593 // ordered such that the numerically smaller opcode is in slot 1.
594 if ((MIaG != HexagonII::HSIG_None) && (MIaG == MIbG) && bisReversable) {
597
598 unsigned zeroedSubInstS0 =
599 subinstOpcodeMap.find(SubInst0.getOpcode())->second;
600 unsigned zeroedSubInstS1 =
601 subinstOpcodeMap.find(SubInst1.getOpcode())->second;
602
603 if (zeroedSubInstS0 < zeroedSubInstS1)
604 // subinstS0 (maps to slot 0) must be greater than
605 // subinstS1 (maps to slot 1)
606 return false;
607 }
608
609 // allocframe must always be in slot 0
610 if (MIb.getOpcode() == Hexagon::S2_allocframe)
611 return false;
612
613 if ((MIaG != HexagonII::HSIG_None) && (MIbG != HexagonII::HSIG_None)) {
614 // Prevent 2 instructions with extenders from duplexing
615 // Note that MIb (slot1) can be extended and MIa (slot0)
616 // can never be extended
617 if (subInstWouldBeExtended(MIa))
618 return false;
619
620 // If duplexing produces an extender, but the original did not
621 // have an extender, do not duplex.
622 if (subInstWouldBeExtended(MIb) && !ExtendedB)
623 return false;
624 }
625
626 // If jumpr r31 appears, it must be in slot 0, and never slot 1 (MIb).
627 if (MIbG == HexagonII::HSIG_L2) {
628 if ((MIb.getNumOperands() > 1) && MIb.getOperand(1).isReg() &&
629 (MIb.getOperand(1).getReg() == Hexagon::R31))
630 return false;
631 if ((MIb.getNumOperands() > 0) && MIb.getOperand(0).isReg() &&
632 (MIb.getOperand(0).getReg() == Hexagon::R31))
633 return false;
634 }
635
636 if (STI.getCPU().equals_insensitive("hexagonv5") ||
637 STI.getCPU().equals_insensitive("hexagonv55") ||
638 STI.getCPU().equals_insensitive("hexagonv60")) {
639 // If a store appears, it must be in slot 0 (MIa) 1st, and then slot 1 (MIb);
640 // therefore, not duplexable if slot 1 is a store, and slot 0 is not.
641 if ((MIbG == HexagonII::HSIG_S1) || (MIbG == HexagonII::HSIG_S2)) {
642 if ((MIaG != HexagonII::HSIG_S1) && (MIaG != HexagonII::HSIG_S2))
643 return false;
644 }
645 }
646
647 return (isDuplexPairMatch(MIaG, MIbG));
648}
649
650/// Symmetrical. See if these two instructions are fit for duplex pair.
651bool HexagonMCInstrInfo::isDuplexPair(MCInst const &MIa, MCInst const &MIb) {
652 unsigned MIaG = getDuplexCandidateGroup(MIa),
653 MIbG = getDuplexCandidateGroup(MIb);
654 return (isDuplexPairMatch(MIaG, MIbG) || isDuplexPairMatch(MIbG, MIaG));
655}
656
657inline static void addOps(MCInst &subInstPtr, MCInst const &Inst,
658 unsigned opNum) {
659 if (Inst.getOperand(opNum).isReg()) {
660 switch (Inst.getOperand(opNum).getReg().id()) {
661 default:
662 llvm_unreachable("Not Duplexable Register");
663 break;
664 case Hexagon::R0:
665 case Hexagon::R1:
666 case Hexagon::R2:
667 case Hexagon::R3:
668 case Hexagon::R4:
669 case Hexagon::R5:
670 case Hexagon::R6:
671 case Hexagon::R7:
672 case Hexagon::D0:
673 case Hexagon::D1:
674 case Hexagon::D2:
675 case Hexagon::D3:
676 case Hexagon::R16:
677 case Hexagon::R17:
678 case Hexagon::R18:
679 case Hexagon::R19:
680 case Hexagon::R20:
681 case Hexagon::R21:
682 case Hexagon::R22:
683 case Hexagon::R23:
684 case Hexagon::D8:
685 case Hexagon::D9:
686 case Hexagon::D10:
687 case Hexagon::D11:
688 case Hexagon::P0:
689 subInstPtr.addOperand(Inst.getOperand(opNum));
690 break;
691 }
692 } else
693 subInstPtr.addOperand(Inst.getOperand(opNum));
694}
695
697 MCInst Result;
698 Result.setLoc(Inst.getLoc());
699 bool Absolute;
700 int64_t Value;
701 switch (Inst.getOpcode()) {
702 default:
703 // dbgs() << "opcode: "<< Inst->getOpcode() << "\n";
704 llvm_unreachable("Unimplemented subinstruction \n");
705 break;
706 case Hexagon::A2_addi:
707 Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
708 if (Absolute) {
709 if (Value == 1) {
710 Result.setOpcode(Hexagon::SA1_inc);
711 addOps(Result, Inst, 0);
712 addOps(Result, Inst, 1);
713 break;
714 } // 1,2 SUBInst $Rd = add($Rs, #1)
715 if (Value == -1) {
716 Result.setOpcode(Hexagon::SA1_dec);
717 addOps(Result, Inst, 0);
718 addOps(Result, Inst, 1);
719 addOps(Result, Inst, 2);
720 break;
721 } // 1,2 SUBInst $Rd = add($Rs,#-1)
722 if (Inst.getOperand(1).getReg() == Hexagon::R29) {
723 Result.setOpcode(Hexagon::SA1_addsp);
724 addOps(Result, Inst, 0);
725 addOps(Result, Inst, 2);
726 break;
727 } // 1,3 SUBInst $Rd = add(r29, #$u6_2)
728 }
729 Result.setOpcode(Hexagon::SA1_addi);
730 addOps(Result, Inst, 0);
731 addOps(Result, Inst, 1);
732 addOps(Result, Inst, 2);
733 break; // 1,2,3 SUBInst $Rx = add($Rx, #$s7)
734 case Hexagon::A2_add:
735 Result.setOpcode(Hexagon::SA1_addrx);
736 addOps(Result, Inst, 0);
737 addOps(Result, Inst, 1);
738 addOps(Result, Inst, 2);
739 break; // 1,2,3 SUBInst $Rx = add($_src_, $Rs)
740 case Hexagon::S2_allocframe:
741 Result.setOpcode(Hexagon::SS2_allocframe);
742 addOps(Result, Inst, 2);
743 break; // 1 SUBInst allocframe(#$u5_3)
744 case Hexagon::A2_andir:
745 if (minConstant(Inst, 2) == 255) {
746 Result.setOpcode(Hexagon::SA1_zxtb);
747 addOps(Result, Inst, 0);
748 addOps(Result, Inst, 1);
749 break; // 1,2 $Rd = and($Rs, #255)
750 } else {
751 Result.setOpcode(Hexagon::SA1_and1);
752 addOps(Result, Inst, 0);
753 addOps(Result, Inst, 1);
754 break; // 1,2 SUBInst $Rd = and($Rs, #1)
755 }
756 case Hexagon::C2_cmpeqi:
757 Result.setOpcode(Hexagon::SA1_cmpeqi);
758 addOps(Result, Inst, 1);
759 addOps(Result, Inst, 2);
760 break; // 2,3 SUBInst p0 = cmp.eq($Rs, #$u2)
761 case Hexagon::A4_combineii:
762 case Hexagon::A2_combineii:
763 Absolute = Inst.getOperand(1).getExpr()->evaluateAsAbsolute(Value);
764 assert(Absolute);(void)Absolute;
765 if (Value == 1) {
766 Result.setOpcode(Hexagon::SA1_combine1i);
767 addOps(Result, Inst, 0);
768 addOps(Result, Inst, 2);
769 break; // 1,3 SUBInst $Rdd = combine(#1, #$u2)
770 }
771 if (Value == 3) {
772 Result.setOpcode(Hexagon::SA1_combine3i);
773 addOps(Result, Inst, 0);
774 addOps(Result, Inst, 2);
775 break; // 1,3 SUBInst $Rdd = combine(#3, #$u2)
776 }
777 if (Value == 0) {
778 Result.setOpcode(Hexagon::SA1_combine0i);
779 addOps(Result, Inst, 0);
780 addOps(Result, Inst, 2);
781 break; // 1,3 SUBInst $Rdd = combine(#0, #$u2)
782 }
783 if (Value == 2) {
784 Result.setOpcode(Hexagon::SA1_combine2i);
785 addOps(Result, Inst, 0);
786 addOps(Result, Inst, 2);
787 break; // 1,3 SUBInst $Rdd = combine(#2, #$u2)
788 }
789 break;
790 case Hexagon::A4_combineir:
791 Result.setOpcode(Hexagon::SA1_combinezr);
792 addOps(Result, Inst, 0);
793 addOps(Result, Inst, 2);
794 break; // 1,3 SUBInst $Rdd = combine(#0, $Rs)
795 case Hexagon::A4_combineri:
796 Result.setOpcode(Hexagon::SA1_combinerz);
797 addOps(Result, Inst, 0);
798 addOps(Result, Inst, 1);
799 break; // 1,2 SUBInst $Rdd = combine($Rs, #0)
800 case Hexagon::L4_return_tnew_pnt:
801 case Hexagon::L4_return_tnew_pt:
802 Result.setOpcode(Hexagon::SL2_return_tnew);
803 break; // none SUBInst if (p0.new) dealloc_return:nt
804 case Hexagon::L4_return_fnew_pnt:
805 case Hexagon::L4_return_fnew_pt:
806 Result.setOpcode(Hexagon::SL2_return_fnew);
807 break; // none SUBInst if (!p0.new) dealloc_return:nt
808 case Hexagon::L4_return_f:
809 Result.setOpcode(Hexagon::SL2_return_f);
810 break; // none SUBInst if (!p0) dealloc_return
811 case Hexagon::L4_return_t:
812 Result.setOpcode(Hexagon::SL2_return_t);
813 break; // none SUBInst if (p0) dealloc_return
814 case Hexagon::L4_return:
815 Result.setOpcode(Hexagon::SL2_return);
816 break; // none SUBInst dealloc_return
817 case Hexagon::L2_deallocframe:
818 Result.setOpcode(Hexagon::SL2_deallocframe);
819 break; // none SUBInst deallocframe
820 case Hexagon::EH_RETURN_JMPR:
821 case Hexagon::J2_jumpr:
822 case Hexagon::PS_jmpret:
823 Result.setOpcode(Hexagon::SL2_jumpr31);
824 break; // none SUBInst jumpr r31
825 case Hexagon::J2_jumprf:
826 case Hexagon::PS_jmpretf:
827 Result.setOpcode(Hexagon::SL2_jumpr31_f);
828 break; // none SUBInst if (!p0) jumpr r31
829 case Hexagon::J2_jumprfnew:
830 case Hexagon::PS_jmpretfnewpt:
831 case Hexagon::PS_jmpretfnew:
832 Result.setOpcode(Hexagon::SL2_jumpr31_fnew);
833 break; // none SUBInst if (!p0.new) jumpr:nt r31
834 case Hexagon::J2_jumprt:
835 case Hexagon::PS_jmprett:
836 Result.setOpcode(Hexagon::SL2_jumpr31_t);
837 break; // none SUBInst if (p0) jumpr r31
838 case Hexagon::J2_jumprtnew:
839 case Hexagon::PS_jmprettnewpt:
840 case Hexagon::PS_jmprettnew:
841 Result.setOpcode(Hexagon::SL2_jumpr31_tnew);
842 break; // none SUBInst if (p0.new) jumpr:nt r31
843 case Hexagon::L2_loadrb_io:
844 Result.setOpcode(Hexagon::SL2_loadrb_io);
845 addOps(Result, Inst, 0);
846 addOps(Result, Inst, 1);
847 addOps(Result, Inst, 2);
848 break; // 1,2,3 SUBInst $Rd = memb($Rs + #$u3_0)
849 case Hexagon::L2_loadrd_io:
850 Result.setOpcode(Hexagon::SL2_loadrd_sp);
851 addOps(Result, Inst, 0);
852 addOps(Result, Inst, 2);
853 break; // 1,3 SUBInst $Rdd = memd(r29 + #$u5_3)
854 case Hexagon::L2_loadrh_io:
855 Result.setOpcode(Hexagon::SL2_loadrh_io);
856 addOps(Result, Inst, 0);
857 addOps(Result, Inst, 1);
858 addOps(Result, Inst, 2);
859 break; // 1,2,3 SUBInst $Rd = memh($Rs + #$u3_1)
860 case Hexagon::L2_loadrub_io:
861 Result.setOpcode(Hexagon::SL1_loadrub_io);
862 addOps(Result, Inst, 0);
863 addOps(Result, Inst, 1);
864 addOps(Result, Inst, 2);
865 break; // 1,2,3 SUBInst $Rd = memub($Rs + #$u4_0)
866 case Hexagon::L2_loadruh_io:
867 Result.setOpcode(Hexagon::SL2_loadruh_io);
868 addOps(Result, Inst, 0);
869 addOps(Result, Inst, 1);
870 addOps(Result, Inst, 2);
871 break; // 1,2,3 SUBInst $Rd = memuh($Rs + #$u3_1)
872 case Hexagon::L2_loadri_io:
873 if (Inst.getOperand(1).getReg() == Hexagon::R29) {
874 Result.setOpcode(Hexagon::SL2_loadri_sp);
875 addOps(Result, Inst, 0);
876 addOps(Result, Inst, 2);
877 break; // 2 1,3 SUBInst $Rd = memw(r29 + #$u5_2)
878 } else {
879 Result.setOpcode(Hexagon::SL1_loadri_io);
880 addOps(Result, Inst, 0);
881 addOps(Result, Inst, 1);
882 addOps(Result, Inst, 2);
883 break; // 1,2,3 SUBInst $Rd = memw($Rs + #$u4_2)
884 }
885 case Hexagon::S4_storeirb_io:
886 Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
887 assert(Absolute);(void)Absolute;
888 if (Value == 0) {
889 Result.setOpcode(Hexagon::SS2_storebi0);
890 addOps(Result, Inst, 0);
891 addOps(Result, Inst, 1);
892 break; // 1,2 SUBInst memb($Rs + #$u4_0)=#0
893 } else if (Value == 1) {
894 Result.setOpcode(Hexagon::SS2_storebi1);
895 addOps(Result, Inst, 0);
896 addOps(Result, Inst, 1);
897 break; // 2 1,2 SUBInst memb($Rs + #$u4_0)=#1
898 }
899 break;
900 case Hexagon::S2_storerb_io:
901 Result.setOpcode(Hexagon::SS1_storeb_io);
902 addOps(Result, Inst, 0);
903 addOps(Result, Inst, 1);
904 addOps(Result, Inst, 2);
905 break; // 1,2,3 SUBInst memb($Rs + #$u4_0) = $Rt
906 case Hexagon::S2_storerd_io:
907 Result.setOpcode(Hexagon::SS2_stored_sp);
908 addOps(Result, Inst, 1);
909 addOps(Result, Inst, 2);
910 break; // 2,3 SUBInst memd(r29 + #$s6_3) = $Rtt
911 case Hexagon::S2_storerh_io:
912 Result.setOpcode(Hexagon::SS2_storeh_io);
913 addOps(Result, Inst, 0);
914 addOps(Result, Inst, 1);
915 addOps(Result, Inst, 2);
916 break; // 1,2,3 SUBInst memb($Rs + #$u4_0) = $Rt
917 case Hexagon::S4_storeiri_io:
918 Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
919 assert(Absolute);(void)Absolute;
920 if (Value == 0) {
921 Result.setOpcode(Hexagon::SS2_storewi0);
922 addOps(Result, Inst, 0);
923 addOps(Result, Inst, 1);
924 break; // 3 1,2 SUBInst memw($Rs + #$u4_2)=#0
925 } else if (Value == 1) {
926 Result.setOpcode(Hexagon::SS2_storewi1);
927 addOps(Result, Inst, 0);
928 addOps(Result, Inst, 1);
929 break; // 3 1,2 SUBInst memw($Rs + #$u4_2)=#1
930 } else if (Inst.getOperand(0).getReg() == Hexagon::R29) {
931 Result.setOpcode(Hexagon::SS2_storew_sp);
932 addOps(Result, Inst, 1);
933 addOps(Result, Inst, 2);
934 break; // 1 2,3 SUBInst memw(r29 + #$u5_2) = $Rt
935 }
936 break;
937 case Hexagon::S2_storeri_io:
938 if (Inst.getOperand(0).getReg() == Hexagon::R29) {
939 Result.setOpcode(Hexagon::SS2_storew_sp);
940 addOps(Result, Inst, 1);
941 addOps(Result, Inst, 2); // 1,2,3 SUBInst memw(sp + #$u5_2) = $Rt
942 } else {
943 Result.setOpcode(Hexagon::SS1_storew_io);
944 addOps(Result, Inst, 0);
945 addOps(Result, Inst, 1);
946 addOps(Result, Inst, 2); // 1,2,3 SUBInst memw($Rs + #$u4_2) = $Rt
947 }
948 break;
949 case Hexagon::A2_sxtb:
950 Result.setOpcode(Hexagon::SA1_sxtb);
951 addOps(Result, Inst, 0);
952 addOps(Result, Inst, 1);
953 break; // 1,2 SUBInst $Rd = sxtb($Rs)
954 case Hexagon::A2_sxth:
955 Result.setOpcode(Hexagon::SA1_sxth);
956 addOps(Result, Inst, 0);
957 addOps(Result, Inst, 1);
958 break; // 1,2 SUBInst $Rd = sxth($Rs)
959 case Hexagon::A2_tfr:
960 Result.setOpcode(Hexagon::SA1_tfr);
961 addOps(Result, Inst, 0);
962 addOps(Result, Inst, 1);
963 break; // 1,2 SUBInst $Rd = $Rs
964 case Hexagon::C2_cmovenewif:
965 Result.setOpcode(Hexagon::SA1_clrfnew);
966 addOps(Result, Inst, 0);
967 addOps(Result, Inst, 1);
968 break; // 2 SUBInst if (!p0.new) $Rd = #0
969 case Hexagon::C2_cmovenewit:
970 Result.setOpcode(Hexagon::SA1_clrtnew);
971 addOps(Result, Inst, 0);
972 addOps(Result, Inst, 1);
973 break; // 2 SUBInst if (p0.new) $Rd = #0
974 case Hexagon::C2_cmoveif:
975 Result.setOpcode(Hexagon::SA1_clrf);
976 addOps(Result, Inst, 0);
977 addOps(Result, Inst, 1);
978 break; // 2 SUBInst if (!p0) $Rd = #0
979 case Hexagon::C2_cmoveit:
980 Result.setOpcode(Hexagon::SA1_clrt);
981 addOps(Result, Inst, 0);
982 addOps(Result, Inst, 1);
983 break; // 2 SUBInst if (p0) $Rd = #0
984 case Hexagon::A2_tfrsi:
985 Absolute = Inst.getOperand(1).getExpr()->evaluateAsAbsolute(Value);
986 if (Absolute && Value == -1) {
987 Result.setOpcode(Hexagon::SA1_setin1);
988 addOps(Result, Inst, 0);
989 addOps(Result, Inst, 1);
990 break; // 2 1 SUBInst $Rd = #-1
991 } else {
992 Result.setOpcode(Hexagon::SA1_seti);
993 addOps(Result, Inst, 0);
994 addOps(Result, Inst, 1);
995 break; // 1,2 SUBInst $Rd = #$u6
996 }
997 case Hexagon::A2_zxtb:
998 Result.setOpcode(Hexagon::SA1_zxtb);
999 addOps(Result, Inst, 0);
1000 addOps(Result, Inst, 1);
1001 break; // 1,2 $Rd = and($Rs, #255)
1002
1003 case Hexagon::A2_zxth:
1004 Result.setOpcode(Hexagon::SA1_zxth);
1005 addOps(Result, Inst, 0);
1006 addOps(Result, Inst, 1);
1007 break; // 1,2 SUBInst $Rd = zxth($Rs)
1008 }
1009 return Result;
1010}
1011
1012static bool isStoreInst(unsigned opCode) {
1013 switch (opCode) {
1014 case Hexagon::S2_storeri_io:
1015 case Hexagon::S2_storerb_io:
1016 case Hexagon::S2_storerh_io:
1017 case Hexagon::S2_storerd_io:
1018 case Hexagon::S4_storeiri_io:
1019 case Hexagon::S4_storeirb_io:
1020 case Hexagon::S2_allocframe:
1021 return true;
1022 default:
1023 return false;
1024 }
1025}
1026
1029 MCSubtargetInfo const &STI,
1030 MCInst const &MCB) {
1031 assert(isBundle(MCB));
1033 // Use an "order matters" version of isDuplexPair.
1034 unsigned numInstrInPacket = MCB.getNumOperands();
1035
1036 for (unsigned distance = 1; distance < numInstrInPacket; ++distance) {
1038 k = j + distance;
1039 (j < numInstrInPacket) && (k < numInstrInPacket); ++j, ++k) {
1040
1041 // Check if reversible.
1042 bool bisReversable = true;
1043 if (isStoreInst(MCB.getOperand(j).getInst()->getOpcode()) &&
1044 isStoreInst(MCB.getOperand(k).getInst()->getOpcode())) {
1045 LLVM_DEBUG(dbgs() << "skip out of order write pair: " << k << "," << j
1046 << "\n");
1047 bisReversable = false;
1048 }
1049 if (HexagonMCInstrInfo::isMemReorderDisabled(MCB)) // }:mem_noshuf
1050 bisReversable = false;
1051
1052 // Try in order.
1054 MCII, *MCB.getOperand(k).getInst(),
1056 *MCB.getOperand(j).getInst(),
1058 bisReversable, STI)) {
1059 // Get iClass.
1060 unsigned iClass = iClassOfDuplexPair(
1063
1064 // Save off pairs for duplex checking.
1065 duplexToTry.push_back(DuplexCandidate(j, k, iClass));
1066 LLVM_DEBUG(dbgs() << "adding pair: " << j << "," << k << ":"
1067 << MCB.getOperand(j).getInst()->getOpcode() << ","
1068 << MCB.getOperand(k).getInst()->getOpcode() << "\n");
1069 continue;
1070 } else {
1071 LLVM_DEBUG(dbgs() << "skipping pair: " << j << "," << k << ":"
1072 << MCB.getOperand(j).getInst()->getOpcode() << ","
1073 << MCB.getOperand(k).getInst()->getOpcode() << "\n");
1074 }
1075
1076 // Try reverse.
1077 if (bisReversable) {
1079 MCII, *MCB.getOperand(j).getInst(),
1081 *MCB.getOperand(k).getInst(),
1083 bisReversable, STI)) {
1084 // Get iClass.
1085 unsigned iClass = iClassOfDuplexPair(
1088
1089 // Save off pairs for duplex checking.
1090 duplexToTry.push_back(DuplexCandidate(k, j, iClass));
1092 << "adding pair:" << k << "," << j << ":"
1093 << MCB.getOperand(j).getInst()->getOpcode() << ","
1094 << MCB.getOperand(k).getInst()->getOpcode() << "\n");
1095 } else {
1097 << "skipping pair: " << k << "," << j << ":"
1098 << MCB.getOperand(j).getInst()->getOpcode() << ","
1099 << MCB.getOperand(k).getInst()->getOpcode() << "\n");
1100 }
1101 }
1102 }
1103 }
1104 return duplexToTry;
1105}
#define LLVM_DEBUG(...)
Definition: Debug.h:106
static bool isDuplexPairMatch(unsigned Ga, unsigned Gb)
static const std::pair< unsigned, unsigned > opcodeData[]
static void addOps(MCInst &subInstPtr, MCInst const &Inst, unsigned opNum)
static bool isStoreInst(unsigned opCode)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
unsigned getNumOperands() const
Definition: MCInst.h:209
SMLoc getLoc() const
Definition: MCInst.h:205
unsigned getOpcode() const
Definition: MCInst.h:199
void addOperand(const MCOperand Op)
Definition: MCInst.h:211
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:207
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
bool isReg() const
Definition: MCInst.h:62
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:70
const MCInst * getInst() const
Definition: MCInst.h:125
const MCExpr * getExpr() const
Definition: MCInst.h:115
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
constexpr unsigned id() const
Definition: MCRegister.h:79
Generic base class for all target subtargets.
StringRef getCPU() const
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition: StringRef.h:176
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isOrderedDuplexPair(MCInstrInfo const &MCII, MCInst const &MIa, bool ExtendedA, MCInst const &MIb, bool ExtendedB, bool bisReversable, MCSubtargetInfo const &STI)
non-Symmetrical. See if these two instructions are fit for duplex pair.
bool isDuplexPairMatch(unsigned Ga, unsigned Gb)
bool subInstWouldBeExtended(MCInst const &potentialDuplex)
MCInst deriveSubInst(MCInst const &Inst)
bool isIntReg(MCRegister Reg)
SmallVector< DuplexCandidate, 8 > getDuplexPossibilties(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &MCB)
bool isMemReorderDisabled(MCInst const &MCI)
bool isBundle(MCInst const &MCI)
int64_t minConstant(MCInst const &MCI, size_t Index)
bool isDblRegForSubInst(MCRegister Reg)
bool isDuplexPair(MCInst const &MIa, MCInst const &MIb)
Symmetrical. See if these two instructions are fit for duplex pair.
bool isIntRegForSubInst(MCRegister Reg)
constexpr size_t bundleInstructionsOffset
bool hasExtenderForIndex(MCInst const &MCB, size_t Index)
unsigned getDuplexCandidateGroup(MCInst const &MI)
unsigned iClassOfDuplexPair(unsigned Ga, unsigned Gb)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163