10b57cec5SDimitry Andric //===- HexagonInstrInfo.cpp - Hexagon Instruction Information -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the Hexagon implementation of the TargetInstrInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "HexagonInstrInfo.h" 140b57cec5SDimitry Andric #include "Hexagon.h" 150b57cec5SDimitry Andric #include "HexagonFrameLowering.h" 160b57cec5SDimitry Andric #include "HexagonHazardRecognizer.h" 170b57cec5SDimitry Andric #include "HexagonRegisterInfo.h" 180b57cec5SDimitry Andric #include "HexagonSubtarget.h" 190b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 2206c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/DFAPacketizer.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 360b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 370b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 380b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 390b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 400b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 410b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 42*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h" 430b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 44*0fca6ea1SDimitry Andric #include "llvm/IR/GlobalVariable.h" 450b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 460eae32dcSDimitry Andric #include "llvm/MC/MCInstBuilder.h" 470b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 480b57cec5SDimitry Andric #include "llvm/MC/MCInstrItineraries.h" 490b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 500b57cec5SDimitry Andric #include "llvm/Support/BranchProbability.h" 510b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 520b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 530b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 540b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 550b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 560b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 570b57cec5SDimitry Andric #include <cassert> 580b57cec5SDimitry Andric #include <cctype> 590b57cec5SDimitry Andric #include <cstdint> 600b57cec5SDimitry Andric #include <cstring> 610b57cec5SDimitry Andric #include <iterator> 62bdd1243dSDimitry Andric #include <optional> 630b57cec5SDimitry Andric #include <string> 640b57cec5SDimitry Andric #include <utility> 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric using namespace llvm; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric #define DEBUG_TYPE "hexagon-instrinfo" 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR 710b57cec5SDimitry Andric #define GET_INSTRMAP_INFO 720b57cec5SDimitry Andric #include "HexagonDepTimingClasses.h" 730b57cec5SDimitry Andric #include "HexagonGenDFAPacketizer.inc" 740b57cec5SDimitry Andric #include "HexagonGenInstrInfo.inc" 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric cl::opt<bool> ScheduleInlineAsm("hexagon-sched-inline-asm", cl::Hidden, 770b57cec5SDimitry Andric cl::init(false), cl::desc("Do not consider inline-asm a scheduling/" 780b57cec5SDimitry Andric "packetization boundary.")); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric static cl::opt<bool> EnableBranchPrediction("hexagon-enable-branch-prediction", 810b57cec5SDimitry Andric cl::Hidden, cl::init(true), cl::desc("Enable branch prediction")); 820b57cec5SDimitry Andric 8381ad6265SDimitry Andric static cl::opt<bool> DisableNVSchedule( 8481ad6265SDimitry Andric "disable-hexagon-nv-schedule", cl::Hidden, 850b57cec5SDimitry Andric cl::desc("Disable schedule adjustment for new value stores.")); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric static cl::opt<bool> EnableTimingClassLatency( 880b57cec5SDimitry Andric "enable-timing-class-latency", cl::Hidden, cl::init(false), 890b57cec5SDimitry Andric cl::desc("Enable timing class latency")); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric static cl::opt<bool> EnableALUForwarding( 920b57cec5SDimitry Andric "enable-alu-forwarding", cl::Hidden, cl::init(true), 930b57cec5SDimitry Andric cl::desc("Enable vec alu forwarding")); 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric static cl::opt<bool> EnableACCForwarding( 960b57cec5SDimitry Andric "enable-acc-forwarding", cl::Hidden, cl::init(true), 970b57cec5SDimitry Andric cl::desc("Enable vec acc forwarding")); 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric static cl::opt<bool> BranchRelaxAsmLarge("branch-relax-asm-large", 10081ad6265SDimitry Andric cl::init(true), cl::Hidden, 10181ad6265SDimitry Andric cl::desc("branch relax asm")); 1020b57cec5SDimitry Andric 10381ad6265SDimitry Andric static cl::opt<bool> 10481ad6265SDimitry Andric UseDFAHazardRec("dfa-hazard-rec", cl::init(true), cl::Hidden, 1050b57cec5SDimitry Andric cl::desc("Use the DFA based hazard recognizer.")); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// Constants for Hexagon instructions. 1080b57cec5SDimitry Andric const int Hexagon_MEMW_OFFSET_MAX = 4095; 1090b57cec5SDimitry Andric const int Hexagon_MEMW_OFFSET_MIN = -4096; 1100b57cec5SDimitry Andric const int Hexagon_MEMD_OFFSET_MAX = 8191; 1110b57cec5SDimitry Andric const int Hexagon_MEMD_OFFSET_MIN = -8192; 1120b57cec5SDimitry Andric const int Hexagon_MEMH_OFFSET_MAX = 2047; 1130b57cec5SDimitry Andric const int Hexagon_MEMH_OFFSET_MIN = -2048; 1140b57cec5SDimitry Andric const int Hexagon_MEMB_OFFSET_MAX = 1023; 1150b57cec5SDimitry Andric const int Hexagon_MEMB_OFFSET_MIN = -1024; 1160b57cec5SDimitry Andric const int Hexagon_ADDI_OFFSET_MAX = 32767; 1170b57cec5SDimitry Andric const int Hexagon_ADDI_OFFSET_MIN = -32768; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric // Pin the vtable to this file. 1200b57cec5SDimitry Andric void HexagonInstrInfo::anchor() {} 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric HexagonInstrInfo::HexagonInstrInfo(HexagonSubtarget &ST) 1230b57cec5SDimitry Andric : HexagonGenInstrInfo(Hexagon::ADJCALLSTACKDOWN, Hexagon::ADJCALLSTACKUP), 1240b57cec5SDimitry Andric Subtarget(ST) {} 1250b57cec5SDimitry Andric 1265ffd83dbSDimitry Andric namespace llvm { 1275ffd83dbSDimitry Andric namespace HexagonFUnits { 1285ffd83dbSDimitry Andric bool isSlot0Only(unsigned units); 1295ffd83dbSDimitry Andric } 1305ffd83dbSDimitry Andric } 1315ffd83dbSDimitry Andric 132bdd1243dSDimitry Andric static bool isIntRegForSubInst(Register Reg) { 1330b57cec5SDimitry Andric return (Reg >= Hexagon::R0 && Reg <= Hexagon::R7) || 1340b57cec5SDimitry Andric (Reg >= Hexagon::R16 && Reg <= Hexagon::R23); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 137bdd1243dSDimitry Andric static bool isDblRegForSubInst(Register Reg, const HexagonRegisterInfo &HRI) { 1380b57cec5SDimitry Andric return isIntRegForSubInst(HRI.getSubReg(Reg, Hexagon::isub_lo)) && 1390b57cec5SDimitry Andric isIntRegForSubInst(HRI.getSubReg(Reg, Hexagon::isub_hi)); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric /// Calculate number of instructions excluding the debug instructions. 1430b57cec5SDimitry Andric static unsigned nonDbgMICount(MachineBasicBlock::const_instr_iterator MIB, 1440b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator MIE) { 1450b57cec5SDimitry Andric unsigned Count = 0; 1460b57cec5SDimitry Andric for (; MIB != MIE; ++MIB) { 1470b57cec5SDimitry Andric if (!MIB->isDebugInstr()) 1480b57cec5SDimitry Andric ++Count; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric return Count; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 15304eeddc0SDimitry Andric // Check if the A2_tfrsi instruction is cheap or not. If the operand has 15404eeddc0SDimitry Andric // to be constant-extendend it is not cheap since it occupies two slots 15504eeddc0SDimitry Andric // in a packet. 15604eeddc0SDimitry Andric bool HexagonInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const { 15704eeddc0SDimitry Andric // Enable the following steps only at Os/Oz 15804eeddc0SDimitry Andric if (!(MI.getMF()->getFunction().hasOptSize())) 15904eeddc0SDimitry Andric return MI.isAsCheapAsAMove(); 16004eeddc0SDimitry Andric 16104eeddc0SDimitry Andric if (MI.getOpcode() == Hexagon::A2_tfrsi) { 16204eeddc0SDimitry Andric auto Op = MI.getOperand(1); 16304eeddc0SDimitry Andric // If the instruction has a global address as operand, it is not cheap 16404eeddc0SDimitry Andric // since the operand will be constant extended. 16581ad6265SDimitry Andric if (Op.isGlobal()) 16604eeddc0SDimitry Andric return false; 16704eeddc0SDimitry Andric // If the instruction has an operand of size > 16bits, its will be 16804eeddc0SDimitry Andric // const-extended and hence, it is not cheap. 16904eeddc0SDimitry Andric if (Op.isImm()) { 17004eeddc0SDimitry Andric int64_t Imm = Op.getImm(); 17104eeddc0SDimitry Andric if (!isInt<16>(Imm)) 17204eeddc0SDimitry Andric return false; 17304eeddc0SDimitry Andric } 17404eeddc0SDimitry Andric } 17504eeddc0SDimitry Andric return MI.isAsCheapAsAMove(); 17604eeddc0SDimitry Andric } 17704eeddc0SDimitry Andric 17804eeddc0SDimitry Andric // Do not sink floating point instructions that updates USR register. 17904eeddc0SDimitry Andric // Example: 18004eeddc0SDimitry Andric // feclearexcept 18104eeddc0SDimitry Andric // F2_conv_w2sf 18204eeddc0SDimitry Andric // fetestexcept 18304eeddc0SDimitry Andric // MachineSink sinks F2_conv_w2sf and we are not able to catch exceptions. 18404eeddc0SDimitry Andric // TODO: On some of these floating point instructions, USR is marked as Use. 18504eeddc0SDimitry Andric // In reality, these instructions also Def the USR. If USR is marked as Def, 18604eeddc0SDimitry Andric // some of the assumptions in assembler packetization are broken. 18704eeddc0SDimitry Andric bool HexagonInstrInfo::shouldSink(const MachineInstr &MI) const { 18804eeddc0SDimitry Andric // Assumption: A floating point instruction that reads the USR will write 18904eeddc0SDimitry Andric // the USR as well. 19004eeddc0SDimitry Andric if (isFloat(MI) && MI.hasRegisterImplicitUseOperand(Hexagon::USR)) 19104eeddc0SDimitry Andric return false; 19204eeddc0SDimitry Andric return true; 19304eeddc0SDimitry Andric } 19404eeddc0SDimitry Andric 1950b57cec5SDimitry Andric /// Find the hardware loop instruction used to set-up the specified loop. 1960b57cec5SDimitry Andric /// On Hexagon, we have two instructions used to set-up the hardware loop 1970b57cec5SDimitry Andric /// (LOOP0, LOOP1) with corresponding endloop (ENDLOOP0, ENDLOOP1) instructions 1980b57cec5SDimitry Andric /// to indicate the end of a loop. 1990b57cec5SDimitry Andric MachineInstr *HexagonInstrInfo::findLoopInstr(MachineBasicBlock *BB, 2000b57cec5SDimitry Andric unsigned EndLoopOp, MachineBasicBlock *TargetBB, 2010b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> &Visited) const { 2020b57cec5SDimitry Andric unsigned LOOPi; 2030b57cec5SDimitry Andric unsigned LOOPr; 2040b57cec5SDimitry Andric if (EndLoopOp == Hexagon::ENDLOOP0) { 2050b57cec5SDimitry Andric LOOPi = Hexagon::J2_loop0i; 2060b57cec5SDimitry Andric LOOPr = Hexagon::J2_loop0r; 2070b57cec5SDimitry Andric } else { // EndLoopOp == Hexagon::EndLOOP1 2080b57cec5SDimitry Andric LOOPi = Hexagon::J2_loop1i; 2090b57cec5SDimitry Andric LOOPr = Hexagon::J2_loop1r; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric // The loop set-up instruction will be in a predecessor block 2130b57cec5SDimitry Andric for (MachineBasicBlock *PB : BB->predecessors()) { 2140b57cec5SDimitry Andric // If this has been visited, already skip it. 2150b57cec5SDimitry Andric if (!Visited.insert(PB).second) 2160b57cec5SDimitry Andric continue; 2170b57cec5SDimitry Andric if (PB == BB) 2180b57cec5SDimitry Andric continue; 219349cc55cSDimitry Andric for (MachineInstr &I : llvm::reverse(PB->instrs())) { 220349cc55cSDimitry Andric unsigned Opc = I.getOpcode(); 2210b57cec5SDimitry Andric if (Opc == LOOPi || Opc == LOOPr) 222349cc55cSDimitry Andric return &I; 2230b57cec5SDimitry Andric // We've reached a different loop, which means the loop01 has been 2240b57cec5SDimitry Andric // removed. 225349cc55cSDimitry Andric if (Opc == EndLoopOp && I.getOperand(0).getMBB() != TargetBB) 2260b57cec5SDimitry Andric return nullptr; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric // Check the predecessors for the LOOP instruction. 2290b57cec5SDimitry Andric if (MachineInstr *Loop = findLoopInstr(PB, EndLoopOp, TargetBB, Visited)) 2300b57cec5SDimitry Andric return Loop; 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric return nullptr; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric /// Gather register def/uses from MI. 2360b57cec5SDimitry Andric /// This treats possible (predicated) defs as actually happening ones 2370b57cec5SDimitry Andric /// (conservatively). 2380b57cec5SDimitry Andric static inline void parseOperands(const MachineInstr &MI, 239bdd1243dSDimitry Andric SmallVectorImpl<Register> &Defs, SmallVectorImpl<Register> &Uses) { 2400b57cec5SDimitry Andric Defs.clear(); 2410b57cec5SDimitry Andric Uses.clear(); 2420b57cec5SDimitry Andric 2434824e7fdSDimitry Andric for (const MachineOperand &MO : MI.operands()) { 2440b57cec5SDimitry Andric if (!MO.isReg()) 2450b57cec5SDimitry Andric continue; 2460b57cec5SDimitry Andric 2478bcb0991SDimitry Andric Register Reg = MO.getReg(); 2480b57cec5SDimitry Andric if (!Reg) 2490b57cec5SDimitry Andric continue; 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric if (MO.isUse()) 2520b57cec5SDimitry Andric Uses.push_back(MO.getReg()); 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric if (MO.isDef()) 2550b57cec5SDimitry Andric Defs.push_back(MO.getReg()); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric // Position dependent, so check twice for swap. 2600b57cec5SDimitry Andric static bool isDuplexPairMatch(unsigned Ga, unsigned Gb) { 2610b57cec5SDimitry Andric switch (Ga) { 2620b57cec5SDimitry Andric case HexagonII::HSIG_None: 2630b57cec5SDimitry Andric default: 2640b57cec5SDimitry Andric return false; 2650b57cec5SDimitry Andric case HexagonII::HSIG_L1: 2660b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_A); 2670b57cec5SDimitry Andric case HexagonII::HSIG_L2: 2680b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 || 2690b57cec5SDimitry Andric Gb == HexagonII::HSIG_A); 2700b57cec5SDimitry Andric case HexagonII::HSIG_S1: 2710b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 || 2720b57cec5SDimitry Andric Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_A); 2730b57cec5SDimitry Andric case HexagonII::HSIG_S2: 2740b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 || 2750b57cec5SDimitry Andric Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_S2 || 2760b57cec5SDimitry Andric Gb == HexagonII::HSIG_A); 2770b57cec5SDimitry Andric case HexagonII::HSIG_A: 2780b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_A); 2790b57cec5SDimitry Andric case HexagonII::HSIG_Compound: 2800b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_Compound); 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric return false; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric /// isLoadFromStackSlot - If the specified machine instruction is a direct 2860b57cec5SDimitry Andric /// load from a stack slot, return the virtual or physical register number of 2870b57cec5SDimitry Andric /// the destination along with the FrameIndex of the loaded stack slot. If 2880b57cec5SDimitry Andric /// not, return 0. This predicate must return 0 if the instruction has 2890b57cec5SDimitry Andric /// any side effects other than loading from the stack slot. 290*0fca6ea1SDimitry Andric Register HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, 2910b57cec5SDimitry Andric int &FrameIndex) const { 2920b57cec5SDimitry Andric switch (MI.getOpcode()) { 2930b57cec5SDimitry Andric default: 2940b57cec5SDimitry Andric break; 2950b57cec5SDimitry Andric case Hexagon::L2_loadri_io: 2960b57cec5SDimitry Andric case Hexagon::L2_loadrd_io: 2970b57cec5SDimitry Andric case Hexagon::V6_vL32b_ai: 2980b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_ai: 2990b57cec5SDimitry Andric case Hexagon::V6_vL32Ub_ai: 3000b57cec5SDimitry Andric case Hexagon::LDriw_pred: 3010b57cec5SDimitry Andric case Hexagon::LDriw_ctr: 3020b57cec5SDimitry Andric case Hexagon::PS_vloadrq_ai: 3030b57cec5SDimitry Andric case Hexagon::PS_vloadrw_ai: 3040b57cec5SDimitry Andric case Hexagon::PS_vloadrw_nt_ai: { 3050b57cec5SDimitry Andric const MachineOperand OpFI = MI.getOperand(1); 3060b57cec5SDimitry Andric if (!OpFI.isFI()) 3070b57cec5SDimitry Andric return 0; 3080b57cec5SDimitry Andric const MachineOperand OpOff = MI.getOperand(2); 3090b57cec5SDimitry Andric if (!OpOff.isImm() || OpOff.getImm() != 0) 3100b57cec5SDimitry Andric return 0; 3110b57cec5SDimitry Andric FrameIndex = OpFI.getIndex(); 3120b57cec5SDimitry Andric return MI.getOperand(0).getReg(); 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric case Hexagon::L2_ploadrit_io: 3160b57cec5SDimitry Andric case Hexagon::L2_ploadrif_io: 3170b57cec5SDimitry Andric case Hexagon::L2_ploadrdt_io: 3180b57cec5SDimitry Andric case Hexagon::L2_ploadrdf_io: { 3190b57cec5SDimitry Andric const MachineOperand OpFI = MI.getOperand(2); 3200b57cec5SDimitry Andric if (!OpFI.isFI()) 3210b57cec5SDimitry Andric return 0; 3220b57cec5SDimitry Andric const MachineOperand OpOff = MI.getOperand(3); 3230b57cec5SDimitry Andric if (!OpOff.isImm() || OpOff.getImm() != 0) 3240b57cec5SDimitry Andric return 0; 3250b57cec5SDimitry Andric FrameIndex = OpFI.getIndex(); 3260b57cec5SDimitry Andric return MI.getOperand(0).getReg(); 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric return 0; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric /// isStoreToStackSlot - If the specified machine instruction is a direct 3340b57cec5SDimitry Andric /// store to a stack slot, return the virtual or physical register number of 3350b57cec5SDimitry Andric /// the source reg along with the FrameIndex of the loaded stack slot. If 3360b57cec5SDimitry Andric /// not, return 0. This predicate must return 0 if the instruction has 3370b57cec5SDimitry Andric /// any side effects other than storing to the stack slot. 338*0fca6ea1SDimitry Andric Register HexagonInstrInfo::isStoreToStackSlot(const MachineInstr &MI, 3390b57cec5SDimitry Andric int &FrameIndex) const { 3400b57cec5SDimitry Andric switch (MI.getOpcode()) { 3410b57cec5SDimitry Andric default: 3420b57cec5SDimitry Andric break; 3430b57cec5SDimitry Andric case Hexagon::S2_storerb_io: 3440b57cec5SDimitry Andric case Hexagon::S2_storerh_io: 3450b57cec5SDimitry Andric case Hexagon::S2_storeri_io: 3460b57cec5SDimitry Andric case Hexagon::S2_storerd_io: 3470b57cec5SDimitry Andric case Hexagon::V6_vS32b_ai: 3480b57cec5SDimitry Andric case Hexagon::V6_vS32Ub_ai: 3490b57cec5SDimitry Andric case Hexagon::STriw_pred: 3500b57cec5SDimitry Andric case Hexagon::STriw_ctr: 3510b57cec5SDimitry Andric case Hexagon::PS_vstorerq_ai: 3520b57cec5SDimitry Andric case Hexagon::PS_vstorerw_ai: { 3530b57cec5SDimitry Andric const MachineOperand &OpFI = MI.getOperand(0); 3540b57cec5SDimitry Andric if (!OpFI.isFI()) 3550b57cec5SDimitry Andric return 0; 3560b57cec5SDimitry Andric const MachineOperand &OpOff = MI.getOperand(1); 3570b57cec5SDimitry Andric if (!OpOff.isImm() || OpOff.getImm() != 0) 3580b57cec5SDimitry Andric return 0; 3590b57cec5SDimitry Andric FrameIndex = OpFI.getIndex(); 3600b57cec5SDimitry Andric return MI.getOperand(2).getReg(); 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric case Hexagon::S2_pstorerbt_io: 3640b57cec5SDimitry Andric case Hexagon::S2_pstorerbf_io: 3650b57cec5SDimitry Andric case Hexagon::S2_pstorerht_io: 3660b57cec5SDimitry Andric case Hexagon::S2_pstorerhf_io: 3670b57cec5SDimitry Andric case Hexagon::S2_pstorerit_io: 3680b57cec5SDimitry Andric case Hexagon::S2_pstorerif_io: 3690b57cec5SDimitry Andric case Hexagon::S2_pstorerdt_io: 3700b57cec5SDimitry Andric case Hexagon::S2_pstorerdf_io: { 3710b57cec5SDimitry Andric const MachineOperand &OpFI = MI.getOperand(1); 3720b57cec5SDimitry Andric if (!OpFI.isFI()) 3730b57cec5SDimitry Andric return 0; 3740b57cec5SDimitry Andric const MachineOperand &OpOff = MI.getOperand(2); 3750b57cec5SDimitry Andric if (!OpOff.isImm() || OpOff.getImm() != 0) 3760b57cec5SDimitry Andric return 0; 3770b57cec5SDimitry Andric FrameIndex = OpFI.getIndex(); 3780b57cec5SDimitry Andric return MI.getOperand(3).getReg(); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric return 0; 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric /// This function checks if the instruction or bundle of instructions 3860b57cec5SDimitry Andric /// has load from stack slot and returns frameindex and machine memory 3870b57cec5SDimitry Andric /// operand of that instruction if true. 3880b57cec5SDimitry Andric bool HexagonInstrInfo::hasLoadFromStackSlot( 3890b57cec5SDimitry Andric const MachineInstr &MI, 3900b57cec5SDimitry Andric SmallVectorImpl<const MachineMemOperand *> &Accesses) const { 3910b57cec5SDimitry Andric if (MI.isBundle()) { 3920b57cec5SDimitry Andric const MachineBasicBlock *MBB = MI.getParent(); 3930b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator MII = MI.getIterator(); 3940b57cec5SDimitry Andric for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) 3950b57cec5SDimitry Andric if (TargetInstrInfo::hasLoadFromStackSlot(*MII, Accesses)) 3960b57cec5SDimitry Andric return true; 3970b57cec5SDimitry Andric return false; 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric return TargetInstrInfo::hasLoadFromStackSlot(MI, Accesses); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric /// This function checks if the instruction or bundle of instructions 4040b57cec5SDimitry Andric /// has store to stack slot and returns frameindex and machine memory 4050b57cec5SDimitry Andric /// operand of that instruction if true. 4060b57cec5SDimitry Andric bool HexagonInstrInfo::hasStoreToStackSlot( 4070b57cec5SDimitry Andric const MachineInstr &MI, 4080b57cec5SDimitry Andric SmallVectorImpl<const MachineMemOperand *> &Accesses) const { 4090b57cec5SDimitry Andric if (MI.isBundle()) { 4100b57cec5SDimitry Andric const MachineBasicBlock *MBB = MI.getParent(); 4110b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator MII = MI.getIterator(); 4120b57cec5SDimitry Andric for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) 4130b57cec5SDimitry Andric if (TargetInstrInfo::hasStoreToStackSlot(*MII, Accesses)) 4140b57cec5SDimitry Andric return true; 4150b57cec5SDimitry Andric return false; 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric return TargetInstrInfo::hasStoreToStackSlot(MI, Accesses); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric /// This function can analyze one/two way branching only and should (mostly) be 4220b57cec5SDimitry Andric /// called by target independent side. 4230b57cec5SDimitry Andric /// First entry is always the opcode of the branching instruction, except when 4245ffd83dbSDimitry Andric /// the Cond vector is supposed to be empty, e.g., when analyzeBranch fails, a 4250b57cec5SDimitry Andric /// BB with only unconditional jump. Subsequent entries depend upon the opcode, 4260b57cec5SDimitry Andric /// e.g. Jump_c p will have 4270b57cec5SDimitry Andric /// Cond[0] = Jump_c 4280b57cec5SDimitry Andric /// Cond[1] = p 4290b57cec5SDimitry Andric /// HW-loop ENDLOOP: 4300b57cec5SDimitry Andric /// Cond[0] = ENDLOOP 4310b57cec5SDimitry Andric /// Cond[1] = MBB 4320b57cec5SDimitry Andric /// New value jump: 4330b57cec5SDimitry Andric /// Cond[0] = Hexagon::CMPEQri_f_Jumpnv_t_V4 -- specific opcode 4340b57cec5SDimitry Andric /// Cond[1] = R 4350b57cec5SDimitry Andric /// Cond[2] = Imm 4360b57cec5SDimitry Andric bool HexagonInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 4370b57cec5SDimitry Andric MachineBasicBlock *&TBB, 4380b57cec5SDimitry Andric MachineBasicBlock *&FBB, 4390b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 4400b57cec5SDimitry Andric bool AllowModify) const { 4410b57cec5SDimitry Andric TBB = nullptr; 4420b57cec5SDimitry Andric FBB = nullptr; 4430b57cec5SDimitry Andric Cond.clear(); 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric // If the block has no terminators, it just falls into the block after it. 4460b57cec5SDimitry Andric MachineBasicBlock::instr_iterator I = MBB.instr_end(); 4470b57cec5SDimitry Andric if (I == MBB.instr_begin()) 4480b57cec5SDimitry Andric return false; 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric // A basic block may looks like this: 4510b57cec5SDimitry Andric // 4520b57cec5SDimitry Andric // [ insn 4530b57cec5SDimitry Andric // EH_LABEL 4540b57cec5SDimitry Andric // insn 4550b57cec5SDimitry Andric // insn 4560b57cec5SDimitry Andric // insn 4570b57cec5SDimitry Andric // EH_LABEL 4580b57cec5SDimitry Andric // insn ] 4590b57cec5SDimitry Andric // 4600b57cec5SDimitry Andric // It has two succs but does not have a terminator 4610b57cec5SDimitry Andric // Don't know how to handle it. 4620b57cec5SDimitry Andric do { 4630b57cec5SDimitry Andric --I; 4640b57cec5SDimitry Andric if (I->isEHLabel()) 4650b57cec5SDimitry Andric // Don't analyze EH branches. 4660b57cec5SDimitry Andric return true; 4670b57cec5SDimitry Andric } while (I != MBB.instr_begin()); 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric I = MBB.instr_end(); 4700b57cec5SDimitry Andric --I; 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric while (I->isDebugInstr()) { 4730b57cec5SDimitry Andric if (I == MBB.instr_begin()) 4740b57cec5SDimitry Andric return false; 4750b57cec5SDimitry Andric --I; 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric bool JumpToBlock = I->getOpcode() == Hexagon::J2_jump && 4790b57cec5SDimitry Andric I->getOperand(0).isMBB(); 4800b57cec5SDimitry Andric // Delete the J2_jump if it's equivalent to a fall-through. 4810b57cec5SDimitry Andric if (AllowModify && JumpToBlock && 4820b57cec5SDimitry Andric MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { 4830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nErasing the jump to successor block\n";); 4840b57cec5SDimitry Andric I->eraseFromParent(); 4850b57cec5SDimitry Andric I = MBB.instr_end(); 4860b57cec5SDimitry Andric if (I == MBB.instr_begin()) 4870b57cec5SDimitry Andric return false; 4880b57cec5SDimitry Andric --I; 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric if (!isUnpredicatedTerminator(*I)) 4910b57cec5SDimitry Andric return false; 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric // Get the last instruction in the block. 4940b57cec5SDimitry Andric MachineInstr *LastInst = &*I; 4950b57cec5SDimitry Andric MachineInstr *SecondLastInst = nullptr; 4960b57cec5SDimitry Andric // Find one more terminator if present. 4970b57cec5SDimitry Andric while (true) { 4980b57cec5SDimitry Andric if (&*I != LastInst && !I->isBundle() && isUnpredicatedTerminator(*I)) { 4990b57cec5SDimitry Andric if (!SecondLastInst) 5000b57cec5SDimitry Andric SecondLastInst = &*I; 5010b57cec5SDimitry Andric else 5020b57cec5SDimitry Andric // This is a third branch. 5030b57cec5SDimitry Andric return true; 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric if (I == MBB.instr_begin()) 5060b57cec5SDimitry Andric break; 5070b57cec5SDimitry Andric --I; 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric int LastOpcode = LastInst->getOpcode(); 5110b57cec5SDimitry Andric int SecLastOpcode = SecondLastInst ? SecondLastInst->getOpcode() : 0; 5120b57cec5SDimitry Andric // If the branch target is not a basic block, it could be a tail call. 5130b57cec5SDimitry Andric // (It is, if the target is a function.) 5140b57cec5SDimitry Andric if (LastOpcode == Hexagon::J2_jump && !LastInst->getOperand(0).isMBB()) 5150b57cec5SDimitry Andric return true; 5160b57cec5SDimitry Andric if (SecLastOpcode == Hexagon::J2_jump && 5170b57cec5SDimitry Andric !SecondLastInst->getOperand(0).isMBB()) 5180b57cec5SDimitry Andric return true; 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric bool LastOpcodeHasJMP_c = PredOpcodeHasJMP_c(LastOpcode); 5210b57cec5SDimitry Andric bool LastOpcodeHasNVJump = isNewValueJump(*LastInst); 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric if (LastOpcodeHasJMP_c && !LastInst->getOperand(1).isMBB()) 5240b57cec5SDimitry Andric return true; 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric // If there is only one terminator instruction, process it. 5270b57cec5SDimitry Andric if (LastInst && !SecondLastInst) { 5280b57cec5SDimitry Andric if (LastOpcode == Hexagon::J2_jump) { 5290b57cec5SDimitry Andric TBB = LastInst->getOperand(0).getMBB(); 5300b57cec5SDimitry Andric return false; 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric if (isEndLoopN(LastOpcode)) { 5330b57cec5SDimitry Andric TBB = LastInst->getOperand(0).getMBB(); 5340b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); 5350b57cec5SDimitry Andric Cond.push_back(LastInst->getOperand(0)); 5360b57cec5SDimitry Andric return false; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric if (LastOpcodeHasJMP_c) { 5390b57cec5SDimitry Andric TBB = LastInst->getOperand(1).getMBB(); 5400b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); 5410b57cec5SDimitry Andric Cond.push_back(LastInst->getOperand(0)); 5420b57cec5SDimitry Andric return false; 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric // Only supporting rr/ri versions of new-value jumps. 5450b57cec5SDimitry Andric if (LastOpcodeHasNVJump && (LastInst->getNumExplicitOperands() == 3)) { 5460b57cec5SDimitry Andric TBB = LastInst->getOperand(2).getMBB(); 5470b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); 5480b57cec5SDimitry Andric Cond.push_back(LastInst->getOperand(0)); 5490b57cec5SDimitry Andric Cond.push_back(LastInst->getOperand(1)); 5500b57cec5SDimitry Andric return false; 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nCant analyze " << printMBBReference(MBB) 5530b57cec5SDimitry Andric << " with one jump\n";); 5540b57cec5SDimitry Andric // Otherwise, don't know what this is. 5550b57cec5SDimitry Andric return true; 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric bool SecLastOpcodeHasJMP_c = PredOpcodeHasJMP_c(SecLastOpcode); 5590b57cec5SDimitry Andric bool SecLastOpcodeHasNVJump = isNewValueJump(*SecondLastInst); 5600b57cec5SDimitry Andric if (SecLastOpcodeHasJMP_c && (LastOpcode == Hexagon::J2_jump)) { 5610b57cec5SDimitry Andric if (!SecondLastInst->getOperand(1).isMBB()) 5620b57cec5SDimitry Andric return true; 5630b57cec5SDimitry Andric TBB = SecondLastInst->getOperand(1).getMBB(); 5640b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); 5650b57cec5SDimitry Andric Cond.push_back(SecondLastInst->getOperand(0)); 5660b57cec5SDimitry Andric FBB = LastInst->getOperand(0).getMBB(); 5670b57cec5SDimitry Andric return false; 5680b57cec5SDimitry Andric } 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric // Only supporting rr/ri versions of new-value jumps. 5710b57cec5SDimitry Andric if (SecLastOpcodeHasNVJump && 5720b57cec5SDimitry Andric (SecondLastInst->getNumExplicitOperands() == 3) && 5730b57cec5SDimitry Andric (LastOpcode == Hexagon::J2_jump)) { 5740b57cec5SDimitry Andric TBB = SecondLastInst->getOperand(2).getMBB(); 5750b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); 5760b57cec5SDimitry Andric Cond.push_back(SecondLastInst->getOperand(0)); 5770b57cec5SDimitry Andric Cond.push_back(SecondLastInst->getOperand(1)); 5780b57cec5SDimitry Andric FBB = LastInst->getOperand(0).getMBB(); 5790b57cec5SDimitry Andric return false; 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric // If the block ends with two Hexagon:JMPs, handle it. The second one is not 5830b57cec5SDimitry Andric // executed, so remove it. 5840b57cec5SDimitry Andric if (SecLastOpcode == Hexagon::J2_jump && LastOpcode == Hexagon::J2_jump) { 5850b57cec5SDimitry Andric TBB = SecondLastInst->getOperand(0).getMBB(); 5860b57cec5SDimitry Andric I = LastInst->getIterator(); 5870b57cec5SDimitry Andric if (AllowModify) 5880b57cec5SDimitry Andric I->eraseFromParent(); 5890b57cec5SDimitry Andric return false; 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric // If the block ends with an ENDLOOP, and J2_jump, handle it. 5930b57cec5SDimitry Andric if (isEndLoopN(SecLastOpcode) && LastOpcode == Hexagon::J2_jump) { 5940b57cec5SDimitry Andric TBB = SecondLastInst->getOperand(0).getMBB(); 5950b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); 5960b57cec5SDimitry Andric Cond.push_back(SecondLastInst->getOperand(0)); 5970b57cec5SDimitry Andric FBB = LastInst->getOperand(0).getMBB(); 5980b57cec5SDimitry Andric return false; 5990b57cec5SDimitry Andric } 6000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nCant analyze " << printMBBReference(MBB) 6010b57cec5SDimitry Andric << " with two jumps";); 6020b57cec5SDimitry Andric // Otherwise, can't handle this. 6030b57cec5SDimitry Andric return true; 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric unsigned HexagonInstrInfo::removeBranch(MachineBasicBlock &MBB, 6070b57cec5SDimitry Andric int *BytesRemoved) const { 6080b57cec5SDimitry Andric assert(!BytesRemoved && "code size not handled"); 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nRemoving branches out of " << printMBBReference(MBB)); 6110b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.end(); 6120b57cec5SDimitry Andric unsigned Count = 0; 6130b57cec5SDimitry Andric while (I != MBB.begin()) { 6140b57cec5SDimitry Andric --I; 6150b57cec5SDimitry Andric if (I->isDebugInstr()) 6160b57cec5SDimitry Andric continue; 6170b57cec5SDimitry Andric // Only removing branches from end of MBB. 6180b57cec5SDimitry Andric if (!I->isBranch()) 6190b57cec5SDimitry Andric return Count; 6200b57cec5SDimitry Andric if (Count && (I->getOpcode() == Hexagon::J2_jump)) 6210b57cec5SDimitry Andric llvm_unreachable("Malformed basic block: unconditional branch not last"); 6220b57cec5SDimitry Andric MBB.erase(&MBB.back()); 6230b57cec5SDimitry Andric I = MBB.end(); 6240b57cec5SDimitry Andric ++Count; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric return Count; 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB, 6300b57cec5SDimitry Andric MachineBasicBlock *TBB, 6310b57cec5SDimitry Andric MachineBasicBlock *FBB, 6320b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond, 6330b57cec5SDimitry Andric const DebugLoc &DL, 6340b57cec5SDimitry Andric int *BytesAdded) const { 6350b57cec5SDimitry Andric unsigned BOpc = Hexagon::J2_jump; 6360b57cec5SDimitry Andric unsigned BccOpc = Hexagon::J2_jumpt; 6370b57cec5SDimitry Andric assert(validateBranchCond(Cond) && "Invalid branching condition"); 6380b57cec5SDimitry Andric assert(TBB && "insertBranch must not be told to insert a fallthrough"); 6390b57cec5SDimitry Andric assert(!BytesAdded && "code size not handled"); 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric // Check if reverseBranchCondition has asked to reverse this branch 6420b57cec5SDimitry Andric // If we want to reverse the branch an odd number of times, we want 6430b57cec5SDimitry Andric // J2_jumpf. 6440b57cec5SDimitry Andric if (!Cond.empty() && Cond[0].isImm()) 6450b57cec5SDimitry Andric BccOpc = Cond[0].getImm(); 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric if (!FBB) { 6480b57cec5SDimitry Andric if (Cond.empty()) { 6490b57cec5SDimitry Andric // Due to a bug in TailMerging/CFG Optimization, we need to add a 6500b57cec5SDimitry Andric // special case handling of a predicated jump followed by an 6510b57cec5SDimitry Andric // unconditional jump. If not, Tail Merging and CFG Optimization go 6520b57cec5SDimitry Andric // into an infinite loop. 6530b57cec5SDimitry Andric MachineBasicBlock *NewTBB, *NewFBB; 6540b57cec5SDimitry Andric SmallVector<MachineOperand, 4> Cond; 6550b57cec5SDimitry Andric auto Term = MBB.getFirstTerminator(); 6560b57cec5SDimitry Andric if (Term != MBB.end() && isPredicated(*Term) && 6570b57cec5SDimitry Andric !analyzeBranch(MBB, NewTBB, NewFBB, Cond, false) && 6580b57cec5SDimitry Andric MachineFunction::iterator(NewTBB) == ++MBB.getIterator()) { 6590b57cec5SDimitry Andric reverseBranchCondition(Cond); 6600b57cec5SDimitry Andric removeBranch(MBB); 6610b57cec5SDimitry Andric return insertBranch(MBB, TBB, nullptr, Cond, DL); 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB); 6640b57cec5SDimitry Andric } else if (isEndLoopN(Cond[0].getImm())) { 6650b57cec5SDimitry Andric int EndLoopOp = Cond[0].getImm(); 6660b57cec5SDimitry Andric assert(Cond[1].isMBB()); 6670b57cec5SDimitry Andric // Since we're adding an ENDLOOP, there better be a LOOP instruction. 6680b57cec5SDimitry Andric // Check for it, and change the BB target if needed. 6690b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; 6700b57cec5SDimitry Andric MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(), 6710b57cec5SDimitry Andric VisitedBBs); 6720b57cec5SDimitry Andric assert(Loop != nullptr && "Inserting an ENDLOOP without a LOOP"); 6730b57cec5SDimitry Andric Loop->getOperand(0).setMBB(TBB); 6740b57cec5SDimitry Andric // Add the ENDLOOP after the finding the LOOP0. 6750b57cec5SDimitry Andric BuildMI(&MBB, DL, get(EndLoopOp)).addMBB(TBB); 6760b57cec5SDimitry Andric } else if (isNewValueJump(Cond[0].getImm())) { 6770b57cec5SDimitry Andric assert((Cond.size() == 3) && "Only supporting rr/ri version of nvjump"); 6780b57cec5SDimitry Andric // New value jump 6790b57cec5SDimitry Andric // (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset) 6800b57cec5SDimitry Andric // (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset) 6810b57cec5SDimitry Andric unsigned Flags1 = getUndefRegState(Cond[1].isUndef()); 6820b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nInserting NVJump for " 6830b57cec5SDimitry Andric << printMBBReference(MBB);); 6840b57cec5SDimitry Andric if (Cond[2].isReg()) { 6850b57cec5SDimitry Andric unsigned Flags2 = getUndefRegState(Cond[2].isUndef()); 6860b57cec5SDimitry Andric BuildMI(&MBB, DL, get(BccOpc)).addReg(Cond[1].getReg(), Flags1). 6870b57cec5SDimitry Andric addReg(Cond[2].getReg(), Flags2).addMBB(TBB); 6880b57cec5SDimitry Andric } else if(Cond[2].isImm()) { 6890b57cec5SDimitry Andric BuildMI(&MBB, DL, get(BccOpc)).addReg(Cond[1].getReg(), Flags1). 6900b57cec5SDimitry Andric addImm(Cond[2].getImm()).addMBB(TBB); 6910b57cec5SDimitry Andric } else 6920b57cec5SDimitry Andric llvm_unreachable("Invalid condition for branching"); 6930b57cec5SDimitry Andric } else { 6940b57cec5SDimitry Andric assert((Cond.size() == 2) && "Malformed cond vector"); 6950b57cec5SDimitry Andric const MachineOperand &RO = Cond[1]; 6960b57cec5SDimitry Andric unsigned Flags = getUndefRegState(RO.isUndef()); 6970b57cec5SDimitry Andric BuildMI(&MBB, DL, get(BccOpc)).addReg(RO.getReg(), Flags).addMBB(TBB); 6980b57cec5SDimitry Andric } 6990b57cec5SDimitry Andric return 1; 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric assert((!Cond.empty()) && 7020b57cec5SDimitry Andric "Cond. cannot be empty when multiple branchings are required"); 7030b57cec5SDimitry Andric assert((!isNewValueJump(Cond[0].getImm())) && 7040b57cec5SDimitry Andric "NV-jump cannot be inserted with another branch"); 7050b57cec5SDimitry Andric // Special case for hardware loops. The condition is a basic block. 7060b57cec5SDimitry Andric if (isEndLoopN(Cond[0].getImm())) { 7070b57cec5SDimitry Andric int EndLoopOp = Cond[0].getImm(); 7080b57cec5SDimitry Andric assert(Cond[1].isMBB()); 7090b57cec5SDimitry Andric // Since we're adding an ENDLOOP, there better be a LOOP instruction. 7100b57cec5SDimitry Andric // Check for it, and change the BB target if needed. 7110b57cec5SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; 7120b57cec5SDimitry Andric MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(), 7130b57cec5SDimitry Andric VisitedBBs); 7140b57cec5SDimitry Andric assert(Loop != nullptr && "Inserting an ENDLOOP without a LOOP"); 7150b57cec5SDimitry Andric Loop->getOperand(0).setMBB(TBB); 7160b57cec5SDimitry Andric // Add the ENDLOOP after the finding the LOOP0. 7170b57cec5SDimitry Andric BuildMI(&MBB, DL, get(EndLoopOp)).addMBB(TBB); 7180b57cec5SDimitry Andric } else { 7190b57cec5SDimitry Andric const MachineOperand &RO = Cond[1]; 7200b57cec5SDimitry Andric unsigned Flags = getUndefRegState(RO.isUndef()); 7210b57cec5SDimitry Andric BuildMI(&MBB, DL, get(BccOpc)).addReg(RO.getReg(), Flags).addMBB(TBB); 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB); 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric return 2; 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric 7288bcb0991SDimitry Andric namespace { 7298bcb0991SDimitry Andric class HexagonPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo { 7308bcb0991SDimitry Andric MachineInstr *Loop, *EndLoop; 7318bcb0991SDimitry Andric MachineFunction *MF; 7328bcb0991SDimitry Andric const HexagonInstrInfo *TII; 7338bcb0991SDimitry Andric int64_t TripCount; 7348bcb0991SDimitry Andric Register LoopCount; 7358bcb0991SDimitry Andric DebugLoc DL; 7360b57cec5SDimitry Andric 7378bcb0991SDimitry Andric public: 7388bcb0991SDimitry Andric HexagonPipelinerLoopInfo(MachineInstr *Loop, MachineInstr *EndLoop) 7398bcb0991SDimitry Andric : Loop(Loop), EndLoop(EndLoop), MF(Loop->getParent()->getParent()), 7408bcb0991SDimitry Andric TII(MF->getSubtarget<HexagonSubtarget>().getInstrInfo()), 7418bcb0991SDimitry Andric DL(Loop->getDebugLoc()) { 7428bcb0991SDimitry Andric // Inspect the Loop instruction up-front, as it may be deleted when we call 7438bcb0991SDimitry Andric // createTripCountGreaterCondition. 7448bcb0991SDimitry Andric TripCount = Loop->getOpcode() == Hexagon::J2_loop0r 7458bcb0991SDimitry Andric ? -1 7468bcb0991SDimitry Andric : Loop->getOperand(1).getImm(); 7478bcb0991SDimitry Andric if (TripCount == -1) 7488bcb0991SDimitry Andric LoopCount = Loop->getOperand(1).getReg(); 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric 7518bcb0991SDimitry Andric bool shouldIgnoreForPipelining(const MachineInstr *MI) const override { 7528bcb0991SDimitry Andric // Only ignore the terminator. 7538bcb0991SDimitry Andric return MI == EndLoop; 7548bcb0991SDimitry Andric } 7558bcb0991SDimitry Andric 756bdd1243dSDimitry Andric std::optional<bool> createTripCountGreaterCondition( 757bdd1243dSDimitry Andric int TC, MachineBasicBlock &MBB, 7588bcb0991SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) override { 7598bcb0991SDimitry Andric if (TripCount == -1) { 7608bcb0991SDimitry Andric // Check if we're done with the loop. 761bdd1243dSDimitry Andric Register Done = TII->createVR(MF, MVT::i1); 7628bcb0991SDimitry Andric MachineInstr *NewCmp = BuildMI(&MBB, DL, 7638bcb0991SDimitry Andric TII->get(Hexagon::C2_cmpgtui), Done) 7648bcb0991SDimitry Andric .addReg(LoopCount) 7658bcb0991SDimitry Andric .addImm(TC); 7668bcb0991SDimitry Andric Cond.push_back(MachineOperand::CreateImm(Hexagon::J2_jumpf)); 7678bcb0991SDimitry Andric Cond.push_back(NewCmp->getOperand(0)); 7688bcb0991SDimitry Andric return {}; 7698bcb0991SDimitry Andric } 7708bcb0991SDimitry Andric 7718bcb0991SDimitry Andric return TripCount > TC; 7728bcb0991SDimitry Andric } 7738bcb0991SDimitry Andric 7748bcb0991SDimitry Andric void setPreheader(MachineBasicBlock *NewPreheader) override { 7758bcb0991SDimitry Andric NewPreheader->splice(NewPreheader->getFirstTerminator(), Loop->getParent(), 7768bcb0991SDimitry Andric Loop); 7778bcb0991SDimitry Andric } 7788bcb0991SDimitry Andric 7798bcb0991SDimitry Andric void adjustTripCount(int TripCountAdjust) override { 7800b57cec5SDimitry Andric // If the loop trip count is a compile-time value, then just change the 7810b57cec5SDimitry Andric // value. 7820b57cec5SDimitry Andric if (Loop->getOpcode() == Hexagon::J2_loop0i || 7830b57cec5SDimitry Andric Loop->getOpcode() == Hexagon::J2_loop1i) { 7848bcb0991SDimitry Andric int64_t TripCount = Loop->getOperand(1).getImm() + TripCountAdjust; 7858bcb0991SDimitry Andric assert(TripCount > 0 && "Can't create an empty or negative loop!"); 7868bcb0991SDimitry Andric Loop->getOperand(1).setImm(TripCount); 7878bcb0991SDimitry Andric return; 7880b57cec5SDimitry Andric } 7898bcb0991SDimitry Andric 7900b57cec5SDimitry Andric // The loop trip count is a run-time value. We generate code to subtract 7910b57cec5SDimitry Andric // one from the trip count, and update the loop instruction. 7928bcb0991SDimitry Andric Register LoopCount = Loop->getOperand(1).getReg(); 7938bcb0991SDimitry Andric Register NewLoopCount = TII->createVR(MF, MVT::i32); 7948bcb0991SDimitry Andric BuildMI(*Loop->getParent(), Loop, Loop->getDebugLoc(), 7958bcb0991SDimitry Andric TII->get(Hexagon::A2_addi), NewLoopCount) 7968bcb0991SDimitry Andric .addReg(LoopCount) 7978bcb0991SDimitry Andric .addImm(TripCountAdjust); 7988bcb0991SDimitry Andric Loop->getOperand(1).setReg(NewLoopCount); 7998bcb0991SDimitry Andric } 8008bcb0991SDimitry Andric 8018bcb0991SDimitry Andric void disposed() override { Loop->eraseFromParent(); } 8028bcb0991SDimitry Andric }; 8038bcb0991SDimitry Andric } // namespace 8048bcb0991SDimitry Andric 8058bcb0991SDimitry Andric std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo> 8068bcb0991SDimitry Andric HexagonInstrInfo::analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const { 8078bcb0991SDimitry Andric // We really "analyze" only hardware loops right now. 8088bcb0991SDimitry Andric MachineBasicBlock::iterator I = LoopBB->getFirstTerminator(); 8098bcb0991SDimitry Andric 8108bcb0991SDimitry Andric if (I != LoopBB->end() && isEndLoopN(I->getOpcode())) { 8118bcb0991SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; 8128bcb0991SDimitry Andric MachineInstr *LoopInst = findLoopInstr( 8138bcb0991SDimitry Andric LoopBB, I->getOpcode(), I->getOperand(0).getMBB(), VisitedBBs); 8148bcb0991SDimitry Andric if (LoopInst) 8158bcb0991SDimitry Andric return std::make_unique<HexagonPipelinerLoopInfo>(LoopInst, &*I); 8168bcb0991SDimitry Andric } 8178bcb0991SDimitry Andric return nullptr; 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric bool HexagonInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, 8210b57cec5SDimitry Andric unsigned NumCycles, unsigned ExtraPredCycles, 8220b57cec5SDimitry Andric BranchProbability Probability) const { 8230b57cec5SDimitry Andric return nonDbgBBSize(&MBB) <= 3; 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric bool HexagonInstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB, 8270b57cec5SDimitry Andric unsigned NumTCycles, unsigned ExtraTCycles, MachineBasicBlock &FMBB, 8280b57cec5SDimitry Andric unsigned NumFCycles, unsigned ExtraFCycles, BranchProbability Probability) 8290b57cec5SDimitry Andric const { 8300b57cec5SDimitry Andric return nonDbgBBSize(&TMBB) <= 3 && nonDbgBBSize(&FMBB) <= 3; 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric bool HexagonInstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB, 8340b57cec5SDimitry Andric unsigned NumInstrs, BranchProbability Probability) const { 8350b57cec5SDimitry Andric return NumInstrs <= 4; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8385ffd83dbSDimitry Andric static void getLiveInRegsAt(LivePhysRegs &Regs, const MachineInstr &MI) { 8395ffd83dbSDimitry Andric SmallVector<std::pair<MCPhysReg, const MachineOperand*>,2> Clobbers; 8405ffd83dbSDimitry Andric const MachineBasicBlock &B = *MI.getParent(); 8415ffd83dbSDimitry Andric Regs.addLiveIns(B); 8425ffd83dbSDimitry Andric auto E = MachineBasicBlock::const_iterator(MI.getIterator()); 8435ffd83dbSDimitry Andric for (auto I = B.begin(); I != E; ++I) { 8445ffd83dbSDimitry Andric Clobbers.clear(); 8455ffd83dbSDimitry Andric Regs.stepForward(*I, Clobbers); 8465ffd83dbSDimitry Andric } 8475ffd83dbSDimitry Andric } 8485ffd83dbSDimitry Andric 8495ffd83dbSDimitry Andric static void getLiveOutRegsAt(LivePhysRegs &Regs, const MachineInstr &MI) { 8505ffd83dbSDimitry Andric const MachineBasicBlock &B = *MI.getParent(); 8515ffd83dbSDimitry Andric Regs.addLiveOuts(B); 8525ffd83dbSDimitry Andric auto E = ++MachineBasicBlock::const_iterator(MI.getIterator()).getReverse(); 8535ffd83dbSDimitry Andric for (auto I = B.rbegin(); I != E; ++I) 8545ffd83dbSDimitry Andric Regs.stepBackward(*I); 8555ffd83dbSDimitry Andric } 8565ffd83dbSDimitry Andric 8570b57cec5SDimitry Andric void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 8580b57cec5SDimitry Andric MachineBasicBlock::iterator I, 859480093f4SDimitry Andric const DebugLoc &DL, MCRegister DestReg, 860480093f4SDimitry Andric MCRegister SrcReg, bool KillSrc) const { 8610b57cec5SDimitry Andric const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); 8620b57cec5SDimitry Andric unsigned KillFlag = getKillRegState(KillSrc); 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.contains(SrcReg, DestReg)) { 8650b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::A2_tfr), DestReg) 8660b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 8670b57cec5SDimitry Andric return; 8680b57cec5SDimitry Andric } 8690b57cec5SDimitry Andric if (Hexagon::DoubleRegsRegClass.contains(SrcReg, DestReg)) { 8700b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::A2_tfrp), DestReg) 8710b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 8720b57cec5SDimitry Andric return; 8730b57cec5SDimitry Andric } 8740b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(SrcReg, DestReg)) { 8750b57cec5SDimitry Andric // Map Pd = Ps to Pd = or(Ps, Ps). 8760b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::C2_or), DestReg) 8770b57cec5SDimitry Andric .addReg(SrcReg).addReg(SrcReg, KillFlag); 8780b57cec5SDimitry Andric return; 8790b57cec5SDimitry Andric } 8800b57cec5SDimitry Andric if (Hexagon::CtrRegsRegClass.contains(DestReg) && 8810b57cec5SDimitry Andric Hexagon::IntRegsRegClass.contains(SrcReg)) { 8820b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::A2_tfrrcr), DestReg) 8830b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 8840b57cec5SDimitry Andric return; 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.contains(DestReg) && 8870b57cec5SDimitry Andric Hexagon::CtrRegsRegClass.contains(SrcReg)) { 8880b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::A2_tfrcrr), DestReg) 8890b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 8900b57cec5SDimitry Andric return; 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric if (Hexagon::ModRegsRegClass.contains(DestReg) && 8930b57cec5SDimitry Andric Hexagon::IntRegsRegClass.contains(SrcReg)) { 8940b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::A2_tfrrcr), DestReg) 8950b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 8960b57cec5SDimitry Andric return; 8970b57cec5SDimitry Andric } 8980b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(SrcReg) && 8990b57cec5SDimitry Andric Hexagon::IntRegsRegClass.contains(DestReg)) { 9000b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg) 9010b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 9020b57cec5SDimitry Andric return; 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.contains(SrcReg) && 9050b57cec5SDimitry Andric Hexagon::PredRegsRegClass.contains(DestReg)) { 9060b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::C2_tfrrp), DestReg) 9070b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 9080b57cec5SDimitry Andric return; 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(SrcReg) && 9110b57cec5SDimitry Andric Hexagon::IntRegsRegClass.contains(DestReg)) { 9120b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg) 9130b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 9140b57cec5SDimitry Andric return; 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric if (Hexagon::HvxVRRegClass.contains(SrcReg, DestReg)) { 9170b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::V6_vassign), DestReg). 9180b57cec5SDimitry Andric addReg(SrcReg, KillFlag); 9190b57cec5SDimitry Andric return; 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric if (Hexagon::HvxWRRegClass.contains(SrcReg, DestReg)) { 9225ffd83dbSDimitry Andric LivePhysRegs LiveAtMI(HRI); 9235ffd83dbSDimitry Andric getLiveInRegsAt(LiveAtMI, *I); 9245ffd83dbSDimitry Andric Register SrcLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); 9255ffd83dbSDimitry Andric Register SrcHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); 9265ffd83dbSDimitry Andric unsigned UndefLo = getUndefRegState(!LiveAtMI.contains(SrcLo)); 9275ffd83dbSDimitry Andric unsigned UndefHi = getUndefRegState(!LiveAtMI.contains(SrcHi)); 9280b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::V6_vcombine), DestReg) 9295ffd83dbSDimitry Andric .addReg(SrcHi, KillFlag | UndefHi) 9305ffd83dbSDimitry Andric .addReg(SrcLo, KillFlag | UndefLo); 9310b57cec5SDimitry Andric return; 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric if (Hexagon::HvxQRRegClass.contains(SrcReg, DestReg)) { 9340b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and), DestReg) 9350b57cec5SDimitry Andric .addReg(SrcReg) 9360b57cec5SDimitry Andric .addReg(SrcReg, KillFlag); 9370b57cec5SDimitry Andric return; 9380b57cec5SDimitry Andric } 9390b57cec5SDimitry Andric if (Hexagon::HvxQRRegClass.contains(SrcReg) && 9400b57cec5SDimitry Andric Hexagon::HvxVRRegClass.contains(DestReg)) { 9410b57cec5SDimitry Andric llvm_unreachable("Unimplemented pred to vec"); 9420b57cec5SDimitry Andric return; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric if (Hexagon::HvxQRRegClass.contains(DestReg) && 9450b57cec5SDimitry Andric Hexagon::HvxVRRegClass.contains(SrcReg)) { 9460b57cec5SDimitry Andric llvm_unreachable("Unimplemented vec to pred"); 9470b57cec5SDimitry Andric return; 9480b57cec5SDimitry Andric } 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric #ifndef NDEBUG 9510b57cec5SDimitry Andric // Show the invalid registers to ease debugging. 9520b57cec5SDimitry Andric dbgs() << "Invalid registers for copy in " << printMBBReference(MBB) << ": " 9530b57cec5SDimitry Andric << printReg(DestReg, &HRI) << " = " << printReg(SrcReg, &HRI) << '\n'; 9540b57cec5SDimitry Andric #endif 9550b57cec5SDimitry Andric llvm_unreachable("Unimplemented"); 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 959bdd1243dSDimitry Andric MachineBasicBlock::iterator I, 960bdd1243dSDimitry Andric Register SrcReg, bool isKill, int FI, 961bdd1243dSDimitry Andric const TargetRegisterClass *RC, 962bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 963bdd1243dSDimitry Andric Register VReg) const { 9640b57cec5SDimitry Andric DebugLoc DL = MBB.findDebugLoc(I); 9650b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 9660b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 9670b57cec5SDimitry Andric unsigned KillFlag = getKillRegState(isKill); 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand( 9700b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, 9715ffd83dbSDimitry Andric MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) { 9740b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::S2_storeri_io)) 9750b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0) 9760b57cec5SDimitry Andric .addReg(SrcReg, KillFlag).addMemOperand(MMO); 9770b57cec5SDimitry Andric } else if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC)) { 9780b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::S2_storerd_io)) 9790b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0) 9800b57cec5SDimitry Andric .addReg(SrcReg, KillFlag).addMemOperand(MMO); 9810b57cec5SDimitry Andric } else if (Hexagon::PredRegsRegClass.hasSubClassEq(RC)) { 9820b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::STriw_pred)) 9830b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0) 9840b57cec5SDimitry Andric .addReg(SrcReg, KillFlag).addMemOperand(MMO); 9850b57cec5SDimitry Andric } else if (Hexagon::ModRegsRegClass.hasSubClassEq(RC)) { 9860b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::STriw_ctr)) 9870b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0) 9880b57cec5SDimitry Andric .addReg(SrcReg, KillFlag).addMemOperand(MMO); 9890b57cec5SDimitry Andric } else if (Hexagon::HvxQRRegClass.hasSubClassEq(RC)) { 9900b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::PS_vstorerq_ai)) 9910b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0) 9920b57cec5SDimitry Andric .addReg(SrcReg, KillFlag).addMemOperand(MMO); 9930b57cec5SDimitry Andric } else if (Hexagon::HvxVRRegClass.hasSubClassEq(RC)) { 994480093f4SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::PS_vstorerv_ai)) 9950b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0) 996480093f4SDimitry Andric .addReg(SrcReg, KillFlag).addMemOperand(MMO); 9970b57cec5SDimitry Andric } else if (Hexagon::HvxWRRegClass.hasSubClassEq(RC)) { 998480093f4SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::PS_vstorerw_ai)) 9990b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0) 1000480093f4SDimitry Andric .addReg(SrcReg, KillFlag).addMemOperand(MMO); 10010b57cec5SDimitry Andric } else { 10020b57cec5SDimitry Andric llvm_unreachable("Unimplemented"); 10030b57cec5SDimitry Andric } 10040b57cec5SDimitry Andric } 10050b57cec5SDimitry Andric 1006bdd1243dSDimitry Andric void HexagonInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 1007bdd1243dSDimitry Andric MachineBasicBlock::iterator I, 1008bdd1243dSDimitry Andric Register DestReg, int FI, 1009bdd1243dSDimitry Andric const TargetRegisterClass *RC, 1010bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 1011bdd1243dSDimitry Andric Register VReg) const { 10120b57cec5SDimitry Andric DebugLoc DL = MBB.findDebugLoc(I); 10130b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 10140b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand( 10170b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, 10185ffd83dbSDimitry Andric MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) { 10210b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::L2_loadri_io), DestReg) 10220b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0).addMemOperand(MMO); 10230b57cec5SDimitry Andric } else if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC)) { 10240b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::L2_loadrd_io), DestReg) 10250b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0).addMemOperand(MMO); 10260b57cec5SDimitry Andric } else if (Hexagon::PredRegsRegClass.hasSubClassEq(RC)) { 10270b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::LDriw_pred), DestReg) 10280b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0).addMemOperand(MMO); 10290b57cec5SDimitry Andric } else if (Hexagon::ModRegsRegClass.hasSubClassEq(RC)) { 10300b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::LDriw_ctr), DestReg) 10310b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0).addMemOperand(MMO); 10320b57cec5SDimitry Andric } else if (Hexagon::HvxQRRegClass.hasSubClassEq(RC)) { 10330b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrq_ai), DestReg) 10340b57cec5SDimitry Andric .addFrameIndex(FI).addImm(0).addMemOperand(MMO); 10350b57cec5SDimitry Andric } else if (Hexagon::HvxVRRegClass.hasSubClassEq(RC)) { 1036480093f4SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrv_ai), DestReg) 1037480093f4SDimitry Andric .addFrameIndex(FI).addImm(0).addMemOperand(MMO); 10380b57cec5SDimitry Andric } else if (Hexagon::HvxWRRegClass.hasSubClassEq(RC)) { 1039480093f4SDimitry Andric BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrw_ai), DestReg) 1040480093f4SDimitry Andric .addFrameIndex(FI).addImm(0).addMemOperand(MMO); 10410b57cec5SDimitry Andric } else { 10420b57cec5SDimitry Andric llvm_unreachable("Can't store this register to stack slot"); 10430b57cec5SDimitry Andric } 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric /// expandPostRAPseudo - This function is called for all pseudo instructions 10470b57cec5SDimitry Andric /// that remain after register allocation. Many pseudo instructions are 10480b57cec5SDimitry Andric /// created to help register allocation. This is the place to convert them 10490b57cec5SDimitry Andric /// into real instructions. The target can edit MI in place, or it can insert 10500b57cec5SDimitry Andric /// new instructions and erase MI. The function should return true if 10510b57cec5SDimitry Andric /// anything was changed. 10520b57cec5SDimitry Andric bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { 10530b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI.getParent(); 10540b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 10550b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 10560b57cec5SDimitry Andric const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); 10575ffd83dbSDimitry Andric LivePhysRegs LiveIn(HRI), LiveOut(HRI); 10580b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 10590b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric auto RealCirc = [&](unsigned Opc, bool HasImm, unsigned MxOp) { 10628bcb0991SDimitry Andric Register Mx = MI.getOperand(MxOp).getReg(); 1063bdd1243dSDimitry Andric Register CSx = (Mx == Hexagon::M0 ? Hexagon::CS0 : Hexagon::CS1); 10640b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrrcr), CSx) 10650b57cec5SDimitry Andric .add(MI.getOperand((HasImm ? 5 : 4))); 10660b57cec5SDimitry Andric auto MIB = BuildMI(MBB, MI, DL, get(Opc)).add(MI.getOperand(0)) 10670b57cec5SDimitry Andric .add(MI.getOperand(1)).add(MI.getOperand(2)).add(MI.getOperand(3)); 10680b57cec5SDimitry Andric if (HasImm) 10690b57cec5SDimitry Andric MIB.add(MI.getOperand(4)); 10700b57cec5SDimitry Andric MIB.addReg(CSx, RegState::Implicit); 10710b57cec5SDimitry Andric MBB.erase(MI); 10720b57cec5SDimitry Andric return true; 10730b57cec5SDimitry Andric }; 10740b57cec5SDimitry Andric 1075fe6060f1SDimitry Andric auto UseAligned = [&](const MachineInstr &MI, Align NeedAlign) { 1076480093f4SDimitry Andric if (MI.memoperands().empty()) 1077480093f4SDimitry Andric return false; 10785ffd83dbSDimitry Andric return all_of(MI.memoperands(), [NeedAlign](const MachineMemOperand *MMO) { 10795ffd83dbSDimitry Andric return MMO->getAlign() >= NeedAlign; 1080480093f4SDimitry Andric }); 1081480093f4SDimitry Andric }; 1082480093f4SDimitry Andric 10830b57cec5SDimitry Andric switch (Opc) { 108481ad6265SDimitry Andric case Hexagon::PS_call_instrprof_custom: { 108581ad6265SDimitry Andric auto Op0 = MI.getOperand(0); 108681ad6265SDimitry Andric assert(Op0.isGlobal() && 108781ad6265SDimitry Andric "First operand must be a global containing handler name."); 108881ad6265SDimitry Andric const GlobalValue *NameVar = Op0.getGlobal(); 108981ad6265SDimitry Andric const GlobalVariable *GV = dyn_cast<GlobalVariable>(NameVar); 109081ad6265SDimitry Andric auto *Arr = cast<ConstantDataArray>(GV->getInitializer()); 109181ad6265SDimitry Andric StringRef NameStr = Arr->isCString() ? Arr->getAsCString() : Arr->getAsString(); 109281ad6265SDimitry Andric 109381ad6265SDimitry Andric MachineOperand &Op1 = MI.getOperand(1); 109481ad6265SDimitry Andric // Set R0 with the imm value to be passed to the custom profiling handler. 109581ad6265SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrsi), Hexagon::R0) 109681ad6265SDimitry Andric .addImm(Op1.getImm()); 109781ad6265SDimitry Andric // The call to the custom handler is being treated as a special one as the 109881ad6265SDimitry Andric // callee is responsible for saving and restoring all the registers 109981ad6265SDimitry Andric // (including caller saved registers) it needs to modify. This is 110081ad6265SDimitry Andric // done to reduce the impact of instrumentation on the code being 110181ad6265SDimitry Andric // instrumented/profiled. 110281ad6265SDimitry Andric // NOTE: R14, R15 and R28 are reserved for PLT handling. These registers 110381ad6265SDimitry Andric // are in the Def list of the Hexagon::PS_call_instrprof_custom and 110481ad6265SDimitry Andric // therefore will be handled appropriately duing register allocation. 110581ad6265SDimitry Andric 110681ad6265SDimitry Andric // TODO: It may be a good idea to add a separate pseudo instruction for 110781ad6265SDimitry Andric // static relocation which doesn't need to reserve r14, r15 and r28. 110881ad6265SDimitry Andric 110981ad6265SDimitry Andric auto MIB = BuildMI(MBB, MI, DL, get(Hexagon::J2_call)) 111081ad6265SDimitry Andric .addUse(Hexagon::R0, RegState::Implicit|RegState::InternalRead) 111181ad6265SDimitry Andric .addDef(Hexagon::R29, RegState::ImplicitDefine) 111281ad6265SDimitry Andric .addDef(Hexagon::R30, RegState::ImplicitDefine) 111381ad6265SDimitry Andric .addDef(Hexagon::R14, RegState::ImplicitDefine) 111481ad6265SDimitry Andric .addDef(Hexagon::R15, RegState::ImplicitDefine) 111581ad6265SDimitry Andric .addDef(Hexagon::R28, RegState::ImplicitDefine); 111681ad6265SDimitry Andric const char *cstr = MF.createExternalSymbolName(NameStr); 111781ad6265SDimitry Andric MIB.addExternalSymbol(cstr); 111881ad6265SDimitry Andric MBB.erase(MI); 111981ad6265SDimitry Andric return true; 112081ad6265SDimitry Andric } 11210b57cec5SDimitry Andric case TargetOpcode::COPY: { 11220b57cec5SDimitry Andric MachineOperand &MD = MI.getOperand(0); 11230b57cec5SDimitry Andric MachineOperand &MS = MI.getOperand(1); 11240b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MI.getIterator(); 11250b57cec5SDimitry Andric if (MD.getReg() != MS.getReg() && !MS.isUndef()) { 11260b57cec5SDimitry Andric copyPhysReg(MBB, MI, DL, MD.getReg(), MS.getReg(), MS.isKill()); 11270b57cec5SDimitry Andric std::prev(MBBI)->copyImplicitOps(*MBB.getParent(), MI); 11280b57cec5SDimitry Andric } 11290b57cec5SDimitry Andric MBB.erase(MBBI); 11300b57cec5SDimitry Andric return true; 11310b57cec5SDimitry Andric } 11320b57cec5SDimitry Andric case Hexagon::PS_aligna: 11330b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::A2_andir), MI.getOperand(0).getReg()) 11340b57cec5SDimitry Andric .addReg(HRI.getFrameRegister()) 11350b57cec5SDimitry Andric .addImm(-MI.getOperand(1).getImm()); 11360b57cec5SDimitry Andric MBB.erase(MI); 11370b57cec5SDimitry Andric return true; 11380b57cec5SDimitry Andric case Hexagon::V6_vassignp: { 11398bcb0991SDimitry Andric Register SrcReg = MI.getOperand(1).getReg(); 11408bcb0991SDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 11415ffd83dbSDimitry Andric Register SrcLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); 11425ffd83dbSDimitry Andric Register SrcHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); 11435ffd83dbSDimitry Andric getLiveInRegsAt(LiveIn, MI); 11445ffd83dbSDimitry Andric unsigned UndefLo = getUndefRegState(!LiveIn.contains(SrcLo)); 11455ffd83dbSDimitry Andric unsigned UndefHi = getUndefRegState(!LiveIn.contains(SrcHi)); 11460b57cec5SDimitry Andric unsigned Kill = getKillRegState(MI.getOperand(1).isKill()); 11470b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vcombine), DstReg) 11485ffd83dbSDimitry Andric .addReg(SrcHi, UndefHi) 11495ffd83dbSDimitry Andric .addReg(SrcLo, Kill | UndefLo); 11500b57cec5SDimitry Andric MBB.erase(MI); 11510b57cec5SDimitry Andric return true; 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric case Hexagon::V6_lo: { 11548bcb0991SDimitry Andric Register SrcReg = MI.getOperand(1).getReg(); 11558bcb0991SDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 11568bcb0991SDimitry Andric Register SrcSubLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); 11570b57cec5SDimitry Andric copyPhysReg(MBB, MI, DL, DstReg, SrcSubLo, MI.getOperand(1).isKill()); 11580b57cec5SDimitry Andric MBB.erase(MI); 11590b57cec5SDimitry Andric MRI.clearKillFlags(SrcSubLo); 11600b57cec5SDimitry Andric return true; 11610b57cec5SDimitry Andric } 11620b57cec5SDimitry Andric case Hexagon::V6_hi: { 11638bcb0991SDimitry Andric Register SrcReg = MI.getOperand(1).getReg(); 11648bcb0991SDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 11658bcb0991SDimitry Andric Register SrcSubHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); 11660b57cec5SDimitry Andric copyPhysReg(MBB, MI, DL, DstReg, SrcSubHi, MI.getOperand(1).isKill()); 11670b57cec5SDimitry Andric MBB.erase(MI); 11680b57cec5SDimitry Andric MRI.clearKillFlags(SrcSubHi); 11690b57cec5SDimitry Andric return true; 11700b57cec5SDimitry Andric } 1171480093f4SDimitry Andric case Hexagon::PS_vloadrv_ai: { 1172480093f4SDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 1173480093f4SDimitry Andric const MachineOperand &BaseOp = MI.getOperand(1); 1174480093f4SDimitry Andric assert(BaseOp.getSubReg() == 0); 1175480093f4SDimitry Andric int Offset = MI.getOperand(2).getImm(); 1176fe6060f1SDimitry Andric Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass); 1177480093f4SDimitry Andric unsigned NewOpc = UseAligned(MI, NeedAlign) ? Hexagon::V6_vL32b_ai 1178480093f4SDimitry Andric : Hexagon::V6_vL32Ub_ai; 1179480093f4SDimitry Andric BuildMI(MBB, MI, DL, get(NewOpc), DstReg) 1180480093f4SDimitry Andric .addReg(BaseOp.getReg(), getRegState(BaseOp)) 1181480093f4SDimitry Andric .addImm(Offset) 11820b57cec5SDimitry Andric .cloneMemRefs(MI); 11830b57cec5SDimitry Andric MBB.erase(MI); 11840b57cec5SDimitry Andric return true; 11850b57cec5SDimitry Andric } 1186480093f4SDimitry Andric case Hexagon::PS_vloadrw_ai: { 11878bcb0991SDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 1188480093f4SDimitry Andric const MachineOperand &BaseOp = MI.getOperand(1); 1189480093f4SDimitry Andric assert(BaseOp.getSubReg() == 0); 1190480093f4SDimitry Andric int Offset = MI.getOperand(2).getImm(); 1191480093f4SDimitry Andric unsigned VecOffset = HRI.getSpillSize(Hexagon::HvxVRRegClass); 1192fe6060f1SDimitry Andric Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass); 1193480093f4SDimitry Andric unsigned NewOpc = UseAligned(MI, NeedAlign) ? Hexagon::V6_vL32b_ai 1194480093f4SDimitry Andric : Hexagon::V6_vL32Ub_ai; 1195480093f4SDimitry Andric BuildMI(MBB, MI, DL, get(NewOpc), 11960b57cec5SDimitry Andric HRI.getSubReg(DstReg, Hexagon::vsub_lo)) 1197480093f4SDimitry Andric .addReg(BaseOp.getReg(), getRegState(BaseOp) & ~RegState::Kill) 1198480093f4SDimitry Andric .addImm(Offset) 11990b57cec5SDimitry Andric .cloneMemRefs(MI); 1200480093f4SDimitry Andric BuildMI(MBB, MI, DL, get(NewOpc), 1201480093f4SDimitry Andric HRI.getSubReg(DstReg, Hexagon::vsub_hi)) 1202480093f4SDimitry Andric .addReg(BaseOp.getReg(), getRegState(BaseOp)) 1203480093f4SDimitry Andric .addImm(Offset + VecOffset) 1204480093f4SDimitry Andric .cloneMemRefs(MI); 1205480093f4SDimitry Andric MBB.erase(MI); 1206480093f4SDimitry Andric return true; 1207480093f4SDimitry Andric } 1208480093f4SDimitry Andric case Hexagon::PS_vstorerv_ai: { 1209480093f4SDimitry Andric const MachineOperand &SrcOp = MI.getOperand(2); 1210480093f4SDimitry Andric assert(SrcOp.getSubReg() == 0); 1211480093f4SDimitry Andric const MachineOperand &BaseOp = MI.getOperand(0); 1212480093f4SDimitry Andric assert(BaseOp.getSubReg() == 0); 1213480093f4SDimitry Andric int Offset = MI.getOperand(1).getImm(); 1214fe6060f1SDimitry Andric Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass); 1215480093f4SDimitry Andric unsigned NewOpc = UseAligned(MI, NeedAlign) ? Hexagon::V6_vS32b_ai 1216480093f4SDimitry Andric : Hexagon::V6_vS32Ub_ai; 1217480093f4SDimitry Andric BuildMI(MBB, MI, DL, get(NewOpc)) 1218480093f4SDimitry Andric .addReg(BaseOp.getReg(), getRegState(BaseOp)) 1219480093f4SDimitry Andric .addImm(Offset) 1220480093f4SDimitry Andric .addReg(SrcOp.getReg(), getRegState(SrcOp)) 1221480093f4SDimitry Andric .cloneMemRefs(MI); 1222480093f4SDimitry Andric MBB.erase(MI); 1223480093f4SDimitry Andric return true; 1224480093f4SDimitry Andric } 1225480093f4SDimitry Andric case Hexagon::PS_vstorerw_ai: { 1226480093f4SDimitry Andric Register SrcReg = MI.getOperand(2).getReg(); 1227480093f4SDimitry Andric const MachineOperand &BaseOp = MI.getOperand(0); 1228480093f4SDimitry Andric assert(BaseOp.getSubReg() == 0); 1229480093f4SDimitry Andric int Offset = MI.getOperand(1).getImm(); 1230480093f4SDimitry Andric unsigned VecOffset = HRI.getSpillSize(Hexagon::HvxVRRegClass); 1231fe6060f1SDimitry Andric Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass); 1232480093f4SDimitry Andric unsigned NewOpc = UseAligned(MI, NeedAlign) ? Hexagon::V6_vS32b_ai 1233480093f4SDimitry Andric : Hexagon::V6_vS32Ub_ai; 1234480093f4SDimitry Andric BuildMI(MBB, MI, DL, get(NewOpc)) 1235480093f4SDimitry Andric .addReg(BaseOp.getReg(), getRegState(BaseOp) & ~RegState::Kill) 1236480093f4SDimitry Andric .addImm(Offset) 1237480093f4SDimitry Andric .addReg(HRI.getSubReg(SrcReg, Hexagon::vsub_lo)) 1238480093f4SDimitry Andric .cloneMemRefs(MI); 1239480093f4SDimitry Andric BuildMI(MBB, MI, DL, get(NewOpc)) 1240480093f4SDimitry Andric .addReg(BaseOp.getReg(), getRegState(BaseOp)) 1241480093f4SDimitry Andric .addImm(Offset + VecOffset) 1242480093f4SDimitry Andric .addReg(HRI.getSubReg(SrcReg, Hexagon::vsub_hi)) 12430b57cec5SDimitry Andric .cloneMemRefs(MI); 12440b57cec5SDimitry Andric MBB.erase(MI); 12450b57cec5SDimitry Andric return true; 12460b57cec5SDimitry Andric } 12470b57cec5SDimitry Andric case Hexagon::PS_true: { 12488bcb0991SDimitry Andric Register Reg = MI.getOperand(0).getReg(); 12490b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::C2_orn), Reg) 12500b57cec5SDimitry Andric .addReg(Reg, RegState::Undef) 12510b57cec5SDimitry Andric .addReg(Reg, RegState::Undef); 12520b57cec5SDimitry Andric MBB.erase(MI); 12530b57cec5SDimitry Andric return true; 12540b57cec5SDimitry Andric } 12550b57cec5SDimitry Andric case Hexagon::PS_false: { 12568bcb0991SDimitry Andric Register Reg = MI.getOperand(0).getReg(); 12570b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::C2_andn), Reg) 12580b57cec5SDimitry Andric .addReg(Reg, RegState::Undef) 12590b57cec5SDimitry Andric .addReg(Reg, RegState::Undef); 12600b57cec5SDimitry Andric MBB.erase(MI); 12610b57cec5SDimitry Andric return true; 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric case Hexagon::PS_qtrue: { 12640b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_veqw), MI.getOperand(0).getReg()) 12650b57cec5SDimitry Andric .addReg(Hexagon::V0, RegState::Undef) 12660b57cec5SDimitry Andric .addReg(Hexagon::V0, RegState::Undef); 12670b57cec5SDimitry Andric MBB.erase(MI); 12680b57cec5SDimitry Andric return true; 12690b57cec5SDimitry Andric } 12700b57cec5SDimitry Andric case Hexagon::PS_qfalse: { 12710b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vgtw), MI.getOperand(0).getReg()) 12720b57cec5SDimitry Andric .addReg(Hexagon::V0, RegState::Undef) 12730b57cec5SDimitry Andric .addReg(Hexagon::V0, RegState::Undef); 12740b57cec5SDimitry Andric MBB.erase(MI); 12750b57cec5SDimitry Andric return true; 12760b57cec5SDimitry Andric } 12770b57cec5SDimitry Andric case Hexagon::PS_vdd0: { 12788bcb0991SDimitry Andric Register Vd = MI.getOperand(0).getReg(); 12790b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vsubw_dv), Vd) 12800b57cec5SDimitry Andric .addReg(Vd, RegState::Undef) 12810b57cec5SDimitry Andric .addReg(Vd, RegState::Undef); 12820b57cec5SDimitry Andric MBB.erase(MI); 12830b57cec5SDimitry Andric return true; 12840b57cec5SDimitry Andric } 12850b57cec5SDimitry Andric case Hexagon::PS_vmulw: { 12860b57cec5SDimitry Andric // Expand a 64-bit vector multiply into 2 32-bit scalar multiplies. 12878bcb0991SDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 12888bcb0991SDimitry Andric Register Src1Reg = MI.getOperand(1).getReg(); 12898bcb0991SDimitry Andric Register Src2Reg = MI.getOperand(2).getReg(); 12908bcb0991SDimitry Andric Register Src1SubHi = HRI.getSubReg(Src1Reg, Hexagon::isub_hi); 12918bcb0991SDimitry Andric Register Src1SubLo = HRI.getSubReg(Src1Reg, Hexagon::isub_lo); 12928bcb0991SDimitry Andric Register Src2SubHi = HRI.getSubReg(Src2Reg, Hexagon::isub_hi); 12938bcb0991SDimitry Andric Register Src2SubLo = HRI.getSubReg(Src2Reg, Hexagon::isub_lo); 12940b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_mpyi), 12950b57cec5SDimitry Andric HRI.getSubReg(DstReg, Hexagon::isub_hi)) 12960b57cec5SDimitry Andric .addReg(Src1SubHi) 12970b57cec5SDimitry Andric .addReg(Src2SubHi); 12980b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_mpyi), 12990b57cec5SDimitry Andric HRI.getSubReg(DstReg, Hexagon::isub_lo)) 13000b57cec5SDimitry Andric .addReg(Src1SubLo) 13010b57cec5SDimitry Andric .addReg(Src2SubLo); 13020b57cec5SDimitry Andric MBB.erase(MI); 13030b57cec5SDimitry Andric MRI.clearKillFlags(Src1SubHi); 13040b57cec5SDimitry Andric MRI.clearKillFlags(Src1SubLo); 13050b57cec5SDimitry Andric MRI.clearKillFlags(Src2SubHi); 13060b57cec5SDimitry Andric MRI.clearKillFlags(Src2SubLo); 13070b57cec5SDimitry Andric return true; 13080b57cec5SDimitry Andric } 13090b57cec5SDimitry Andric case Hexagon::PS_vmulw_acc: { 13100b57cec5SDimitry Andric // Expand 64-bit vector multiply with addition into 2 scalar multiplies. 13118bcb0991SDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 13128bcb0991SDimitry Andric Register Src1Reg = MI.getOperand(1).getReg(); 13138bcb0991SDimitry Andric Register Src2Reg = MI.getOperand(2).getReg(); 13148bcb0991SDimitry Andric Register Src3Reg = MI.getOperand(3).getReg(); 13158bcb0991SDimitry Andric Register Src1SubHi = HRI.getSubReg(Src1Reg, Hexagon::isub_hi); 13168bcb0991SDimitry Andric Register Src1SubLo = HRI.getSubReg(Src1Reg, Hexagon::isub_lo); 13178bcb0991SDimitry Andric Register Src2SubHi = HRI.getSubReg(Src2Reg, Hexagon::isub_hi); 13188bcb0991SDimitry Andric Register Src2SubLo = HRI.getSubReg(Src2Reg, Hexagon::isub_lo); 13198bcb0991SDimitry Andric Register Src3SubHi = HRI.getSubReg(Src3Reg, Hexagon::isub_hi); 13208bcb0991SDimitry Andric Register Src3SubLo = HRI.getSubReg(Src3Reg, Hexagon::isub_lo); 13210b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_maci), 13220b57cec5SDimitry Andric HRI.getSubReg(DstReg, Hexagon::isub_hi)) 13230b57cec5SDimitry Andric .addReg(Src1SubHi) 13240b57cec5SDimitry Andric .addReg(Src2SubHi) 13250b57cec5SDimitry Andric .addReg(Src3SubHi); 13260b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_maci), 13270b57cec5SDimitry Andric HRI.getSubReg(DstReg, Hexagon::isub_lo)) 13280b57cec5SDimitry Andric .addReg(Src1SubLo) 13290b57cec5SDimitry Andric .addReg(Src2SubLo) 13300b57cec5SDimitry Andric .addReg(Src3SubLo); 13310b57cec5SDimitry Andric MBB.erase(MI); 13320b57cec5SDimitry Andric MRI.clearKillFlags(Src1SubHi); 13330b57cec5SDimitry Andric MRI.clearKillFlags(Src1SubLo); 13340b57cec5SDimitry Andric MRI.clearKillFlags(Src2SubHi); 13350b57cec5SDimitry Andric MRI.clearKillFlags(Src2SubLo); 13360b57cec5SDimitry Andric MRI.clearKillFlags(Src3SubHi); 13370b57cec5SDimitry Andric MRI.clearKillFlags(Src3SubLo); 13380b57cec5SDimitry Andric return true; 13390b57cec5SDimitry Andric } 13400b57cec5SDimitry Andric case Hexagon::PS_pselect: { 13410b57cec5SDimitry Andric const MachineOperand &Op0 = MI.getOperand(0); 13420b57cec5SDimitry Andric const MachineOperand &Op1 = MI.getOperand(1); 13430b57cec5SDimitry Andric const MachineOperand &Op2 = MI.getOperand(2); 13440b57cec5SDimitry Andric const MachineOperand &Op3 = MI.getOperand(3); 13458bcb0991SDimitry Andric Register Rd = Op0.getReg(); 13468bcb0991SDimitry Andric Register Pu = Op1.getReg(); 13478bcb0991SDimitry Andric Register Rs = Op2.getReg(); 13488bcb0991SDimitry Andric Register Rt = Op3.getReg(); 13490b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 13500b57cec5SDimitry Andric unsigned K1 = getKillRegState(Op1.isKill()); 13510b57cec5SDimitry Andric unsigned K2 = getKillRegState(Op2.isKill()); 13520b57cec5SDimitry Andric unsigned K3 = getKillRegState(Op3.isKill()); 13530b57cec5SDimitry Andric if (Rd != Rs) 13540b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrpt), Rd) 13550b57cec5SDimitry Andric .addReg(Pu, (Rd == Rt) ? K1 : 0) 13560b57cec5SDimitry Andric .addReg(Rs, K2); 13570b57cec5SDimitry Andric if (Rd != Rt) 13580b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrpf), Rd) 13590b57cec5SDimitry Andric .addReg(Pu, K1) 13600b57cec5SDimitry Andric .addReg(Rt, K3); 13610b57cec5SDimitry Andric MBB.erase(MI); 13620b57cec5SDimitry Andric return true; 13630b57cec5SDimitry Andric } 13640b57cec5SDimitry Andric case Hexagon::PS_vselect: { 13650b57cec5SDimitry Andric const MachineOperand &Op0 = MI.getOperand(0); 13660b57cec5SDimitry Andric const MachineOperand &Op1 = MI.getOperand(1); 13670b57cec5SDimitry Andric const MachineOperand &Op2 = MI.getOperand(2); 13680b57cec5SDimitry Andric const MachineOperand &Op3 = MI.getOperand(3); 13695ffd83dbSDimitry Andric getLiveOutRegsAt(LiveOut, MI); 13705ffd83dbSDimitry Andric bool IsDestLive = !LiveOut.available(MRI, Op0.getReg()); 13718bcb0991SDimitry Andric Register PReg = Op1.getReg(); 13720b57cec5SDimitry Andric assert(Op1.getSubReg() == 0); 13730b57cec5SDimitry Andric unsigned PState = getRegState(Op1); 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric if (Op0.getReg() != Op2.getReg()) { 13760b57cec5SDimitry Andric unsigned S = Op0.getReg() != Op3.getReg() ? PState & ~RegState::Kill 13770b57cec5SDimitry Andric : PState; 13780b57cec5SDimitry Andric auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vcmov)) 13790b57cec5SDimitry Andric .add(Op0) 13800b57cec5SDimitry Andric .addReg(PReg, S) 13810b57cec5SDimitry Andric .add(Op2); 13820b57cec5SDimitry Andric if (IsDestLive) 13830b57cec5SDimitry Andric T.addReg(Op0.getReg(), RegState::Implicit); 13840b57cec5SDimitry Andric IsDestLive = true; 13850b57cec5SDimitry Andric } 13860b57cec5SDimitry Andric if (Op0.getReg() != Op3.getReg()) { 13870b57cec5SDimitry Andric auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vncmov)) 13880b57cec5SDimitry Andric .add(Op0) 13890b57cec5SDimitry Andric .addReg(PReg, PState) 13900b57cec5SDimitry Andric .add(Op3); 13910b57cec5SDimitry Andric if (IsDestLive) 13920b57cec5SDimitry Andric T.addReg(Op0.getReg(), RegState::Implicit); 13930b57cec5SDimitry Andric } 13940b57cec5SDimitry Andric MBB.erase(MI); 13950b57cec5SDimitry Andric return true; 13960b57cec5SDimitry Andric } 13970b57cec5SDimitry Andric case Hexagon::PS_wselect: { 13980b57cec5SDimitry Andric MachineOperand &Op0 = MI.getOperand(0); 13990b57cec5SDimitry Andric MachineOperand &Op1 = MI.getOperand(1); 14000b57cec5SDimitry Andric MachineOperand &Op2 = MI.getOperand(2); 14010b57cec5SDimitry Andric MachineOperand &Op3 = MI.getOperand(3); 14025ffd83dbSDimitry Andric getLiveOutRegsAt(LiveOut, MI); 14035ffd83dbSDimitry Andric bool IsDestLive = !LiveOut.available(MRI, Op0.getReg()); 14048bcb0991SDimitry Andric Register PReg = Op1.getReg(); 14050b57cec5SDimitry Andric assert(Op1.getSubReg() == 0); 14060b57cec5SDimitry Andric unsigned PState = getRegState(Op1); 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric if (Op0.getReg() != Op2.getReg()) { 14090b57cec5SDimitry Andric unsigned S = Op0.getReg() != Op3.getReg() ? PState & ~RegState::Kill 14100b57cec5SDimitry Andric : PState; 14118bcb0991SDimitry Andric Register SrcLo = HRI.getSubReg(Op2.getReg(), Hexagon::vsub_lo); 14128bcb0991SDimitry Andric Register SrcHi = HRI.getSubReg(Op2.getReg(), Hexagon::vsub_hi); 14130b57cec5SDimitry Andric auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vccombine)) 14140b57cec5SDimitry Andric .add(Op0) 14150b57cec5SDimitry Andric .addReg(PReg, S) 14160b57cec5SDimitry Andric .addReg(SrcHi) 14170b57cec5SDimitry Andric .addReg(SrcLo); 14180b57cec5SDimitry Andric if (IsDestLive) 14190b57cec5SDimitry Andric T.addReg(Op0.getReg(), RegState::Implicit); 14200b57cec5SDimitry Andric IsDestLive = true; 14210b57cec5SDimitry Andric } 14220b57cec5SDimitry Andric if (Op0.getReg() != Op3.getReg()) { 14238bcb0991SDimitry Andric Register SrcLo = HRI.getSubReg(Op3.getReg(), Hexagon::vsub_lo); 14248bcb0991SDimitry Andric Register SrcHi = HRI.getSubReg(Op3.getReg(), Hexagon::vsub_hi); 14250b57cec5SDimitry Andric auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vnccombine)) 14260b57cec5SDimitry Andric .add(Op0) 14270b57cec5SDimitry Andric .addReg(PReg, PState) 14280b57cec5SDimitry Andric .addReg(SrcHi) 14290b57cec5SDimitry Andric .addReg(SrcLo); 14300b57cec5SDimitry Andric if (IsDestLive) 14310b57cec5SDimitry Andric T.addReg(Op0.getReg(), RegState::Implicit); 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric MBB.erase(MI); 14340b57cec5SDimitry Andric return true; 14350b57cec5SDimitry Andric } 14360b57cec5SDimitry Andric 14370b57cec5SDimitry Andric case Hexagon::PS_crash: { 14380b57cec5SDimitry Andric // Generate a misaligned load that is guaranteed to cause a crash. 14390b57cec5SDimitry Andric class CrashPseudoSourceValue : public PseudoSourceValue { 14400b57cec5SDimitry Andric public: 144181ad6265SDimitry Andric CrashPseudoSourceValue(const TargetMachine &TM) 144281ad6265SDimitry Andric : PseudoSourceValue(TargetCustom, TM) {} 14430b57cec5SDimitry Andric 14440b57cec5SDimitry Andric bool isConstant(const MachineFrameInfo *) const override { 14450b57cec5SDimitry Andric return false; 14460b57cec5SDimitry Andric } 14470b57cec5SDimitry Andric bool isAliased(const MachineFrameInfo *) const override { 14480b57cec5SDimitry Andric return false; 14490b57cec5SDimitry Andric } 14500b57cec5SDimitry Andric bool mayAlias(const MachineFrameInfo *) const override { 14510b57cec5SDimitry Andric return false; 14520b57cec5SDimitry Andric } 14530b57cec5SDimitry Andric void printCustom(raw_ostream &OS) const override { 14540b57cec5SDimitry Andric OS << "MisalignedCrash"; 14550b57cec5SDimitry Andric } 14560b57cec5SDimitry Andric }; 14570b57cec5SDimitry Andric 145881ad6265SDimitry Andric static const CrashPseudoSourceValue CrashPSV(MF.getTarget()); 14590b57cec5SDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand( 14600b57cec5SDimitry Andric MachinePointerInfo(&CrashPSV), 14615ffd83dbSDimitry Andric MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile, 8, 14625ffd83dbSDimitry Andric Align(1)); 14630b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::PS_loadrdabs), Hexagon::D13) 14640b57cec5SDimitry Andric .addImm(0xBADC0FEE) // Misaligned load. 14650b57cec5SDimitry Andric .addMemOperand(MMO); 14660b57cec5SDimitry Andric MBB.erase(MI); 14670b57cec5SDimitry Andric return true; 14680b57cec5SDimitry Andric } 14690b57cec5SDimitry Andric 14700b57cec5SDimitry Andric case Hexagon::PS_tailcall_i: 14710b57cec5SDimitry Andric MI.setDesc(get(Hexagon::J2_jump)); 14720b57cec5SDimitry Andric return true; 14730b57cec5SDimitry Andric case Hexagon::PS_tailcall_r: 14740b57cec5SDimitry Andric case Hexagon::PS_jmpret: 14750b57cec5SDimitry Andric MI.setDesc(get(Hexagon::J2_jumpr)); 14760b57cec5SDimitry Andric return true; 14770b57cec5SDimitry Andric case Hexagon::PS_jmprett: 14780b57cec5SDimitry Andric MI.setDesc(get(Hexagon::J2_jumprt)); 14790b57cec5SDimitry Andric return true; 14800b57cec5SDimitry Andric case Hexagon::PS_jmpretf: 14810b57cec5SDimitry Andric MI.setDesc(get(Hexagon::J2_jumprf)); 14820b57cec5SDimitry Andric return true; 14830b57cec5SDimitry Andric case Hexagon::PS_jmprettnewpt: 14840b57cec5SDimitry Andric MI.setDesc(get(Hexagon::J2_jumprtnewpt)); 14850b57cec5SDimitry Andric return true; 14860b57cec5SDimitry Andric case Hexagon::PS_jmpretfnewpt: 14870b57cec5SDimitry Andric MI.setDesc(get(Hexagon::J2_jumprfnewpt)); 14880b57cec5SDimitry Andric return true; 14890b57cec5SDimitry Andric case Hexagon::PS_jmprettnew: 14900b57cec5SDimitry Andric MI.setDesc(get(Hexagon::J2_jumprtnew)); 14910b57cec5SDimitry Andric return true; 14920b57cec5SDimitry Andric case Hexagon::PS_jmpretfnew: 14930b57cec5SDimitry Andric MI.setDesc(get(Hexagon::J2_jumprfnew)); 14940b57cec5SDimitry Andric return true; 14950b57cec5SDimitry Andric 14960b57cec5SDimitry Andric case Hexagon::PS_loadrub_pci: 14970b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadrub_pci, /*HasImm*/true, /*MxOp*/4); 14980b57cec5SDimitry Andric case Hexagon::PS_loadrb_pci: 14990b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadrb_pci, /*HasImm*/true, /*MxOp*/4); 15000b57cec5SDimitry Andric case Hexagon::PS_loadruh_pci: 15010b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadruh_pci, /*HasImm*/true, /*MxOp*/4); 15020b57cec5SDimitry Andric case Hexagon::PS_loadrh_pci: 15030b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadrh_pci, /*HasImm*/true, /*MxOp*/4); 15040b57cec5SDimitry Andric case Hexagon::PS_loadri_pci: 15050b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadri_pci, /*HasImm*/true, /*MxOp*/4); 15060b57cec5SDimitry Andric case Hexagon::PS_loadrd_pci: 15070b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadrd_pci, /*HasImm*/true, /*MxOp*/4); 15080b57cec5SDimitry Andric case Hexagon::PS_loadrub_pcr: 15090b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadrub_pcr, /*HasImm*/false, /*MxOp*/3); 15100b57cec5SDimitry Andric case Hexagon::PS_loadrb_pcr: 15110b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadrb_pcr, /*HasImm*/false, /*MxOp*/3); 15120b57cec5SDimitry Andric case Hexagon::PS_loadruh_pcr: 15130b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadruh_pcr, /*HasImm*/false, /*MxOp*/3); 15140b57cec5SDimitry Andric case Hexagon::PS_loadrh_pcr: 15150b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadrh_pcr, /*HasImm*/false, /*MxOp*/3); 15160b57cec5SDimitry Andric case Hexagon::PS_loadri_pcr: 15170b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadri_pcr, /*HasImm*/false, /*MxOp*/3); 15180b57cec5SDimitry Andric case Hexagon::PS_loadrd_pcr: 15190b57cec5SDimitry Andric return RealCirc(Hexagon::L2_loadrd_pcr, /*HasImm*/false, /*MxOp*/3); 15200b57cec5SDimitry Andric case Hexagon::PS_storerb_pci: 15210b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storerb_pci, /*HasImm*/true, /*MxOp*/3); 15220b57cec5SDimitry Andric case Hexagon::PS_storerh_pci: 15230b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storerh_pci, /*HasImm*/true, /*MxOp*/3); 15240b57cec5SDimitry Andric case Hexagon::PS_storerf_pci: 15250b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storerf_pci, /*HasImm*/true, /*MxOp*/3); 15260b57cec5SDimitry Andric case Hexagon::PS_storeri_pci: 15270b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storeri_pci, /*HasImm*/true, /*MxOp*/3); 15280b57cec5SDimitry Andric case Hexagon::PS_storerd_pci: 15290b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storerd_pci, /*HasImm*/true, /*MxOp*/3); 15300b57cec5SDimitry Andric case Hexagon::PS_storerb_pcr: 15310b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storerb_pcr, /*HasImm*/false, /*MxOp*/2); 15320b57cec5SDimitry Andric case Hexagon::PS_storerh_pcr: 15330b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storerh_pcr, /*HasImm*/false, /*MxOp*/2); 15340b57cec5SDimitry Andric case Hexagon::PS_storerf_pcr: 15350b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storerf_pcr, /*HasImm*/false, /*MxOp*/2); 15360b57cec5SDimitry Andric case Hexagon::PS_storeri_pcr: 15370b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storeri_pcr, /*HasImm*/false, /*MxOp*/2); 15380b57cec5SDimitry Andric case Hexagon::PS_storerd_pcr: 15390b57cec5SDimitry Andric return RealCirc(Hexagon::S2_storerd_pcr, /*HasImm*/false, /*MxOp*/2); 15400b57cec5SDimitry Andric } 15410b57cec5SDimitry Andric 15420b57cec5SDimitry Andric return false; 15430b57cec5SDimitry Andric } 15440b57cec5SDimitry Andric 15450b57cec5SDimitry Andric MachineBasicBlock::instr_iterator 15460b57cec5SDimitry Andric HexagonInstrInfo::expandVGatherPseudo(MachineInstr &MI) const { 15470b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI.getParent(); 15480b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 15490b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 15500b57cec5SDimitry Andric MachineBasicBlock::iterator First; 15510b57cec5SDimitry Andric 15520b57cec5SDimitry Andric switch (Opc) { 15530b57cec5SDimitry Andric case Hexagon::V6_vgathermh_pseudo: 15540b57cec5SDimitry Andric First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermh)) 15550b57cec5SDimitry Andric .add(MI.getOperand(2)) 155604eeddc0SDimitry Andric .add(MI.getOperand(3)) 155704eeddc0SDimitry Andric .add(MI.getOperand(4)); 15580b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) 15590b57cec5SDimitry Andric .add(MI.getOperand(0)) 156004eeddc0SDimitry Andric .addImm(MI.getOperand(1).getImm()) 15610b57cec5SDimitry Andric .addReg(Hexagon::VTMP); 15620b57cec5SDimitry Andric MBB.erase(MI); 15630b57cec5SDimitry Andric return First.getInstrIterator(); 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric case Hexagon::V6_vgathermw_pseudo: 15660b57cec5SDimitry Andric First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermw)) 15670b57cec5SDimitry Andric .add(MI.getOperand(2)) 156804eeddc0SDimitry Andric .add(MI.getOperand(3)) 156904eeddc0SDimitry Andric .add(MI.getOperand(4)); 15700b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) 15710b57cec5SDimitry Andric .add(MI.getOperand(0)) 157204eeddc0SDimitry Andric .addImm(MI.getOperand(1).getImm()) 15730b57cec5SDimitry Andric .addReg(Hexagon::VTMP); 15740b57cec5SDimitry Andric MBB.erase(MI); 15750b57cec5SDimitry Andric return First.getInstrIterator(); 15760b57cec5SDimitry Andric 15770b57cec5SDimitry Andric case Hexagon::V6_vgathermhw_pseudo: 15780b57cec5SDimitry Andric First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhw)) 15790b57cec5SDimitry Andric .add(MI.getOperand(2)) 158004eeddc0SDimitry Andric .add(MI.getOperand(3)) 158104eeddc0SDimitry Andric .add(MI.getOperand(4)); 15820b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) 15830b57cec5SDimitry Andric .add(MI.getOperand(0)) 158404eeddc0SDimitry Andric .addImm(MI.getOperand(1).getImm()) 15850b57cec5SDimitry Andric .addReg(Hexagon::VTMP); 15860b57cec5SDimitry Andric MBB.erase(MI); 15870b57cec5SDimitry Andric return First.getInstrIterator(); 15880b57cec5SDimitry Andric 15890b57cec5SDimitry Andric case Hexagon::V6_vgathermhq_pseudo: 15900b57cec5SDimitry Andric First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhq)) 15910b57cec5SDimitry Andric .add(MI.getOperand(2)) 15920b57cec5SDimitry Andric .add(MI.getOperand(3)) 159304eeddc0SDimitry Andric .add(MI.getOperand(4)) 159404eeddc0SDimitry Andric .add(MI.getOperand(5)); 15950b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) 15960b57cec5SDimitry Andric .add(MI.getOperand(0)) 159704eeddc0SDimitry Andric .addImm(MI.getOperand(1).getImm()) 15980b57cec5SDimitry Andric .addReg(Hexagon::VTMP); 15990b57cec5SDimitry Andric MBB.erase(MI); 16000b57cec5SDimitry Andric return First.getInstrIterator(); 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric case Hexagon::V6_vgathermwq_pseudo: 16030b57cec5SDimitry Andric First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermwq)) 16040b57cec5SDimitry Andric .add(MI.getOperand(2)) 16050b57cec5SDimitry Andric .add(MI.getOperand(3)) 160604eeddc0SDimitry Andric .add(MI.getOperand(4)) 160704eeddc0SDimitry Andric .add(MI.getOperand(5)); 16080b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) 16090b57cec5SDimitry Andric .add(MI.getOperand(0)) 161004eeddc0SDimitry Andric .addImm(MI.getOperand(1).getImm()) 16110b57cec5SDimitry Andric .addReg(Hexagon::VTMP); 16120b57cec5SDimitry Andric MBB.erase(MI); 16130b57cec5SDimitry Andric return First.getInstrIterator(); 16140b57cec5SDimitry Andric 16150b57cec5SDimitry Andric case Hexagon::V6_vgathermhwq_pseudo: 16160b57cec5SDimitry Andric First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhwq)) 16170b57cec5SDimitry Andric .add(MI.getOperand(2)) 16180b57cec5SDimitry Andric .add(MI.getOperand(3)) 161904eeddc0SDimitry Andric .add(MI.getOperand(4)) 162004eeddc0SDimitry Andric .add(MI.getOperand(5)); 16210b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) 16220b57cec5SDimitry Andric .add(MI.getOperand(0)) 162304eeddc0SDimitry Andric .addImm(MI.getOperand(1).getImm()) 16240b57cec5SDimitry Andric .addReg(Hexagon::VTMP); 16250b57cec5SDimitry Andric MBB.erase(MI); 16260b57cec5SDimitry Andric return First.getInstrIterator(); 16270b57cec5SDimitry Andric } 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric return MI.getIterator(); 16300b57cec5SDimitry Andric } 16310b57cec5SDimitry Andric 16320b57cec5SDimitry Andric // We indicate that we want to reverse the branch by 16330b57cec5SDimitry Andric // inserting the reversed branching opcode. 16340b57cec5SDimitry Andric bool HexagonInstrInfo::reverseBranchCondition( 16350b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) const { 16360b57cec5SDimitry Andric if (Cond.empty()) 16370b57cec5SDimitry Andric return true; 16380b57cec5SDimitry Andric assert(Cond[0].isImm() && "First entry in the cond vector not imm-val"); 16390b57cec5SDimitry Andric unsigned opcode = Cond[0].getImm(); 16400b57cec5SDimitry Andric //unsigned temp; 16410b57cec5SDimitry Andric assert(get(opcode).isBranch() && "Should be a branching condition."); 16420b57cec5SDimitry Andric if (isEndLoopN(opcode)) 16430b57cec5SDimitry Andric return true; 16440b57cec5SDimitry Andric unsigned NewOpcode = getInvertedPredicatedOpcode(opcode); 16450b57cec5SDimitry Andric Cond[0].setImm(NewOpcode); 16460b57cec5SDimitry Andric return false; 16470b57cec5SDimitry Andric } 16480b57cec5SDimitry Andric 16490b57cec5SDimitry Andric void HexagonInstrInfo::insertNoop(MachineBasicBlock &MBB, 16500b57cec5SDimitry Andric MachineBasicBlock::iterator MI) const { 16510b57cec5SDimitry Andric DebugLoc DL; 16520b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Hexagon::A2_nop)); 16530b57cec5SDimitry Andric } 16540b57cec5SDimitry Andric 16550b57cec5SDimitry Andric bool HexagonInstrInfo::isPostIncrement(const MachineInstr &MI) const { 16560b57cec5SDimitry Andric return getAddrMode(MI) == HexagonII::PostInc; 16570b57cec5SDimitry Andric } 16580b57cec5SDimitry Andric 16590b57cec5SDimitry Andric // Returns true if an instruction is predicated irrespective of the predicate 16600b57cec5SDimitry Andric // sense. For example, all of the following will return true. 16610b57cec5SDimitry Andric // if (p0) R1 = add(R2, R3) 16620b57cec5SDimitry Andric // if (!p0) R1 = add(R2, R3) 16630b57cec5SDimitry Andric // if (p0.new) R1 = add(R2, R3) 16640b57cec5SDimitry Andric // if (!p0.new) R1 = add(R2, R3) 16650b57cec5SDimitry Andric // Note: New-value stores are not included here as in the current 16660b57cec5SDimitry Andric // implementation, we don't need to check their predicate sense. 16670b57cec5SDimitry Andric bool HexagonInstrInfo::isPredicated(const MachineInstr &MI) const { 16680b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 16690b57cec5SDimitry Andric return (F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask; 16700b57cec5SDimitry Andric } 16710b57cec5SDimitry Andric 16720b57cec5SDimitry Andric bool HexagonInstrInfo::PredicateInstruction( 16730b57cec5SDimitry Andric MachineInstr &MI, ArrayRef<MachineOperand> Cond) const { 16740b57cec5SDimitry Andric if (Cond.empty() || isNewValueJump(Cond[0].getImm()) || 16750b57cec5SDimitry Andric isEndLoopN(Cond[0].getImm())) { 16760b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nCannot predicate:"; MI.dump();); 16770b57cec5SDimitry Andric return false; 16780b57cec5SDimitry Andric } 16790b57cec5SDimitry Andric int Opc = MI.getOpcode(); 16800b57cec5SDimitry Andric assert (isPredicable(MI) && "Expected predicable instruction"); 16810b57cec5SDimitry Andric bool invertJump = predOpcodeHasNot(Cond); 16820b57cec5SDimitry Andric 16830b57cec5SDimitry Andric // We have to predicate MI "in place", i.e. after this function returns, 16840b57cec5SDimitry Andric // MI will need to be transformed into a predicated form. To avoid com- 16850b57cec5SDimitry Andric // plicated manipulations with the operands (handling tied operands, 16860b57cec5SDimitry Andric // etc.), build a new temporary instruction, then overwrite MI with it. 16870b57cec5SDimitry Andric 16880b57cec5SDimitry Andric MachineBasicBlock &B = *MI.getParent(); 16890b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 16900b57cec5SDimitry Andric unsigned PredOpc = getCondOpcode(Opc, invertJump); 16910b57cec5SDimitry Andric MachineInstrBuilder T = BuildMI(B, MI, DL, get(PredOpc)); 16920b57cec5SDimitry Andric unsigned NOp = 0, NumOps = MI.getNumOperands(); 16930b57cec5SDimitry Andric while (NOp < NumOps) { 16940b57cec5SDimitry Andric MachineOperand &Op = MI.getOperand(NOp); 16950b57cec5SDimitry Andric if (!Op.isReg() || !Op.isDef() || Op.isImplicit()) 16960b57cec5SDimitry Andric break; 16970b57cec5SDimitry Andric T.add(Op); 16980b57cec5SDimitry Andric NOp++; 16990b57cec5SDimitry Andric } 17000b57cec5SDimitry Andric 1701bdd1243dSDimitry Andric Register PredReg; 1702bdd1243dSDimitry Andric unsigned PredRegPos, PredRegFlags; 17030b57cec5SDimitry Andric bool GotPredReg = getPredReg(Cond, PredReg, PredRegPos, PredRegFlags); 17040b57cec5SDimitry Andric (void)GotPredReg; 17050b57cec5SDimitry Andric assert(GotPredReg); 17060b57cec5SDimitry Andric T.addReg(PredReg, PredRegFlags); 17070b57cec5SDimitry Andric while (NOp < NumOps) 17080b57cec5SDimitry Andric T.add(MI.getOperand(NOp++)); 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric MI.setDesc(get(PredOpc)); 17110b57cec5SDimitry Andric while (unsigned n = MI.getNumOperands()) 171281ad6265SDimitry Andric MI.removeOperand(n-1); 17130b57cec5SDimitry Andric for (unsigned i = 0, n = T->getNumOperands(); i < n; ++i) 17140b57cec5SDimitry Andric MI.addOperand(T->getOperand(i)); 17150b57cec5SDimitry Andric 17160b57cec5SDimitry Andric MachineBasicBlock::instr_iterator TI = T->getIterator(); 17170b57cec5SDimitry Andric B.erase(TI); 17180b57cec5SDimitry Andric 17190b57cec5SDimitry Andric MachineRegisterInfo &MRI = B.getParent()->getRegInfo(); 17200b57cec5SDimitry Andric MRI.clearKillFlags(PredReg); 17210b57cec5SDimitry Andric return true; 17220b57cec5SDimitry Andric } 17230b57cec5SDimitry Andric 17240b57cec5SDimitry Andric bool HexagonInstrInfo::SubsumesPredicate(ArrayRef<MachineOperand> Pred1, 17250b57cec5SDimitry Andric ArrayRef<MachineOperand> Pred2) const { 17260b57cec5SDimitry Andric // TODO: Fix this 17270b57cec5SDimitry Andric return false; 17280b57cec5SDimitry Andric } 17290b57cec5SDimitry Andric 1730e8d8bef9SDimitry Andric bool HexagonInstrInfo::ClobbersPredicate(MachineInstr &MI, 1731e8d8bef9SDimitry Andric std::vector<MachineOperand> &Pred, 1732e8d8bef9SDimitry Andric bool SkipDead) const { 17330b57cec5SDimitry Andric const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); 17340b57cec5SDimitry Andric 17354824e7fdSDimitry Andric for (const MachineOperand &MO : MI.operands()) { 17360b57cec5SDimitry Andric if (MO.isReg()) { 17370b57cec5SDimitry Andric if (!MO.isDef()) 17380b57cec5SDimitry Andric continue; 17390b57cec5SDimitry Andric const TargetRegisterClass* RC = HRI.getMinimalPhysRegClass(MO.getReg()); 17400b57cec5SDimitry Andric if (RC == &Hexagon::PredRegsRegClass) { 17410b57cec5SDimitry Andric Pred.push_back(MO); 17420b57cec5SDimitry Andric return true; 17430b57cec5SDimitry Andric } 17440b57cec5SDimitry Andric continue; 17450b57cec5SDimitry Andric } else if (MO.isRegMask()) { 1746bdd1243dSDimitry Andric for (Register PR : Hexagon::PredRegsRegClass) { 17470b57cec5SDimitry Andric if (!MI.modifiesRegister(PR, &HRI)) 17480b57cec5SDimitry Andric continue; 17490b57cec5SDimitry Andric Pred.push_back(MO); 17500b57cec5SDimitry Andric return true; 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric } 17530b57cec5SDimitry Andric } 17540b57cec5SDimitry Andric return false; 17550b57cec5SDimitry Andric } 17560b57cec5SDimitry Andric 17570b57cec5SDimitry Andric bool HexagonInstrInfo::isPredicable(const MachineInstr &MI) const { 17580b57cec5SDimitry Andric if (!MI.getDesc().isPredicable()) 17590b57cec5SDimitry Andric return false; 17600b57cec5SDimitry Andric 17610b57cec5SDimitry Andric if (MI.isCall() || isTailCall(MI)) { 17620b57cec5SDimitry Andric if (!Subtarget.usePredicatedCalls()) 17630b57cec5SDimitry Andric return false; 17640b57cec5SDimitry Andric } 17650b57cec5SDimitry Andric 17660b57cec5SDimitry Andric // HVX loads are not predicable on v60, but are on v62. 17670b57cec5SDimitry Andric if (!Subtarget.hasV62Ops()) { 17680b57cec5SDimitry Andric switch (MI.getOpcode()) { 17690b57cec5SDimitry Andric case Hexagon::V6_vL32b_ai: 17700b57cec5SDimitry Andric case Hexagon::V6_vL32b_pi: 17710b57cec5SDimitry Andric case Hexagon::V6_vL32b_ppu: 17720b57cec5SDimitry Andric case Hexagon::V6_vL32b_cur_ai: 17730b57cec5SDimitry Andric case Hexagon::V6_vL32b_cur_pi: 17740b57cec5SDimitry Andric case Hexagon::V6_vL32b_cur_ppu: 17750b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_ai: 17760b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_pi: 17770b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_ppu: 17780b57cec5SDimitry Andric case Hexagon::V6_vL32b_tmp_ai: 17790b57cec5SDimitry Andric case Hexagon::V6_vL32b_tmp_pi: 17800b57cec5SDimitry Andric case Hexagon::V6_vL32b_tmp_ppu: 17810b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_cur_ai: 17820b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_cur_pi: 17830b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_cur_ppu: 17840b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_tmp_ai: 17850b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_tmp_pi: 17860b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_tmp_ppu: 17870b57cec5SDimitry Andric return false; 17880b57cec5SDimitry Andric } 17890b57cec5SDimitry Andric } 17900b57cec5SDimitry Andric return true; 17910b57cec5SDimitry Andric } 17920b57cec5SDimitry Andric 17930b57cec5SDimitry Andric bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr &MI, 17940b57cec5SDimitry Andric const MachineBasicBlock *MBB, 17950b57cec5SDimitry Andric const MachineFunction &MF) const { 17960b57cec5SDimitry Andric // Debug info is never a scheduling boundary. It's necessary to be explicit 17970b57cec5SDimitry Andric // due to the special treatment of IT instructions below, otherwise a 17980b57cec5SDimitry Andric // dbg_value followed by an IT will result in the IT instruction being 17990b57cec5SDimitry Andric // considered a scheduling hazard, which is wrong. It should be the actual 18000b57cec5SDimitry Andric // instruction preceding the dbg_value instruction(s), just like it is 18010b57cec5SDimitry Andric // when debug info is not present. 18020b57cec5SDimitry Andric if (MI.isDebugInstr()) 18030b57cec5SDimitry Andric return false; 18040b57cec5SDimitry Andric 18050b57cec5SDimitry Andric // Throwing call is a boundary. 18060b57cec5SDimitry Andric if (MI.isCall()) { 18070b57cec5SDimitry Andric // Don't mess around with no return calls. 18080b57cec5SDimitry Andric if (doesNotReturn(MI)) 18090b57cec5SDimitry Andric return true; 18100b57cec5SDimitry Andric // If any of the block's successors is a landing pad, this could be a 18110b57cec5SDimitry Andric // throwing call. 1812bdd1243dSDimitry Andric for (auto *I : MBB->successors()) 18130b57cec5SDimitry Andric if (I->isEHPad()) 18140b57cec5SDimitry Andric return true; 18150b57cec5SDimitry Andric } 18160b57cec5SDimitry Andric 18170b57cec5SDimitry Andric // Terminators and labels can't be scheduled around. 18180b57cec5SDimitry Andric if (MI.getDesc().isTerminator() || MI.isPosition()) 18190b57cec5SDimitry Andric return true; 18200b57cec5SDimitry Andric 18215ffd83dbSDimitry Andric // INLINEASM_BR can jump to another block 18225ffd83dbSDimitry Andric if (MI.getOpcode() == TargetOpcode::INLINEASM_BR) 18235ffd83dbSDimitry Andric return true; 18245ffd83dbSDimitry Andric 18250b57cec5SDimitry Andric if (MI.isInlineAsm() && !ScheduleInlineAsm) 18260b57cec5SDimitry Andric return true; 18270b57cec5SDimitry Andric 18280b57cec5SDimitry Andric return false; 18290b57cec5SDimitry Andric } 18300b57cec5SDimitry Andric 18310b57cec5SDimitry Andric /// Measure the specified inline asm to determine an approximation of its 18320b57cec5SDimitry Andric /// length. 18330b57cec5SDimitry Andric /// Comments (which run till the next SeparatorString or newline) do not 18340b57cec5SDimitry Andric /// count as an instruction. 18350b57cec5SDimitry Andric /// Any other non-whitespace text is considered an instruction, with 18360b57cec5SDimitry Andric /// multiple instructions separated by SeparatorString or newlines. 18370b57cec5SDimitry Andric /// Variable-length instructions are not handled here; this function 18380b57cec5SDimitry Andric /// may be overloaded in the target code to do that. 18390b57cec5SDimitry Andric /// Hexagon counts the number of ##'s and adjust for that many 18400b57cec5SDimitry Andric /// constant exenders. 18410b57cec5SDimitry Andric unsigned HexagonInstrInfo::getInlineAsmLength(const char *Str, 18420b57cec5SDimitry Andric const MCAsmInfo &MAI, 18430b57cec5SDimitry Andric const TargetSubtargetInfo *STI) const { 18440b57cec5SDimitry Andric StringRef AStr(Str); 18450b57cec5SDimitry Andric // Count the number of instructions in the asm. 18460b57cec5SDimitry Andric bool atInsnStart = true; 18470b57cec5SDimitry Andric unsigned Length = 0; 18480b57cec5SDimitry Andric const unsigned MaxInstLength = MAI.getMaxInstLength(STI); 18490b57cec5SDimitry Andric for (; *Str; ++Str) { 18500b57cec5SDimitry Andric if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(), 18510b57cec5SDimitry Andric strlen(MAI.getSeparatorString())) == 0) 18520b57cec5SDimitry Andric atInsnStart = true; 18535ffd83dbSDimitry Andric if (atInsnStart && !isSpace(static_cast<unsigned char>(*Str))) { 18540b57cec5SDimitry Andric Length += MaxInstLength; 18550b57cec5SDimitry Andric atInsnStart = false; 18560b57cec5SDimitry Andric } 18570b57cec5SDimitry Andric if (atInsnStart && strncmp(Str, MAI.getCommentString().data(), 18580b57cec5SDimitry Andric MAI.getCommentString().size()) == 0) 18590b57cec5SDimitry Andric atInsnStart = false; 18600b57cec5SDimitry Andric } 18610b57cec5SDimitry Andric 18620b57cec5SDimitry Andric // Add to size number of constant extenders seen * 4. 18630b57cec5SDimitry Andric StringRef Occ("##"); 18640b57cec5SDimitry Andric Length += AStr.count(Occ)*4; 18650b57cec5SDimitry Andric return Length; 18660b57cec5SDimitry Andric } 18670b57cec5SDimitry Andric 18680b57cec5SDimitry Andric ScheduleHazardRecognizer* 18690b57cec5SDimitry Andric HexagonInstrInfo::CreateTargetPostRAHazardRecognizer( 18700b57cec5SDimitry Andric const InstrItineraryData *II, const ScheduleDAG *DAG) const { 18710b57cec5SDimitry Andric if (UseDFAHazardRec) 18720b57cec5SDimitry Andric return new HexagonHazardRecognizer(II, this, Subtarget); 18730b57cec5SDimitry Andric return TargetInstrInfo::CreateTargetPostRAHazardRecognizer(II, DAG); 18740b57cec5SDimitry Andric } 18750b57cec5SDimitry Andric 18760b57cec5SDimitry Andric /// For a comparison instruction, return the source registers in 18770b57cec5SDimitry Andric /// \p SrcReg and \p SrcReg2 if having two register operands, and the value it 18780b57cec5SDimitry Andric /// compares against in CmpValue. Return true if the comparison instruction 18790b57cec5SDimitry Andric /// can be analyzed. 18805ffd83dbSDimitry Andric bool HexagonInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg, 1881349cc55cSDimitry Andric Register &SrcReg2, int64_t &Mask, 1882349cc55cSDimitry Andric int64_t &Value) const { 18830b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 18840b57cec5SDimitry Andric 18850b57cec5SDimitry Andric // Set mask and the first source register. 18860b57cec5SDimitry Andric switch (Opc) { 18870b57cec5SDimitry Andric case Hexagon::C2_cmpeq: 18880b57cec5SDimitry Andric case Hexagon::C2_cmpeqp: 18890b57cec5SDimitry Andric case Hexagon::C2_cmpgt: 18900b57cec5SDimitry Andric case Hexagon::C2_cmpgtp: 18910b57cec5SDimitry Andric case Hexagon::C2_cmpgtu: 18920b57cec5SDimitry Andric case Hexagon::C2_cmpgtup: 18930b57cec5SDimitry Andric case Hexagon::C4_cmpneq: 18940b57cec5SDimitry Andric case Hexagon::C4_cmplte: 18950b57cec5SDimitry Andric case Hexagon::C4_cmplteu: 18960b57cec5SDimitry Andric case Hexagon::C2_cmpeqi: 18970b57cec5SDimitry Andric case Hexagon::C2_cmpgti: 18980b57cec5SDimitry Andric case Hexagon::C2_cmpgtui: 18990b57cec5SDimitry Andric case Hexagon::C4_cmpneqi: 19000b57cec5SDimitry Andric case Hexagon::C4_cmplteui: 19010b57cec5SDimitry Andric case Hexagon::C4_cmpltei: 19020b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 19030b57cec5SDimitry Andric Mask = ~0; 19040b57cec5SDimitry Andric break; 19050b57cec5SDimitry Andric case Hexagon::A4_cmpbeq: 19060b57cec5SDimitry Andric case Hexagon::A4_cmpbgt: 19070b57cec5SDimitry Andric case Hexagon::A4_cmpbgtu: 19080b57cec5SDimitry Andric case Hexagon::A4_cmpbeqi: 19090b57cec5SDimitry Andric case Hexagon::A4_cmpbgti: 19100b57cec5SDimitry Andric case Hexagon::A4_cmpbgtui: 19110b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 19120b57cec5SDimitry Andric Mask = 0xFF; 19130b57cec5SDimitry Andric break; 19140b57cec5SDimitry Andric case Hexagon::A4_cmpheq: 19150b57cec5SDimitry Andric case Hexagon::A4_cmphgt: 19160b57cec5SDimitry Andric case Hexagon::A4_cmphgtu: 19170b57cec5SDimitry Andric case Hexagon::A4_cmpheqi: 19180b57cec5SDimitry Andric case Hexagon::A4_cmphgti: 19190b57cec5SDimitry Andric case Hexagon::A4_cmphgtui: 19200b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 19210b57cec5SDimitry Andric Mask = 0xFFFF; 19220b57cec5SDimitry Andric break; 19230b57cec5SDimitry Andric } 19240b57cec5SDimitry Andric 19250b57cec5SDimitry Andric // Set the value/second source register. 19260b57cec5SDimitry Andric switch (Opc) { 19270b57cec5SDimitry Andric case Hexagon::C2_cmpeq: 19280b57cec5SDimitry Andric case Hexagon::C2_cmpeqp: 19290b57cec5SDimitry Andric case Hexagon::C2_cmpgt: 19300b57cec5SDimitry Andric case Hexagon::C2_cmpgtp: 19310b57cec5SDimitry Andric case Hexagon::C2_cmpgtu: 19320b57cec5SDimitry Andric case Hexagon::C2_cmpgtup: 19330b57cec5SDimitry Andric case Hexagon::A4_cmpbeq: 19340b57cec5SDimitry Andric case Hexagon::A4_cmpbgt: 19350b57cec5SDimitry Andric case Hexagon::A4_cmpbgtu: 19360b57cec5SDimitry Andric case Hexagon::A4_cmpheq: 19370b57cec5SDimitry Andric case Hexagon::A4_cmphgt: 19380b57cec5SDimitry Andric case Hexagon::A4_cmphgtu: 19390b57cec5SDimitry Andric case Hexagon::C4_cmpneq: 19400b57cec5SDimitry Andric case Hexagon::C4_cmplte: 19410b57cec5SDimitry Andric case Hexagon::C4_cmplteu: 19420b57cec5SDimitry Andric SrcReg2 = MI.getOperand(2).getReg(); 194304eeddc0SDimitry Andric Value = 0; 19440b57cec5SDimitry Andric return true; 19450b57cec5SDimitry Andric 19460b57cec5SDimitry Andric case Hexagon::C2_cmpeqi: 19470b57cec5SDimitry Andric case Hexagon::C2_cmpgtui: 19480b57cec5SDimitry Andric case Hexagon::C2_cmpgti: 19490b57cec5SDimitry Andric case Hexagon::C4_cmpneqi: 19500b57cec5SDimitry Andric case Hexagon::C4_cmplteui: 19510b57cec5SDimitry Andric case Hexagon::C4_cmpltei: 19520b57cec5SDimitry Andric case Hexagon::A4_cmpbeqi: 19530b57cec5SDimitry Andric case Hexagon::A4_cmpbgti: 19540b57cec5SDimitry Andric case Hexagon::A4_cmpbgtui: 19550b57cec5SDimitry Andric case Hexagon::A4_cmpheqi: 19560b57cec5SDimitry Andric case Hexagon::A4_cmphgti: 19570b57cec5SDimitry Andric case Hexagon::A4_cmphgtui: { 19580b57cec5SDimitry Andric SrcReg2 = 0; 19590b57cec5SDimitry Andric const MachineOperand &Op2 = MI.getOperand(2); 19600b57cec5SDimitry Andric if (!Op2.isImm()) 19610b57cec5SDimitry Andric return false; 19620b57cec5SDimitry Andric Value = MI.getOperand(2).getImm(); 19630b57cec5SDimitry Andric return true; 19640b57cec5SDimitry Andric } 19650b57cec5SDimitry Andric } 19660b57cec5SDimitry Andric 19670b57cec5SDimitry Andric return false; 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric 19700b57cec5SDimitry Andric unsigned HexagonInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, 19710b57cec5SDimitry Andric const MachineInstr &MI, 19720b57cec5SDimitry Andric unsigned *PredCost) const { 19730b57cec5SDimitry Andric return getInstrTimingClassLatency(ItinData, MI); 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric 19760b57cec5SDimitry Andric DFAPacketizer *HexagonInstrInfo::CreateTargetScheduleState( 19770b57cec5SDimitry Andric const TargetSubtargetInfo &STI) const { 19780b57cec5SDimitry Andric const InstrItineraryData *II = STI.getInstrItineraryData(); 19790b57cec5SDimitry Andric return static_cast<const HexagonSubtarget&>(STI).createDFAPacketizer(II); 19800b57cec5SDimitry Andric } 19810b57cec5SDimitry Andric 19820b57cec5SDimitry Andric // Inspired by this pair: 19830b57cec5SDimitry Andric // %r13 = L2_loadri_io %r29, 136; mem:LD4[FixedStack0] 19840b57cec5SDimitry Andric // S2_storeri_io %r29, 132, killed %r1; flags: mem:ST4[FixedStack1] 19850b57cec5SDimitry Andric // Currently AA considers the addresses in these instructions to be aliasing. 19860b57cec5SDimitry Andric bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint( 19878bcb0991SDimitry Andric const MachineInstr &MIa, const MachineInstr &MIb) const { 19880b57cec5SDimitry Andric if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() || 19890b57cec5SDimitry Andric MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef()) 19900b57cec5SDimitry Andric return false; 19910b57cec5SDimitry Andric 19920b57cec5SDimitry Andric // Instructions that are pure loads, not loads and stores like memops are not 19930b57cec5SDimitry Andric // dependent. 19940b57cec5SDimitry Andric if (MIa.mayLoad() && !isMemOp(MIa) && MIb.mayLoad() && !isMemOp(MIb)) 19950b57cec5SDimitry Andric return true; 19960b57cec5SDimitry Andric 19970b57cec5SDimitry Andric // Get the base register in MIa. 19980b57cec5SDimitry Andric unsigned BasePosA, OffsetPosA; 19990b57cec5SDimitry Andric if (!getBaseAndOffsetPosition(MIa, BasePosA, OffsetPosA)) 20000b57cec5SDimitry Andric return false; 20010b57cec5SDimitry Andric const MachineOperand &BaseA = MIa.getOperand(BasePosA); 20028bcb0991SDimitry Andric Register BaseRegA = BaseA.getReg(); 20030b57cec5SDimitry Andric unsigned BaseSubA = BaseA.getSubReg(); 20040b57cec5SDimitry Andric 20050b57cec5SDimitry Andric // Get the base register in MIb. 20060b57cec5SDimitry Andric unsigned BasePosB, OffsetPosB; 20070b57cec5SDimitry Andric if (!getBaseAndOffsetPosition(MIb, BasePosB, OffsetPosB)) 20080b57cec5SDimitry Andric return false; 20090b57cec5SDimitry Andric const MachineOperand &BaseB = MIb.getOperand(BasePosB); 20108bcb0991SDimitry Andric Register BaseRegB = BaseB.getReg(); 20110b57cec5SDimitry Andric unsigned BaseSubB = BaseB.getSubReg(); 20120b57cec5SDimitry Andric 20130b57cec5SDimitry Andric if (BaseRegA != BaseRegB || BaseSubA != BaseSubB) 20140b57cec5SDimitry Andric return false; 20150b57cec5SDimitry Andric 20160b57cec5SDimitry Andric // Get the access sizes. 20170b57cec5SDimitry Andric unsigned SizeA = getMemAccessSize(MIa); 20180b57cec5SDimitry Andric unsigned SizeB = getMemAccessSize(MIb); 20190b57cec5SDimitry Andric 20200b57cec5SDimitry Andric // Get the offsets. Handle immediates only for now. 20210b57cec5SDimitry Andric const MachineOperand &OffA = MIa.getOperand(OffsetPosA); 20220b57cec5SDimitry Andric const MachineOperand &OffB = MIb.getOperand(OffsetPosB); 20230b57cec5SDimitry Andric if (!MIa.getOperand(OffsetPosA).isImm() || 20240b57cec5SDimitry Andric !MIb.getOperand(OffsetPosB).isImm()) 20250b57cec5SDimitry Andric return false; 20260b57cec5SDimitry Andric int OffsetA = isPostIncrement(MIa) ? 0 : OffA.getImm(); 20270b57cec5SDimitry Andric int OffsetB = isPostIncrement(MIb) ? 0 : OffB.getImm(); 20280b57cec5SDimitry Andric 20290b57cec5SDimitry Andric // This is a mem access with the same base register and known offsets from it. 20300b57cec5SDimitry Andric // Reason about it. 20310b57cec5SDimitry Andric if (OffsetA > OffsetB) { 20320b57cec5SDimitry Andric uint64_t OffDiff = (uint64_t)((int64_t)OffsetA - (int64_t)OffsetB); 20330b57cec5SDimitry Andric return SizeB <= OffDiff; 20340b57cec5SDimitry Andric } 20350b57cec5SDimitry Andric if (OffsetA < OffsetB) { 20360b57cec5SDimitry Andric uint64_t OffDiff = (uint64_t)((int64_t)OffsetB - (int64_t)OffsetA); 20370b57cec5SDimitry Andric return SizeA <= OffDiff; 20380b57cec5SDimitry Andric } 20390b57cec5SDimitry Andric 20400b57cec5SDimitry Andric return false; 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric 20430b57cec5SDimitry Andric /// If the instruction is an increment of a constant value, return the amount. 20440b57cec5SDimitry Andric bool HexagonInstrInfo::getIncrementValue(const MachineInstr &MI, 20450b57cec5SDimitry Andric int &Value) const { 20460b57cec5SDimitry Andric if (isPostIncrement(MI)) { 20470b57cec5SDimitry Andric unsigned BasePos = 0, OffsetPos = 0; 20480b57cec5SDimitry Andric if (!getBaseAndOffsetPosition(MI, BasePos, OffsetPos)) 20490b57cec5SDimitry Andric return false; 20500b57cec5SDimitry Andric const MachineOperand &OffsetOp = MI.getOperand(OffsetPos); 20510b57cec5SDimitry Andric if (OffsetOp.isImm()) { 20520b57cec5SDimitry Andric Value = OffsetOp.getImm(); 20530b57cec5SDimitry Andric return true; 20540b57cec5SDimitry Andric } 20550b57cec5SDimitry Andric } else if (MI.getOpcode() == Hexagon::A2_addi) { 20560b57cec5SDimitry Andric const MachineOperand &AddOp = MI.getOperand(2); 20570b57cec5SDimitry Andric if (AddOp.isImm()) { 20580b57cec5SDimitry Andric Value = AddOp.getImm(); 20590b57cec5SDimitry Andric return true; 20600b57cec5SDimitry Andric } 20610b57cec5SDimitry Andric } 20620b57cec5SDimitry Andric 20630b57cec5SDimitry Andric return false; 20640b57cec5SDimitry Andric } 20650b57cec5SDimitry Andric 20660b57cec5SDimitry Andric std::pair<unsigned, unsigned> 20670b57cec5SDimitry Andric HexagonInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { 20680b57cec5SDimitry Andric return std::make_pair(TF & ~HexagonII::MO_Bitmasks, 20690b57cec5SDimitry Andric TF & HexagonII::MO_Bitmasks); 20700b57cec5SDimitry Andric } 20710b57cec5SDimitry Andric 20720b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, const char*>> 20730b57cec5SDimitry Andric HexagonInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { 20740b57cec5SDimitry Andric using namespace HexagonII; 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric static const std::pair<unsigned, const char*> Flags[] = { 20770b57cec5SDimitry Andric {MO_PCREL, "hexagon-pcrel"}, 20780b57cec5SDimitry Andric {MO_GOT, "hexagon-got"}, 20790b57cec5SDimitry Andric {MO_LO16, "hexagon-lo16"}, 20800b57cec5SDimitry Andric {MO_HI16, "hexagon-hi16"}, 20810b57cec5SDimitry Andric {MO_GPREL, "hexagon-gprel"}, 20820b57cec5SDimitry Andric {MO_GDGOT, "hexagon-gdgot"}, 20830b57cec5SDimitry Andric {MO_GDPLT, "hexagon-gdplt"}, 20840b57cec5SDimitry Andric {MO_IE, "hexagon-ie"}, 20850b57cec5SDimitry Andric {MO_IEGOT, "hexagon-iegot"}, 20860b57cec5SDimitry Andric {MO_TPREL, "hexagon-tprel"} 20870b57cec5SDimitry Andric }; 2088bdd1243dSDimitry Andric return ArrayRef(Flags); 20890b57cec5SDimitry Andric } 20900b57cec5SDimitry Andric 20910b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, const char*>> 20920b57cec5SDimitry Andric HexagonInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { 20930b57cec5SDimitry Andric using namespace HexagonII; 20940b57cec5SDimitry Andric 20950b57cec5SDimitry Andric static const std::pair<unsigned, const char*> Flags[] = { 20960b57cec5SDimitry Andric {HMOTF_ConstExtended, "hexagon-ext"} 20970b57cec5SDimitry Andric }; 2098bdd1243dSDimitry Andric return ArrayRef(Flags); 20990b57cec5SDimitry Andric } 21000b57cec5SDimitry Andric 2101bdd1243dSDimitry Andric Register HexagonInstrInfo::createVR(MachineFunction *MF, MVT VT) const { 21020b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 21030b57cec5SDimitry Andric const TargetRegisterClass *TRC; 21040b57cec5SDimitry Andric if (VT == MVT::i1) { 21050b57cec5SDimitry Andric TRC = &Hexagon::PredRegsRegClass; 21060b57cec5SDimitry Andric } else if (VT == MVT::i32 || VT == MVT::f32) { 21070b57cec5SDimitry Andric TRC = &Hexagon::IntRegsRegClass; 21080b57cec5SDimitry Andric } else if (VT == MVT::i64 || VT == MVT::f64) { 21090b57cec5SDimitry Andric TRC = &Hexagon::DoubleRegsRegClass; 21100b57cec5SDimitry Andric } else { 21110b57cec5SDimitry Andric llvm_unreachable("Cannot handle this register class"); 21120b57cec5SDimitry Andric } 21130b57cec5SDimitry Andric 21148bcb0991SDimitry Andric Register NewReg = MRI.createVirtualRegister(TRC); 21150b57cec5SDimitry Andric return NewReg; 21160b57cec5SDimitry Andric } 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric bool HexagonInstrInfo::isAbsoluteSet(const MachineInstr &MI) const { 21190b57cec5SDimitry Andric return (getAddrMode(MI) == HexagonII::AbsoluteSet); 21200b57cec5SDimitry Andric } 21210b57cec5SDimitry Andric 21220b57cec5SDimitry Andric bool HexagonInstrInfo::isAccumulator(const MachineInstr &MI) const { 21230b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 21240b57cec5SDimitry Andric return((F >> HexagonII::AccumulatorPos) & HexagonII::AccumulatorMask); 21250b57cec5SDimitry Andric } 21260b57cec5SDimitry Andric 21270b57cec5SDimitry Andric bool HexagonInstrInfo::isBaseImmOffset(const MachineInstr &MI) const { 21280b57cec5SDimitry Andric return getAddrMode(MI) == HexagonII::BaseImmOffset; 21290b57cec5SDimitry Andric } 21300b57cec5SDimitry Andric 21310b57cec5SDimitry Andric bool HexagonInstrInfo::isComplex(const MachineInstr &MI) const { 21320b57cec5SDimitry Andric return !isTC1(MI) && !isTC2Early(MI) && !MI.getDesc().mayLoad() && 21330b57cec5SDimitry Andric !MI.getDesc().mayStore() && 21340b57cec5SDimitry Andric MI.getDesc().getOpcode() != Hexagon::S2_allocframe && 21350b57cec5SDimitry Andric MI.getDesc().getOpcode() != Hexagon::L2_deallocframe && 21360b57cec5SDimitry Andric !isMemOp(MI) && !MI.isBranch() && !MI.isReturn() && !MI.isCall(); 21370b57cec5SDimitry Andric } 21380b57cec5SDimitry Andric 2139bdd1243dSDimitry Andric // Return true if the instruction is a compound branch instruction. 21400b57cec5SDimitry Andric bool HexagonInstrInfo::isCompoundBranchInstr(const MachineInstr &MI) const { 21410b57cec5SDimitry Andric return getType(MI) == HexagonII::TypeCJ && MI.isBranch(); 21420b57cec5SDimitry Andric } 21430b57cec5SDimitry Andric 21440b57cec5SDimitry Andric // TODO: In order to have isExtendable for fpimm/f32Ext, we need to handle 21450b57cec5SDimitry Andric // isFPImm and later getFPImm as well. 21460b57cec5SDimitry Andric bool HexagonInstrInfo::isConstExtended(const MachineInstr &MI) const { 21470b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 21480b57cec5SDimitry Andric unsigned isExtended = (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; 21490b57cec5SDimitry Andric if (isExtended) // Instruction must be extended. 21500b57cec5SDimitry Andric return true; 21510b57cec5SDimitry Andric 21520b57cec5SDimitry Andric unsigned isExtendable = 21530b57cec5SDimitry Andric (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; 21540b57cec5SDimitry Andric if (!isExtendable) 21550b57cec5SDimitry Andric return false; 21560b57cec5SDimitry Andric 21570b57cec5SDimitry Andric if (MI.isCall()) 21580b57cec5SDimitry Andric return false; 21590b57cec5SDimitry Andric 21600b57cec5SDimitry Andric short ExtOpNum = getCExtOpNum(MI); 21610b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(ExtOpNum); 21620b57cec5SDimitry Andric // Use MO operand flags to determine if MO 21630b57cec5SDimitry Andric // has the HMOTF_ConstExtended flag set. 21640b57cec5SDimitry Andric if (MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended) 21650b57cec5SDimitry Andric return true; 21660b57cec5SDimitry Andric // If this is a Machine BB address we are talking about, and it is 21670b57cec5SDimitry Andric // not marked as extended, say so. 21680b57cec5SDimitry Andric if (MO.isMBB()) 21690b57cec5SDimitry Andric return false; 21700b57cec5SDimitry Andric 21710b57cec5SDimitry Andric // We could be using an instruction with an extendable immediate and shoehorn 21720b57cec5SDimitry Andric // a global address into it. If it is a global address it will be constant 21730b57cec5SDimitry Andric // extended. We do this for COMBINE. 21740b57cec5SDimitry Andric if (MO.isGlobal() || MO.isSymbol() || MO.isBlockAddress() || 21750b57cec5SDimitry Andric MO.isJTI() || MO.isCPI() || MO.isFPImm()) 21760b57cec5SDimitry Andric return true; 21770b57cec5SDimitry Andric 21780b57cec5SDimitry Andric // If the extendable operand is not 'Immediate' type, the instruction should 21790b57cec5SDimitry Andric // have 'isExtended' flag set. 21800b57cec5SDimitry Andric assert(MO.isImm() && "Extendable operand must be Immediate type"); 21810b57cec5SDimitry Andric 218206c3fb27SDimitry Andric int64_t Value = MO.getImm(); 218306c3fb27SDimitry Andric if ((F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask) { 218406c3fb27SDimitry Andric int32_t SValue = Value; 218506c3fb27SDimitry Andric int32_t MinValue = getMinValue(MI); 218606c3fb27SDimitry Andric int32_t MaxValue = getMaxValue(MI); 218706c3fb27SDimitry Andric return SValue < MinValue || SValue > MaxValue; 218806c3fb27SDimitry Andric } 218906c3fb27SDimitry Andric uint32_t UValue = Value; 219006c3fb27SDimitry Andric uint32_t MinValue = getMinValue(MI); 219106c3fb27SDimitry Andric uint32_t MaxValue = getMaxValue(MI); 219206c3fb27SDimitry Andric return UValue < MinValue || UValue > MaxValue; 21930b57cec5SDimitry Andric } 21940b57cec5SDimitry Andric 21950b57cec5SDimitry Andric bool HexagonInstrInfo::isDeallocRet(const MachineInstr &MI) const { 21960b57cec5SDimitry Andric switch (MI.getOpcode()) { 21970b57cec5SDimitry Andric case Hexagon::L4_return: 21980b57cec5SDimitry Andric case Hexagon::L4_return_t: 21990b57cec5SDimitry Andric case Hexagon::L4_return_f: 22000b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pnt: 22010b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pnt: 22020b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pt: 22030b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pt: 22040b57cec5SDimitry Andric return true; 22050b57cec5SDimitry Andric } 22060b57cec5SDimitry Andric return false; 22070b57cec5SDimitry Andric } 22080b57cec5SDimitry Andric 22090b57cec5SDimitry Andric // Return true when ConsMI uses a register defined by ProdMI. 22100b57cec5SDimitry Andric bool HexagonInstrInfo::isDependent(const MachineInstr &ProdMI, 22110b57cec5SDimitry Andric const MachineInstr &ConsMI) const { 22120b57cec5SDimitry Andric if (!ProdMI.getDesc().getNumDefs()) 22130b57cec5SDimitry Andric return false; 22140b57cec5SDimitry Andric const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); 22150b57cec5SDimitry Andric 2216bdd1243dSDimitry Andric SmallVector<Register, 4> DefsA; 2217bdd1243dSDimitry Andric SmallVector<Register, 4> DefsB; 2218bdd1243dSDimitry Andric SmallVector<Register, 8> UsesA; 2219bdd1243dSDimitry Andric SmallVector<Register, 8> UsesB; 22200b57cec5SDimitry Andric 22210b57cec5SDimitry Andric parseOperands(ProdMI, DefsA, UsesA); 22220b57cec5SDimitry Andric parseOperands(ConsMI, DefsB, UsesB); 22230b57cec5SDimitry Andric 22240b57cec5SDimitry Andric for (auto &RegA : DefsA) 22250b57cec5SDimitry Andric for (auto &RegB : UsesB) { 22260b57cec5SDimitry Andric // True data dependency. 22270b57cec5SDimitry Andric if (RegA == RegB) 22280b57cec5SDimitry Andric return true; 22290b57cec5SDimitry Andric 223006c3fb27SDimitry Andric if (RegA.isPhysical() && llvm::is_contained(HRI.subregs(RegA), RegB)) 22310b57cec5SDimitry Andric return true; 22320b57cec5SDimitry Andric 223306c3fb27SDimitry Andric if (RegB.isPhysical() && llvm::is_contained(HRI.subregs(RegB), RegA)) 22340b57cec5SDimitry Andric return true; 22350b57cec5SDimitry Andric } 22360b57cec5SDimitry Andric 22370b57cec5SDimitry Andric return false; 22380b57cec5SDimitry Andric } 22390b57cec5SDimitry Andric 22400b57cec5SDimitry Andric // Returns true if the instruction is alread a .cur. 22410b57cec5SDimitry Andric bool HexagonInstrInfo::isDotCurInst(const MachineInstr &MI) const { 22420b57cec5SDimitry Andric switch (MI.getOpcode()) { 22430b57cec5SDimitry Andric case Hexagon::V6_vL32b_cur_pi: 22440b57cec5SDimitry Andric case Hexagon::V6_vL32b_cur_ai: 22450b57cec5SDimitry Andric return true; 22460b57cec5SDimitry Andric } 22470b57cec5SDimitry Andric return false; 22480b57cec5SDimitry Andric } 22490b57cec5SDimitry Andric 22500b57cec5SDimitry Andric // Returns true, if any one of the operands is a dot new 22510b57cec5SDimitry Andric // insn, whether it is predicated dot new or register dot new. 22520b57cec5SDimitry Andric bool HexagonInstrInfo::isDotNewInst(const MachineInstr &MI) const { 22530b57cec5SDimitry Andric if (isNewValueInst(MI) || (isPredicated(MI) && isPredicatedNew(MI))) 22540b57cec5SDimitry Andric return true; 22550b57cec5SDimitry Andric 22560b57cec5SDimitry Andric return false; 22570b57cec5SDimitry Andric } 22580b57cec5SDimitry Andric 22590b57cec5SDimitry Andric /// Symmetrical. See if these two instructions are fit for duplex pair. 22600b57cec5SDimitry Andric bool HexagonInstrInfo::isDuplexPair(const MachineInstr &MIa, 22610b57cec5SDimitry Andric const MachineInstr &MIb) const { 22620b57cec5SDimitry Andric HexagonII::SubInstructionGroup MIaG = getDuplexCandidateGroup(MIa); 22630b57cec5SDimitry Andric HexagonII::SubInstructionGroup MIbG = getDuplexCandidateGroup(MIb); 22640b57cec5SDimitry Andric return (isDuplexPairMatch(MIaG, MIbG) || isDuplexPairMatch(MIbG, MIaG)); 22650b57cec5SDimitry Andric } 22660b57cec5SDimitry Andric 22670b57cec5SDimitry Andric bool HexagonInstrInfo::isEndLoopN(unsigned Opcode) const { 22680b57cec5SDimitry Andric return (Opcode == Hexagon::ENDLOOP0 || 22690b57cec5SDimitry Andric Opcode == Hexagon::ENDLOOP1); 22700b57cec5SDimitry Andric } 22710b57cec5SDimitry Andric 22720b57cec5SDimitry Andric bool HexagonInstrInfo::isExpr(unsigned OpType) const { 22730b57cec5SDimitry Andric switch(OpType) { 22740b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 22750b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 22760b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 22770b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 22780b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 22790b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 22800b57cec5SDimitry Andric return true; 22810b57cec5SDimitry Andric default: 22820b57cec5SDimitry Andric return false; 22830b57cec5SDimitry Andric } 22840b57cec5SDimitry Andric } 22850b57cec5SDimitry Andric 22860b57cec5SDimitry Andric bool HexagonInstrInfo::isExtendable(const MachineInstr &MI) const { 22870b57cec5SDimitry Andric const MCInstrDesc &MID = MI.getDesc(); 22880b57cec5SDimitry Andric const uint64_t F = MID.TSFlags; 22890b57cec5SDimitry Andric if ((F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask) 22900b57cec5SDimitry Andric return true; 22910b57cec5SDimitry Andric 22920b57cec5SDimitry Andric // TODO: This is largely obsolete now. Will need to be removed 22930b57cec5SDimitry Andric // in consecutive patches. 22940b57cec5SDimitry Andric switch (MI.getOpcode()) { 22950b57cec5SDimitry Andric // PS_fi and PS_fia remain special cases. 22960b57cec5SDimitry Andric case Hexagon::PS_fi: 22970b57cec5SDimitry Andric case Hexagon::PS_fia: 22980b57cec5SDimitry Andric return true; 22990b57cec5SDimitry Andric default: 23000b57cec5SDimitry Andric return false; 23010b57cec5SDimitry Andric } 23020b57cec5SDimitry Andric return false; 23030b57cec5SDimitry Andric } 23040b57cec5SDimitry Andric 23050b57cec5SDimitry Andric // This returns true in two cases: 23060b57cec5SDimitry Andric // - The OP code itself indicates that this is an extended instruction. 23070b57cec5SDimitry Andric // - One of MOs has been marked with HMOTF_ConstExtended flag. 23080b57cec5SDimitry Andric bool HexagonInstrInfo::isExtended(const MachineInstr &MI) const { 23090b57cec5SDimitry Andric // First check if this is permanently extended op code. 23100b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 23110b57cec5SDimitry Andric if ((F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask) 23120b57cec5SDimitry Andric return true; 23130b57cec5SDimitry Andric // Use MO operand flags to determine if one of MI's operands 23140b57cec5SDimitry Andric // has HMOTF_ConstExtended flag set. 23150b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) 23160b57cec5SDimitry Andric if (MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended) 23170b57cec5SDimitry Andric return true; 23180b57cec5SDimitry Andric return false; 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric 23210b57cec5SDimitry Andric bool HexagonInstrInfo::isFloat(const MachineInstr &MI) const { 23220b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode(); 23230b57cec5SDimitry Andric const uint64_t F = get(Opcode).TSFlags; 23240b57cec5SDimitry Andric return (F >> HexagonII::FPPos) & HexagonII::FPMask; 23250b57cec5SDimitry Andric } 23260b57cec5SDimitry Andric 23270b57cec5SDimitry Andric // No V60 HVX VMEM with A_INDIRECT. 23280b57cec5SDimitry Andric bool HexagonInstrInfo::isHVXMemWithAIndirect(const MachineInstr &I, 23290b57cec5SDimitry Andric const MachineInstr &J) const { 23300b57cec5SDimitry Andric if (!isHVXVec(I)) 23310b57cec5SDimitry Andric return false; 23320b57cec5SDimitry Andric if (!I.mayLoad() && !I.mayStore()) 23330b57cec5SDimitry Andric return false; 23340b57cec5SDimitry Andric return J.isIndirectBranch() || isIndirectCall(J) || isIndirectL4Return(J); 23350b57cec5SDimitry Andric } 23360b57cec5SDimitry Andric 23370b57cec5SDimitry Andric bool HexagonInstrInfo::isIndirectCall(const MachineInstr &MI) const { 23380b57cec5SDimitry Andric switch (MI.getOpcode()) { 23390b57cec5SDimitry Andric case Hexagon::J2_callr: 23400b57cec5SDimitry Andric case Hexagon::J2_callrf: 23410b57cec5SDimitry Andric case Hexagon::J2_callrt: 23420b57cec5SDimitry Andric case Hexagon::PS_call_nr: 23430b57cec5SDimitry Andric return true; 23440b57cec5SDimitry Andric } 23450b57cec5SDimitry Andric return false; 23460b57cec5SDimitry Andric } 23470b57cec5SDimitry Andric 23480b57cec5SDimitry Andric bool HexagonInstrInfo::isIndirectL4Return(const MachineInstr &MI) const { 23490b57cec5SDimitry Andric switch (MI.getOpcode()) { 23500b57cec5SDimitry Andric case Hexagon::L4_return: 23510b57cec5SDimitry Andric case Hexagon::L4_return_t: 23520b57cec5SDimitry Andric case Hexagon::L4_return_f: 23530b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pnt: 23540b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pt: 23550b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pnt: 23560b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pt: 23570b57cec5SDimitry Andric return true; 23580b57cec5SDimitry Andric } 23590b57cec5SDimitry Andric return false; 23600b57cec5SDimitry Andric } 23610b57cec5SDimitry Andric 23620b57cec5SDimitry Andric bool HexagonInstrInfo::isJumpR(const MachineInstr &MI) const { 23630b57cec5SDimitry Andric switch (MI.getOpcode()) { 23640b57cec5SDimitry Andric case Hexagon::J2_jumpr: 23650b57cec5SDimitry Andric case Hexagon::J2_jumprt: 23660b57cec5SDimitry Andric case Hexagon::J2_jumprf: 23670b57cec5SDimitry Andric case Hexagon::J2_jumprtnewpt: 23680b57cec5SDimitry Andric case Hexagon::J2_jumprfnewpt: 23690b57cec5SDimitry Andric case Hexagon::J2_jumprtnew: 23700b57cec5SDimitry Andric case Hexagon::J2_jumprfnew: 23710b57cec5SDimitry Andric return true; 23720b57cec5SDimitry Andric } 23730b57cec5SDimitry Andric return false; 23740b57cec5SDimitry Andric } 23750b57cec5SDimitry Andric 23760b57cec5SDimitry Andric // Return true if a given MI can accommodate given offset. 23770b57cec5SDimitry Andric // Use abs estimate as oppose to the exact number. 23780b57cec5SDimitry Andric // TODO: This will need to be changed to use MC level 23790b57cec5SDimitry Andric // definition of instruction extendable field size. 23800b57cec5SDimitry Andric bool HexagonInstrInfo::isJumpWithinBranchRange(const MachineInstr &MI, 23810b57cec5SDimitry Andric unsigned offset) const { 23820b57cec5SDimitry Andric // This selection of jump instructions matches to that what 23830b57cec5SDimitry Andric // analyzeBranch can parse, plus NVJ. 23840b57cec5SDimitry Andric if (isNewValueJump(MI)) // r9:2 23850b57cec5SDimitry Andric return isInt<11>(offset); 23860b57cec5SDimitry Andric 23870b57cec5SDimitry Andric switch (MI.getOpcode()) { 23880b57cec5SDimitry Andric // Still missing Jump to address condition on register value. 23890b57cec5SDimitry Andric default: 23900b57cec5SDimitry Andric return false; 23910b57cec5SDimitry Andric case Hexagon::J2_jump: // bits<24> dst; // r22:2 23920b57cec5SDimitry Andric case Hexagon::J2_call: 23930b57cec5SDimitry Andric case Hexagon::PS_call_nr: 23940b57cec5SDimitry Andric return isInt<24>(offset); 23950b57cec5SDimitry Andric case Hexagon::J2_jumpt: //bits<17> dst; // r15:2 23960b57cec5SDimitry Andric case Hexagon::J2_jumpf: 23970b57cec5SDimitry Andric case Hexagon::J2_jumptnew: 23980b57cec5SDimitry Andric case Hexagon::J2_jumptnewpt: 23990b57cec5SDimitry Andric case Hexagon::J2_jumpfnew: 24000b57cec5SDimitry Andric case Hexagon::J2_jumpfnewpt: 24010b57cec5SDimitry Andric case Hexagon::J2_callt: 24020b57cec5SDimitry Andric case Hexagon::J2_callf: 24030b57cec5SDimitry Andric return isInt<17>(offset); 24040b57cec5SDimitry Andric case Hexagon::J2_loop0i: 24050b57cec5SDimitry Andric case Hexagon::J2_loop0iext: 24060b57cec5SDimitry Andric case Hexagon::J2_loop0r: 24070b57cec5SDimitry Andric case Hexagon::J2_loop0rext: 24080b57cec5SDimitry Andric case Hexagon::J2_loop1i: 24090b57cec5SDimitry Andric case Hexagon::J2_loop1iext: 24100b57cec5SDimitry Andric case Hexagon::J2_loop1r: 24110b57cec5SDimitry Andric case Hexagon::J2_loop1rext: 24120b57cec5SDimitry Andric return isInt<9>(offset); 24130b57cec5SDimitry Andric // TODO: Add all the compound branches here. Can we do this in Relation model? 24140b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_tp0_jump_nt: 24150b57cec5SDimitry Andric case Hexagon::J4_cmpeqi_tp1_jump_nt: 24160b57cec5SDimitry Andric case Hexagon::J4_cmpeqn1_tp0_jump_nt: 24170b57cec5SDimitry Andric case Hexagon::J4_cmpeqn1_tp1_jump_nt: 24180b57cec5SDimitry Andric return isInt<11>(offset); 24190b57cec5SDimitry Andric } 24200b57cec5SDimitry Andric } 24210b57cec5SDimitry Andric 24220b57cec5SDimitry Andric bool HexagonInstrInfo::isLateSourceInstr(const MachineInstr &MI) const { 24230b57cec5SDimitry Andric // Instructions with iclass A_CVI_VX and attribute A_CVI_LATE uses a multiply 24240b57cec5SDimitry Andric // resource, but all operands can be received late like an ALU instruction. 24250b57cec5SDimitry Andric return getType(MI) == HexagonII::TypeCVI_VX_LATE; 24260b57cec5SDimitry Andric } 24270b57cec5SDimitry Andric 24280b57cec5SDimitry Andric bool HexagonInstrInfo::isLoopN(const MachineInstr &MI) const { 24290b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode(); 24300b57cec5SDimitry Andric return Opcode == Hexagon::J2_loop0i || 24310b57cec5SDimitry Andric Opcode == Hexagon::J2_loop0r || 24320b57cec5SDimitry Andric Opcode == Hexagon::J2_loop0iext || 24330b57cec5SDimitry Andric Opcode == Hexagon::J2_loop0rext || 24340b57cec5SDimitry Andric Opcode == Hexagon::J2_loop1i || 24350b57cec5SDimitry Andric Opcode == Hexagon::J2_loop1r || 24360b57cec5SDimitry Andric Opcode == Hexagon::J2_loop1iext || 24370b57cec5SDimitry Andric Opcode == Hexagon::J2_loop1rext; 24380b57cec5SDimitry Andric } 24390b57cec5SDimitry Andric 24400b57cec5SDimitry Andric bool HexagonInstrInfo::isMemOp(const MachineInstr &MI) const { 24410b57cec5SDimitry Andric switch (MI.getOpcode()) { 24420b57cec5SDimitry Andric default: return false; 24430b57cec5SDimitry Andric case Hexagon::L4_iadd_memopw_io: 24440b57cec5SDimitry Andric case Hexagon::L4_isub_memopw_io: 24450b57cec5SDimitry Andric case Hexagon::L4_add_memopw_io: 24460b57cec5SDimitry Andric case Hexagon::L4_sub_memopw_io: 24470b57cec5SDimitry Andric case Hexagon::L4_and_memopw_io: 24480b57cec5SDimitry Andric case Hexagon::L4_or_memopw_io: 24490b57cec5SDimitry Andric case Hexagon::L4_iadd_memoph_io: 24500b57cec5SDimitry Andric case Hexagon::L4_isub_memoph_io: 24510b57cec5SDimitry Andric case Hexagon::L4_add_memoph_io: 24520b57cec5SDimitry Andric case Hexagon::L4_sub_memoph_io: 24530b57cec5SDimitry Andric case Hexagon::L4_and_memoph_io: 24540b57cec5SDimitry Andric case Hexagon::L4_or_memoph_io: 24550b57cec5SDimitry Andric case Hexagon::L4_iadd_memopb_io: 24560b57cec5SDimitry Andric case Hexagon::L4_isub_memopb_io: 24570b57cec5SDimitry Andric case Hexagon::L4_add_memopb_io: 24580b57cec5SDimitry Andric case Hexagon::L4_sub_memopb_io: 24590b57cec5SDimitry Andric case Hexagon::L4_and_memopb_io: 24600b57cec5SDimitry Andric case Hexagon::L4_or_memopb_io: 24610b57cec5SDimitry Andric case Hexagon::L4_ior_memopb_io: 24620b57cec5SDimitry Andric case Hexagon::L4_ior_memoph_io: 24630b57cec5SDimitry Andric case Hexagon::L4_ior_memopw_io: 24640b57cec5SDimitry Andric case Hexagon::L4_iand_memopb_io: 24650b57cec5SDimitry Andric case Hexagon::L4_iand_memoph_io: 24660b57cec5SDimitry Andric case Hexagon::L4_iand_memopw_io: 24670b57cec5SDimitry Andric return true; 24680b57cec5SDimitry Andric } 24690b57cec5SDimitry Andric return false; 24700b57cec5SDimitry Andric } 24710b57cec5SDimitry Andric 24720b57cec5SDimitry Andric bool HexagonInstrInfo::isNewValue(const MachineInstr &MI) const { 24730b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 24740b57cec5SDimitry Andric return (F >> HexagonII::NewValuePos) & HexagonII::NewValueMask; 24750b57cec5SDimitry Andric } 24760b57cec5SDimitry Andric 24770b57cec5SDimitry Andric bool HexagonInstrInfo::isNewValue(unsigned Opcode) const { 24780b57cec5SDimitry Andric const uint64_t F = get(Opcode).TSFlags; 24790b57cec5SDimitry Andric return (F >> HexagonII::NewValuePos) & HexagonII::NewValueMask; 24800b57cec5SDimitry Andric } 24810b57cec5SDimitry Andric 24820b57cec5SDimitry Andric bool HexagonInstrInfo::isNewValueInst(const MachineInstr &MI) const { 24830b57cec5SDimitry Andric return isNewValueJump(MI) || isNewValueStore(MI); 24840b57cec5SDimitry Andric } 24850b57cec5SDimitry Andric 24860b57cec5SDimitry Andric bool HexagonInstrInfo::isNewValueJump(const MachineInstr &MI) const { 24870b57cec5SDimitry Andric return isNewValue(MI) && MI.isBranch(); 24880b57cec5SDimitry Andric } 24890b57cec5SDimitry Andric 24900b57cec5SDimitry Andric bool HexagonInstrInfo::isNewValueJump(unsigned Opcode) const { 24910b57cec5SDimitry Andric return isNewValue(Opcode) && get(Opcode).isBranch() && isPredicated(Opcode); 24920b57cec5SDimitry Andric } 24930b57cec5SDimitry Andric 24940b57cec5SDimitry Andric bool HexagonInstrInfo::isNewValueStore(const MachineInstr &MI) const { 24950b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 24960b57cec5SDimitry Andric return (F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask; 24970b57cec5SDimitry Andric } 24980b57cec5SDimitry Andric 24990b57cec5SDimitry Andric bool HexagonInstrInfo::isNewValueStore(unsigned Opcode) const { 25000b57cec5SDimitry Andric const uint64_t F = get(Opcode).TSFlags; 25010b57cec5SDimitry Andric return (F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask; 25020b57cec5SDimitry Andric } 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric // Returns true if a particular operand is extendable for an instruction. 25050b57cec5SDimitry Andric bool HexagonInstrInfo::isOperandExtended(const MachineInstr &MI, 25060b57cec5SDimitry Andric unsigned OperandNum) const { 25070b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 25080b57cec5SDimitry Andric return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) 25090b57cec5SDimitry Andric == OperandNum; 25100b57cec5SDimitry Andric } 25110b57cec5SDimitry Andric 25120b57cec5SDimitry Andric bool HexagonInstrInfo::isPredicatedNew(const MachineInstr &MI) const { 25130b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 25140b57cec5SDimitry Andric assert(isPredicated(MI)); 25150b57cec5SDimitry Andric return (F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask; 25160b57cec5SDimitry Andric } 25170b57cec5SDimitry Andric 25180b57cec5SDimitry Andric bool HexagonInstrInfo::isPredicatedNew(unsigned Opcode) const { 25190b57cec5SDimitry Andric const uint64_t F = get(Opcode).TSFlags; 25200b57cec5SDimitry Andric assert(isPredicated(Opcode)); 25210b57cec5SDimitry Andric return (F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask; 25220b57cec5SDimitry Andric } 25230b57cec5SDimitry Andric 25240b57cec5SDimitry Andric bool HexagonInstrInfo::isPredicatedTrue(const MachineInstr &MI) const { 25250b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 25260b57cec5SDimitry Andric return !((F >> HexagonII::PredicatedFalsePos) & 25270b57cec5SDimitry Andric HexagonII::PredicatedFalseMask); 25280b57cec5SDimitry Andric } 25290b57cec5SDimitry Andric 25300b57cec5SDimitry Andric bool HexagonInstrInfo::isPredicatedTrue(unsigned Opcode) const { 25310b57cec5SDimitry Andric const uint64_t F = get(Opcode).TSFlags; 25320b57cec5SDimitry Andric // Make sure that the instruction is predicated. 25330b57cec5SDimitry Andric assert((F>> HexagonII::PredicatedPos) & HexagonII::PredicatedMask); 25340b57cec5SDimitry Andric return !((F >> HexagonII::PredicatedFalsePos) & 25350b57cec5SDimitry Andric HexagonII::PredicatedFalseMask); 25360b57cec5SDimitry Andric } 25370b57cec5SDimitry Andric 25380b57cec5SDimitry Andric bool HexagonInstrInfo::isPredicated(unsigned Opcode) const { 25390b57cec5SDimitry Andric const uint64_t F = get(Opcode).TSFlags; 25400b57cec5SDimitry Andric return (F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask; 25410b57cec5SDimitry Andric } 25420b57cec5SDimitry Andric 25430b57cec5SDimitry Andric bool HexagonInstrInfo::isPredicateLate(unsigned Opcode) const { 25440b57cec5SDimitry Andric const uint64_t F = get(Opcode).TSFlags; 25450b57cec5SDimitry Andric return (F >> HexagonII::PredicateLatePos) & HexagonII::PredicateLateMask; 25460b57cec5SDimitry Andric } 25470b57cec5SDimitry Andric 25480b57cec5SDimitry Andric bool HexagonInstrInfo::isPredictedTaken(unsigned Opcode) const { 25490b57cec5SDimitry Andric const uint64_t F = get(Opcode).TSFlags; 25500b57cec5SDimitry Andric assert(get(Opcode).isBranch() && 25510b57cec5SDimitry Andric (isPredicatedNew(Opcode) || isNewValue(Opcode))); 25520b57cec5SDimitry Andric return (F >> HexagonII::TakenPos) & HexagonII::TakenMask; 25530b57cec5SDimitry Andric } 25540b57cec5SDimitry Andric 25550b57cec5SDimitry Andric bool HexagonInstrInfo::isSaveCalleeSavedRegsCall(const MachineInstr &MI) const { 25560b57cec5SDimitry Andric return MI.getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4 || 25570b57cec5SDimitry Andric MI.getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_EXT || 25580b57cec5SDimitry Andric MI.getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_PIC || 25590b57cec5SDimitry Andric MI.getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC; 25600b57cec5SDimitry Andric } 25610b57cec5SDimitry Andric 25620b57cec5SDimitry Andric bool HexagonInstrInfo::isSignExtendingLoad(const MachineInstr &MI) const { 25630b57cec5SDimitry Andric switch (MI.getOpcode()) { 25640b57cec5SDimitry Andric // Byte 25650b57cec5SDimitry Andric case Hexagon::L2_loadrb_io: 25660b57cec5SDimitry Andric case Hexagon::L4_loadrb_ur: 25670b57cec5SDimitry Andric case Hexagon::L4_loadrb_ap: 25680b57cec5SDimitry Andric case Hexagon::L2_loadrb_pr: 25690b57cec5SDimitry Andric case Hexagon::L2_loadrb_pbr: 25700b57cec5SDimitry Andric case Hexagon::L2_loadrb_pi: 25710b57cec5SDimitry Andric case Hexagon::L2_loadrb_pci: 25720b57cec5SDimitry Andric case Hexagon::L2_loadrb_pcr: 25730b57cec5SDimitry Andric case Hexagon::L2_loadbsw2_io: 25740b57cec5SDimitry Andric case Hexagon::L4_loadbsw2_ur: 25750b57cec5SDimitry Andric case Hexagon::L4_loadbsw2_ap: 25760b57cec5SDimitry Andric case Hexagon::L2_loadbsw2_pr: 25770b57cec5SDimitry Andric case Hexagon::L2_loadbsw2_pbr: 25780b57cec5SDimitry Andric case Hexagon::L2_loadbsw2_pi: 25790b57cec5SDimitry Andric case Hexagon::L2_loadbsw2_pci: 25800b57cec5SDimitry Andric case Hexagon::L2_loadbsw2_pcr: 25810b57cec5SDimitry Andric case Hexagon::L2_loadbsw4_io: 25820b57cec5SDimitry Andric case Hexagon::L4_loadbsw4_ur: 25830b57cec5SDimitry Andric case Hexagon::L4_loadbsw4_ap: 25840b57cec5SDimitry Andric case Hexagon::L2_loadbsw4_pr: 25850b57cec5SDimitry Andric case Hexagon::L2_loadbsw4_pbr: 25860b57cec5SDimitry Andric case Hexagon::L2_loadbsw4_pi: 25870b57cec5SDimitry Andric case Hexagon::L2_loadbsw4_pci: 25880b57cec5SDimitry Andric case Hexagon::L2_loadbsw4_pcr: 25890b57cec5SDimitry Andric case Hexagon::L4_loadrb_rr: 25900b57cec5SDimitry Andric case Hexagon::L2_ploadrbt_io: 25910b57cec5SDimitry Andric case Hexagon::L2_ploadrbt_pi: 25920b57cec5SDimitry Andric case Hexagon::L2_ploadrbf_io: 25930b57cec5SDimitry Andric case Hexagon::L2_ploadrbf_pi: 25940b57cec5SDimitry Andric case Hexagon::L2_ploadrbtnew_io: 25950b57cec5SDimitry Andric case Hexagon::L2_ploadrbfnew_io: 25960b57cec5SDimitry Andric case Hexagon::L4_ploadrbt_rr: 25970b57cec5SDimitry Andric case Hexagon::L4_ploadrbf_rr: 25980b57cec5SDimitry Andric case Hexagon::L4_ploadrbtnew_rr: 25990b57cec5SDimitry Andric case Hexagon::L4_ploadrbfnew_rr: 26000b57cec5SDimitry Andric case Hexagon::L2_ploadrbtnew_pi: 26010b57cec5SDimitry Andric case Hexagon::L2_ploadrbfnew_pi: 26020b57cec5SDimitry Andric case Hexagon::L4_ploadrbt_abs: 26030b57cec5SDimitry Andric case Hexagon::L4_ploadrbf_abs: 26040b57cec5SDimitry Andric case Hexagon::L4_ploadrbtnew_abs: 26050b57cec5SDimitry Andric case Hexagon::L4_ploadrbfnew_abs: 26060b57cec5SDimitry Andric case Hexagon::L2_loadrbgp: 26070b57cec5SDimitry Andric // Half 26080b57cec5SDimitry Andric case Hexagon::L2_loadrh_io: 26090b57cec5SDimitry Andric case Hexagon::L4_loadrh_ur: 26100b57cec5SDimitry Andric case Hexagon::L4_loadrh_ap: 26110b57cec5SDimitry Andric case Hexagon::L2_loadrh_pr: 26120b57cec5SDimitry Andric case Hexagon::L2_loadrh_pbr: 26130b57cec5SDimitry Andric case Hexagon::L2_loadrh_pi: 26140b57cec5SDimitry Andric case Hexagon::L2_loadrh_pci: 26150b57cec5SDimitry Andric case Hexagon::L2_loadrh_pcr: 26160b57cec5SDimitry Andric case Hexagon::L4_loadrh_rr: 26170b57cec5SDimitry Andric case Hexagon::L2_ploadrht_io: 26180b57cec5SDimitry Andric case Hexagon::L2_ploadrht_pi: 26190b57cec5SDimitry Andric case Hexagon::L2_ploadrhf_io: 26200b57cec5SDimitry Andric case Hexagon::L2_ploadrhf_pi: 26210b57cec5SDimitry Andric case Hexagon::L2_ploadrhtnew_io: 26220b57cec5SDimitry Andric case Hexagon::L2_ploadrhfnew_io: 26230b57cec5SDimitry Andric case Hexagon::L4_ploadrht_rr: 26240b57cec5SDimitry Andric case Hexagon::L4_ploadrhf_rr: 26250b57cec5SDimitry Andric case Hexagon::L4_ploadrhtnew_rr: 26260b57cec5SDimitry Andric case Hexagon::L4_ploadrhfnew_rr: 26270b57cec5SDimitry Andric case Hexagon::L2_ploadrhtnew_pi: 26280b57cec5SDimitry Andric case Hexagon::L2_ploadrhfnew_pi: 26290b57cec5SDimitry Andric case Hexagon::L4_ploadrht_abs: 26300b57cec5SDimitry Andric case Hexagon::L4_ploadrhf_abs: 26310b57cec5SDimitry Andric case Hexagon::L4_ploadrhtnew_abs: 26320b57cec5SDimitry Andric case Hexagon::L4_ploadrhfnew_abs: 26330b57cec5SDimitry Andric case Hexagon::L2_loadrhgp: 26340b57cec5SDimitry Andric return true; 26350b57cec5SDimitry Andric default: 26360b57cec5SDimitry Andric return false; 26370b57cec5SDimitry Andric } 26380b57cec5SDimitry Andric } 26390b57cec5SDimitry Andric 26400b57cec5SDimitry Andric bool HexagonInstrInfo::isSolo(const MachineInstr &MI) const { 26410b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 26420b57cec5SDimitry Andric return (F >> HexagonII::SoloPos) & HexagonII::SoloMask; 26430b57cec5SDimitry Andric } 26440b57cec5SDimitry Andric 26450b57cec5SDimitry Andric bool HexagonInstrInfo::isSpillPredRegOp(const MachineInstr &MI) const { 26460b57cec5SDimitry Andric switch (MI.getOpcode()) { 26470b57cec5SDimitry Andric case Hexagon::STriw_pred: 26480b57cec5SDimitry Andric case Hexagon::LDriw_pred: 26490b57cec5SDimitry Andric return true; 26500b57cec5SDimitry Andric default: 26510b57cec5SDimitry Andric return false; 26520b57cec5SDimitry Andric } 26530b57cec5SDimitry Andric } 26540b57cec5SDimitry Andric 26550b57cec5SDimitry Andric bool HexagonInstrInfo::isTailCall(const MachineInstr &MI) const { 26560b57cec5SDimitry Andric if (!MI.isBranch()) 26570b57cec5SDimitry Andric return false; 26580b57cec5SDimitry Andric 26590b57cec5SDimitry Andric for (auto &Op : MI.operands()) 26600b57cec5SDimitry Andric if (Op.isGlobal() || Op.isSymbol()) 26610b57cec5SDimitry Andric return true; 26620b57cec5SDimitry Andric return false; 26630b57cec5SDimitry Andric } 26640b57cec5SDimitry Andric 26650b57cec5SDimitry Andric // Returns true when SU has a timing class TC1. 26660b57cec5SDimitry Andric bool HexagonInstrInfo::isTC1(const MachineInstr &MI) const { 26670b57cec5SDimitry Andric unsigned SchedClass = MI.getDesc().getSchedClass(); 26680b57cec5SDimitry Andric return is_TC1(SchedClass); 26690b57cec5SDimitry Andric } 26700b57cec5SDimitry Andric 26710b57cec5SDimitry Andric bool HexagonInstrInfo::isTC2(const MachineInstr &MI) const { 26720b57cec5SDimitry Andric unsigned SchedClass = MI.getDesc().getSchedClass(); 26730b57cec5SDimitry Andric return is_TC2(SchedClass); 26740b57cec5SDimitry Andric } 26750b57cec5SDimitry Andric 26760b57cec5SDimitry Andric bool HexagonInstrInfo::isTC2Early(const MachineInstr &MI) const { 26770b57cec5SDimitry Andric unsigned SchedClass = MI.getDesc().getSchedClass(); 26780b57cec5SDimitry Andric return is_TC2early(SchedClass); 26790b57cec5SDimitry Andric } 26800b57cec5SDimitry Andric 26810b57cec5SDimitry Andric bool HexagonInstrInfo::isTC4x(const MachineInstr &MI) const { 26820b57cec5SDimitry Andric unsigned SchedClass = MI.getDesc().getSchedClass(); 26830b57cec5SDimitry Andric return is_TC4x(SchedClass); 26840b57cec5SDimitry Andric } 26850b57cec5SDimitry Andric 26860b57cec5SDimitry Andric // Schedule this ASAP. 26870b57cec5SDimitry Andric bool HexagonInstrInfo::isToBeScheduledASAP(const MachineInstr &MI1, 26880b57cec5SDimitry Andric const MachineInstr &MI2) const { 26890b57cec5SDimitry Andric if (mayBeCurLoad(MI1)) { 26900b57cec5SDimitry Andric // if (result of SU is used in Next) return true; 26918bcb0991SDimitry Andric Register DstReg = MI1.getOperand(0).getReg(); 26920b57cec5SDimitry Andric int N = MI2.getNumOperands(); 26930b57cec5SDimitry Andric for (int I = 0; I < N; I++) 26940b57cec5SDimitry Andric if (MI2.getOperand(I).isReg() && DstReg == MI2.getOperand(I).getReg()) 26950b57cec5SDimitry Andric return true; 26960b57cec5SDimitry Andric } 26970b57cec5SDimitry Andric if (mayBeNewStore(MI2)) 26980b57cec5SDimitry Andric if (MI2.getOpcode() == Hexagon::V6_vS32b_pi) 26990b57cec5SDimitry Andric if (MI1.getOperand(0).isReg() && MI2.getOperand(3).isReg() && 27000b57cec5SDimitry Andric MI1.getOperand(0).getReg() == MI2.getOperand(3).getReg()) 27010b57cec5SDimitry Andric return true; 27020b57cec5SDimitry Andric return false; 27030b57cec5SDimitry Andric } 27040b57cec5SDimitry Andric 27050b57cec5SDimitry Andric bool HexagonInstrInfo::isHVXVec(const MachineInstr &MI) const { 27060b57cec5SDimitry Andric const uint64_t V = getType(MI); 27070b57cec5SDimitry Andric return HexagonII::TypeCVI_FIRST <= V && V <= HexagonII::TypeCVI_LAST; 27080b57cec5SDimitry Andric } 27090b57cec5SDimitry Andric 27100b57cec5SDimitry Andric // Check if the Offset is a valid auto-inc imm by Load/Store Type. 27110b57cec5SDimitry Andric bool HexagonInstrInfo::isValidAutoIncImm(const EVT VT, int Offset) const { 27120b57cec5SDimitry Andric int Size = VT.getSizeInBits() / 8; 27130b57cec5SDimitry Andric if (Offset % Size != 0) 27140b57cec5SDimitry Andric return false; 27150b57cec5SDimitry Andric int Count = Offset / Size; 27160b57cec5SDimitry Andric 27170b57cec5SDimitry Andric switch (VT.getSimpleVT().SimpleTy) { 27180b57cec5SDimitry Andric // For scalars the auto-inc is s4 27190b57cec5SDimitry Andric case MVT::i8: 27200b57cec5SDimitry Andric case MVT::i16: 27210b57cec5SDimitry Andric case MVT::i32: 27220b57cec5SDimitry Andric case MVT::i64: 27230b57cec5SDimitry Andric case MVT::f32: 27240b57cec5SDimitry Andric case MVT::f64: 27250b57cec5SDimitry Andric case MVT::v2i16: 27260b57cec5SDimitry Andric case MVT::v2i32: 27270b57cec5SDimitry Andric case MVT::v4i8: 27280b57cec5SDimitry Andric case MVT::v4i16: 27290b57cec5SDimitry Andric case MVT::v8i8: 27300b57cec5SDimitry Andric return isInt<4>(Count); 27310b57cec5SDimitry Andric // For HVX vectors the auto-inc is s3 27320b57cec5SDimitry Andric case MVT::v64i8: 27330b57cec5SDimitry Andric case MVT::v32i16: 27340b57cec5SDimitry Andric case MVT::v16i32: 27350b57cec5SDimitry Andric case MVT::v8i64: 27360b57cec5SDimitry Andric case MVT::v128i8: 27370b57cec5SDimitry Andric case MVT::v64i16: 27380b57cec5SDimitry Andric case MVT::v32i32: 27390b57cec5SDimitry Andric case MVT::v16i64: 27400b57cec5SDimitry Andric return isInt<3>(Count); 27410b57cec5SDimitry Andric default: 27420b57cec5SDimitry Andric break; 27430b57cec5SDimitry Andric } 27440b57cec5SDimitry Andric 27450b57cec5SDimitry Andric llvm_unreachable("Not an valid type!"); 27460b57cec5SDimitry Andric } 27470b57cec5SDimitry Andric 27480b57cec5SDimitry Andric bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset, 27490b57cec5SDimitry Andric const TargetRegisterInfo *TRI, bool Extend) const { 27500b57cec5SDimitry Andric // This function is to check whether the "Offset" is in the correct range of 27510b57cec5SDimitry Andric // the given "Opcode". If "Offset" is not in the correct range, "A2_addi" is 27520b57cec5SDimitry Andric // inserted to calculate the final address. Due to this reason, the function 27530b57cec5SDimitry Andric // assumes that the "Offset" has correct alignment. 27540b57cec5SDimitry Andric // We used to assert if the offset was not properly aligned, however, 27550b57cec5SDimitry Andric // there are cases where a misaligned pointer recast can cause this 27560b57cec5SDimitry Andric // problem, and we need to allow for it. The front end warns of such 27570b57cec5SDimitry Andric // misaligns with respect to load size. 27580b57cec5SDimitry Andric switch (Opcode) { 27590b57cec5SDimitry Andric case Hexagon::PS_vstorerq_ai: 2760480093f4SDimitry Andric case Hexagon::PS_vstorerv_ai: 27610b57cec5SDimitry Andric case Hexagon::PS_vstorerw_ai: 27620b57cec5SDimitry Andric case Hexagon::PS_vstorerw_nt_ai: 27630b57cec5SDimitry Andric case Hexagon::PS_vloadrq_ai: 2764480093f4SDimitry Andric case Hexagon::PS_vloadrv_ai: 27650b57cec5SDimitry Andric case Hexagon::PS_vloadrw_ai: 27660b57cec5SDimitry Andric case Hexagon::PS_vloadrw_nt_ai: 27670b57cec5SDimitry Andric case Hexagon::V6_vL32b_ai: 27680b57cec5SDimitry Andric case Hexagon::V6_vS32b_ai: 2769*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_pred_ai: 2770*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_npred_ai: 2771e8d8bef9SDimitry Andric case Hexagon::V6_vS32b_qpred_ai: 2772e8d8bef9SDimitry Andric case Hexagon::V6_vS32b_nqpred_ai: 2773*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_new_ai: 2774*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_new_pred_ai: 2775*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_new_npred_ai: 2776*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_nt_pred_ai: 2777*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_nt_npred_ai: 2778*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_nt_new_ai: 2779*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_nt_new_pred_ai: 2780*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_nt_new_npred_ai: 2781*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_nt_qpred_ai: 2782*0fca6ea1SDimitry Andric case Hexagon::V6_vS32b_nt_nqpred_ai: 27830b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_ai: 27840b57cec5SDimitry Andric case Hexagon::V6_vS32b_nt_ai: 27850b57cec5SDimitry Andric case Hexagon::V6_vL32Ub_ai: 278604eeddc0SDimitry Andric case Hexagon::V6_vS32Ub_ai: 2787*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_cur_ai: 2788*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_tmp_ai: 2789*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_pred_ai: 2790*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_npred_ai: 2791*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_cur_pred_ai: 2792*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_cur_npred_ai: 2793*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_tmp_pred_ai: 2794*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_tmp_npred_ai: 2795*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_nt_cur_ai: 2796*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_nt_tmp_ai: 2797*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_nt_pred_ai: 2798*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_nt_npred_ai: 2799*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_nt_cur_pred_ai: 2800*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_nt_cur_npred_ai: 2801*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_nt_tmp_pred_ai: 2802*0fca6ea1SDimitry Andric case Hexagon::V6_vL32b_nt_tmp_npred_ai: 280304eeddc0SDimitry Andric case Hexagon::V6_vgathermh_pseudo: 280404eeddc0SDimitry Andric case Hexagon::V6_vgathermw_pseudo: 280504eeddc0SDimitry Andric case Hexagon::V6_vgathermhw_pseudo: 280604eeddc0SDimitry Andric case Hexagon::V6_vgathermhq_pseudo: 280704eeddc0SDimitry Andric case Hexagon::V6_vgathermwq_pseudo: 280804eeddc0SDimitry Andric case Hexagon::V6_vgathermhwq_pseudo: { 28090b57cec5SDimitry Andric unsigned VectorSize = TRI->getSpillSize(Hexagon::HvxVRRegClass); 28100b57cec5SDimitry Andric assert(isPowerOf2_32(VectorSize)); 28110b57cec5SDimitry Andric if (Offset & (VectorSize-1)) 28120b57cec5SDimitry Andric return false; 28130b57cec5SDimitry Andric return isInt<4>(Offset >> Log2_32(VectorSize)); 28140b57cec5SDimitry Andric } 28150b57cec5SDimitry Andric 28160b57cec5SDimitry Andric case Hexagon::J2_loop0i: 28170b57cec5SDimitry Andric case Hexagon::J2_loop1i: 28180b57cec5SDimitry Andric return isUInt<10>(Offset); 28190b57cec5SDimitry Andric 28200b57cec5SDimitry Andric case Hexagon::S4_storeirb_io: 28210b57cec5SDimitry Andric case Hexagon::S4_storeirbt_io: 28220b57cec5SDimitry Andric case Hexagon::S4_storeirbf_io: 28230b57cec5SDimitry Andric return isUInt<6>(Offset); 28240b57cec5SDimitry Andric 28250b57cec5SDimitry Andric case Hexagon::S4_storeirh_io: 28260b57cec5SDimitry Andric case Hexagon::S4_storeirht_io: 28270b57cec5SDimitry Andric case Hexagon::S4_storeirhf_io: 28280b57cec5SDimitry Andric return isShiftedUInt<6,1>(Offset); 28290b57cec5SDimitry Andric 28300b57cec5SDimitry Andric case Hexagon::S4_storeiri_io: 28310b57cec5SDimitry Andric case Hexagon::S4_storeirit_io: 28320b57cec5SDimitry Andric case Hexagon::S4_storeirif_io: 28330b57cec5SDimitry Andric return isShiftedUInt<6,2>(Offset); 283404eeddc0SDimitry Andric // Handle these two compare instructions that are not extendable. 283504eeddc0SDimitry Andric case Hexagon::A4_cmpbeqi: 283604eeddc0SDimitry Andric return isUInt<8>(Offset); 283704eeddc0SDimitry Andric case Hexagon::A4_cmpbgti: 283804eeddc0SDimitry Andric return isInt<8>(Offset); 28390b57cec5SDimitry Andric } 28400b57cec5SDimitry Andric 28410b57cec5SDimitry Andric if (Extend) 28420b57cec5SDimitry Andric return true; 28430b57cec5SDimitry Andric 28440b57cec5SDimitry Andric switch (Opcode) { 28450b57cec5SDimitry Andric case Hexagon::L2_loadri_io: 28460b57cec5SDimitry Andric case Hexagon::S2_storeri_io: 28470b57cec5SDimitry Andric return (Offset >= Hexagon_MEMW_OFFSET_MIN) && 28480b57cec5SDimitry Andric (Offset <= Hexagon_MEMW_OFFSET_MAX); 28490b57cec5SDimitry Andric 28500b57cec5SDimitry Andric case Hexagon::L2_loadrd_io: 28510b57cec5SDimitry Andric case Hexagon::S2_storerd_io: 28520b57cec5SDimitry Andric return (Offset >= Hexagon_MEMD_OFFSET_MIN) && 28530b57cec5SDimitry Andric (Offset <= Hexagon_MEMD_OFFSET_MAX); 28540b57cec5SDimitry Andric 28550b57cec5SDimitry Andric case Hexagon::L2_loadrh_io: 28560b57cec5SDimitry Andric case Hexagon::L2_loadruh_io: 28570b57cec5SDimitry Andric case Hexagon::S2_storerh_io: 28580b57cec5SDimitry Andric case Hexagon::S2_storerf_io: 28590b57cec5SDimitry Andric return (Offset >= Hexagon_MEMH_OFFSET_MIN) && 28600b57cec5SDimitry Andric (Offset <= Hexagon_MEMH_OFFSET_MAX); 28610b57cec5SDimitry Andric 28620b57cec5SDimitry Andric case Hexagon::L2_loadrb_io: 28630b57cec5SDimitry Andric case Hexagon::L2_loadrub_io: 28640b57cec5SDimitry Andric case Hexagon::S2_storerb_io: 28650b57cec5SDimitry Andric return (Offset >= Hexagon_MEMB_OFFSET_MIN) && 28660b57cec5SDimitry Andric (Offset <= Hexagon_MEMB_OFFSET_MAX); 28670b57cec5SDimitry Andric 28680b57cec5SDimitry Andric case Hexagon::A2_addi: 28690b57cec5SDimitry Andric return (Offset >= Hexagon_ADDI_OFFSET_MIN) && 28700b57cec5SDimitry Andric (Offset <= Hexagon_ADDI_OFFSET_MAX); 28710b57cec5SDimitry Andric 28720b57cec5SDimitry Andric case Hexagon::L4_iadd_memopw_io: 28730b57cec5SDimitry Andric case Hexagon::L4_isub_memopw_io: 28740b57cec5SDimitry Andric case Hexagon::L4_add_memopw_io: 28750b57cec5SDimitry Andric case Hexagon::L4_sub_memopw_io: 287604eeddc0SDimitry Andric case Hexagon::L4_iand_memopw_io: 287704eeddc0SDimitry Andric case Hexagon::L4_ior_memopw_io: 28780b57cec5SDimitry Andric case Hexagon::L4_and_memopw_io: 28790b57cec5SDimitry Andric case Hexagon::L4_or_memopw_io: 28800b57cec5SDimitry Andric return (0 <= Offset && Offset <= 255); 28810b57cec5SDimitry Andric 28820b57cec5SDimitry Andric case Hexagon::L4_iadd_memoph_io: 28830b57cec5SDimitry Andric case Hexagon::L4_isub_memoph_io: 28840b57cec5SDimitry Andric case Hexagon::L4_add_memoph_io: 28850b57cec5SDimitry Andric case Hexagon::L4_sub_memoph_io: 288604eeddc0SDimitry Andric case Hexagon::L4_iand_memoph_io: 288704eeddc0SDimitry Andric case Hexagon::L4_ior_memoph_io: 28880b57cec5SDimitry Andric case Hexagon::L4_and_memoph_io: 28890b57cec5SDimitry Andric case Hexagon::L4_or_memoph_io: 28900b57cec5SDimitry Andric return (0 <= Offset && Offset <= 127); 28910b57cec5SDimitry Andric 28920b57cec5SDimitry Andric case Hexagon::L4_iadd_memopb_io: 28930b57cec5SDimitry Andric case Hexagon::L4_isub_memopb_io: 28940b57cec5SDimitry Andric case Hexagon::L4_add_memopb_io: 28950b57cec5SDimitry Andric case Hexagon::L4_sub_memopb_io: 289604eeddc0SDimitry Andric case Hexagon::L4_iand_memopb_io: 289704eeddc0SDimitry Andric case Hexagon::L4_ior_memopb_io: 28980b57cec5SDimitry Andric case Hexagon::L4_and_memopb_io: 28990b57cec5SDimitry Andric case Hexagon::L4_or_memopb_io: 29000b57cec5SDimitry Andric return (0 <= Offset && Offset <= 63); 29010b57cec5SDimitry Andric 29020b57cec5SDimitry Andric // LDriw_xxx and STriw_xxx are pseudo operations, so it has to take offset of 29030b57cec5SDimitry Andric // any size. Later pass knows how to handle it. 29040b57cec5SDimitry Andric case Hexagon::STriw_pred: 29050b57cec5SDimitry Andric case Hexagon::LDriw_pred: 29060b57cec5SDimitry Andric case Hexagon::STriw_ctr: 29070b57cec5SDimitry Andric case Hexagon::LDriw_ctr: 29080b57cec5SDimitry Andric return true; 29090b57cec5SDimitry Andric 29100b57cec5SDimitry Andric case Hexagon::PS_fi: 29110b57cec5SDimitry Andric case Hexagon::PS_fia: 29120b57cec5SDimitry Andric case Hexagon::INLINEASM: 29130b57cec5SDimitry Andric return true; 29140b57cec5SDimitry Andric 29150b57cec5SDimitry Andric case Hexagon::L2_ploadrbt_io: 29160b57cec5SDimitry Andric case Hexagon::L2_ploadrbf_io: 29170b57cec5SDimitry Andric case Hexagon::L2_ploadrubt_io: 29180b57cec5SDimitry Andric case Hexagon::L2_ploadrubf_io: 29190b57cec5SDimitry Andric case Hexagon::S2_pstorerbt_io: 29200b57cec5SDimitry Andric case Hexagon::S2_pstorerbf_io: 29210b57cec5SDimitry Andric return isUInt<6>(Offset); 29220b57cec5SDimitry Andric 29230b57cec5SDimitry Andric case Hexagon::L2_ploadrht_io: 29240b57cec5SDimitry Andric case Hexagon::L2_ploadrhf_io: 29250b57cec5SDimitry Andric case Hexagon::L2_ploadruht_io: 29260b57cec5SDimitry Andric case Hexagon::L2_ploadruhf_io: 29270b57cec5SDimitry Andric case Hexagon::S2_pstorerht_io: 29280b57cec5SDimitry Andric case Hexagon::S2_pstorerhf_io: 29290b57cec5SDimitry Andric return isShiftedUInt<6,1>(Offset); 29300b57cec5SDimitry Andric 29310b57cec5SDimitry Andric case Hexagon::L2_ploadrit_io: 29320b57cec5SDimitry Andric case Hexagon::L2_ploadrif_io: 29330b57cec5SDimitry Andric case Hexagon::S2_pstorerit_io: 29340b57cec5SDimitry Andric case Hexagon::S2_pstorerif_io: 29350b57cec5SDimitry Andric return isShiftedUInt<6,2>(Offset); 29360b57cec5SDimitry Andric 29370b57cec5SDimitry Andric case Hexagon::L2_ploadrdt_io: 29380b57cec5SDimitry Andric case Hexagon::L2_ploadrdf_io: 29390b57cec5SDimitry Andric case Hexagon::S2_pstorerdt_io: 29400b57cec5SDimitry Andric case Hexagon::S2_pstorerdf_io: 29410b57cec5SDimitry Andric return isShiftedUInt<6,3>(Offset); 294204eeddc0SDimitry Andric 294304eeddc0SDimitry Andric case Hexagon::L2_loadbsw2_io: 294404eeddc0SDimitry Andric case Hexagon::L2_loadbzw2_io: 294504eeddc0SDimitry Andric return isShiftedInt<11,1>(Offset); 294604eeddc0SDimitry Andric 294704eeddc0SDimitry Andric case Hexagon::L2_loadbsw4_io: 294804eeddc0SDimitry Andric case Hexagon::L2_loadbzw4_io: 294904eeddc0SDimitry Andric return isShiftedInt<11,2>(Offset); 29500b57cec5SDimitry Andric } // switch 29510b57cec5SDimitry Andric 295204eeddc0SDimitry Andric dbgs() << "Failed Opcode is : " << Opcode << " (" << getName(Opcode) 295304eeddc0SDimitry Andric << ")\n"; 29540b57cec5SDimitry Andric llvm_unreachable("No offset range is defined for this opcode. " 29550b57cec5SDimitry Andric "Please define it in the above switch statement!"); 29560b57cec5SDimitry Andric } 29570b57cec5SDimitry Andric 29580b57cec5SDimitry Andric bool HexagonInstrInfo::isVecAcc(const MachineInstr &MI) const { 29590b57cec5SDimitry Andric return isHVXVec(MI) && isAccumulator(MI); 29600b57cec5SDimitry Andric } 29610b57cec5SDimitry Andric 29620b57cec5SDimitry Andric bool HexagonInstrInfo::isVecALU(const MachineInstr &MI) const { 29630b57cec5SDimitry Andric const uint64_t F = get(MI.getOpcode()).TSFlags; 29640b57cec5SDimitry Andric const uint64_t V = ((F >> HexagonII::TypePos) & HexagonII::TypeMask); 29650b57cec5SDimitry Andric return 29660b57cec5SDimitry Andric V == HexagonII::TypeCVI_VA || 29670b57cec5SDimitry Andric V == HexagonII::TypeCVI_VA_DV; 29680b57cec5SDimitry Andric } 29690b57cec5SDimitry Andric 29700b57cec5SDimitry Andric bool HexagonInstrInfo::isVecUsableNextPacket(const MachineInstr &ProdMI, 29710b57cec5SDimitry Andric const MachineInstr &ConsMI) const { 29720b57cec5SDimitry Andric if (EnableACCForwarding && isVecAcc(ProdMI) && isVecAcc(ConsMI)) 29730b57cec5SDimitry Andric return true; 29740b57cec5SDimitry Andric 29750b57cec5SDimitry Andric if (EnableALUForwarding && (isVecALU(ConsMI) || isLateSourceInstr(ConsMI))) 29760b57cec5SDimitry Andric return true; 29770b57cec5SDimitry Andric 29780b57cec5SDimitry Andric if (mayBeNewStore(ConsMI)) 29790b57cec5SDimitry Andric return true; 29800b57cec5SDimitry Andric 29810b57cec5SDimitry Andric return false; 29820b57cec5SDimitry Andric } 29830b57cec5SDimitry Andric 29840b57cec5SDimitry Andric bool HexagonInstrInfo::isZeroExtendingLoad(const MachineInstr &MI) const { 29850b57cec5SDimitry Andric switch (MI.getOpcode()) { 29860b57cec5SDimitry Andric // Byte 29870b57cec5SDimitry Andric case Hexagon::L2_loadrub_io: 29880b57cec5SDimitry Andric case Hexagon::L4_loadrub_ur: 29890b57cec5SDimitry Andric case Hexagon::L4_loadrub_ap: 29900b57cec5SDimitry Andric case Hexagon::L2_loadrub_pr: 29910b57cec5SDimitry Andric case Hexagon::L2_loadrub_pbr: 29920b57cec5SDimitry Andric case Hexagon::L2_loadrub_pi: 29930b57cec5SDimitry Andric case Hexagon::L2_loadrub_pci: 29940b57cec5SDimitry Andric case Hexagon::L2_loadrub_pcr: 29950b57cec5SDimitry Andric case Hexagon::L2_loadbzw2_io: 29960b57cec5SDimitry Andric case Hexagon::L4_loadbzw2_ur: 29970b57cec5SDimitry Andric case Hexagon::L4_loadbzw2_ap: 29980b57cec5SDimitry Andric case Hexagon::L2_loadbzw2_pr: 29990b57cec5SDimitry Andric case Hexagon::L2_loadbzw2_pbr: 30000b57cec5SDimitry Andric case Hexagon::L2_loadbzw2_pi: 30010b57cec5SDimitry Andric case Hexagon::L2_loadbzw2_pci: 30020b57cec5SDimitry Andric case Hexagon::L2_loadbzw2_pcr: 30030b57cec5SDimitry Andric case Hexagon::L2_loadbzw4_io: 30040b57cec5SDimitry Andric case Hexagon::L4_loadbzw4_ur: 30050b57cec5SDimitry Andric case Hexagon::L4_loadbzw4_ap: 30060b57cec5SDimitry Andric case Hexagon::L2_loadbzw4_pr: 30070b57cec5SDimitry Andric case Hexagon::L2_loadbzw4_pbr: 30080b57cec5SDimitry Andric case Hexagon::L2_loadbzw4_pi: 30090b57cec5SDimitry Andric case Hexagon::L2_loadbzw4_pci: 30100b57cec5SDimitry Andric case Hexagon::L2_loadbzw4_pcr: 30110b57cec5SDimitry Andric case Hexagon::L4_loadrub_rr: 30120b57cec5SDimitry Andric case Hexagon::L2_ploadrubt_io: 30130b57cec5SDimitry Andric case Hexagon::L2_ploadrubt_pi: 30140b57cec5SDimitry Andric case Hexagon::L2_ploadrubf_io: 30150b57cec5SDimitry Andric case Hexagon::L2_ploadrubf_pi: 30160b57cec5SDimitry Andric case Hexagon::L2_ploadrubtnew_io: 30170b57cec5SDimitry Andric case Hexagon::L2_ploadrubfnew_io: 30180b57cec5SDimitry Andric case Hexagon::L4_ploadrubt_rr: 30190b57cec5SDimitry Andric case Hexagon::L4_ploadrubf_rr: 30200b57cec5SDimitry Andric case Hexagon::L4_ploadrubtnew_rr: 30210b57cec5SDimitry Andric case Hexagon::L4_ploadrubfnew_rr: 30220b57cec5SDimitry Andric case Hexagon::L2_ploadrubtnew_pi: 30230b57cec5SDimitry Andric case Hexagon::L2_ploadrubfnew_pi: 30240b57cec5SDimitry Andric case Hexagon::L4_ploadrubt_abs: 30250b57cec5SDimitry Andric case Hexagon::L4_ploadrubf_abs: 30260b57cec5SDimitry Andric case Hexagon::L4_ploadrubtnew_abs: 30270b57cec5SDimitry Andric case Hexagon::L4_ploadrubfnew_abs: 30280b57cec5SDimitry Andric case Hexagon::L2_loadrubgp: 30290b57cec5SDimitry Andric // Half 30300b57cec5SDimitry Andric case Hexagon::L2_loadruh_io: 30310b57cec5SDimitry Andric case Hexagon::L4_loadruh_ur: 30320b57cec5SDimitry Andric case Hexagon::L4_loadruh_ap: 30330b57cec5SDimitry Andric case Hexagon::L2_loadruh_pr: 30340b57cec5SDimitry Andric case Hexagon::L2_loadruh_pbr: 30350b57cec5SDimitry Andric case Hexagon::L2_loadruh_pi: 30360b57cec5SDimitry Andric case Hexagon::L2_loadruh_pci: 30370b57cec5SDimitry Andric case Hexagon::L2_loadruh_pcr: 30380b57cec5SDimitry Andric case Hexagon::L4_loadruh_rr: 30390b57cec5SDimitry Andric case Hexagon::L2_ploadruht_io: 30400b57cec5SDimitry Andric case Hexagon::L2_ploadruht_pi: 30410b57cec5SDimitry Andric case Hexagon::L2_ploadruhf_io: 30420b57cec5SDimitry Andric case Hexagon::L2_ploadruhf_pi: 30430b57cec5SDimitry Andric case Hexagon::L2_ploadruhtnew_io: 30440b57cec5SDimitry Andric case Hexagon::L2_ploadruhfnew_io: 30450b57cec5SDimitry Andric case Hexagon::L4_ploadruht_rr: 30460b57cec5SDimitry Andric case Hexagon::L4_ploadruhf_rr: 30470b57cec5SDimitry Andric case Hexagon::L4_ploadruhtnew_rr: 30480b57cec5SDimitry Andric case Hexagon::L4_ploadruhfnew_rr: 30490b57cec5SDimitry Andric case Hexagon::L2_ploadruhtnew_pi: 30500b57cec5SDimitry Andric case Hexagon::L2_ploadruhfnew_pi: 30510b57cec5SDimitry Andric case Hexagon::L4_ploadruht_abs: 30520b57cec5SDimitry Andric case Hexagon::L4_ploadruhf_abs: 30530b57cec5SDimitry Andric case Hexagon::L4_ploadruhtnew_abs: 30540b57cec5SDimitry Andric case Hexagon::L4_ploadruhfnew_abs: 30550b57cec5SDimitry Andric case Hexagon::L2_loadruhgp: 30560b57cec5SDimitry Andric return true; 30570b57cec5SDimitry Andric default: 30580b57cec5SDimitry Andric return false; 30590b57cec5SDimitry Andric } 30600b57cec5SDimitry Andric } 30610b57cec5SDimitry Andric 30620b57cec5SDimitry Andric // Add latency to instruction. 30630b57cec5SDimitry Andric bool HexagonInstrInfo::addLatencyToSchedule(const MachineInstr &MI1, 30640b57cec5SDimitry Andric const MachineInstr &MI2) const { 30650b57cec5SDimitry Andric if (isHVXVec(MI1) && isHVXVec(MI2)) 30660b57cec5SDimitry Andric if (!isVecUsableNextPacket(MI1, MI2)) 30670b57cec5SDimitry Andric return true; 30680b57cec5SDimitry Andric return false; 30690b57cec5SDimitry Andric } 30700b57cec5SDimitry Andric 30710b57cec5SDimitry Andric /// Get the base register and byte offset of a load/store instr. 30725ffd83dbSDimitry Andric bool HexagonInstrInfo::getMemOperandsWithOffsetWidth( 30735ffd83dbSDimitry Andric const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps, 3074*0fca6ea1SDimitry Andric int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, 30750b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 30765ffd83dbSDimitry Andric OffsetIsScalable = false; 30775ffd83dbSDimitry Andric const MachineOperand *BaseOp = getBaseAndOffset(LdSt, Offset, Width); 30785ffd83dbSDimitry Andric if (!BaseOp || !BaseOp->isReg()) 30795ffd83dbSDimitry Andric return false; 30805ffd83dbSDimitry Andric BaseOps.push_back(BaseOp); 30815ffd83dbSDimitry Andric return true; 30820b57cec5SDimitry Andric } 30830b57cec5SDimitry Andric 30840b57cec5SDimitry Andric /// Can these instructions execute at the same time in a bundle. 30850b57cec5SDimitry Andric bool HexagonInstrInfo::canExecuteInBundle(const MachineInstr &First, 30860b57cec5SDimitry Andric const MachineInstr &Second) const { 30870b57cec5SDimitry Andric if (Second.mayStore() && First.getOpcode() == Hexagon::S2_allocframe) { 30880b57cec5SDimitry Andric const MachineOperand &Op = Second.getOperand(0); 30890b57cec5SDimitry Andric if (Op.isReg() && Op.isUse() && Op.getReg() == Hexagon::R29) 30900b57cec5SDimitry Andric return true; 30910b57cec5SDimitry Andric } 30920b57cec5SDimitry Andric if (DisableNVSchedule) 30930b57cec5SDimitry Andric return false; 30940b57cec5SDimitry Andric if (mayBeNewStore(Second)) { 30950b57cec5SDimitry Andric // Make sure the definition of the first instruction is the value being 30960b57cec5SDimitry Andric // stored. 30970b57cec5SDimitry Andric const MachineOperand &Stored = 30980b57cec5SDimitry Andric Second.getOperand(Second.getNumOperands() - 1); 30990b57cec5SDimitry Andric if (!Stored.isReg()) 31000b57cec5SDimitry Andric return false; 31010b57cec5SDimitry Andric for (unsigned i = 0, e = First.getNumOperands(); i < e; ++i) { 31020b57cec5SDimitry Andric const MachineOperand &Op = First.getOperand(i); 31030b57cec5SDimitry Andric if (Op.isReg() && Op.isDef() && Op.getReg() == Stored.getReg()) 31040b57cec5SDimitry Andric return true; 31050b57cec5SDimitry Andric } 31060b57cec5SDimitry Andric } 31070b57cec5SDimitry Andric return false; 31080b57cec5SDimitry Andric } 31090b57cec5SDimitry Andric 31100b57cec5SDimitry Andric bool HexagonInstrInfo::doesNotReturn(const MachineInstr &CallMI) const { 31110b57cec5SDimitry Andric unsigned Opc = CallMI.getOpcode(); 31120b57cec5SDimitry Andric return Opc == Hexagon::PS_call_nr || Opc == Hexagon::PS_callr_nr; 31130b57cec5SDimitry Andric } 31140b57cec5SDimitry Andric 31150b57cec5SDimitry Andric bool HexagonInstrInfo::hasEHLabel(const MachineBasicBlock *B) const { 31160b57cec5SDimitry Andric for (auto &I : *B) 31170b57cec5SDimitry Andric if (I.isEHLabel()) 31180b57cec5SDimitry Andric return true; 31190b57cec5SDimitry Andric return false; 31200b57cec5SDimitry Andric } 31210b57cec5SDimitry Andric 31220b57cec5SDimitry Andric // Returns true if an instruction can be converted into a non-extended 31230b57cec5SDimitry Andric // equivalent instruction. 31240b57cec5SDimitry Andric bool HexagonInstrInfo::hasNonExtEquivalent(const MachineInstr &MI) const { 31250b57cec5SDimitry Andric short NonExtOpcode; 31260b57cec5SDimitry Andric // Check if the instruction has a register form that uses register in place 31270b57cec5SDimitry Andric // of the extended operand, if so return that as the non-extended form. 31280b57cec5SDimitry Andric if (Hexagon::getRegForm(MI.getOpcode()) >= 0) 31290b57cec5SDimitry Andric return true; 31300b57cec5SDimitry Andric 31310b57cec5SDimitry Andric if (MI.getDesc().mayLoad() || MI.getDesc().mayStore()) { 31320b57cec5SDimitry Andric // Check addressing mode and retrieve non-ext equivalent instruction. 31330b57cec5SDimitry Andric 31340b57cec5SDimitry Andric switch (getAddrMode(MI)) { 31350b57cec5SDimitry Andric case HexagonII::Absolute: 31360b57cec5SDimitry Andric // Load/store with absolute addressing mode can be converted into 31370b57cec5SDimitry Andric // base+offset mode. 31380b57cec5SDimitry Andric NonExtOpcode = Hexagon::changeAddrMode_abs_io(MI.getOpcode()); 31390b57cec5SDimitry Andric break; 31400b57cec5SDimitry Andric case HexagonII::BaseImmOffset: 31410b57cec5SDimitry Andric // Load/store with base+offset addressing mode can be converted into 31420b57cec5SDimitry Andric // base+register offset addressing mode. However left shift operand should 31430b57cec5SDimitry Andric // be set to 0. 31440b57cec5SDimitry Andric NonExtOpcode = Hexagon::changeAddrMode_io_rr(MI.getOpcode()); 31450b57cec5SDimitry Andric break; 31460b57cec5SDimitry Andric case HexagonII::BaseLongOffset: 31470b57cec5SDimitry Andric NonExtOpcode = Hexagon::changeAddrMode_ur_rr(MI.getOpcode()); 31480b57cec5SDimitry Andric break; 31490b57cec5SDimitry Andric default: 31500b57cec5SDimitry Andric return false; 31510b57cec5SDimitry Andric } 31520b57cec5SDimitry Andric if (NonExtOpcode < 0) 31530b57cec5SDimitry Andric return false; 31540b57cec5SDimitry Andric return true; 31550b57cec5SDimitry Andric } 31560b57cec5SDimitry Andric return false; 31570b57cec5SDimitry Andric } 31580b57cec5SDimitry Andric 31590b57cec5SDimitry Andric bool HexagonInstrInfo::hasPseudoInstrPair(const MachineInstr &MI) const { 31600b57cec5SDimitry Andric return Hexagon::getRealHWInstr(MI.getOpcode(), 31610b57cec5SDimitry Andric Hexagon::InstrType_Pseudo) >= 0; 31620b57cec5SDimitry Andric } 31630b57cec5SDimitry Andric 31640b57cec5SDimitry Andric bool HexagonInstrInfo::hasUncondBranch(const MachineBasicBlock *B) 31650b57cec5SDimitry Andric const { 31660b57cec5SDimitry Andric MachineBasicBlock::const_iterator I = B->getFirstTerminator(), E = B->end(); 31670b57cec5SDimitry Andric while (I != E) { 31680b57cec5SDimitry Andric if (I->isBarrier()) 31690b57cec5SDimitry Andric return true; 31700b57cec5SDimitry Andric ++I; 31710b57cec5SDimitry Andric } 31720b57cec5SDimitry Andric return false; 31730b57cec5SDimitry Andric } 31740b57cec5SDimitry Andric 31750b57cec5SDimitry Andric // Returns true, if a LD insn can be promoted to a cur load. 31760b57cec5SDimitry Andric bool HexagonInstrInfo::mayBeCurLoad(const MachineInstr &MI) const { 31770b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 31780b57cec5SDimitry Andric return ((F >> HexagonII::mayCVLoadPos) & HexagonII::mayCVLoadMask) && 31790b57cec5SDimitry Andric Subtarget.hasV60Ops(); 31800b57cec5SDimitry Andric } 31810b57cec5SDimitry Andric 31820b57cec5SDimitry Andric // Returns true, if a ST insn can be promoted to a new-value store. 31830b57cec5SDimitry Andric bool HexagonInstrInfo::mayBeNewStore(const MachineInstr &MI) const { 31840b57cec5SDimitry Andric if (MI.mayStore() && !Subtarget.useNewValueStores()) 31850b57cec5SDimitry Andric return false; 31860b57cec5SDimitry Andric 31870b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 31880b57cec5SDimitry Andric return (F >> HexagonII::mayNVStorePos) & HexagonII::mayNVStoreMask; 31890b57cec5SDimitry Andric } 31900b57cec5SDimitry Andric 31910b57cec5SDimitry Andric bool HexagonInstrInfo::producesStall(const MachineInstr &ProdMI, 31920b57cec5SDimitry Andric const MachineInstr &ConsMI) const { 31930b57cec5SDimitry Andric // There is no stall when ProdMI is not a V60 vector. 31940b57cec5SDimitry Andric if (!isHVXVec(ProdMI)) 31950b57cec5SDimitry Andric return false; 31960b57cec5SDimitry Andric 31970b57cec5SDimitry Andric // There is no stall when ProdMI and ConsMI are not dependent. 31980b57cec5SDimitry Andric if (!isDependent(ProdMI, ConsMI)) 31990b57cec5SDimitry Andric return false; 32000b57cec5SDimitry Andric 32010b57cec5SDimitry Andric // When Forward Scheduling is enabled, there is no stall if ProdMI and ConsMI 32020b57cec5SDimitry Andric // are scheduled in consecutive packets. 32030b57cec5SDimitry Andric if (isVecUsableNextPacket(ProdMI, ConsMI)) 32040b57cec5SDimitry Andric return false; 32050b57cec5SDimitry Andric 32060b57cec5SDimitry Andric return true; 32070b57cec5SDimitry Andric } 32080b57cec5SDimitry Andric 32090b57cec5SDimitry Andric bool HexagonInstrInfo::producesStall(const MachineInstr &MI, 32100b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator BII) const { 32110b57cec5SDimitry Andric // There is no stall when I is not a V60 vector. 32120b57cec5SDimitry Andric if (!isHVXVec(MI)) 32130b57cec5SDimitry Andric return false; 32140b57cec5SDimitry Andric 32150b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator MII = BII; 32160b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator MIE = MII->getParent()->instr_end(); 32170b57cec5SDimitry Andric 32180b57cec5SDimitry Andric if (!MII->isBundle()) 32190b57cec5SDimitry Andric return producesStall(*MII, MI); 32200b57cec5SDimitry Andric 32210b57cec5SDimitry Andric for (++MII; MII != MIE && MII->isInsideBundle(); ++MII) { 32220b57cec5SDimitry Andric const MachineInstr &J = *MII; 32230b57cec5SDimitry Andric if (producesStall(J, MI)) 32240b57cec5SDimitry Andric return true; 32250b57cec5SDimitry Andric } 32260b57cec5SDimitry Andric return false; 32270b57cec5SDimitry Andric } 32280b57cec5SDimitry Andric 32290b57cec5SDimitry Andric bool HexagonInstrInfo::predCanBeUsedAsDotNew(const MachineInstr &MI, 3230bdd1243dSDimitry Andric Register PredReg) const { 32310b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 32320b57cec5SDimitry Andric // Predicate register must be explicitly defined. 32330b57cec5SDimitry Andric if (MO.isRegMask() && MO.clobbersPhysReg(PredReg)) 32340b57cec5SDimitry Andric return false; 32350b57cec5SDimitry Andric if (MO.isReg() && MO.isDef() && MO.isImplicit() && (MO.getReg() == PredReg)) 32360b57cec5SDimitry Andric return false; 32370b57cec5SDimitry Andric } 32380b57cec5SDimitry Andric 32390b57cec5SDimitry Andric // Instruction that produce late predicate cannot be used as sources of 32400b57cec5SDimitry Andric // dot-new. 32410b57cec5SDimitry Andric switch (MI.getOpcode()) { 32420b57cec5SDimitry Andric case Hexagon::A4_addp_c: 32430b57cec5SDimitry Andric case Hexagon::A4_subp_c: 32440b57cec5SDimitry Andric case Hexagon::A4_tlbmatch: 32450b57cec5SDimitry Andric case Hexagon::A5_ACS: 32460b57cec5SDimitry Andric case Hexagon::F2_sfinvsqrta: 32470b57cec5SDimitry Andric case Hexagon::F2_sfrecipa: 32480b57cec5SDimitry Andric case Hexagon::J2_endloop0: 32490b57cec5SDimitry Andric case Hexagon::J2_endloop01: 32500b57cec5SDimitry Andric case Hexagon::J2_ploop1si: 32510b57cec5SDimitry Andric case Hexagon::J2_ploop1sr: 32520b57cec5SDimitry Andric case Hexagon::J2_ploop2si: 32530b57cec5SDimitry Andric case Hexagon::J2_ploop2sr: 32540b57cec5SDimitry Andric case Hexagon::J2_ploop3si: 32550b57cec5SDimitry Andric case Hexagon::J2_ploop3sr: 32560b57cec5SDimitry Andric case Hexagon::S2_cabacdecbin: 32570b57cec5SDimitry Andric case Hexagon::S2_storew_locked: 32580b57cec5SDimitry Andric case Hexagon::S4_stored_locked: 32590b57cec5SDimitry Andric return false; 32600b57cec5SDimitry Andric } 32610b57cec5SDimitry Andric return true; 32620b57cec5SDimitry Andric } 32630b57cec5SDimitry Andric 32640b57cec5SDimitry Andric bool HexagonInstrInfo::PredOpcodeHasJMP_c(unsigned Opcode) const { 32650b57cec5SDimitry Andric return Opcode == Hexagon::J2_jumpt || 32660b57cec5SDimitry Andric Opcode == Hexagon::J2_jumptpt || 32670b57cec5SDimitry Andric Opcode == Hexagon::J2_jumpf || 32680b57cec5SDimitry Andric Opcode == Hexagon::J2_jumpfpt || 32690b57cec5SDimitry Andric Opcode == Hexagon::J2_jumptnew || 32700b57cec5SDimitry Andric Opcode == Hexagon::J2_jumpfnew || 32710b57cec5SDimitry Andric Opcode == Hexagon::J2_jumptnewpt || 32720b57cec5SDimitry Andric Opcode == Hexagon::J2_jumpfnewpt; 32730b57cec5SDimitry Andric } 32740b57cec5SDimitry Andric 32750b57cec5SDimitry Andric bool HexagonInstrInfo::predOpcodeHasNot(ArrayRef<MachineOperand> Cond) const { 32760b57cec5SDimitry Andric if (Cond.empty() || !isPredicated(Cond[0].getImm())) 32770b57cec5SDimitry Andric return false; 32780b57cec5SDimitry Andric return !isPredicatedTrue(Cond[0].getImm()); 32790b57cec5SDimitry Andric } 32800b57cec5SDimitry Andric 32810b57cec5SDimitry Andric unsigned HexagonInstrInfo::getAddrMode(const MachineInstr &MI) const { 32820b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 32830b57cec5SDimitry Andric return (F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask; 32840b57cec5SDimitry Andric } 32850b57cec5SDimitry Andric 32860b57cec5SDimitry Andric // Returns the base register in a memory access (load/store). The offset is 32870b57cec5SDimitry Andric // returned in Offset and the access size is returned in AccessSize. 32880b57cec5SDimitry Andric // If the base operand has a subregister or the offset field does not contain 32890b57cec5SDimitry Andric // an immediate value, return nullptr. 3290*0fca6ea1SDimitry Andric MachineOperand * 3291*0fca6ea1SDimitry Andric HexagonInstrInfo::getBaseAndOffset(const MachineInstr &MI, int64_t &Offset, 3292*0fca6ea1SDimitry Andric LocationSize &AccessSize) const { 32930b57cec5SDimitry Andric // Return if it is not a base+offset type instruction or a MemOp. 32940b57cec5SDimitry Andric if (getAddrMode(MI) != HexagonII::BaseImmOffset && 32950b57cec5SDimitry Andric getAddrMode(MI) != HexagonII::BaseLongOffset && 32960b57cec5SDimitry Andric !isMemOp(MI) && !isPostIncrement(MI)) 32970b57cec5SDimitry Andric return nullptr; 32980b57cec5SDimitry Andric 32990b57cec5SDimitry Andric AccessSize = getMemAccessSize(MI); 33000b57cec5SDimitry Andric 33010b57cec5SDimitry Andric unsigned BasePos = 0, OffsetPos = 0; 33020b57cec5SDimitry Andric if (!getBaseAndOffsetPosition(MI, BasePos, OffsetPos)) 33030b57cec5SDimitry Andric return nullptr; 33040b57cec5SDimitry Andric 33050b57cec5SDimitry Andric // Post increment updates its EA after the mem access, 33060b57cec5SDimitry Andric // so we need to treat its offset as zero. 33070b57cec5SDimitry Andric if (isPostIncrement(MI)) { 33080b57cec5SDimitry Andric Offset = 0; 33090b57cec5SDimitry Andric } else { 33100b57cec5SDimitry Andric const MachineOperand &OffsetOp = MI.getOperand(OffsetPos); 33110b57cec5SDimitry Andric if (!OffsetOp.isImm()) 33120b57cec5SDimitry Andric return nullptr; 33130b57cec5SDimitry Andric Offset = OffsetOp.getImm(); 33140b57cec5SDimitry Andric } 33150b57cec5SDimitry Andric 33160b57cec5SDimitry Andric const MachineOperand &BaseOp = MI.getOperand(BasePos); 33170b57cec5SDimitry Andric if (BaseOp.getSubReg() != 0) 33180b57cec5SDimitry Andric return nullptr; 33190b57cec5SDimitry Andric return &const_cast<MachineOperand&>(BaseOp); 33200b57cec5SDimitry Andric } 33210b57cec5SDimitry Andric 33220b57cec5SDimitry Andric /// Return the position of the base and offset operands for this instruction. 33230b57cec5SDimitry Andric bool HexagonInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI, 33240b57cec5SDimitry Andric unsigned &BasePos, unsigned &OffsetPos) const { 33250b57cec5SDimitry Andric if (!isAddrModeWithOffset(MI) && !isPostIncrement(MI)) 33260b57cec5SDimitry Andric return false; 33270b57cec5SDimitry Andric 33280b57cec5SDimitry Andric // Deal with memops first. 33290b57cec5SDimitry Andric if (isMemOp(MI)) { 33300b57cec5SDimitry Andric BasePos = 0; 33310b57cec5SDimitry Andric OffsetPos = 1; 33320b57cec5SDimitry Andric } else if (MI.mayStore()) { 33330b57cec5SDimitry Andric BasePos = 0; 33340b57cec5SDimitry Andric OffsetPos = 1; 33350b57cec5SDimitry Andric } else if (MI.mayLoad()) { 33360b57cec5SDimitry Andric BasePos = 1; 33370b57cec5SDimitry Andric OffsetPos = 2; 33380b57cec5SDimitry Andric } else 33390b57cec5SDimitry Andric return false; 33400b57cec5SDimitry Andric 33410b57cec5SDimitry Andric if (isPredicated(MI)) { 33420b57cec5SDimitry Andric BasePos++; 33430b57cec5SDimitry Andric OffsetPos++; 33440b57cec5SDimitry Andric } 33450b57cec5SDimitry Andric if (isPostIncrement(MI)) { 33460b57cec5SDimitry Andric BasePos++; 33470b57cec5SDimitry Andric OffsetPos++; 33480b57cec5SDimitry Andric } 33490b57cec5SDimitry Andric 33500b57cec5SDimitry Andric if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm()) 33510b57cec5SDimitry Andric return false; 33520b57cec5SDimitry Andric 33530b57cec5SDimitry Andric return true; 33540b57cec5SDimitry Andric } 33550b57cec5SDimitry Andric 33560b57cec5SDimitry Andric // Inserts branching instructions in reverse order of their occurrence. 33570b57cec5SDimitry Andric // e.g. jump_t t1 (i1) 33580b57cec5SDimitry Andric // jump t2 (i2) 33590b57cec5SDimitry Andric // Jumpers = {i2, i1} 33600b57cec5SDimitry Andric SmallVector<MachineInstr*, 2> HexagonInstrInfo::getBranchingInstrs( 33610b57cec5SDimitry Andric MachineBasicBlock& MBB) const { 33620b57cec5SDimitry Andric SmallVector<MachineInstr*, 2> Jumpers; 33630b57cec5SDimitry Andric // If the block has no terminators, it just falls into the block after it. 33640b57cec5SDimitry Andric MachineBasicBlock::instr_iterator I = MBB.instr_end(); 33650b57cec5SDimitry Andric if (I == MBB.instr_begin()) 33660b57cec5SDimitry Andric return Jumpers; 33670b57cec5SDimitry Andric 33680b57cec5SDimitry Andric // A basic block may looks like this: 33690b57cec5SDimitry Andric // 33700b57cec5SDimitry Andric // [ insn 33710b57cec5SDimitry Andric // EH_LABEL 33720b57cec5SDimitry Andric // insn 33730b57cec5SDimitry Andric // insn 33740b57cec5SDimitry Andric // insn 33750b57cec5SDimitry Andric // EH_LABEL 33760b57cec5SDimitry Andric // insn ] 33770b57cec5SDimitry Andric // 33780b57cec5SDimitry Andric // It has two succs but does not have a terminator 33790b57cec5SDimitry Andric // Don't know how to handle it. 33800b57cec5SDimitry Andric do { 33810b57cec5SDimitry Andric --I; 33820b57cec5SDimitry Andric if (I->isEHLabel()) 33830b57cec5SDimitry Andric return Jumpers; 33840b57cec5SDimitry Andric } while (I != MBB.instr_begin()); 33850b57cec5SDimitry Andric 33860b57cec5SDimitry Andric I = MBB.instr_end(); 33870b57cec5SDimitry Andric --I; 33880b57cec5SDimitry Andric 33890b57cec5SDimitry Andric while (I->isDebugInstr()) { 33900b57cec5SDimitry Andric if (I == MBB.instr_begin()) 33910b57cec5SDimitry Andric return Jumpers; 33920b57cec5SDimitry Andric --I; 33930b57cec5SDimitry Andric } 33940b57cec5SDimitry Andric if (!isUnpredicatedTerminator(*I)) 33950b57cec5SDimitry Andric return Jumpers; 33960b57cec5SDimitry Andric 33970b57cec5SDimitry Andric // Get the last instruction in the block. 33980b57cec5SDimitry Andric MachineInstr *LastInst = &*I; 33990b57cec5SDimitry Andric Jumpers.push_back(LastInst); 34000b57cec5SDimitry Andric MachineInstr *SecondLastInst = nullptr; 34010b57cec5SDimitry Andric // Find one more terminator if present. 34020b57cec5SDimitry Andric do { 34030b57cec5SDimitry Andric if (&*I != LastInst && !I->isBundle() && isUnpredicatedTerminator(*I)) { 34040b57cec5SDimitry Andric if (!SecondLastInst) { 34050b57cec5SDimitry Andric SecondLastInst = &*I; 34060b57cec5SDimitry Andric Jumpers.push_back(SecondLastInst); 34070b57cec5SDimitry Andric } else // This is a third branch. 34080b57cec5SDimitry Andric return Jumpers; 34090b57cec5SDimitry Andric } 34100b57cec5SDimitry Andric if (I == MBB.instr_begin()) 34110b57cec5SDimitry Andric break; 34120b57cec5SDimitry Andric --I; 34130b57cec5SDimitry Andric } while (true); 34140b57cec5SDimitry Andric return Jumpers; 34150b57cec5SDimitry Andric } 34160b57cec5SDimitry Andric 34170b57cec5SDimitry Andric // Returns Operand Index for the constant extended instruction. 34180b57cec5SDimitry Andric unsigned HexagonInstrInfo::getCExtOpNum(const MachineInstr &MI) const { 34190b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 34200b57cec5SDimitry Andric return (F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask; 34210b57cec5SDimitry Andric } 34220b57cec5SDimitry Andric 34230b57cec5SDimitry Andric // See if instruction could potentially be a duplex candidate. 34240b57cec5SDimitry Andric // If so, return its group. Zero otherwise. 34250b57cec5SDimitry Andric HexagonII::CompoundGroup HexagonInstrInfo::getCompoundCandidateGroup( 34260b57cec5SDimitry Andric const MachineInstr &MI) const { 3427bdd1243dSDimitry Andric Register DstReg, SrcReg, Src1Reg, Src2Reg; 34280b57cec5SDimitry Andric 34290b57cec5SDimitry Andric switch (MI.getOpcode()) { 34300b57cec5SDimitry Andric default: 34310b57cec5SDimitry Andric return HexagonII::HCG_None; 34320b57cec5SDimitry Andric // 34330b57cec5SDimitry Andric // Compound pairs. 34340b57cec5SDimitry Andric // "p0=cmp.eq(Rs16,Rt16); if (p0.new) jump:nt #r9:2" 34350b57cec5SDimitry Andric // "Rd16=#U6 ; jump #r9:2" 34360b57cec5SDimitry Andric // "Rd16=Rs16 ; jump #r9:2" 34370b57cec5SDimitry Andric // 34380b57cec5SDimitry Andric case Hexagon::C2_cmpeq: 34390b57cec5SDimitry Andric case Hexagon::C2_cmpgt: 34400b57cec5SDimitry Andric case Hexagon::C2_cmpgtu: 34410b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 34420b57cec5SDimitry Andric Src1Reg = MI.getOperand(1).getReg(); 34430b57cec5SDimitry Andric Src2Reg = MI.getOperand(2).getReg(); 34440b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(DstReg) && 34450b57cec5SDimitry Andric (Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && 34460b57cec5SDimitry Andric isIntRegForSubInst(Src1Reg) && isIntRegForSubInst(Src2Reg)) 34470b57cec5SDimitry Andric return HexagonII::HCG_A; 34480b57cec5SDimitry Andric break; 34490b57cec5SDimitry Andric case Hexagon::C2_cmpeqi: 34500b57cec5SDimitry Andric case Hexagon::C2_cmpgti: 34510b57cec5SDimitry Andric case Hexagon::C2_cmpgtui: 34520b57cec5SDimitry Andric // P0 = cmp.eq(Rs,#u2) 34530b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 34540b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 34550b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(DstReg) && 34560b57cec5SDimitry Andric (Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && 34570b57cec5SDimitry Andric isIntRegForSubInst(SrcReg) && MI.getOperand(2).isImm() && 34580b57cec5SDimitry Andric ((isUInt<5>(MI.getOperand(2).getImm())) || 34590b57cec5SDimitry Andric (MI.getOperand(2).getImm() == -1))) 34600b57cec5SDimitry Andric return HexagonII::HCG_A; 34610b57cec5SDimitry Andric break; 34620b57cec5SDimitry Andric case Hexagon::A2_tfr: 34630b57cec5SDimitry Andric // Rd = Rs 34640b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 34650b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 34660b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg)) 34670b57cec5SDimitry Andric return HexagonII::HCG_A; 34680b57cec5SDimitry Andric break; 34690b57cec5SDimitry Andric case Hexagon::A2_tfrsi: 34700b57cec5SDimitry Andric // Rd = #u6 34710b57cec5SDimitry Andric // Do not test for #u6 size since the const is getting extended 34720b57cec5SDimitry Andric // regardless and compound could be formed. 34730b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 34740b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg)) 34750b57cec5SDimitry Andric return HexagonII::HCG_A; 34760b57cec5SDimitry Andric break; 34770b57cec5SDimitry Andric case Hexagon::S2_tstbit_i: 34780b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 34790b57cec5SDimitry Andric Src1Reg = MI.getOperand(1).getReg(); 34800b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(DstReg) && 34810b57cec5SDimitry Andric (Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && 34820b57cec5SDimitry Andric MI.getOperand(2).isImm() && 34830b57cec5SDimitry Andric isIntRegForSubInst(Src1Reg) && (MI.getOperand(2).getImm() == 0)) 34840b57cec5SDimitry Andric return HexagonII::HCG_A; 34850b57cec5SDimitry Andric break; 34860b57cec5SDimitry Andric // The fact that .new form is used pretty much guarantees 34870b57cec5SDimitry Andric // that predicate register will match. Nevertheless, 34880b57cec5SDimitry Andric // there could be some false positives without additional 34890b57cec5SDimitry Andric // checking. 34900b57cec5SDimitry Andric case Hexagon::J2_jumptnew: 34910b57cec5SDimitry Andric case Hexagon::J2_jumpfnew: 34920b57cec5SDimitry Andric case Hexagon::J2_jumptnewpt: 34930b57cec5SDimitry Andric case Hexagon::J2_jumpfnewpt: 34940b57cec5SDimitry Andric Src1Reg = MI.getOperand(0).getReg(); 34950b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(Src1Reg) && 34960b57cec5SDimitry Andric (Hexagon::P0 == Src1Reg || Hexagon::P1 == Src1Reg)) 34970b57cec5SDimitry Andric return HexagonII::HCG_B; 34980b57cec5SDimitry Andric break; 34990b57cec5SDimitry Andric // Transfer and jump: 35000b57cec5SDimitry Andric // Rd=#U6 ; jump #r9:2 35010b57cec5SDimitry Andric // Rd=Rs ; jump #r9:2 35020b57cec5SDimitry Andric // Do not test for jump range here. 35030b57cec5SDimitry Andric case Hexagon::J2_jump: 35040b57cec5SDimitry Andric case Hexagon::RESTORE_DEALLOC_RET_JMP_V4: 35050b57cec5SDimitry Andric case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC: 35060b57cec5SDimitry Andric return HexagonII::HCG_C; 35070b57cec5SDimitry Andric } 35080b57cec5SDimitry Andric 35090b57cec5SDimitry Andric return HexagonII::HCG_None; 35100b57cec5SDimitry Andric } 35110b57cec5SDimitry Andric 35120b57cec5SDimitry Andric // Returns -1 when there is no opcode found. 35130b57cec5SDimitry Andric unsigned HexagonInstrInfo::getCompoundOpcode(const MachineInstr &GA, 35140b57cec5SDimitry Andric const MachineInstr &GB) const { 35150b57cec5SDimitry Andric assert(getCompoundCandidateGroup(GA) == HexagonII::HCG_A); 35160b57cec5SDimitry Andric assert(getCompoundCandidateGroup(GB) == HexagonII::HCG_B); 35170b57cec5SDimitry Andric if ((GA.getOpcode() != Hexagon::C2_cmpeqi) || 35180b57cec5SDimitry Andric (GB.getOpcode() != Hexagon::J2_jumptnew)) 35190b57cec5SDimitry Andric return -1u; 35208bcb0991SDimitry Andric Register DestReg = GA.getOperand(0).getReg(); 3521*0fca6ea1SDimitry Andric if (!GB.readsRegister(DestReg, /*TRI=*/nullptr)) 35220b57cec5SDimitry Andric return -1u; 35230b57cec5SDimitry Andric if (DestReg != Hexagon::P0 && DestReg != Hexagon::P1) 35240b57cec5SDimitry Andric return -1u; 35250b57cec5SDimitry Andric // The value compared against must be either u5 or -1. 35260b57cec5SDimitry Andric const MachineOperand &CmpOp = GA.getOperand(2); 35270b57cec5SDimitry Andric if (!CmpOp.isImm()) 35280b57cec5SDimitry Andric return -1u; 35290b57cec5SDimitry Andric int V = CmpOp.getImm(); 35300b57cec5SDimitry Andric if (V == -1) 35310b57cec5SDimitry Andric return DestReg == Hexagon::P0 ? Hexagon::J4_cmpeqn1_tp0_jump_nt 35320b57cec5SDimitry Andric : Hexagon::J4_cmpeqn1_tp1_jump_nt; 35330b57cec5SDimitry Andric if (!isUInt<5>(V)) 35340b57cec5SDimitry Andric return -1u; 35350b57cec5SDimitry Andric return DestReg == Hexagon::P0 ? Hexagon::J4_cmpeqi_tp0_jump_nt 35360b57cec5SDimitry Andric : Hexagon::J4_cmpeqi_tp1_jump_nt; 35370b57cec5SDimitry Andric } 35380b57cec5SDimitry Andric 35395ffd83dbSDimitry Andric // Returns -1 if there is no opcode found. 35405ffd83dbSDimitry Andric int HexagonInstrInfo::getDuplexOpcode(const MachineInstr &MI, 35415ffd83dbSDimitry Andric bool ForBigCore) const { 35425ffd83dbSDimitry Andric // Static table to switch the opcodes across Tiny Core and Big Core. 35435ffd83dbSDimitry Andric // dup_ opcodes are Big core opcodes. 35445ffd83dbSDimitry Andric // NOTE: There are special instructions that need to handled later. 35455ffd83dbSDimitry Andric // L4_return* instructions, they will only occupy SLOT0 (on big core too). 35465ffd83dbSDimitry Andric // PS_jmpret - This pseudo translates to J2_jumpr which occupies only SLOT2. 35475ffd83dbSDimitry Andric // The compiler need to base the root instruction to L6_return_map_to_raw 35485ffd83dbSDimitry Andric // which can go any slot. 35495ffd83dbSDimitry Andric static const std::map<unsigned, unsigned> DupMap = { 35505ffd83dbSDimitry Andric {Hexagon::A2_add, Hexagon::dup_A2_add}, 35515ffd83dbSDimitry Andric {Hexagon::A2_addi, Hexagon::dup_A2_addi}, 35525ffd83dbSDimitry Andric {Hexagon::A2_andir, Hexagon::dup_A2_andir}, 35535ffd83dbSDimitry Andric {Hexagon::A2_combineii, Hexagon::dup_A2_combineii}, 35545ffd83dbSDimitry Andric {Hexagon::A2_sxtb, Hexagon::dup_A2_sxtb}, 35555ffd83dbSDimitry Andric {Hexagon::A2_sxth, Hexagon::dup_A2_sxth}, 35565ffd83dbSDimitry Andric {Hexagon::A2_tfr, Hexagon::dup_A2_tfr}, 35575ffd83dbSDimitry Andric {Hexagon::A2_tfrsi, Hexagon::dup_A2_tfrsi}, 35585ffd83dbSDimitry Andric {Hexagon::A2_zxtb, Hexagon::dup_A2_zxtb}, 35595ffd83dbSDimitry Andric {Hexagon::A2_zxth, Hexagon::dup_A2_zxth}, 35605ffd83dbSDimitry Andric {Hexagon::A4_combineii, Hexagon::dup_A4_combineii}, 35615ffd83dbSDimitry Andric {Hexagon::A4_combineir, Hexagon::dup_A4_combineir}, 35625ffd83dbSDimitry Andric {Hexagon::A4_combineri, Hexagon::dup_A4_combineri}, 35635ffd83dbSDimitry Andric {Hexagon::C2_cmoveif, Hexagon::dup_C2_cmoveif}, 35645ffd83dbSDimitry Andric {Hexagon::C2_cmoveit, Hexagon::dup_C2_cmoveit}, 35655ffd83dbSDimitry Andric {Hexagon::C2_cmovenewif, Hexagon::dup_C2_cmovenewif}, 35665ffd83dbSDimitry Andric {Hexagon::C2_cmovenewit, Hexagon::dup_C2_cmovenewit}, 35675ffd83dbSDimitry Andric {Hexagon::C2_cmpeqi, Hexagon::dup_C2_cmpeqi}, 35685ffd83dbSDimitry Andric {Hexagon::L2_deallocframe, Hexagon::dup_L2_deallocframe}, 35695ffd83dbSDimitry Andric {Hexagon::L2_loadrb_io, Hexagon::dup_L2_loadrb_io}, 35705ffd83dbSDimitry Andric {Hexagon::L2_loadrd_io, Hexagon::dup_L2_loadrd_io}, 35715ffd83dbSDimitry Andric {Hexagon::L2_loadrh_io, Hexagon::dup_L2_loadrh_io}, 35725ffd83dbSDimitry Andric {Hexagon::L2_loadri_io, Hexagon::dup_L2_loadri_io}, 35735ffd83dbSDimitry Andric {Hexagon::L2_loadrub_io, Hexagon::dup_L2_loadrub_io}, 35745ffd83dbSDimitry Andric {Hexagon::L2_loadruh_io, Hexagon::dup_L2_loadruh_io}, 35755ffd83dbSDimitry Andric {Hexagon::S2_allocframe, Hexagon::dup_S2_allocframe}, 35765ffd83dbSDimitry Andric {Hexagon::S2_storerb_io, Hexagon::dup_S2_storerb_io}, 35775ffd83dbSDimitry Andric {Hexagon::S2_storerd_io, Hexagon::dup_S2_storerd_io}, 35785ffd83dbSDimitry Andric {Hexagon::S2_storerh_io, Hexagon::dup_S2_storerh_io}, 35795ffd83dbSDimitry Andric {Hexagon::S2_storeri_io, Hexagon::dup_S2_storeri_io}, 35805ffd83dbSDimitry Andric {Hexagon::S4_storeirb_io, Hexagon::dup_S4_storeirb_io}, 35815ffd83dbSDimitry Andric {Hexagon::S4_storeiri_io, Hexagon::dup_S4_storeiri_io}, 35825ffd83dbSDimitry Andric }; 35835ffd83dbSDimitry Andric unsigned OpNum = MI.getOpcode(); 35845ffd83dbSDimitry Andric // Conversion to Big core. 35855ffd83dbSDimitry Andric if (ForBigCore) { 35865ffd83dbSDimitry Andric auto Iter = DupMap.find(OpNum); 35875ffd83dbSDimitry Andric if (Iter != DupMap.end()) 35885ffd83dbSDimitry Andric return Iter->second; 35895ffd83dbSDimitry Andric } else { // Conversion to Tiny core. 359004eeddc0SDimitry Andric for (const auto &Iter : DupMap) 359104eeddc0SDimitry Andric if (Iter.second == OpNum) 359204eeddc0SDimitry Andric return Iter.first; 35935ffd83dbSDimitry Andric } 35945ffd83dbSDimitry Andric return -1; 35955ffd83dbSDimitry Andric } 35965ffd83dbSDimitry Andric 35970b57cec5SDimitry Andric int HexagonInstrInfo::getCondOpcode(int Opc, bool invertPredicate) const { 35980b57cec5SDimitry Andric enum Hexagon::PredSense inPredSense; 35990b57cec5SDimitry Andric inPredSense = invertPredicate ? Hexagon::PredSense_false : 36000b57cec5SDimitry Andric Hexagon::PredSense_true; 36010b57cec5SDimitry Andric int CondOpcode = Hexagon::getPredOpcode(Opc, inPredSense); 36020b57cec5SDimitry Andric if (CondOpcode >= 0) // Valid Conditional opcode/instruction 36030b57cec5SDimitry Andric return CondOpcode; 36040b57cec5SDimitry Andric 36050b57cec5SDimitry Andric llvm_unreachable("Unexpected predicable instruction"); 36060b57cec5SDimitry Andric } 36070b57cec5SDimitry Andric 36080b57cec5SDimitry Andric // Return the cur value instruction for a given store. 36090b57cec5SDimitry Andric int HexagonInstrInfo::getDotCurOp(const MachineInstr &MI) const { 36100b57cec5SDimitry Andric switch (MI.getOpcode()) { 36110b57cec5SDimitry Andric default: llvm_unreachable("Unknown .cur type"); 36120b57cec5SDimitry Andric case Hexagon::V6_vL32b_pi: 36130b57cec5SDimitry Andric return Hexagon::V6_vL32b_cur_pi; 36140b57cec5SDimitry Andric case Hexagon::V6_vL32b_ai: 36150b57cec5SDimitry Andric return Hexagon::V6_vL32b_cur_ai; 36160b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_pi: 36170b57cec5SDimitry Andric return Hexagon::V6_vL32b_nt_cur_pi; 36180b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_ai: 36190b57cec5SDimitry Andric return Hexagon::V6_vL32b_nt_cur_ai; 362004eeddc0SDimitry Andric case Hexagon::V6_vL32b_ppu: 362104eeddc0SDimitry Andric return Hexagon::V6_vL32b_cur_ppu; 362204eeddc0SDimitry Andric case Hexagon::V6_vL32b_nt_ppu: 362304eeddc0SDimitry Andric return Hexagon::V6_vL32b_nt_cur_ppu; 36240b57cec5SDimitry Andric } 36250b57cec5SDimitry Andric return 0; 36260b57cec5SDimitry Andric } 36270b57cec5SDimitry Andric 36280b57cec5SDimitry Andric // Return the regular version of the .cur instruction. 36290b57cec5SDimitry Andric int HexagonInstrInfo::getNonDotCurOp(const MachineInstr &MI) const { 36300b57cec5SDimitry Andric switch (MI.getOpcode()) { 36310b57cec5SDimitry Andric default: llvm_unreachable("Unknown .cur type"); 36320b57cec5SDimitry Andric case Hexagon::V6_vL32b_cur_pi: 36330b57cec5SDimitry Andric return Hexagon::V6_vL32b_pi; 36340b57cec5SDimitry Andric case Hexagon::V6_vL32b_cur_ai: 36350b57cec5SDimitry Andric return Hexagon::V6_vL32b_ai; 36360b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_cur_pi: 36370b57cec5SDimitry Andric return Hexagon::V6_vL32b_nt_pi; 36380b57cec5SDimitry Andric case Hexagon::V6_vL32b_nt_cur_ai: 36390b57cec5SDimitry Andric return Hexagon::V6_vL32b_nt_ai; 364004eeddc0SDimitry Andric case Hexagon::V6_vL32b_cur_ppu: 364104eeddc0SDimitry Andric return Hexagon::V6_vL32b_ppu; 364204eeddc0SDimitry Andric case Hexagon::V6_vL32b_nt_cur_ppu: 364304eeddc0SDimitry Andric return Hexagon::V6_vL32b_nt_ppu; 36440b57cec5SDimitry Andric } 36450b57cec5SDimitry Andric return 0; 36460b57cec5SDimitry Andric } 36470b57cec5SDimitry Andric 36480b57cec5SDimitry Andric // The diagram below shows the steps involved in the conversion of a predicated 36490b57cec5SDimitry Andric // store instruction to its .new predicated new-value form. 36500b57cec5SDimitry Andric // 36510b57cec5SDimitry Andric // Note: It doesn't include conditional new-value stores as they can't be 36520b57cec5SDimitry Andric // converted to .new predicate. 36530b57cec5SDimitry Andric // 36540b57cec5SDimitry Andric // p.new NV store [ if(p0.new)memw(R0+#0)=R2.new ] 36550b57cec5SDimitry Andric // ^ ^ 36560b57cec5SDimitry Andric // / \ (not OK. it will cause new-value store to be 36570b57cec5SDimitry Andric // / X conditional on p0.new while R2 producer is 36580b57cec5SDimitry Andric // / \ on p0) 36590b57cec5SDimitry Andric // / \. 36600b57cec5SDimitry Andric // p.new store p.old NV store 36610b57cec5SDimitry Andric // [if(p0.new)memw(R0+#0)=R2] [if(p0)memw(R0+#0)=R2.new] 36620b57cec5SDimitry Andric // ^ ^ 36630b57cec5SDimitry Andric // \ / 36640b57cec5SDimitry Andric // \ / 36650b57cec5SDimitry Andric // \ / 36660b57cec5SDimitry Andric // p.old store 36670b57cec5SDimitry Andric // [if (p0)memw(R0+#0)=R2] 36680b57cec5SDimitry Andric // 36690b57cec5SDimitry Andric // The following set of instructions further explains the scenario where 36700b57cec5SDimitry Andric // conditional new-value store becomes invalid when promoted to .new predicate 36710b57cec5SDimitry Andric // form. 36720b57cec5SDimitry Andric // 36730b57cec5SDimitry Andric // { 1) if (p0) r0 = add(r1, r2) 36740b57cec5SDimitry Andric // 2) p0 = cmp.eq(r3, #0) } 36750b57cec5SDimitry Andric // 36760b57cec5SDimitry Andric // 3) if (p0) memb(r1+#0) = r0 --> this instruction can't be grouped with 36770b57cec5SDimitry Andric // the first two instructions because in instr 1, r0 is conditional on old value 36780b57cec5SDimitry Andric // of p0 but its use in instr 3 is conditional on p0 modified by instr 2 which 36790b57cec5SDimitry Andric // is not valid for new-value stores. 36800b57cec5SDimitry Andric // Predicated new value stores (i.e. if (p0) memw(..)=r0.new) are excluded 36810b57cec5SDimitry Andric // from the "Conditional Store" list. Because a predicated new value store 36820b57cec5SDimitry Andric // would NOT be promoted to a double dot new store. See diagram below: 36830b57cec5SDimitry Andric // This function returns yes for those stores that are predicated but not 36840b57cec5SDimitry Andric // yet promoted to predicate dot new instructions. 36850b57cec5SDimitry Andric // 36860b57cec5SDimitry Andric // +---------------------+ 36870b57cec5SDimitry Andric // /-----| if (p0) memw(..)=r0 |---------\~ 36880b57cec5SDimitry Andric // || +---------------------+ || 36890b57cec5SDimitry Andric // promote || /\ /\ || promote 36900b57cec5SDimitry Andric // || /||\ /||\ || 36910b57cec5SDimitry Andric // \||/ demote || \||/ 36920b57cec5SDimitry Andric // \/ || || \/ 36930b57cec5SDimitry Andric // +-------------------------+ || +-------------------------+ 36940b57cec5SDimitry Andric // | if (p0.new) memw(..)=r0 | || | if (p0) memw(..)=r0.new | 36950b57cec5SDimitry Andric // +-------------------------+ || +-------------------------+ 36960b57cec5SDimitry Andric // || || || 36970b57cec5SDimitry Andric // || demote \||/ 36980b57cec5SDimitry Andric // promote || \/ NOT possible 36990b57cec5SDimitry Andric // || || /\~ 37000b57cec5SDimitry Andric // \||/ || /||\~ 37010b57cec5SDimitry Andric // \/ || || 37020b57cec5SDimitry Andric // +-----------------------------+ 37030b57cec5SDimitry Andric // | if (p0.new) memw(..)=r0.new | 37040b57cec5SDimitry Andric // +-----------------------------+ 37050b57cec5SDimitry Andric // Double Dot New Store 37060b57cec5SDimitry Andric // 37070b57cec5SDimitry Andric // Returns the most basic instruction for the .new predicated instructions and 37080b57cec5SDimitry Andric // new-value stores. 37090b57cec5SDimitry Andric // For example, all of the following instructions will be converted back to the 37100b57cec5SDimitry Andric // same instruction: 37110b57cec5SDimitry Andric // 1) if (p0.new) memw(R0+#0) = R1.new ---> 37120b57cec5SDimitry Andric // 2) if (p0) memw(R0+#0)= R1.new -------> if (p0) memw(R0+#0) = R1 37130b57cec5SDimitry Andric // 3) if (p0.new) memw(R0+#0) = R1 ---> 37140b57cec5SDimitry Andric // 37150b57cec5SDimitry Andric // To understand the translation of instruction 1 to its original form, consider 37160b57cec5SDimitry Andric // a packet with 3 instructions. 37170b57cec5SDimitry Andric // { p0 = cmp.eq(R0,R1) 37180b57cec5SDimitry Andric // if (p0.new) R2 = add(R3, R4) 37190b57cec5SDimitry Andric // R5 = add (R3, R1) 37200b57cec5SDimitry Andric // } 37210b57cec5SDimitry Andric // if (p0) memw(R5+#0) = R2 <--- trying to include it in the previous packet 37220b57cec5SDimitry Andric // 37230b57cec5SDimitry Andric // This instruction can be part of the previous packet only if both p0 and R2 37240b57cec5SDimitry Andric // are promoted to .new values. This promotion happens in steps, first 37250b57cec5SDimitry Andric // predicate register is promoted to .new and in the next iteration R2 is 37260b57cec5SDimitry Andric // promoted. Therefore, in case of dependence check failure (due to R5) during 37270b57cec5SDimitry Andric // next iteration, it should be converted back to its most basic form. 37280b57cec5SDimitry Andric 37290b57cec5SDimitry Andric // Return the new value instruction for a given store. 37300b57cec5SDimitry Andric int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const { 37310b57cec5SDimitry Andric int NVOpcode = Hexagon::getNewValueOpcode(MI.getOpcode()); 37320b57cec5SDimitry Andric if (NVOpcode >= 0) // Valid new-value store instruction. 37330b57cec5SDimitry Andric return NVOpcode; 37340b57cec5SDimitry Andric 37350b57cec5SDimitry Andric switch (MI.getOpcode()) { 37360b57cec5SDimitry Andric default: 3737349cc55cSDimitry Andric report_fatal_error(Twine("Unknown .new type: ") + 37380b57cec5SDimitry Andric std::to_string(MI.getOpcode())); 37390b57cec5SDimitry Andric case Hexagon::S4_storerb_ur: 37400b57cec5SDimitry Andric return Hexagon::S4_storerbnew_ur; 37410b57cec5SDimitry Andric 37420b57cec5SDimitry Andric case Hexagon::S2_storerb_pci: 37430b57cec5SDimitry Andric return Hexagon::S2_storerb_pci; 37440b57cec5SDimitry Andric 37450b57cec5SDimitry Andric case Hexagon::S2_storeri_pci: 37460b57cec5SDimitry Andric return Hexagon::S2_storeri_pci; 37470b57cec5SDimitry Andric 37480b57cec5SDimitry Andric case Hexagon::S2_storerh_pci: 37490b57cec5SDimitry Andric return Hexagon::S2_storerh_pci; 37500b57cec5SDimitry Andric 37510b57cec5SDimitry Andric case Hexagon::S2_storerd_pci: 37520b57cec5SDimitry Andric return Hexagon::S2_storerd_pci; 37530b57cec5SDimitry Andric 37540b57cec5SDimitry Andric case Hexagon::S2_storerf_pci: 37550b57cec5SDimitry Andric return Hexagon::S2_storerf_pci; 37560b57cec5SDimitry Andric 37570b57cec5SDimitry Andric case Hexagon::V6_vS32b_ai: 37580b57cec5SDimitry Andric return Hexagon::V6_vS32b_new_ai; 37590b57cec5SDimitry Andric 37600b57cec5SDimitry Andric case Hexagon::V6_vS32b_pi: 37610b57cec5SDimitry Andric return Hexagon::V6_vS32b_new_pi; 37620b57cec5SDimitry Andric } 37630b57cec5SDimitry Andric return 0; 37640b57cec5SDimitry Andric } 37650b57cec5SDimitry Andric 37660b57cec5SDimitry Andric // Returns the opcode to use when converting MI, which is a conditional jump, 37670b57cec5SDimitry Andric // into a conditional instruction which uses the .new value of the predicate. 37680b57cec5SDimitry Andric // We also use branch probabilities to add a hint to the jump. 37690b57cec5SDimitry Andric // If MBPI is null, all edges will be treated as equally likely for the 37700b57cec5SDimitry Andric // purposes of establishing a predication hint. 37710b57cec5SDimitry Andric int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI, 37720b57cec5SDimitry Andric const MachineBranchProbabilityInfo *MBPI) const { 37730b57cec5SDimitry Andric // We assume that block can have at most two successors. 37740b57cec5SDimitry Andric const MachineBasicBlock *Src = MI.getParent(); 37750b57cec5SDimitry Andric const MachineOperand &BrTarget = MI.getOperand(1); 37760b57cec5SDimitry Andric bool Taken = false; 37770b57cec5SDimitry Andric const BranchProbability OneHalf(1, 2); 37780b57cec5SDimitry Andric 37790b57cec5SDimitry Andric auto getEdgeProbability = [MBPI] (const MachineBasicBlock *Src, 37800b57cec5SDimitry Andric const MachineBasicBlock *Dst) { 37810b57cec5SDimitry Andric if (MBPI) 37820b57cec5SDimitry Andric return MBPI->getEdgeProbability(Src, Dst); 37830b57cec5SDimitry Andric return BranchProbability(1, Src->succ_size()); 37840b57cec5SDimitry Andric }; 37850b57cec5SDimitry Andric 37860b57cec5SDimitry Andric if (BrTarget.isMBB()) { 37870b57cec5SDimitry Andric const MachineBasicBlock *Dst = BrTarget.getMBB(); 37880b57cec5SDimitry Andric Taken = getEdgeProbability(Src, Dst) >= OneHalf; 37890b57cec5SDimitry Andric } else { 37900b57cec5SDimitry Andric // The branch target is not a basic block (most likely a function). 37910b57cec5SDimitry Andric // Since BPI only gives probabilities for targets that are basic blocks, 37920b57cec5SDimitry Andric // try to identify another target of this branch (potentially a fall- 37930b57cec5SDimitry Andric // -through) and check the probability of that target. 37940b57cec5SDimitry Andric // 37950b57cec5SDimitry Andric // The only handled branch combinations are: 37960b57cec5SDimitry Andric // - one conditional branch, 37970b57cec5SDimitry Andric // - one conditional branch followed by one unconditional branch. 37980b57cec5SDimitry Andric // Otherwise, assume not-taken. 37990b57cec5SDimitry Andric assert(MI.isConditionalBranch()); 38000b57cec5SDimitry Andric const MachineBasicBlock &B = *MI.getParent(); 38010b57cec5SDimitry Andric bool SawCond = false, Bad = false; 38020b57cec5SDimitry Andric for (const MachineInstr &I : B) { 38030b57cec5SDimitry Andric if (!I.isBranch()) 38040b57cec5SDimitry Andric continue; 38050b57cec5SDimitry Andric if (I.isConditionalBranch()) { 38060b57cec5SDimitry Andric SawCond = true; 38070b57cec5SDimitry Andric if (&I != &MI) { 38080b57cec5SDimitry Andric Bad = true; 38090b57cec5SDimitry Andric break; 38100b57cec5SDimitry Andric } 38110b57cec5SDimitry Andric } 38120b57cec5SDimitry Andric if (I.isUnconditionalBranch() && !SawCond) { 38130b57cec5SDimitry Andric Bad = true; 38140b57cec5SDimitry Andric break; 38150b57cec5SDimitry Andric } 38160b57cec5SDimitry Andric } 38170b57cec5SDimitry Andric if (!Bad) { 38180b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator It(MI); 38190b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator NextIt = std::next(It); 38200b57cec5SDimitry Andric if (NextIt == B.instr_end()) { 38210b57cec5SDimitry Andric // If this branch is the last, look for the fall-through block. 38220b57cec5SDimitry Andric for (const MachineBasicBlock *SB : B.successors()) { 38230b57cec5SDimitry Andric if (!B.isLayoutSuccessor(SB)) 38240b57cec5SDimitry Andric continue; 38250b57cec5SDimitry Andric Taken = getEdgeProbability(Src, SB) < OneHalf; 38260b57cec5SDimitry Andric break; 38270b57cec5SDimitry Andric } 38280b57cec5SDimitry Andric } else { 38290b57cec5SDimitry Andric assert(NextIt->isUnconditionalBranch()); 38300b57cec5SDimitry Andric // Find the first MBB operand and assume it's the target. 38310b57cec5SDimitry Andric const MachineBasicBlock *BT = nullptr; 38320b57cec5SDimitry Andric for (const MachineOperand &Op : NextIt->operands()) { 38330b57cec5SDimitry Andric if (!Op.isMBB()) 38340b57cec5SDimitry Andric continue; 38350b57cec5SDimitry Andric BT = Op.getMBB(); 38360b57cec5SDimitry Andric break; 38370b57cec5SDimitry Andric } 38380b57cec5SDimitry Andric Taken = BT && getEdgeProbability(Src, BT) < OneHalf; 38390b57cec5SDimitry Andric } 38400b57cec5SDimitry Andric } // if (!Bad) 38410b57cec5SDimitry Andric } 38420b57cec5SDimitry Andric 38430b57cec5SDimitry Andric // The Taken flag should be set to something reasonable by this point. 38440b57cec5SDimitry Andric 38450b57cec5SDimitry Andric switch (MI.getOpcode()) { 38460b57cec5SDimitry Andric case Hexagon::J2_jumpt: 38470b57cec5SDimitry Andric return Taken ? Hexagon::J2_jumptnewpt : Hexagon::J2_jumptnew; 38480b57cec5SDimitry Andric case Hexagon::J2_jumpf: 38490b57cec5SDimitry Andric return Taken ? Hexagon::J2_jumpfnewpt : Hexagon::J2_jumpfnew; 38500b57cec5SDimitry Andric 38510b57cec5SDimitry Andric default: 38520b57cec5SDimitry Andric llvm_unreachable("Unexpected jump instruction."); 38530b57cec5SDimitry Andric } 38540b57cec5SDimitry Andric } 38550b57cec5SDimitry Andric 38560b57cec5SDimitry Andric // Return .new predicate version for an instruction. 38570b57cec5SDimitry Andric int HexagonInstrInfo::getDotNewPredOp(const MachineInstr &MI, 38580b57cec5SDimitry Andric const MachineBranchProbabilityInfo *MBPI) const { 38590b57cec5SDimitry Andric switch (MI.getOpcode()) { 38600b57cec5SDimitry Andric // Condtional Jumps 38610b57cec5SDimitry Andric case Hexagon::J2_jumpt: 38620b57cec5SDimitry Andric case Hexagon::J2_jumpf: 38630b57cec5SDimitry Andric return getDotNewPredJumpOp(MI, MBPI); 38640b57cec5SDimitry Andric } 38650b57cec5SDimitry Andric 38660b57cec5SDimitry Andric int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode()); 38670b57cec5SDimitry Andric if (NewOpcode >= 0) 38680b57cec5SDimitry Andric return NewOpcode; 38690b57cec5SDimitry Andric return 0; 38700b57cec5SDimitry Andric } 38710b57cec5SDimitry Andric 38720b57cec5SDimitry Andric int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const { 38730b57cec5SDimitry Andric int NewOp = MI.getOpcode(); 38740b57cec5SDimitry Andric if (isPredicated(NewOp) && isPredicatedNew(NewOp)) { // Get predicate old form 38750b57cec5SDimitry Andric NewOp = Hexagon::getPredOldOpcode(NewOp); 38760b57cec5SDimitry Andric // All Hexagon architectures have prediction bits on dot-new branches, 38770b57cec5SDimitry Andric // but only Hexagon V60+ has prediction bits on dot-old ones. Make sure 38780b57cec5SDimitry Andric // to pick the right opcode when converting back to dot-old. 387906c3fb27SDimitry Andric if (!Subtarget.hasFeature(Hexagon::ArchV60)) { 38800b57cec5SDimitry Andric switch (NewOp) { 38810b57cec5SDimitry Andric case Hexagon::J2_jumptpt: 38820b57cec5SDimitry Andric NewOp = Hexagon::J2_jumpt; 38830b57cec5SDimitry Andric break; 38840b57cec5SDimitry Andric case Hexagon::J2_jumpfpt: 38850b57cec5SDimitry Andric NewOp = Hexagon::J2_jumpf; 38860b57cec5SDimitry Andric break; 38870b57cec5SDimitry Andric case Hexagon::J2_jumprtpt: 38880b57cec5SDimitry Andric NewOp = Hexagon::J2_jumprt; 38890b57cec5SDimitry Andric break; 38900b57cec5SDimitry Andric case Hexagon::J2_jumprfpt: 38910b57cec5SDimitry Andric NewOp = Hexagon::J2_jumprf; 38920b57cec5SDimitry Andric break; 38930b57cec5SDimitry Andric } 38940b57cec5SDimitry Andric } 38950b57cec5SDimitry Andric assert(NewOp >= 0 && 38960b57cec5SDimitry Andric "Couldn't change predicate new instruction to its old form."); 38970b57cec5SDimitry Andric } 38980b57cec5SDimitry Andric 38990b57cec5SDimitry Andric if (isNewValueStore(NewOp)) { // Convert into non-new-value format 39000b57cec5SDimitry Andric NewOp = Hexagon::getNonNVStore(NewOp); 39010b57cec5SDimitry Andric assert(NewOp >= 0 && "Couldn't change new-value store to its old form."); 39020b57cec5SDimitry Andric } 39030b57cec5SDimitry Andric 39040b57cec5SDimitry Andric if (Subtarget.hasV60Ops()) 39050b57cec5SDimitry Andric return NewOp; 39060b57cec5SDimitry Andric 39070b57cec5SDimitry Andric // Subtargets prior to V60 didn't support 'taken' forms of predicated jumps. 39080b57cec5SDimitry Andric switch (NewOp) { 39090b57cec5SDimitry Andric case Hexagon::J2_jumpfpt: 39100b57cec5SDimitry Andric return Hexagon::J2_jumpf; 39110b57cec5SDimitry Andric case Hexagon::J2_jumptpt: 39120b57cec5SDimitry Andric return Hexagon::J2_jumpt; 39130b57cec5SDimitry Andric case Hexagon::J2_jumprfpt: 39140b57cec5SDimitry Andric return Hexagon::J2_jumprf; 39150b57cec5SDimitry Andric case Hexagon::J2_jumprtpt: 39160b57cec5SDimitry Andric return Hexagon::J2_jumprt; 39170b57cec5SDimitry Andric } 39180b57cec5SDimitry Andric return NewOp; 39190b57cec5SDimitry Andric } 39200b57cec5SDimitry Andric 39210b57cec5SDimitry Andric // See if instruction could potentially be a duplex candidate. 39220b57cec5SDimitry Andric // If so, return its group. Zero otherwise. 39230b57cec5SDimitry Andric HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( 39240b57cec5SDimitry Andric const MachineInstr &MI) const { 3925bdd1243dSDimitry Andric Register DstReg, SrcReg, Src1Reg, Src2Reg; 39260b57cec5SDimitry Andric const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); 39270b57cec5SDimitry Andric 39280b57cec5SDimitry Andric switch (MI.getOpcode()) { 39290b57cec5SDimitry Andric default: 39300b57cec5SDimitry Andric return HexagonII::HSIG_None; 39310b57cec5SDimitry Andric // 39320b57cec5SDimitry Andric // Group L1: 39330b57cec5SDimitry Andric // 39340b57cec5SDimitry Andric // Rd = memw(Rs+#u4:2) 39350b57cec5SDimitry Andric // Rd = memub(Rs+#u4:0) 39360b57cec5SDimitry Andric case Hexagon::L2_loadri_io: 39375ffd83dbSDimitry Andric case Hexagon::dup_L2_loadri_io: 39380b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 39390b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 39400b57cec5SDimitry Andric // Special case this one from Group L2. 39410b57cec5SDimitry Andric // Rd = memw(r29+#u5:2) 39420b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg)) { 39430b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.contains(SrcReg) && 39440b57cec5SDimitry Andric HRI.getStackRegister() == SrcReg && 39450b57cec5SDimitry Andric MI.getOperand(2).isImm() && 39460b57cec5SDimitry Andric isShiftedUInt<5,2>(MI.getOperand(2).getImm())) 39470b57cec5SDimitry Andric return HexagonII::HSIG_L2; 39480b57cec5SDimitry Andric // Rd = memw(Rs+#u4:2) 39490b57cec5SDimitry Andric if (isIntRegForSubInst(SrcReg) && 39500b57cec5SDimitry Andric (MI.getOperand(2).isImm() && 39510b57cec5SDimitry Andric isShiftedUInt<4,2>(MI.getOperand(2).getImm()))) 39520b57cec5SDimitry Andric return HexagonII::HSIG_L1; 39530b57cec5SDimitry Andric } 39540b57cec5SDimitry Andric break; 39550b57cec5SDimitry Andric case Hexagon::L2_loadrub_io: 39565ffd83dbSDimitry Andric case Hexagon::dup_L2_loadrub_io: 39570b57cec5SDimitry Andric // Rd = memub(Rs+#u4:0) 39580b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 39590b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 39600b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg) && 39610b57cec5SDimitry Andric MI.getOperand(2).isImm() && isUInt<4>(MI.getOperand(2).getImm())) 39620b57cec5SDimitry Andric return HexagonII::HSIG_L1; 39630b57cec5SDimitry Andric break; 39640b57cec5SDimitry Andric // 39650b57cec5SDimitry Andric // Group L2: 39660b57cec5SDimitry Andric // 39670b57cec5SDimitry Andric // Rd = memh/memuh(Rs+#u3:1) 39680b57cec5SDimitry Andric // Rd = memb(Rs+#u3:0) 39690b57cec5SDimitry Andric // Rd = memw(r29+#u5:2) - Handled above. 39700b57cec5SDimitry Andric // Rdd = memd(r29+#u5:3) 39710b57cec5SDimitry Andric // deallocframe 39720b57cec5SDimitry Andric // [if ([!]p0[.new])] dealloc_return 39730b57cec5SDimitry Andric // [if ([!]p0[.new])] jumpr r31 39740b57cec5SDimitry Andric case Hexagon::L2_loadrh_io: 39750b57cec5SDimitry Andric case Hexagon::L2_loadruh_io: 39765ffd83dbSDimitry Andric case Hexagon::dup_L2_loadrh_io: 39775ffd83dbSDimitry Andric case Hexagon::dup_L2_loadruh_io: 39780b57cec5SDimitry Andric // Rd = memh/memuh(Rs+#u3:1) 39790b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 39800b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 39810b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg) && 39820b57cec5SDimitry Andric MI.getOperand(2).isImm() && 39830b57cec5SDimitry Andric isShiftedUInt<3,1>(MI.getOperand(2).getImm())) 39840b57cec5SDimitry Andric return HexagonII::HSIG_L2; 39850b57cec5SDimitry Andric break; 39860b57cec5SDimitry Andric case Hexagon::L2_loadrb_io: 39875ffd83dbSDimitry Andric case Hexagon::dup_L2_loadrb_io: 39880b57cec5SDimitry Andric // Rd = memb(Rs+#u3:0) 39890b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 39900b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 39910b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg) && 39920b57cec5SDimitry Andric MI.getOperand(2).isImm() && 39930b57cec5SDimitry Andric isUInt<3>(MI.getOperand(2).getImm())) 39940b57cec5SDimitry Andric return HexagonII::HSIG_L2; 39950b57cec5SDimitry Andric break; 39960b57cec5SDimitry Andric case Hexagon::L2_loadrd_io: 39975ffd83dbSDimitry Andric case Hexagon::dup_L2_loadrd_io: 39980b57cec5SDimitry Andric // Rdd = memd(r29+#u5:3) 39990b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 40000b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 40010b57cec5SDimitry Andric if (isDblRegForSubInst(DstReg, HRI) && 40020b57cec5SDimitry Andric Hexagon::IntRegsRegClass.contains(SrcReg) && 40030b57cec5SDimitry Andric HRI.getStackRegister() == SrcReg && 40040b57cec5SDimitry Andric MI.getOperand(2).isImm() && 40050b57cec5SDimitry Andric isShiftedUInt<5,3>(MI.getOperand(2).getImm())) 40060b57cec5SDimitry Andric return HexagonII::HSIG_L2; 40070b57cec5SDimitry Andric break; 40080b57cec5SDimitry Andric // dealloc_return is not documented in Hexagon Manual, but marked 40090b57cec5SDimitry Andric // with A_SUBINSN attribute in iset_v4classic.py. 40100b57cec5SDimitry Andric case Hexagon::RESTORE_DEALLOC_RET_JMP_V4: 40110b57cec5SDimitry Andric case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC: 40120b57cec5SDimitry Andric case Hexagon::L4_return: 40130b57cec5SDimitry Andric case Hexagon::L2_deallocframe: 40145ffd83dbSDimitry Andric case Hexagon::dup_L2_deallocframe: 40150b57cec5SDimitry Andric return HexagonII::HSIG_L2; 40160b57cec5SDimitry Andric case Hexagon::EH_RETURN_JMPR: 40170b57cec5SDimitry Andric case Hexagon::PS_jmpret: 40180b57cec5SDimitry Andric case Hexagon::SL2_jumpr31: 40190b57cec5SDimitry Andric // jumpr r31 40200b57cec5SDimitry Andric // Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0 40210b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 40220b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.contains(DstReg) && (Hexagon::R31 == DstReg)) 40230b57cec5SDimitry Andric return HexagonII::HSIG_L2; 40240b57cec5SDimitry Andric break; 40250b57cec5SDimitry Andric case Hexagon::PS_jmprett: 40260b57cec5SDimitry Andric case Hexagon::PS_jmpretf: 40270b57cec5SDimitry Andric case Hexagon::PS_jmprettnewpt: 40280b57cec5SDimitry Andric case Hexagon::PS_jmpretfnewpt: 40290b57cec5SDimitry Andric case Hexagon::PS_jmprettnew: 40300b57cec5SDimitry Andric case Hexagon::PS_jmpretfnew: 40310b57cec5SDimitry Andric case Hexagon::SL2_jumpr31_t: 40320b57cec5SDimitry Andric case Hexagon::SL2_jumpr31_f: 40330b57cec5SDimitry Andric case Hexagon::SL2_jumpr31_tnew: 40345ffd83dbSDimitry Andric case Hexagon::SL2_jumpr31_fnew: 40350b57cec5SDimitry Andric DstReg = MI.getOperand(1).getReg(); 40360b57cec5SDimitry Andric SrcReg = MI.getOperand(0).getReg(); 40370b57cec5SDimitry Andric // [if ([!]p0[.new])] jumpr r31 40380b57cec5SDimitry Andric if ((Hexagon::PredRegsRegClass.contains(SrcReg) && 40390b57cec5SDimitry Andric (Hexagon::P0 == SrcReg)) && 40400b57cec5SDimitry Andric (Hexagon::IntRegsRegClass.contains(DstReg) && (Hexagon::R31 == DstReg))) 40410b57cec5SDimitry Andric return HexagonII::HSIG_L2; 40420b57cec5SDimitry Andric break; 40430b57cec5SDimitry Andric case Hexagon::L4_return_t: 40440b57cec5SDimitry Andric case Hexagon::L4_return_f: 40450b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pnt: 40460b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pnt: 40470b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pt: 40480b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pt: 40490b57cec5SDimitry Andric // [if ([!]p0[.new])] dealloc_return 40500b57cec5SDimitry Andric SrcReg = MI.getOperand(0).getReg(); 40510b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(SrcReg) && (Hexagon::P0 == SrcReg)) 40520b57cec5SDimitry Andric return HexagonII::HSIG_L2; 40530b57cec5SDimitry Andric break; 40540b57cec5SDimitry Andric // 40550b57cec5SDimitry Andric // Group S1: 40560b57cec5SDimitry Andric // 40570b57cec5SDimitry Andric // memw(Rs+#u4:2) = Rt 40580b57cec5SDimitry Andric // memb(Rs+#u4:0) = Rt 40590b57cec5SDimitry Andric case Hexagon::S2_storeri_io: 40605ffd83dbSDimitry Andric case Hexagon::dup_S2_storeri_io: 40610b57cec5SDimitry Andric // Special case this one from Group S2. 40620b57cec5SDimitry Andric // memw(r29+#u5:2) = Rt 40630b57cec5SDimitry Andric Src1Reg = MI.getOperand(0).getReg(); 40640b57cec5SDimitry Andric Src2Reg = MI.getOperand(2).getReg(); 40650b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.contains(Src1Reg) && 40660b57cec5SDimitry Andric isIntRegForSubInst(Src2Reg) && 40670b57cec5SDimitry Andric HRI.getStackRegister() == Src1Reg && MI.getOperand(1).isImm() && 40680b57cec5SDimitry Andric isShiftedUInt<5,2>(MI.getOperand(1).getImm())) 40690b57cec5SDimitry Andric return HexagonII::HSIG_S2; 40700b57cec5SDimitry Andric // memw(Rs+#u4:2) = Rt 40710b57cec5SDimitry Andric if (isIntRegForSubInst(Src1Reg) && isIntRegForSubInst(Src2Reg) && 40720b57cec5SDimitry Andric MI.getOperand(1).isImm() && 40730b57cec5SDimitry Andric isShiftedUInt<4,2>(MI.getOperand(1).getImm())) 40740b57cec5SDimitry Andric return HexagonII::HSIG_S1; 40750b57cec5SDimitry Andric break; 40760b57cec5SDimitry Andric case Hexagon::S2_storerb_io: 40775ffd83dbSDimitry Andric case Hexagon::dup_S2_storerb_io: 40780b57cec5SDimitry Andric // memb(Rs+#u4:0) = Rt 40790b57cec5SDimitry Andric Src1Reg = MI.getOperand(0).getReg(); 40800b57cec5SDimitry Andric Src2Reg = MI.getOperand(2).getReg(); 40810b57cec5SDimitry Andric if (isIntRegForSubInst(Src1Reg) && isIntRegForSubInst(Src2Reg) && 40820b57cec5SDimitry Andric MI.getOperand(1).isImm() && isUInt<4>(MI.getOperand(1).getImm())) 40830b57cec5SDimitry Andric return HexagonII::HSIG_S1; 40840b57cec5SDimitry Andric break; 40850b57cec5SDimitry Andric // 40860b57cec5SDimitry Andric // Group S2: 40870b57cec5SDimitry Andric // 40880b57cec5SDimitry Andric // memh(Rs+#u3:1) = Rt 40890b57cec5SDimitry Andric // memw(r29+#u5:2) = Rt 40900b57cec5SDimitry Andric // memd(r29+#s6:3) = Rtt 40910b57cec5SDimitry Andric // memw(Rs+#u4:2) = #U1 40920b57cec5SDimitry Andric // memb(Rs+#u4) = #U1 40930b57cec5SDimitry Andric // allocframe(#u5:3) 40940b57cec5SDimitry Andric case Hexagon::S2_storerh_io: 40955ffd83dbSDimitry Andric case Hexagon::dup_S2_storerh_io: 40960b57cec5SDimitry Andric // memh(Rs+#u3:1) = Rt 40970b57cec5SDimitry Andric Src1Reg = MI.getOperand(0).getReg(); 40980b57cec5SDimitry Andric Src2Reg = MI.getOperand(2).getReg(); 40990b57cec5SDimitry Andric if (isIntRegForSubInst(Src1Reg) && isIntRegForSubInst(Src2Reg) && 41000b57cec5SDimitry Andric MI.getOperand(1).isImm() && 41010b57cec5SDimitry Andric isShiftedUInt<3,1>(MI.getOperand(1).getImm())) 41020b57cec5SDimitry Andric return HexagonII::HSIG_S1; 41030b57cec5SDimitry Andric break; 41040b57cec5SDimitry Andric case Hexagon::S2_storerd_io: 41055ffd83dbSDimitry Andric case Hexagon::dup_S2_storerd_io: 41060b57cec5SDimitry Andric // memd(r29+#s6:3) = Rtt 41070b57cec5SDimitry Andric Src1Reg = MI.getOperand(0).getReg(); 41080b57cec5SDimitry Andric Src2Reg = MI.getOperand(2).getReg(); 41090b57cec5SDimitry Andric if (isDblRegForSubInst(Src2Reg, HRI) && 41100b57cec5SDimitry Andric Hexagon::IntRegsRegClass.contains(Src1Reg) && 41110b57cec5SDimitry Andric HRI.getStackRegister() == Src1Reg && MI.getOperand(1).isImm() && 41120b57cec5SDimitry Andric isShiftedInt<6,3>(MI.getOperand(1).getImm())) 41130b57cec5SDimitry Andric return HexagonII::HSIG_S2; 41140b57cec5SDimitry Andric break; 41150b57cec5SDimitry Andric case Hexagon::S4_storeiri_io: 41165ffd83dbSDimitry Andric case Hexagon::dup_S4_storeiri_io: 41170b57cec5SDimitry Andric // memw(Rs+#u4:2) = #U1 41180b57cec5SDimitry Andric Src1Reg = MI.getOperand(0).getReg(); 41190b57cec5SDimitry Andric if (isIntRegForSubInst(Src1Reg) && MI.getOperand(1).isImm() && 41200b57cec5SDimitry Andric isShiftedUInt<4,2>(MI.getOperand(1).getImm()) && 41210b57cec5SDimitry Andric MI.getOperand(2).isImm() && isUInt<1>(MI.getOperand(2).getImm())) 41220b57cec5SDimitry Andric return HexagonII::HSIG_S2; 41230b57cec5SDimitry Andric break; 41240b57cec5SDimitry Andric case Hexagon::S4_storeirb_io: 41255ffd83dbSDimitry Andric case Hexagon::dup_S4_storeirb_io: 41260b57cec5SDimitry Andric // memb(Rs+#u4) = #U1 41270b57cec5SDimitry Andric Src1Reg = MI.getOperand(0).getReg(); 41280b57cec5SDimitry Andric if (isIntRegForSubInst(Src1Reg) && 41290b57cec5SDimitry Andric MI.getOperand(1).isImm() && isUInt<4>(MI.getOperand(1).getImm()) && 41300b57cec5SDimitry Andric MI.getOperand(2).isImm() && isUInt<1>(MI.getOperand(2).getImm())) 41310b57cec5SDimitry Andric return HexagonII::HSIG_S2; 41320b57cec5SDimitry Andric break; 41330b57cec5SDimitry Andric case Hexagon::S2_allocframe: 41345ffd83dbSDimitry Andric case Hexagon::dup_S2_allocframe: 41350b57cec5SDimitry Andric if (MI.getOperand(2).isImm() && 41360b57cec5SDimitry Andric isShiftedUInt<5,3>(MI.getOperand(2).getImm())) 41370b57cec5SDimitry Andric return HexagonII::HSIG_S1; 41380b57cec5SDimitry Andric break; 41390b57cec5SDimitry Andric // 41400b57cec5SDimitry Andric // Group A: 41410b57cec5SDimitry Andric // 41420b57cec5SDimitry Andric // Rx = add(Rx,#s7) 41430b57cec5SDimitry Andric // Rd = Rs 41440b57cec5SDimitry Andric // Rd = #u6 41450b57cec5SDimitry Andric // Rd = #-1 41460b57cec5SDimitry Andric // if ([!]P0[.new]) Rd = #0 41470b57cec5SDimitry Andric // Rd = add(r29,#u6:2) 41480b57cec5SDimitry Andric // Rx = add(Rx,Rs) 41490b57cec5SDimitry Andric // P0 = cmp.eq(Rs,#u2) 41500b57cec5SDimitry Andric // Rdd = combine(#0,Rs) 41510b57cec5SDimitry Andric // Rdd = combine(Rs,#0) 41520b57cec5SDimitry Andric // Rdd = combine(#u2,#U2) 41530b57cec5SDimitry Andric // Rd = add(Rs,#1) 41540b57cec5SDimitry Andric // Rd = add(Rs,#-1) 41550b57cec5SDimitry Andric // Rd = sxth/sxtb/zxtb/zxth(Rs) 41560b57cec5SDimitry Andric // Rd = and(Rs,#1) 41570b57cec5SDimitry Andric case Hexagon::A2_addi: 41585ffd83dbSDimitry Andric case Hexagon::dup_A2_addi: 41590b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 41600b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 41610b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg)) { 41620b57cec5SDimitry Andric // Rd = add(r29,#u6:2) 41630b57cec5SDimitry Andric if (Hexagon::IntRegsRegClass.contains(SrcReg) && 41640b57cec5SDimitry Andric HRI.getStackRegister() == SrcReg && MI.getOperand(2).isImm() && 41650b57cec5SDimitry Andric isShiftedUInt<6,2>(MI.getOperand(2).getImm())) 41660b57cec5SDimitry Andric return HexagonII::HSIG_A; 41670b57cec5SDimitry Andric // Rx = add(Rx,#s7) 41680b57cec5SDimitry Andric if ((DstReg == SrcReg) && MI.getOperand(2).isImm() && 41690b57cec5SDimitry Andric isInt<7>(MI.getOperand(2).getImm())) 41700b57cec5SDimitry Andric return HexagonII::HSIG_A; 41710b57cec5SDimitry Andric // Rd = add(Rs,#1) 41720b57cec5SDimitry Andric // Rd = add(Rs,#-1) 41730b57cec5SDimitry Andric if (isIntRegForSubInst(SrcReg) && MI.getOperand(2).isImm() && 41740b57cec5SDimitry Andric ((MI.getOperand(2).getImm() == 1) || 41750b57cec5SDimitry Andric (MI.getOperand(2).getImm() == -1))) 41760b57cec5SDimitry Andric return HexagonII::HSIG_A; 41770b57cec5SDimitry Andric } 41780b57cec5SDimitry Andric break; 41790b57cec5SDimitry Andric case Hexagon::A2_add: 41805ffd83dbSDimitry Andric case Hexagon::dup_A2_add: 41810b57cec5SDimitry Andric // Rx = add(Rx,Rs) 41820b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 41830b57cec5SDimitry Andric Src1Reg = MI.getOperand(1).getReg(); 41840b57cec5SDimitry Andric Src2Reg = MI.getOperand(2).getReg(); 41850b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && (DstReg == Src1Reg) && 41860b57cec5SDimitry Andric isIntRegForSubInst(Src2Reg)) 41870b57cec5SDimitry Andric return HexagonII::HSIG_A; 41880b57cec5SDimitry Andric break; 41890b57cec5SDimitry Andric case Hexagon::A2_andir: 41905ffd83dbSDimitry Andric case Hexagon::dup_A2_andir: 41910b57cec5SDimitry Andric // Same as zxtb. 41920b57cec5SDimitry Andric // Rd16=and(Rs16,#255) 41930b57cec5SDimitry Andric // Rd16=and(Rs16,#1) 41940b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 41950b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 41960b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg) && 41970b57cec5SDimitry Andric MI.getOperand(2).isImm() && 41980b57cec5SDimitry Andric ((MI.getOperand(2).getImm() == 1) || 41990b57cec5SDimitry Andric (MI.getOperand(2).getImm() == 255))) 42000b57cec5SDimitry Andric return HexagonII::HSIG_A; 42010b57cec5SDimitry Andric break; 42020b57cec5SDimitry Andric case Hexagon::A2_tfr: 42035ffd83dbSDimitry Andric case Hexagon::dup_A2_tfr: 42040b57cec5SDimitry Andric // Rd = Rs 42050b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 42060b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 42070b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg)) 42080b57cec5SDimitry Andric return HexagonII::HSIG_A; 42090b57cec5SDimitry Andric break; 42100b57cec5SDimitry Andric case Hexagon::A2_tfrsi: 42115ffd83dbSDimitry Andric case Hexagon::dup_A2_tfrsi: 42120b57cec5SDimitry Andric // Rd = #u6 42130b57cec5SDimitry Andric // Do not test for #u6 size since the const is getting extended 42140b57cec5SDimitry Andric // regardless and compound could be formed. 42150b57cec5SDimitry Andric // Rd = #-1 42160b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 42170b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg)) 42180b57cec5SDimitry Andric return HexagonII::HSIG_A; 42190b57cec5SDimitry Andric break; 42200b57cec5SDimitry Andric case Hexagon::C2_cmoveit: 42210b57cec5SDimitry Andric case Hexagon::C2_cmovenewit: 42220b57cec5SDimitry Andric case Hexagon::C2_cmoveif: 42230b57cec5SDimitry Andric case Hexagon::C2_cmovenewif: 42245ffd83dbSDimitry Andric case Hexagon::dup_C2_cmoveit: 42255ffd83dbSDimitry Andric case Hexagon::dup_C2_cmovenewit: 42265ffd83dbSDimitry Andric case Hexagon::dup_C2_cmoveif: 42275ffd83dbSDimitry Andric case Hexagon::dup_C2_cmovenewif: 42280b57cec5SDimitry Andric // if ([!]P0[.new]) Rd = #0 42290b57cec5SDimitry Andric // Actual form: 42300b57cec5SDimitry Andric // %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16; 42310b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 42320b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 42330b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && 42340b57cec5SDimitry Andric Hexagon::PredRegsRegClass.contains(SrcReg) && Hexagon::P0 == SrcReg && 42350b57cec5SDimitry Andric MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) 42360b57cec5SDimitry Andric return HexagonII::HSIG_A; 42370b57cec5SDimitry Andric break; 42380b57cec5SDimitry Andric case Hexagon::C2_cmpeqi: 42395ffd83dbSDimitry Andric case Hexagon::dup_C2_cmpeqi: 42400b57cec5SDimitry Andric // P0 = cmp.eq(Rs,#u2) 42410b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 42420b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 42430b57cec5SDimitry Andric if (Hexagon::PredRegsRegClass.contains(DstReg) && 42440b57cec5SDimitry Andric Hexagon::P0 == DstReg && isIntRegForSubInst(SrcReg) && 42450b57cec5SDimitry Andric MI.getOperand(2).isImm() && isUInt<2>(MI.getOperand(2).getImm())) 42460b57cec5SDimitry Andric return HexagonII::HSIG_A; 42470b57cec5SDimitry Andric break; 42480b57cec5SDimitry Andric case Hexagon::A2_combineii: 42490b57cec5SDimitry Andric case Hexagon::A4_combineii: 42505ffd83dbSDimitry Andric case Hexagon::dup_A2_combineii: 42515ffd83dbSDimitry Andric case Hexagon::dup_A4_combineii: 42520b57cec5SDimitry Andric // Rdd = combine(#u2,#U2) 42530b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 42540b57cec5SDimitry Andric if (isDblRegForSubInst(DstReg, HRI) && 42550b57cec5SDimitry Andric ((MI.getOperand(1).isImm() && isUInt<2>(MI.getOperand(1).getImm())) || 42560b57cec5SDimitry Andric (MI.getOperand(1).isGlobal() && 42570b57cec5SDimitry Andric isUInt<2>(MI.getOperand(1).getOffset()))) && 42580b57cec5SDimitry Andric ((MI.getOperand(2).isImm() && isUInt<2>(MI.getOperand(2).getImm())) || 42590b57cec5SDimitry Andric (MI.getOperand(2).isGlobal() && 42600b57cec5SDimitry Andric isUInt<2>(MI.getOperand(2).getOffset())))) 42610b57cec5SDimitry Andric return HexagonII::HSIG_A; 42620b57cec5SDimitry Andric break; 42630b57cec5SDimitry Andric case Hexagon::A4_combineri: 42645ffd83dbSDimitry Andric case Hexagon::dup_A4_combineri: 42655ffd83dbSDimitry Andric // Rdd = combine(Rs,#0) 42660b57cec5SDimitry Andric // Rdd = combine(Rs,#0) 42670b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 42680b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 42690b57cec5SDimitry Andric if (isDblRegForSubInst(DstReg, HRI) && isIntRegForSubInst(SrcReg) && 42700b57cec5SDimitry Andric ((MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) || 42710b57cec5SDimitry Andric (MI.getOperand(2).isGlobal() && MI.getOperand(2).getOffset() == 0))) 42720b57cec5SDimitry Andric return HexagonII::HSIG_A; 42730b57cec5SDimitry Andric break; 42740b57cec5SDimitry Andric case Hexagon::A4_combineir: 42755ffd83dbSDimitry Andric case Hexagon::dup_A4_combineir: 42760b57cec5SDimitry Andric // Rdd = combine(#0,Rs) 42770b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 42780b57cec5SDimitry Andric SrcReg = MI.getOperand(2).getReg(); 42790b57cec5SDimitry Andric if (isDblRegForSubInst(DstReg, HRI) && isIntRegForSubInst(SrcReg) && 42800b57cec5SDimitry Andric ((MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) || 42810b57cec5SDimitry Andric (MI.getOperand(1).isGlobal() && MI.getOperand(1).getOffset() == 0))) 42820b57cec5SDimitry Andric return HexagonII::HSIG_A; 42830b57cec5SDimitry Andric break; 42840b57cec5SDimitry Andric case Hexagon::A2_sxtb: 42850b57cec5SDimitry Andric case Hexagon::A2_sxth: 42860b57cec5SDimitry Andric case Hexagon::A2_zxtb: 42870b57cec5SDimitry Andric case Hexagon::A2_zxth: 42885ffd83dbSDimitry Andric case Hexagon::dup_A2_sxtb: 42895ffd83dbSDimitry Andric case Hexagon::dup_A2_sxth: 42905ffd83dbSDimitry Andric case Hexagon::dup_A2_zxtb: 42915ffd83dbSDimitry Andric case Hexagon::dup_A2_zxth: 42920b57cec5SDimitry Andric // Rd = sxth/sxtb/zxtb/zxth(Rs) 42930b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 42940b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 42950b57cec5SDimitry Andric if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg)) 42960b57cec5SDimitry Andric return HexagonII::HSIG_A; 42970b57cec5SDimitry Andric break; 42980b57cec5SDimitry Andric } 42990b57cec5SDimitry Andric 43000b57cec5SDimitry Andric return HexagonII::HSIG_None; 43010b57cec5SDimitry Andric } 43020b57cec5SDimitry Andric 43030b57cec5SDimitry Andric short HexagonInstrInfo::getEquivalentHWInstr(const MachineInstr &MI) const { 43040b57cec5SDimitry Andric return Hexagon::getRealHWInstr(MI.getOpcode(), Hexagon::InstrType_Real); 43050b57cec5SDimitry Andric } 43060b57cec5SDimitry Andric 43070b57cec5SDimitry Andric unsigned HexagonInstrInfo::getInstrTimingClassLatency( 43080b57cec5SDimitry Andric const InstrItineraryData *ItinData, const MachineInstr &MI) const { 43090b57cec5SDimitry Andric // Default to one cycle for no itinerary. However, an "empty" itinerary may 43100b57cec5SDimitry Andric // still have a MinLatency property, which getStageLatency checks. 43110b57cec5SDimitry Andric if (!ItinData) 43120b57cec5SDimitry Andric return getInstrLatency(ItinData, MI); 43130b57cec5SDimitry Andric 43140b57cec5SDimitry Andric if (MI.isTransient()) 43150b57cec5SDimitry Andric return 0; 43160b57cec5SDimitry Andric return ItinData->getStageLatency(MI.getDesc().getSchedClass()); 43170b57cec5SDimitry Andric } 43180b57cec5SDimitry Andric 43190b57cec5SDimitry Andric /// getOperandLatency - Compute and return the use operand latency of a given 43200b57cec5SDimitry Andric /// pair of def and use. 43210b57cec5SDimitry Andric /// In most cases, the static scheduling itinerary was enough to determine the 43220b57cec5SDimitry Andric /// operand latency. But it may not be possible for instructions with variable 43230b57cec5SDimitry Andric /// number of defs / uses. 43240b57cec5SDimitry Andric /// 43250b57cec5SDimitry Andric /// This is a raw interface to the itinerary that may be directly overriden by 43260b57cec5SDimitry Andric /// a target. Use computeOperandLatency to get the best estimate of latency. 43275f757f3fSDimitry Andric std::optional<unsigned> HexagonInstrInfo::getOperandLatency( 43285f757f3fSDimitry Andric const InstrItineraryData *ItinData, const MachineInstr &DefMI, 43295f757f3fSDimitry Andric unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const { 43300b57cec5SDimitry Andric const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); 43310b57cec5SDimitry Andric 43320b57cec5SDimitry Andric // Get DefIdx and UseIdx for super registers. 43330b57cec5SDimitry Andric const MachineOperand &DefMO = DefMI.getOperand(DefIdx); 43340b57cec5SDimitry Andric 4335bdd1243dSDimitry Andric if (DefMO.isReg() && DefMO.getReg().isPhysical()) { 43360b57cec5SDimitry Andric if (DefMO.isImplicit()) { 433706c3fb27SDimitry Andric for (MCPhysReg SR : HRI.superregs(DefMO.getReg())) { 4338*0fca6ea1SDimitry Andric int Idx = DefMI.findRegisterDefOperandIdx(SR, &HRI, false, false); 43390b57cec5SDimitry Andric if (Idx != -1) { 43400b57cec5SDimitry Andric DefIdx = Idx; 43410b57cec5SDimitry Andric break; 43420b57cec5SDimitry Andric } 43430b57cec5SDimitry Andric } 43440b57cec5SDimitry Andric } 43450b57cec5SDimitry Andric 43460b57cec5SDimitry Andric const MachineOperand &UseMO = UseMI.getOperand(UseIdx); 43470b57cec5SDimitry Andric if (UseMO.isImplicit()) { 434806c3fb27SDimitry Andric for (MCPhysReg SR : HRI.superregs(UseMO.getReg())) { 4349*0fca6ea1SDimitry Andric int Idx = UseMI.findRegisterUseOperandIdx(SR, &HRI, false); 43500b57cec5SDimitry Andric if (Idx != -1) { 43510b57cec5SDimitry Andric UseIdx = Idx; 43520b57cec5SDimitry Andric break; 43530b57cec5SDimitry Andric } 43540b57cec5SDimitry Andric } 43550b57cec5SDimitry Andric } 43560b57cec5SDimitry Andric } 43570b57cec5SDimitry Andric 43585f757f3fSDimitry Andric std::optional<unsigned> Latency = TargetInstrInfo::getOperandLatency( 43595f757f3fSDimitry Andric ItinData, DefMI, DefIdx, UseMI, UseIdx); 43605f757f3fSDimitry Andric if (Latency == 0) 43610b57cec5SDimitry Andric // We should never have 0 cycle latency between two instructions unless 43620b57cec5SDimitry Andric // they can be packetized together. However, this decision can't be made 43630b57cec5SDimitry Andric // here. 43640b57cec5SDimitry Andric Latency = 1; 43650b57cec5SDimitry Andric return Latency; 43660b57cec5SDimitry Andric } 43670b57cec5SDimitry Andric 43680b57cec5SDimitry Andric // inverts the predication logic. 43690b57cec5SDimitry Andric // p -> NotP 43700b57cec5SDimitry Andric // NotP -> P 43710b57cec5SDimitry Andric bool HexagonInstrInfo::getInvertedPredSense( 43720b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) const { 43730b57cec5SDimitry Andric if (Cond.empty()) 43740b57cec5SDimitry Andric return false; 43750b57cec5SDimitry Andric unsigned Opc = getInvertedPredicatedOpcode(Cond[0].getImm()); 43760b57cec5SDimitry Andric Cond[0].setImm(Opc); 43770b57cec5SDimitry Andric return true; 43780b57cec5SDimitry Andric } 43790b57cec5SDimitry Andric 43800b57cec5SDimitry Andric unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { 43810b57cec5SDimitry Andric int InvPredOpcode; 43820b57cec5SDimitry Andric InvPredOpcode = isPredicatedTrue(Opc) ? Hexagon::getFalsePredOpcode(Opc) 43830b57cec5SDimitry Andric : Hexagon::getTruePredOpcode(Opc); 43840b57cec5SDimitry Andric if (InvPredOpcode >= 0) // Valid instruction with the inverted predicate. 43850b57cec5SDimitry Andric return InvPredOpcode; 43860b57cec5SDimitry Andric 43870b57cec5SDimitry Andric llvm_unreachable("Unexpected predicated instruction"); 43880b57cec5SDimitry Andric } 43890b57cec5SDimitry Andric 43900b57cec5SDimitry Andric // Returns the max value that doesn't need to be extended. 43910b57cec5SDimitry Andric int HexagonInstrInfo::getMaxValue(const MachineInstr &MI) const { 43920b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 43930b57cec5SDimitry Andric unsigned isSigned = (F >> HexagonII::ExtentSignedPos) 43940b57cec5SDimitry Andric & HexagonII::ExtentSignedMask; 43950b57cec5SDimitry Andric unsigned bits = (F >> HexagonII::ExtentBitsPos) 43960b57cec5SDimitry Andric & HexagonII::ExtentBitsMask; 43970b57cec5SDimitry Andric 43980b57cec5SDimitry Andric if (isSigned) // if value is signed 43990b57cec5SDimitry Andric return ~(-1U << (bits - 1)); 44000b57cec5SDimitry Andric else 44010b57cec5SDimitry Andric return ~(-1U << bits); 44020b57cec5SDimitry Andric } 44030b57cec5SDimitry Andric 44040b57cec5SDimitry Andric 44050b57cec5SDimitry Andric bool HexagonInstrInfo::isAddrModeWithOffset(const MachineInstr &MI) const { 44060b57cec5SDimitry Andric switch (MI.getOpcode()) { 44070b57cec5SDimitry Andric case Hexagon::L2_loadrbgp: 44080b57cec5SDimitry Andric case Hexagon::L2_loadrdgp: 44090b57cec5SDimitry Andric case Hexagon::L2_loadrhgp: 44100b57cec5SDimitry Andric case Hexagon::L2_loadrigp: 44110b57cec5SDimitry Andric case Hexagon::L2_loadrubgp: 44120b57cec5SDimitry Andric case Hexagon::L2_loadruhgp: 44130b57cec5SDimitry Andric case Hexagon::S2_storerbgp: 44140b57cec5SDimitry Andric case Hexagon::S2_storerbnewgp: 44150b57cec5SDimitry Andric case Hexagon::S2_storerhgp: 44160b57cec5SDimitry Andric case Hexagon::S2_storerhnewgp: 44170b57cec5SDimitry Andric case Hexagon::S2_storerigp: 44180b57cec5SDimitry Andric case Hexagon::S2_storerinewgp: 44190b57cec5SDimitry Andric case Hexagon::S2_storerdgp: 44200b57cec5SDimitry Andric case Hexagon::S2_storerfgp: 44210b57cec5SDimitry Andric return true; 44220b57cec5SDimitry Andric } 44230b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 44240b57cec5SDimitry Andric unsigned addrMode = 44250b57cec5SDimitry Andric ((F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask); 44260b57cec5SDimitry Andric // Disallow any base+offset instruction. The assembler does not yet reorder 44270b57cec5SDimitry Andric // based up any zero offset instruction. 44280b57cec5SDimitry Andric return (addrMode == HexagonII::BaseRegOffset || 44290b57cec5SDimitry Andric addrMode == HexagonII::BaseImmOffset || 44300b57cec5SDimitry Andric addrMode == HexagonII::BaseLongOffset); 44310b57cec5SDimitry Andric } 44320b57cec5SDimitry Andric 44335ffd83dbSDimitry Andric bool HexagonInstrInfo::isPureSlot0(const MachineInstr &MI) const { 44345ffd83dbSDimitry Andric // Workaround for the Global Scheduler. Sometimes, it creates 44355ffd83dbSDimitry Andric // A4_ext as a Pseudo instruction and calls this function to see if 44365ffd83dbSDimitry Andric // it can be added to an existing bundle. Since the instruction doesn't 44375ffd83dbSDimitry Andric // belong to any BB yet, we can't use getUnits API. 44385ffd83dbSDimitry Andric if (MI.getOpcode() == Hexagon::A4_ext) 44395ffd83dbSDimitry Andric return false; 44405ffd83dbSDimitry Andric 44415ffd83dbSDimitry Andric unsigned FuncUnits = getUnits(MI); 44425ffd83dbSDimitry Andric return HexagonFUnits::isSlot0Only(FuncUnits); 44435ffd83dbSDimitry Andric } 44445ffd83dbSDimitry Andric 44455ffd83dbSDimitry Andric bool HexagonInstrInfo::isRestrictNoSlot1Store(const MachineInstr &MI) const { 44465ffd83dbSDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 44475ffd83dbSDimitry Andric return ((F >> HexagonII::RestrictNoSlot1StorePos) & 44485ffd83dbSDimitry Andric HexagonII::RestrictNoSlot1StoreMask); 44495ffd83dbSDimitry Andric } 44505ffd83dbSDimitry Andric 44515ffd83dbSDimitry Andric void HexagonInstrInfo::changeDuplexOpcode(MachineBasicBlock::instr_iterator MII, 44525ffd83dbSDimitry Andric bool ToBigInstrs) const { 44535ffd83dbSDimitry Andric int Opcode = -1; 44545ffd83dbSDimitry Andric if (ToBigInstrs) { // To BigCore Instr. 44555ffd83dbSDimitry Andric // Check if the instruction can form a Duplex. 44565ffd83dbSDimitry Andric if (getDuplexCandidateGroup(*MII)) 44575ffd83dbSDimitry Andric // Get the opcode marked "dup_*" tag. 44585ffd83dbSDimitry Andric Opcode = getDuplexOpcode(*MII, ToBigInstrs); 44595ffd83dbSDimitry Andric } else // To TinyCore Instr. 44605ffd83dbSDimitry Andric Opcode = getDuplexOpcode(*MII, ToBigInstrs); 44615ffd83dbSDimitry Andric 44625ffd83dbSDimitry Andric // Change the opcode of the instruction. 44635ffd83dbSDimitry Andric if (Opcode >= 0) 44645ffd83dbSDimitry Andric MII->setDesc(get(Opcode)); 44655ffd83dbSDimitry Andric } 44665ffd83dbSDimitry Andric 44675ffd83dbSDimitry Andric // This function is used to translate instructions to facilitate generating 44685ffd83dbSDimitry Andric // Duplexes on TinyCore. 44695ffd83dbSDimitry Andric void HexagonInstrInfo::translateInstrsForDup(MachineFunction &MF, 44705ffd83dbSDimitry Andric bool ToBigInstrs) const { 44715ffd83dbSDimitry Andric for (auto &MB : MF) 44725ffd83dbSDimitry Andric for (MachineBasicBlock::instr_iterator Instr = MB.instr_begin(), 44735ffd83dbSDimitry Andric End = MB.instr_end(); 44745ffd83dbSDimitry Andric Instr != End; ++Instr) 44755ffd83dbSDimitry Andric changeDuplexOpcode(Instr, ToBigInstrs); 44765ffd83dbSDimitry Andric } 44775ffd83dbSDimitry Andric 44785ffd83dbSDimitry Andric // This is a specialized form of above function. 44795ffd83dbSDimitry Andric void HexagonInstrInfo::translateInstrsForDup( 44805ffd83dbSDimitry Andric MachineBasicBlock::instr_iterator MII, bool ToBigInstrs) const { 44815ffd83dbSDimitry Andric MachineBasicBlock *MBB = MII->getParent(); 44825ffd83dbSDimitry Andric while ((MII != MBB->instr_end()) && MII->isInsideBundle()) { 44835ffd83dbSDimitry Andric changeDuplexOpcode(MII, ToBigInstrs); 44845ffd83dbSDimitry Andric ++MII; 44855ffd83dbSDimitry Andric } 44865ffd83dbSDimitry Andric } 44875ffd83dbSDimitry Andric 44880b57cec5SDimitry Andric unsigned HexagonInstrInfo::getMemAccessSize(const MachineInstr &MI) const { 44890b57cec5SDimitry Andric using namespace HexagonII; 44900b57cec5SDimitry Andric 44910b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 44920b57cec5SDimitry Andric unsigned S = (F >> MemAccessSizePos) & MemAccesSizeMask; 44930b57cec5SDimitry Andric unsigned Size = getMemAccessSizeInBytes(MemAccessSize(S)); 44940b57cec5SDimitry Andric if (Size != 0) 44950b57cec5SDimitry Andric return Size; 449681ad6265SDimitry Andric // Y2_dcfetchbo is special 449781ad6265SDimitry Andric if (MI.getOpcode() == Hexagon::Y2_dcfetchbo) 449881ad6265SDimitry Andric return HexagonII::DoubleWordAccess; 44990b57cec5SDimitry Andric 45000b57cec5SDimitry Andric // Handle vector access sizes. 45010b57cec5SDimitry Andric const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); 45020b57cec5SDimitry Andric switch (S) { 45030b57cec5SDimitry Andric case HexagonII::HVXVectorAccess: 45040b57cec5SDimitry Andric return HRI.getSpillSize(Hexagon::HvxVRRegClass); 45050b57cec5SDimitry Andric default: 45060b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction"); 45070b57cec5SDimitry Andric } 45080b57cec5SDimitry Andric } 45090b57cec5SDimitry Andric 45100b57cec5SDimitry Andric // Returns the min value that doesn't need to be extended. 45110b57cec5SDimitry Andric int HexagonInstrInfo::getMinValue(const MachineInstr &MI) const { 45120b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 45130b57cec5SDimitry Andric unsigned isSigned = (F >> HexagonII::ExtentSignedPos) 45140b57cec5SDimitry Andric & HexagonII::ExtentSignedMask; 45150b57cec5SDimitry Andric unsigned bits = (F >> HexagonII::ExtentBitsPos) 45160b57cec5SDimitry Andric & HexagonII::ExtentBitsMask; 45170b57cec5SDimitry Andric 45180b57cec5SDimitry Andric if (isSigned) // if value is signed 45190b57cec5SDimitry Andric return -1U << (bits - 1); 45200b57cec5SDimitry Andric else 45210b57cec5SDimitry Andric return 0; 45220b57cec5SDimitry Andric } 45230b57cec5SDimitry Andric 45240b57cec5SDimitry Andric // Returns opcode of the non-extended equivalent instruction. 45250b57cec5SDimitry Andric short HexagonInstrInfo::getNonExtOpcode(const MachineInstr &MI) const { 45260b57cec5SDimitry Andric // Check if the instruction has a register form that uses register in place 45270b57cec5SDimitry Andric // of the extended operand, if so return that as the non-extended form. 45280b57cec5SDimitry Andric short NonExtOpcode = Hexagon::getRegForm(MI.getOpcode()); 45290b57cec5SDimitry Andric if (NonExtOpcode >= 0) 45300b57cec5SDimitry Andric return NonExtOpcode; 45310b57cec5SDimitry Andric 45320b57cec5SDimitry Andric if (MI.getDesc().mayLoad() || MI.getDesc().mayStore()) { 45330b57cec5SDimitry Andric // Check addressing mode and retrieve non-ext equivalent instruction. 45340b57cec5SDimitry Andric switch (getAddrMode(MI)) { 45350b57cec5SDimitry Andric case HexagonII::Absolute: 45360b57cec5SDimitry Andric return Hexagon::changeAddrMode_abs_io(MI.getOpcode()); 45370b57cec5SDimitry Andric case HexagonII::BaseImmOffset: 45380b57cec5SDimitry Andric return Hexagon::changeAddrMode_io_rr(MI.getOpcode()); 45390b57cec5SDimitry Andric case HexagonII::BaseLongOffset: 45400b57cec5SDimitry Andric return Hexagon::changeAddrMode_ur_rr(MI.getOpcode()); 45410b57cec5SDimitry Andric 45420b57cec5SDimitry Andric default: 45430b57cec5SDimitry Andric return -1; 45440b57cec5SDimitry Andric } 45450b57cec5SDimitry Andric } 45460b57cec5SDimitry Andric return -1; 45470b57cec5SDimitry Andric } 45480b57cec5SDimitry Andric 45490b57cec5SDimitry Andric bool HexagonInstrInfo::getPredReg(ArrayRef<MachineOperand> Cond, 4550bdd1243dSDimitry Andric Register &PredReg, unsigned &PredRegPos, unsigned &PredRegFlags) const { 45510b57cec5SDimitry Andric if (Cond.empty()) 45520b57cec5SDimitry Andric return false; 45530b57cec5SDimitry Andric assert(Cond.size() == 2); 45540b57cec5SDimitry Andric if (isNewValueJump(Cond[0].getImm()) || Cond[1].isMBB()) { 45550b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "No predregs for new-value jumps/endloop"); 45560b57cec5SDimitry Andric return false; 45570b57cec5SDimitry Andric } 45580b57cec5SDimitry Andric PredReg = Cond[1].getReg(); 45590b57cec5SDimitry Andric PredRegPos = 1; 45600b57cec5SDimitry Andric // See IfConversion.cpp why we add RegState::Implicit | RegState::Undef 45610b57cec5SDimitry Andric PredRegFlags = 0; 45620b57cec5SDimitry Andric if (Cond[1].isImplicit()) 45630b57cec5SDimitry Andric PredRegFlags = RegState::Implicit; 45640b57cec5SDimitry Andric if (Cond[1].isUndef()) 45650b57cec5SDimitry Andric PredRegFlags |= RegState::Undef; 45660b57cec5SDimitry Andric return true; 45670b57cec5SDimitry Andric } 45680b57cec5SDimitry Andric 45690b57cec5SDimitry Andric short HexagonInstrInfo::getPseudoInstrPair(const MachineInstr &MI) const { 45700b57cec5SDimitry Andric return Hexagon::getRealHWInstr(MI.getOpcode(), Hexagon::InstrType_Pseudo); 45710b57cec5SDimitry Andric } 45720b57cec5SDimitry Andric 45730b57cec5SDimitry Andric short HexagonInstrInfo::getRegForm(const MachineInstr &MI) const { 45740b57cec5SDimitry Andric return Hexagon::getRegForm(MI.getOpcode()); 45750b57cec5SDimitry Andric } 45760b57cec5SDimitry Andric 45770b57cec5SDimitry Andric // Return the number of bytes required to encode the instruction. 45780b57cec5SDimitry Andric // Hexagon instructions are fixed length, 4 bytes, unless they 45790b57cec5SDimitry Andric // use a constant extender, which requires another 4 bytes. 45800b57cec5SDimitry Andric // For debug instructions and prolog labels, return 0. 45810b57cec5SDimitry Andric unsigned HexagonInstrInfo::getSize(const MachineInstr &MI) const { 45820b57cec5SDimitry Andric if (MI.isDebugInstr() || MI.isPosition()) 45830b57cec5SDimitry Andric return 0; 45840b57cec5SDimitry Andric 45850b57cec5SDimitry Andric unsigned Size = MI.getDesc().getSize(); 45860b57cec5SDimitry Andric if (!Size) 45870b57cec5SDimitry Andric // Assume the default insn size in case it cannot be determined 45880b57cec5SDimitry Andric // for whatever reason. 45890b57cec5SDimitry Andric Size = HEXAGON_INSTR_SIZE; 45900b57cec5SDimitry Andric 45910b57cec5SDimitry Andric if (isConstExtended(MI) || isExtended(MI)) 45920b57cec5SDimitry Andric Size += HEXAGON_INSTR_SIZE; 45930b57cec5SDimitry Andric 45940b57cec5SDimitry Andric // Try and compute number of instructions in asm. 45950b57cec5SDimitry Andric if (BranchRelaxAsmLarge && MI.getOpcode() == Hexagon::INLINEASM) { 45960b57cec5SDimitry Andric const MachineBasicBlock &MBB = *MI.getParent(); 45970b57cec5SDimitry Andric const MachineFunction *MF = MBB.getParent(); 45980b57cec5SDimitry Andric const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); 45990b57cec5SDimitry Andric 46000b57cec5SDimitry Andric // Count the number of register definitions to find the asm string. 46010b57cec5SDimitry Andric unsigned NumDefs = 0; 46020b57cec5SDimitry Andric for (; MI.getOperand(NumDefs).isReg() && MI.getOperand(NumDefs).isDef(); 46030b57cec5SDimitry Andric ++NumDefs) 46040b57cec5SDimitry Andric assert(NumDefs != MI.getNumOperands()-2 && "No asm string?"); 46050b57cec5SDimitry Andric 46060b57cec5SDimitry Andric assert(MI.getOperand(NumDefs).isSymbol() && "No asm string?"); 46070b57cec5SDimitry Andric // Disassemble the AsmStr and approximate number of instructions. 46080b57cec5SDimitry Andric const char *AsmStr = MI.getOperand(NumDefs).getSymbolName(); 46090b57cec5SDimitry Andric Size = getInlineAsmLength(AsmStr, *MAI); 46100b57cec5SDimitry Andric } 46110b57cec5SDimitry Andric 46120b57cec5SDimitry Andric return Size; 46130b57cec5SDimitry Andric } 46140b57cec5SDimitry Andric 46150b57cec5SDimitry Andric uint64_t HexagonInstrInfo::getType(const MachineInstr &MI) const { 46160b57cec5SDimitry Andric const uint64_t F = MI.getDesc().TSFlags; 46170b57cec5SDimitry Andric return (F >> HexagonII::TypePos) & HexagonII::TypeMask; 46180b57cec5SDimitry Andric } 46190b57cec5SDimitry Andric 46205ffd83dbSDimitry Andric InstrStage::FuncUnits HexagonInstrInfo::getUnits(const MachineInstr &MI) const { 46210b57cec5SDimitry Andric const InstrItineraryData &II = *Subtarget.getInstrItineraryData(); 46220b57cec5SDimitry Andric const InstrStage &IS = *II.beginStage(MI.getDesc().getSchedClass()); 46230b57cec5SDimitry Andric 46240b57cec5SDimitry Andric return IS.getUnits(); 46250b57cec5SDimitry Andric } 46260b57cec5SDimitry Andric 46270b57cec5SDimitry Andric // Calculate size of the basic block without debug instructions. 46280b57cec5SDimitry Andric unsigned HexagonInstrInfo::nonDbgBBSize(const MachineBasicBlock *BB) const { 46290b57cec5SDimitry Andric return nonDbgMICount(BB->instr_begin(), BB->instr_end()); 46300b57cec5SDimitry Andric } 46310b57cec5SDimitry Andric 46320b57cec5SDimitry Andric unsigned HexagonInstrInfo::nonDbgBundleSize( 46330b57cec5SDimitry Andric MachineBasicBlock::const_iterator BundleHead) const { 46340b57cec5SDimitry Andric assert(BundleHead->isBundle() && "Not a bundle header"); 46350b57cec5SDimitry Andric auto MII = BundleHead.getInstrIterator(); 46360b57cec5SDimitry Andric // Skip the bundle header. 46370b57cec5SDimitry Andric return nonDbgMICount(++MII, getBundleEnd(BundleHead.getInstrIterator())); 46380b57cec5SDimitry Andric } 46390b57cec5SDimitry Andric 46400b57cec5SDimitry Andric /// immediateExtend - Changes the instruction in place to one using an immediate 46410b57cec5SDimitry Andric /// extender. 46420b57cec5SDimitry Andric void HexagonInstrInfo::immediateExtend(MachineInstr &MI) const { 46430b57cec5SDimitry Andric assert((isExtendable(MI)||isConstExtended(MI)) && 46440b57cec5SDimitry Andric "Instruction must be extendable"); 46450b57cec5SDimitry Andric // Find which operand is extendable. 46460b57cec5SDimitry Andric short ExtOpNum = getCExtOpNum(MI); 46470b57cec5SDimitry Andric MachineOperand &MO = MI.getOperand(ExtOpNum); 46480b57cec5SDimitry Andric // This needs to be something we understand. 46490b57cec5SDimitry Andric assert((MO.isMBB() || MO.isImm()) && 46500b57cec5SDimitry Andric "Branch with unknown extendable field type"); 46510b57cec5SDimitry Andric // Mark given operand as extended. 46520b57cec5SDimitry Andric MO.addTargetFlag(HexagonII::HMOTF_ConstExtended); 46530b57cec5SDimitry Andric } 46540b57cec5SDimitry Andric 46550b57cec5SDimitry Andric bool HexagonInstrInfo::invertAndChangeJumpTarget( 46560b57cec5SDimitry Andric MachineInstr &MI, MachineBasicBlock *NewTarget) const { 46570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n[invertAndChangeJumpTarget] to " 46580b57cec5SDimitry Andric << printMBBReference(*NewTarget); 46590b57cec5SDimitry Andric MI.dump();); 46600b57cec5SDimitry Andric assert(MI.isBranch()); 46610b57cec5SDimitry Andric unsigned NewOpcode = getInvertedPredicatedOpcode(MI.getOpcode()); 46620b57cec5SDimitry Andric int TargetPos = MI.getNumOperands() - 1; 46630b57cec5SDimitry Andric // In general branch target is the last operand, 46640b57cec5SDimitry Andric // but some implicit defs added at the end might change it. 46650b57cec5SDimitry Andric while ((TargetPos > -1) && !MI.getOperand(TargetPos).isMBB()) 46660b57cec5SDimitry Andric --TargetPos; 46670b57cec5SDimitry Andric assert((TargetPos >= 0) && MI.getOperand(TargetPos).isMBB()); 46680b57cec5SDimitry Andric MI.getOperand(TargetPos).setMBB(NewTarget); 46690b57cec5SDimitry Andric if (EnableBranchPrediction && isPredicatedNew(MI)) { 46700b57cec5SDimitry Andric NewOpcode = reversePrediction(NewOpcode); 46710b57cec5SDimitry Andric } 46720b57cec5SDimitry Andric MI.setDesc(get(NewOpcode)); 46730b57cec5SDimitry Andric return true; 46740b57cec5SDimitry Andric } 46750b57cec5SDimitry Andric 46760b57cec5SDimitry Andric void HexagonInstrInfo::genAllInsnTimingClasses(MachineFunction &MF) const { 46770b57cec5SDimitry Andric /* +++ The code below is used to generate complete set of Hexagon Insn +++ */ 46780b57cec5SDimitry Andric MachineFunction::iterator A = MF.begin(); 46790b57cec5SDimitry Andric MachineBasicBlock &B = *A; 46800b57cec5SDimitry Andric MachineBasicBlock::iterator I = B.begin(); 46810b57cec5SDimitry Andric DebugLoc DL = I->getDebugLoc(); 46820b57cec5SDimitry Andric MachineInstr *NewMI; 46830b57cec5SDimitry Andric 46840b57cec5SDimitry Andric for (unsigned insn = TargetOpcode::GENERIC_OP_END+1; 46850b57cec5SDimitry Andric insn < Hexagon::INSTRUCTION_LIST_END; ++insn) { 46860b57cec5SDimitry Andric NewMI = BuildMI(B, I, DL, get(insn)); 46870b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n" 46880b57cec5SDimitry Andric << getName(NewMI->getOpcode()) 46890b57cec5SDimitry Andric << " Class: " << NewMI->getDesc().getSchedClass()); 46900b57cec5SDimitry Andric NewMI->eraseFromParent(); 46910b57cec5SDimitry Andric } 46920b57cec5SDimitry Andric /* --- The code above is used to generate complete set of Hexagon Insn --- */ 46930b57cec5SDimitry Andric } 46940b57cec5SDimitry Andric 46950b57cec5SDimitry Andric // inverts the predication logic. 46960b57cec5SDimitry Andric // p -> NotP 46970b57cec5SDimitry Andric // NotP -> P 46980b57cec5SDimitry Andric bool HexagonInstrInfo::reversePredSense(MachineInstr &MI) const { 46990b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nTrying to reverse pred. sense of:"; MI.dump()); 47000b57cec5SDimitry Andric MI.setDesc(get(getInvertedPredicatedOpcode(MI.getOpcode()))); 47010b57cec5SDimitry Andric return true; 47020b57cec5SDimitry Andric } 47030b57cec5SDimitry Andric 47040b57cec5SDimitry Andric // Reverse the branch prediction. 47050b57cec5SDimitry Andric unsigned HexagonInstrInfo::reversePrediction(unsigned Opcode) const { 47060b57cec5SDimitry Andric int PredRevOpcode = -1; 47070b57cec5SDimitry Andric if (isPredictedTaken(Opcode)) 47080b57cec5SDimitry Andric PredRevOpcode = Hexagon::notTakenBranchPrediction(Opcode); 47090b57cec5SDimitry Andric else 47100b57cec5SDimitry Andric PredRevOpcode = Hexagon::takenBranchPrediction(Opcode); 47110b57cec5SDimitry Andric assert(PredRevOpcode > 0); 47120b57cec5SDimitry Andric return PredRevOpcode; 47130b57cec5SDimitry Andric } 47140b57cec5SDimitry Andric 47150b57cec5SDimitry Andric // TODO: Add more rigorous validation. 47160b57cec5SDimitry Andric bool HexagonInstrInfo::validateBranchCond(const ArrayRef<MachineOperand> &Cond) 47170b57cec5SDimitry Andric const { 47180b57cec5SDimitry Andric return Cond.empty() || (Cond[0].isImm() && (Cond.size() != 1)); 47190b57cec5SDimitry Andric } 47200b57cec5SDimitry Andric 47210b57cec5SDimitry Andric void HexagonInstrInfo:: 47220b57cec5SDimitry Andric setBundleNoShuf(MachineBasicBlock::instr_iterator MIB) const { 47230b57cec5SDimitry Andric assert(MIB->isBundle()); 47240b57cec5SDimitry Andric MachineOperand &Operand = MIB->getOperand(0); 47250b57cec5SDimitry Andric if (Operand.isImm()) 47260b57cec5SDimitry Andric Operand.setImm(Operand.getImm() | memShufDisabledMask); 47270b57cec5SDimitry Andric else 47280b57cec5SDimitry Andric MIB->addOperand(MachineOperand::CreateImm(memShufDisabledMask)); 47290b57cec5SDimitry Andric } 47300b57cec5SDimitry Andric 47310b57cec5SDimitry Andric bool HexagonInstrInfo::getBundleNoShuf(const MachineInstr &MIB) const { 47320b57cec5SDimitry Andric assert(MIB.isBundle()); 47330b57cec5SDimitry Andric const MachineOperand &Operand = MIB.getOperand(0); 47340b57cec5SDimitry Andric return (Operand.isImm() && (Operand.getImm() & memShufDisabledMask) != 0); 47350b57cec5SDimitry Andric } 47360b57cec5SDimitry Andric 47370b57cec5SDimitry Andric // Addressing mode relations. 47380b57cec5SDimitry Andric short HexagonInstrInfo::changeAddrMode_abs_io(short Opc) const { 47390b57cec5SDimitry Andric return Opc >= 0 ? Hexagon::changeAddrMode_abs_io(Opc) : Opc; 47400b57cec5SDimitry Andric } 47410b57cec5SDimitry Andric 47420b57cec5SDimitry Andric short HexagonInstrInfo::changeAddrMode_io_abs(short Opc) const { 47430b57cec5SDimitry Andric return Opc >= 0 ? Hexagon::changeAddrMode_io_abs(Opc) : Opc; 47440b57cec5SDimitry Andric } 47450b57cec5SDimitry Andric 47460b57cec5SDimitry Andric short HexagonInstrInfo::changeAddrMode_io_pi(short Opc) const { 47470b57cec5SDimitry Andric return Opc >= 0 ? Hexagon::changeAddrMode_io_pi(Opc) : Opc; 47480b57cec5SDimitry Andric } 47490b57cec5SDimitry Andric 47500b57cec5SDimitry Andric short HexagonInstrInfo::changeAddrMode_io_rr(short Opc) const { 47510b57cec5SDimitry Andric return Opc >= 0 ? Hexagon::changeAddrMode_io_rr(Opc) : Opc; 47520b57cec5SDimitry Andric } 47530b57cec5SDimitry Andric 47540b57cec5SDimitry Andric short HexagonInstrInfo::changeAddrMode_pi_io(short Opc) const { 47550b57cec5SDimitry Andric return Opc >= 0 ? Hexagon::changeAddrMode_pi_io(Opc) : Opc; 47560b57cec5SDimitry Andric } 47570b57cec5SDimitry Andric 47580b57cec5SDimitry Andric short HexagonInstrInfo::changeAddrMode_rr_io(short Opc) const { 47590b57cec5SDimitry Andric return Opc >= 0 ? Hexagon::changeAddrMode_rr_io(Opc) : Opc; 47600b57cec5SDimitry Andric } 47610b57cec5SDimitry Andric 47620b57cec5SDimitry Andric short HexagonInstrInfo::changeAddrMode_rr_ur(short Opc) const { 47630b57cec5SDimitry Andric return Opc >= 0 ? Hexagon::changeAddrMode_rr_ur(Opc) : Opc; 47640b57cec5SDimitry Andric } 47650b57cec5SDimitry Andric 47660b57cec5SDimitry Andric short HexagonInstrInfo::changeAddrMode_ur_rr(short Opc) const { 47670b57cec5SDimitry Andric return Opc >= 0 ? Hexagon::changeAddrMode_ur_rr(Opc) : Opc; 47680b57cec5SDimitry Andric } 47690eae32dcSDimitry Andric 47700eae32dcSDimitry Andric MCInst HexagonInstrInfo::getNop() const { 47710eae32dcSDimitry Andric static const MCInst Nop = MCInstBuilder(Hexagon::A2_nop); 47720eae32dcSDimitry Andric 47730eae32dcSDimitry Andric return MCInstBuilder(Hexagon::BUNDLE) 47740eae32dcSDimitry Andric .addImm(0) 47750eae32dcSDimitry Andric .addInst(&Nop); 47760eae32dcSDimitry Andric } 4777