Path: blob/main/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonCopyToCombine.cpp
35266 views
//===------- HexagonCopyToCombine.cpp - Hexagon Copy-To-Combine Pass ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7// This pass replaces transfer instructions by combine instructions.8// We walk along a basic block and look for two combinable instructions and try9// to move them together. If we can move them next to each other we do so and10// replace them with a combine instruction.11//===----------------------------------------------------------------------===//1213#include "HexagonInstrInfo.h"14#include "HexagonSubtarget.h"15#include "llvm/ADT/DenseMap.h"16#include "llvm/ADT/DenseSet.h"17#include "llvm/CodeGen/MachineBasicBlock.h"18#include "llvm/CodeGen/MachineFunction.h"19#include "llvm/CodeGen/MachineFunctionPass.h"20#include "llvm/CodeGen/MachineInstr.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/CodeGen/Passes.h"23#include "llvm/CodeGen/TargetRegisterInfo.h"24#include "llvm/Pass.h"25#include "llvm/Support/CodeGen.h"26#include "llvm/Support/CommandLine.h"27#include "llvm/Support/Debug.h"28#include "llvm/Support/raw_ostream.h"29#include "llvm/Target/TargetMachine.h"3031using namespace llvm;3233#define DEBUG_TYPE "hexagon-copy-combine"3435static cl::opt<bool>36IsCombinesDisabled("disable-merge-into-combines", cl::Hidden,3738cl::desc("Disable merging into combines"));39static cl::opt<bool>40IsConst64Disabled("disable-const64", cl::Hidden,4142cl::desc("Disable generation of const64"));43static44cl::opt<unsigned>45MaxNumOfInstsBetweenNewValueStoreAndTFR("max-num-inst-between-tfr-and-nv-store",46cl::Hidden, cl::init(4),47cl::desc("Maximum distance between a tfr feeding a store we "48"consider the store still to be newifiable"));4950namespace llvm {51FunctionPass *createHexagonCopyToCombine();52void initializeHexagonCopyToCombinePass(PassRegistry&);53}545556namespace {5758class HexagonCopyToCombine : public MachineFunctionPass {59const HexagonInstrInfo *TII;60const TargetRegisterInfo *TRI;61const HexagonSubtarget *ST;62bool ShouldCombineAggressively;6364DenseSet<MachineInstr *> PotentiallyNewifiableTFR;65SmallVector<MachineInstr *, 8> DbgMItoMove;6667public:68static char ID;6970HexagonCopyToCombine() : MachineFunctionPass(ID) {}7172void getAnalysisUsage(AnalysisUsage &AU) const override {73MachineFunctionPass::getAnalysisUsage(AU);74}7576StringRef getPassName() const override {77return "Hexagon Copy-To-Combine Pass";78}7980bool runOnMachineFunction(MachineFunction &Fn) override;8182MachineFunctionProperties getRequiredProperties() const override {83return MachineFunctionProperties().set(84MachineFunctionProperties::Property::NoVRegs);85}8687private:88MachineInstr *findPairable(MachineInstr &I1, bool &DoInsertAtI1,89bool AllowC64);9091void findPotentialNewifiableTFRs(MachineBasicBlock &);9293void combine(MachineInstr &I1, MachineInstr &I2,94MachineBasicBlock::iterator &MI, bool DoInsertAtI1,95bool OptForSize);9697bool isSafeToMoveTogether(MachineInstr &I1, MachineInstr &I2,98unsigned I1DestReg, unsigned I2DestReg,99bool &DoInsertAtI1);100101void emitCombineRR(MachineBasicBlock::iterator &Before, unsigned DestReg,102MachineOperand &HiOperand, MachineOperand &LoOperand);103104void emitCombineRI(MachineBasicBlock::iterator &Before, unsigned DestReg,105MachineOperand &HiOperand, MachineOperand &LoOperand);106107void emitCombineIR(MachineBasicBlock::iterator &Before, unsigned DestReg,108MachineOperand &HiOperand, MachineOperand &LoOperand);109110void emitCombineII(MachineBasicBlock::iterator &Before, unsigned DestReg,111MachineOperand &HiOperand, MachineOperand &LoOperand);112113void emitConst64(MachineBasicBlock::iterator &Before, unsigned DestReg,114MachineOperand &HiOperand, MachineOperand &LoOperand);115};116117} // End anonymous namespace.118119char HexagonCopyToCombine::ID = 0;120121INITIALIZE_PASS(HexagonCopyToCombine, "hexagon-copy-combine",122"Hexagon Copy-To-Combine Pass", false, false)123124static bool isCombinableInstType(MachineInstr &MI, const HexagonInstrInfo *TII,125bool ShouldCombineAggressively) {126switch (MI.getOpcode()) {127case Hexagon::A2_tfr: {128// A COPY instruction can be combined if its arguments are IntRegs (32bit).129const MachineOperand &Op0 = MI.getOperand(0);130const MachineOperand &Op1 = MI.getOperand(1);131assert(Op0.isReg() && Op1.isReg());132133Register DestReg = Op0.getReg();134Register SrcReg = Op1.getReg();135return Hexagon::IntRegsRegClass.contains(DestReg) &&136Hexagon::IntRegsRegClass.contains(SrcReg);137}138139case Hexagon::A2_tfrsi: {140// A transfer-immediate can be combined if its argument is a signed 8bit141// value.142const MachineOperand &Op0 = MI.getOperand(0);143const MachineOperand &Op1 = MI.getOperand(1);144assert(Op0.isReg());145146Register DestReg = Op0.getReg();147// Ensure that TargetFlags are MO_NO_FLAG for a global. This is a148// workaround for an ABI bug that prevents GOT relocations on combine149// instructions150if (!Op1.isImm() && Op1.getTargetFlags() != HexagonII::MO_NO_FLAG)151return false;152153// Only combine constant extended A2_tfrsi if we are in aggressive mode.154bool NotExt = Op1.isImm() && isInt<8>(Op1.getImm());155return Hexagon::IntRegsRegClass.contains(DestReg) &&156(ShouldCombineAggressively || NotExt);157}158159case Hexagon::V6_vassign:160return true;161162default:163break;164}165166return false;167}168169template <unsigned N> static bool isGreaterThanNBitTFRI(const MachineInstr &I) {170if (I.getOpcode() == Hexagon::TFRI64_V4 ||171I.getOpcode() == Hexagon::A2_tfrsi) {172const MachineOperand &Op = I.getOperand(1);173return !Op.isImm() || !isInt<N>(Op.getImm());174}175return false;176}177178/// areCombinableOperations - Returns true if the two instruction can be merge179/// into a combine (ignoring register constraints).180static bool areCombinableOperations(const TargetRegisterInfo *TRI,181MachineInstr &HighRegInst,182MachineInstr &LowRegInst, bool AllowC64) {183unsigned HiOpc = HighRegInst.getOpcode();184unsigned LoOpc = LowRegInst.getOpcode();185186auto verifyOpc = [](unsigned Opc) -> void {187switch (Opc) {188case Hexagon::A2_tfr:189case Hexagon::A2_tfrsi:190case Hexagon::V6_vassign:191break;192default:193llvm_unreachable("Unexpected opcode");194}195};196verifyOpc(HiOpc);197verifyOpc(LoOpc);198199if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)200return HiOpc == LoOpc;201202if (!AllowC64) {203// There is no combine of two constant extended values.204if (isGreaterThanNBitTFRI<8>(HighRegInst) &&205isGreaterThanNBitTFRI<6>(LowRegInst))206return false;207}208209// There is a combine of two constant extended values into CONST64,210// provided both constants are true immediates.211if (isGreaterThanNBitTFRI<16>(HighRegInst) &&212isGreaterThanNBitTFRI<16>(LowRegInst) && !IsConst64Disabled)213return (HighRegInst.getOperand(1).isImm() &&214LowRegInst.getOperand(1).isImm());215216// There is no combine of two constant extended values, unless handled above217// Make both 8-bit size checks to allow both combine (#,##) and combine(##,#)218if (isGreaterThanNBitTFRI<8>(HighRegInst) &&219isGreaterThanNBitTFRI<8>(LowRegInst))220return false;221222return true;223}224225static bool isEvenReg(unsigned Reg) {226assert(Register::isPhysicalRegister(Reg));227if (Hexagon::IntRegsRegClass.contains(Reg))228return (Reg - Hexagon::R0) % 2 == 0;229if (Hexagon::HvxVRRegClass.contains(Reg))230return (Reg - Hexagon::V0) % 2 == 0;231llvm_unreachable("Invalid register");232}233234static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled) {235for (MachineOperand &Op : MI.operands())236if (Op.isReg() && Op.getReg() == RegNotKilled && Op.isKill())237Op.setIsKill(false);238}239240/// Returns true if it is unsafe to move a copy instruction from \p UseReg to241/// \p DestReg over the instruction \p MI.242static bool isUnsafeToMoveAcross(MachineInstr &MI, unsigned UseReg,243unsigned DestReg,244const TargetRegisterInfo *TRI) {245return (UseReg && (MI.modifiesRegister(UseReg, TRI))) ||246MI.modifiesRegister(DestReg, TRI) || MI.readsRegister(DestReg, TRI) ||247MI.hasUnmodeledSideEffects() || MI.isInlineAsm() ||248MI.isMetaInstruction();249}250251static Register UseReg(const MachineOperand& MO) {252return MO.isReg() ? MO.getReg() : Register();253}254255/// isSafeToMoveTogether - Returns true if it is safe to move I1 next to I2 such256/// that the two instructions can be paired in a combine.257bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1,258MachineInstr &I2,259unsigned I1DestReg,260unsigned I2DestReg,261bool &DoInsertAtI1) {262Register I2UseReg = UseReg(I2.getOperand(1));263264// It is not safe to move I1 and I2 into one combine if I2 has a true265// dependence on I1.266if (I2UseReg && I1.modifiesRegister(I2UseReg, TRI))267return false;268269bool isSafe = true;270271// First try to move I2 towards I1.272{273// A reverse_iterator instantiated like below starts before I2, and I1274// respectively.275// Look at instructions I in between I2 and (excluding) I1.276MachineBasicBlock::reverse_iterator I = ++I2.getIterator().getReverse();277MachineBasicBlock::reverse_iterator End = I1.getIterator().getReverse();278// At 03 we got better results (dhrystone!) by being more conservative.279if (!ShouldCombineAggressively)280End = ++I1.getIterator().getReverse();281// If I2 kills its operand and we move I2 over an instruction that also282// uses I2's use reg we need to modify that (first) instruction to now kill283// this reg.284unsigned KilledOperand = 0;285if (I2.killsRegister(I2UseReg, /*TRI=*/nullptr))286KilledOperand = I2UseReg;287MachineInstr *KillingInstr = nullptr;288289for (; I != End; ++I) {290// If the intervening instruction I:291// * modifies I2's use reg292// * modifies I2's def reg293// * reads I2's def reg294// * or has unmodelled side effects295// we can't move I2 across it.296if (I->isDebugInstr())297continue;298299if (isUnsafeToMoveAcross(*I, I2UseReg, I2DestReg, TRI)) {300isSafe = false;301break;302}303304// Update first use of the killed operand.305if (!KillingInstr && KilledOperand &&306I->readsRegister(KilledOperand, TRI))307KillingInstr = &*I;308}309if (isSafe) {310// Update the intermediate instruction to with the kill flag.311if (KillingInstr) {312bool Added = KillingInstr->addRegisterKilled(KilledOperand, TRI, true);313(void)Added; // suppress compiler warning314assert(Added && "Must successfully update kill flag");315removeKillInfo(I2, KilledOperand);316}317DoInsertAtI1 = true;318return true;319}320}321322// Try to move I1 towards I2.323{324// Look at instructions I in between I1 and (excluding) I2.325MachineBasicBlock::iterator I(I1), End(I2);326// At O3 we got better results (dhrystone) by being more conservative here.327if (!ShouldCombineAggressively)328End = std::next(MachineBasicBlock::iterator(I2));329Register I1UseReg = UseReg(I1.getOperand(1));330// Track killed operands. If we move across an instruction that kills our331// operand, we need to update the kill information on the moved I1. It kills332// the operand now.333MachineInstr *KillingInstr = nullptr;334unsigned KilledOperand = 0;335336while(++I != End) {337MachineInstr &MI = *I;338// If the intervening instruction MI:339// * modifies I1's use reg340// * modifies I1's def reg341// * reads I1's def reg342// * or has unmodelled side effects343// We introduce this special case because llvm has no api to remove a344// kill flag for a register (a removeRegisterKilled() analogous to345// addRegisterKilled) that handles aliased register correctly.346// * or has a killed aliased register use of I1's use reg347// %d4 = A2_tfrpi 16348// %r6 = A2_tfr %r9349// %r8 = KILL %r8, implicit killed %d4350// If we want to move R6 = across the KILL instruction we would have351// to remove the implicit killed %d4 operand. For now, we are352// conservative and disallow the move.353// we can't move I1 across it.354if (MI.isDebugInstr()) {355if (MI.readsRegister(I1DestReg, TRI)) // Move this instruction after I2.356DbgMItoMove.push_back(&MI);357continue;358}359360if (isUnsafeToMoveAcross(MI, I1UseReg, I1DestReg, TRI) ||361// Check for an aliased register kill. Bail out if we see one.362(!MI.killsRegister(I1UseReg, /*TRI=*/nullptr) &&363MI.killsRegister(I1UseReg, TRI)))364return false;365366// Check for an exact kill (registers match).367if (I1UseReg && MI.killsRegister(I1UseReg, /*TRI=*/nullptr)) {368assert(!KillingInstr && "Should only see one killing instruction");369KilledOperand = I1UseReg;370KillingInstr = &MI;371}372}373if (KillingInstr) {374removeKillInfo(*KillingInstr, KilledOperand);375// Update I1 to set the kill flag. This flag will later be picked up by376// the new COMBINE instruction.377bool Added = I1.addRegisterKilled(KilledOperand, TRI);378(void)Added; // suppress compiler warning379assert(Added && "Must successfully update kill flag");380}381DoInsertAtI1 = false;382}383384return true;385}386387/// findPotentialNewifiableTFRs - Finds tranfers that feed stores that could be388/// newified. (A use of a 64 bit register define can not be newified)389void390HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {391DenseMap<unsigned, MachineInstr *> LastDef;392for (MachineInstr &MI : BB) {393if (MI.isDebugInstr())394continue;395396// Mark TFRs that feed a potential new value store as such.397if (TII->mayBeNewStore(MI)) {398// Look for uses of TFR instructions.399for (const MachineOperand &Op : MI.operands()) {400// Skip over anything except register uses.401if (!Op.isReg() || !Op.isUse() || !Op.getReg())402continue;403404// Look for the defining instruction.405Register Reg = Op.getReg();406MachineInstr *DefInst = LastDef[Reg];407if (!DefInst)408continue;409if (!isCombinableInstType(*DefInst, TII, ShouldCombineAggressively))410continue;411412// Only close newifiable stores should influence the decision.413// Ignore the debug instructions in between.414MachineBasicBlock::iterator It(DefInst);415unsigned NumInstsToDef = 0;416while (&*It != &MI) {417if (!It->isDebugInstr())418++NumInstsToDef;419++It;420}421422if (NumInstsToDef > MaxNumOfInstsBetweenNewValueStoreAndTFR)423continue;424425PotentiallyNewifiableTFR.insert(DefInst);426}427// Skip to next instruction.428continue;429}430431// Put instructions that last defined integer or double registers into the432// map.433for (MachineOperand &Op : MI.operands()) {434if (Op.isReg()) {435if (!Op.isDef() || !Op.getReg())436continue;437Register Reg = Op.getReg();438if (Hexagon::DoubleRegsRegClass.contains(Reg)) {439for (MCPhysReg SubReg : TRI->subregs(Reg))440LastDef[SubReg] = &MI;441} else if (Hexagon::IntRegsRegClass.contains(Reg))442LastDef[Reg] = &MI;443} else if (Op.isRegMask()) {444for (unsigned Reg : Hexagon::IntRegsRegClass)445if (Op.clobbersPhysReg(Reg))446LastDef[Reg] = &MI;447}448}449}450}451452bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) {453if (skipFunction(MF.getFunction()))454return false;455456if (IsCombinesDisabled) return false;457458bool HasChanged = false;459460// Get target info.461ST = &MF.getSubtarget<HexagonSubtarget>();462TRI = ST->getRegisterInfo();463TII = ST->getInstrInfo();464465const Function &F = MF.getFunction();466bool OptForSize = F.hasFnAttribute(Attribute::OptimizeForSize);467468// Combine aggressively (for code size)469ShouldCombineAggressively =470MF.getTarget().getOptLevel() <= CodeGenOptLevel::Default;471472// Disable CONST64 for tiny core since it takes a LD resource.473if (!OptForSize && ST->isTinyCore())474IsConst64Disabled = true;475476// Traverse basic blocks.477for (MachineBasicBlock &MBB : MF) {478PotentiallyNewifiableTFR.clear();479findPotentialNewifiableTFRs(MBB);480481// Traverse instructions in basic block.482for (MachineBasicBlock::iterator MI = MBB.begin(), End = MBB.end();483MI != End;) {484MachineInstr &I1 = *MI++;485486if (I1.isDebugInstr())487continue;488489// Don't combine a TFR whose user could be newified (instructions that490// define double registers can not be newified - Programmer's Ref Manual491// 5.4.2 New-value stores).492if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&I1))493continue;494495// Ignore instructions that are not combinable.496if (!isCombinableInstType(I1, TII, ShouldCombineAggressively))497continue;498499// Find a second instruction that can be merged into a combine500// instruction. In addition, also find all the debug instructions that501// need to be moved along with it.502bool DoInsertAtI1 = false;503DbgMItoMove.clear();504MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);505if (I2) {506HasChanged = true;507combine(I1, *I2, MI, DoInsertAtI1, OptForSize);508}509}510}511512return HasChanged;513}514515/// findPairable - Returns an instruction that can be merged with \p I1 into a516/// COMBINE instruction or 0 if no such instruction can be found. Returns true517/// in \p DoInsertAtI1 if the combine must be inserted at instruction \p I1518/// false if the combine must be inserted at the returned instruction.519MachineInstr *HexagonCopyToCombine::findPairable(MachineInstr &I1,520bool &DoInsertAtI1,521bool AllowC64) {522MachineBasicBlock::iterator I2 = std::next(MachineBasicBlock::iterator(I1));523while (I2 != I1.getParent()->end() && I2->isDebugInstr())524++I2;525526Register I1DestReg = I1.getOperand(0).getReg();527528for (MachineBasicBlock::iterator End = I1.getParent()->end(); I2 != End;529++I2) {530// Bail out early if we see a second definition of I1DestReg.531if (I2->modifiesRegister(I1DestReg, TRI))532break;533534// Ignore non-combinable instructions.535if (!isCombinableInstType(*I2, TII, ShouldCombineAggressively))536continue;537538// Don't combine a TFR whose user could be newified.539if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&*I2))540continue;541542Register I2DestReg = I2->getOperand(0).getReg();543544// Check that registers are adjacent and that the first destination register545// is even.546bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;547bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;548unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;549if ((!IsI1LowReg && !IsI2LowReg) || !isEvenReg(FirstRegIndex))550continue;551552// Check that the two instructions are combinable.553// The order matters because in a A2_tfrsi we might can encode a int8 as554// the hi reg operand but only a uint6 as the low reg operand.555if ((IsI2LowReg && !areCombinableOperations(TRI, I1, *I2, AllowC64)) ||556(IsI1LowReg && !areCombinableOperations(TRI, *I2, I1, AllowC64)))557break;558559if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))560return &*I2;561562// Not safe. Stop searching.563break;564}565return nullptr;566}567568void HexagonCopyToCombine::combine(MachineInstr &I1, MachineInstr &I2,569MachineBasicBlock::iterator &MI,570bool DoInsertAtI1, bool OptForSize) {571// We are going to delete I2. If MI points to I2 advance it to the next572// instruction.573if (MI == I2.getIterator())574++MI;575576// Figure out whether I1 or I2 goes into the lowreg part.577Register I1DestReg = I1.getOperand(0).getReg();578Register I2DestReg = I2.getOperand(0).getReg();579bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;580unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;581unsigned SubLo;582583const TargetRegisterClass *SuperRC = nullptr;584if (Hexagon::IntRegsRegClass.contains(LoRegDef)) {585SuperRC = &Hexagon::DoubleRegsRegClass;586SubLo = Hexagon::isub_lo;587} else if (Hexagon::HvxVRRegClass.contains(LoRegDef)) {588assert(ST->useHVXOps());589SuperRC = &Hexagon::HvxWRRegClass;590SubLo = Hexagon::vsub_lo;591} else592llvm_unreachable("Unexpected register class");593594// Get the double word register.595unsigned DoubleRegDest = TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);596assert(DoubleRegDest != 0 && "Expect a valid register");597598// Setup source operands.599MachineOperand &LoOperand = IsI1Loreg ? I1.getOperand(1) : I2.getOperand(1);600MachineOperand &HiOperand = IsI1Loreg ? I2.getOperand(1) : I1.getOperand(1);601602// Figure out which source is a register and which a constant.603bool IsHiReg = HiOperand.isReg();604bool IsLoReg = LoOperand.isReg();605606// There is a combine of two constant extended values into CONST64.607bool IsC64 = OptForSize && LoOperand.isImm() && HiOperand.isImm() &&608isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);609610MachineBasicBlock::iterator InsertPt(DoInsertAtI1 ? I1 : I2);611// Emit combine.612if (IsHiReg && IsLoReg)613emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);614else if (IsHiReg)615emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);616else if (IsLoReg)617emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);618else if (IsC64 && !IsConst64Disabled)619emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);620else621emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);622623// Move debug instructions along with I1 if it's being624// moved towards I2.625if (!DoInsertAtI1 && DbgMItoMove.size() != 0) {626// Insert debug instructions at the new location before I2.627MachineBasicBlock *BB = InsertPt->getParent();628for (auto *NewMI : DbgMItoMove) {629// If iterator MI is pointing to DEBUG_VAL, make sure630// MI now points to next relevant instruction.631if (NewMI == MI)632++MI;633BB->splice(InsertPt, BB, NewMI);634}635}636637I1.eraseFromParent();638I2.eraseFromParent();639}640641void HexagonCopyToCombine::emitConst64(MachineBasicBlock::iterator &InsertPt,642unsigned DoubleDestReg,643MachineOperand &HiOperand,644MachineOperand &LoOperand) {645LLVM_DEBUG(dbgs() << "Found a CONST64\n");646647DebugLoc DL = InsertPt->getDebugLoc();648MachineBasicBlock *BB = InsertPt->getParent();649assert(LoOperand.isImm() && HiOperand.isImm() &&650"Both operands must be immediate");651652int64_t V = HiOperand.getImm();653V = (V << 32) | (0x0ffffffffLL & LoOperand.getImm());654BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::CONST64), DoubleDestReg)655.addImm(V);656}657658void HexagonCopyToCombine::emitCombineII(MachineBasicBlock::iterator &InsertPt,659unsigned DoubleDestReg,660MachineOperand &HiOperand,661MachineOperand &LoOperand) {662DebugLoc DL = InsertPt->getDebugLoc();663MachineBasicBlock *BB = InsertPt->getParent();664665// Handle globals.666if (HiOperand.isGlobal()) {667BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)668.addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(),669HiOperand.getTargetFlags())670.addImm(LoOperand.getImm());671return;672}673if (LoOperand.isGlobal()) {674BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)675.addImm(HiOperand.getImm())676.addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(),677LoOperand.getTargetFlags());678return;679}680681// Handle block addresses.682if (HiOperand.isBlockAddress()) {683BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)684.addBlockAddress(HiOperand.getBlockAddress(), HiOperand.getOffset(),685HiOperand.getTargetFlags())686.addImm(LoOperand.getImm());687return;688}689if (LoOperand.isBlockAddress()) {690BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)691.addImm(HiOperand.getImm())692.addBlockAddress(LoOperand.getBlockAddress(), LoOperand.getOffset(),693LoOperand.getTargetFlags());694return;695}696697// Handle jump tables.698if (HiOperand.isJTI()) {699BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)700.addJumpTableIndex(HiOperand.getIndex(), HiOperand.getTargetFlags())701.addImm(LoOperand.getImm());702return;703}704if (LoOperand.isJTI()) {705BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)706.addImm(HiOperand.getImm())707.addJumpTableIndex(LoOperand.getIndex(), LoOperand.getTargetFlags());708return;709}710711// Handle constant pools.712if (HiOperand.isCPI()) {713BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)714.addConstantPoolIndex(HiOperand.getIndex(), HiOperand.getOffset(),715HiOperand.getTargetFlags())716.addImm(LoOperand.getImm());717return;718}719if (LoOperand.isCPI()) {720BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)721.addImm(HiOperand.getImm())722.addConstantPoolIndex(LoOperand.getIndex(), LoOperand.getOffset(),723LoOperand.getTargetFlags());724return;725}726727// First preference should be given to Hexagon::A2_combineii instruction728// as it can include U6 (in Hexagon::A4_combineii) as well.729// In this instruction, HiOperand is const extended, if required.730if (isInt<8>(LoOperand.getImm())) {731BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)732.addImm(HiOperand.getImm())733.addImm(LoOperand.getImm());734return;735}736737// In this instruction, LoOperand is const extended, if required.738if (isInt<8>(HiOperand.getImm())) {739BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)740.addImm(HiOperand.getImm())741.addImm(LoOperand.getImm());742return;743}744745// Insert new combine instruction.746// DoubleRegDest = combine #HiImm, #LoImm747BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)748.addImm(HiOperand.getImm())749.addImm(LoOperand.getImm());750}751752void HexagonCopyToCombine::emitCombineIR(MachineBasicBlock::iterator &InsertPt,753unsigned DoubleDestReg,754MachineOperand &HiOperand,755MachineOperand &LoOperand) {756Register LoReg = LoOperand.getReg();757unsigned LoRegKillFlag = getKillRegState(LoOperand.isKill());758759DebugLoc DL = InsertPt->getDebugLoc();760MachineBasicBlock *BB = InsertPt->getParent();761762// Handle globals.763if (HiOperand.isGlobal()) {764BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)765.addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(),766HiOperand.getTargetFlags())767.addReg(LoReg, LoRegKillFlag);768return;769}770// Handle block addresses.771if (HiOperand.isBlockAddress()) {772BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)773.addBlockAddress(HiOperand.getBlockAddress(), HiOperand.getOffset(),774HiOperand.getTargetFlags())775.addReg(LoReg, LoRegKillFlag);776return;777}778// Handle jump tables.779if (HiOperand.isJTI()) {780BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)781.addJumpTableIndex(HiOperand.getIndex(), HiOperand.getTargetFlags())782.addReg(LoReg, LoRegKillFlag);783return;784}785// Handle constant pools.786if (HiOperand.isCPI()) {787BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)788.addConstantPoolIndex(HiOperand.getIndex(), HiOperand.getOffset(),789HiOperand.getTargetFlags())790.addReg(LoReg, LoRegKillFlag);791return;792}793// Insert new combine instruction.794// DoubleRegDest = combine #HiImm, LoReg795BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)796.addImm(HiOperand.getImm())797.addReg(LoReg, LoRegKillFlag);798}799800void HexagonCopyToCombine::emitCombineRI(MachineBasicBlock::iterator &InsertPt,801unsigned DoubleDestReg,802MachineOperand &HiOperand,803MachineOperand &LoOperand) {804unsigned HiRegKillFlag = getKillRegState(HiOperand.isKill());805Register HiReg = HiOperand.getReg();806807DebugLoc DL = InsertPt->getDebugLoc();808MachineBasicBlock *BB = InsertPt->getParent();809810// Handle global.811if (LoOperand.isGlobal()) {812BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)813.addReg(HiReg, HiRegKillFlag)814.addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(),815LoOperand.getTargetFlags());816return;817}818// Handle block addresses.819if (LoOperand.isBlockAddress()) {820BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)821.addReg(HiReg, HiRegKillFlag)822.addBlockAddress(LoOperand.getBlockAddress(), LoOperand.getOffset(),823LoOperand.getTargetFlags());824return;825}826// Handle jump tables.827if (LoOperand.isJTI()) {828BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)829.addReg(HiOperand.getReg(), HiRegKillFlag)830.addJumpTableIndex(LoOperand.getIndex(), LoOperand.getTargetFlags());831return;832}833// Handle constant pools.834if (LoOperand.isCPI()) {835BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)836.addReg(HiOperand.getReg(), HiRegKillFlag)837.addConstantPoolIndex(LoOperand.getIndex(), LoOperand.getOffset(),838LoOperand.getTargetFlags());839return;840}841842// Insert new combine instruction.843// DoubleRegDest = combine HiReg, #LoImm844BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)845.addReg(HiReg, HiRegKillFlag)846.addImm(LoOperand.getImm());847}848849void HexagonCopyToCombine::emitCombineRR(MachineBasicBlock::iterator &InsertPt,850unsigned DoubleDestReg,851MachineOperand &HiOperand,852MachineOperand &LoOperand) {853unsigned LoRegKillFlag = getKillRegState(LoOperand.isKill());854unsigned HiRegKillFlag = getKillRegState(HiOperand.isKill());855Register LoReg = LoOperand.getReg();856Register HiReg = HiOperand.getReg();857858DebugLoc DL = InsertPt->getDebugLoc();859MachineBasicBlock *BB = InsertPt->getParent();860861// Insert new combine instruction.862// DoubleRegDest = combine HiReg, LoReg863unsigned NewOpc;864if (Hexagon::DoubleRegsRegClass.contains(DoubleDestReg)) {865NewOpc = Hexagon::A2_combinew;866} else if (Hexagon::HvxWRRegClass.contains(DoubleDestReg)) {867assert(ST->useHVXOps());868NewOpc = Hexagon::V6_vcombine;869} else870llvm_unreachable("Unexpected register");871872BuildMI(*BB, InsertPt, DL, TII->get(NewOpc), DoubleDestReg)873.addReg(HiReg, HiRegKillFlag)874.addReg(LoReg, LoRegKillFlag);875}876877FunctionPass *llvm::createHexagonCopyToCombine() {878return new HexagonCopyToCombine();879}880881882