434 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is looks at a packet and tries to form compound insns10//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_t39};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::CompoundGroup80static unsigned getCompoundCandidateGroup(MCInst const &MI, bool IsExtended) {81 MCRegister 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(0).getReg();98 Src1Reg = MI.getOperand(1).getReg();99 Src2Reg = MI.getOperand(2).getReg();100 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&101 HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&102 HexagonMCInstrInfo::isIntRegForSubInst(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(0).getReg();112 SrcReg = MI.getOperand(1).getReg();113 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&114 HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&115 (HexagonMCInstrInfo::inRange<5>(MI, 2) ||116 HexagonMCInstrInfo::minConstant(MI, 2) == -1))117 return HexagonII::HCG_A;118 break;119 case Hexagon::A2_tfr:120 if (IsExtended)121 return HexagonII::HCG_None;122 // Rd = Rs123 DstReg = MI.getOperand(0).getReg();124 SrcReg = MI.getOperand(1).getReg();125 if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&126 HexagonMCInstrInfo::isIntRegForSubInst(SrcReg))127 return HexagonII::HCG_A;128 break;129 case Hexagon::A2_tfrsi:130 if (IsExtended)131 return HexagonII::HCG_None;132 // Rd = #u6133 DstReg = MI.getOperand(0).getReg();134 if (HexagonMCInstrInfo::minConstant(MI, 1) <= 63 &&135 HexagonMCInstrInfo::minConstant(MI, 1) >= 0 &&136 HexagonMCInstrInfo::isIntRegForSubInst(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(0).getReg();143 Src1Reg = MI.getOperand(1).getReg();144 if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&145 HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&146 HexagonMCInstrInfo::minConstant(MI, 2) == 0)147 return HexagonII::HCG_A;148 break;149 // The fact that .new form is used pretty much guarantees150 // that predicate register will match. Nevertheless,151 // there could be some false positives without additional152 // 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:2163 // Rd=Rs ; jump #r9:2164 // 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)); // Immediate218 CompoundInsn->addOperand(R.getOperand(0)); // Jump target219 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;277 assert(Success);278 if (Value == -1)279 compoundOpcode = cmpeqn1BitOpcode[getCompoundOp(R)];280 else281 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;295 assert(Success);296 if (Value == -1)297 compoundOpcode = cmpgtn1BitOpcode[getCompoundOp(R)];298 else299 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 register340 // 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) {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(*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 =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(*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 one398/// is found update the contents of the bundle with the compound insn.399/// If a compound instruction is found then the bundle will have one400/// 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, false, MCII, STI, MCI);417 418 // Look for compounds until none are found, only update the bundle when419 // 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}434