diff options
Diffstat (limited to 'llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp')
| -rw-r--r-- | llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp | 226 |
1 files changed, 213 insertions, 13 deletions
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp index a85b054a85d7..903ee76fbc8d 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -17,6 +17,7 @@ #include "MCTargetDesc/LoongArchMCTargetDesc.h" #include "MCTargetDesc/LoongArchMatInt.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/StackMaps.h" #include "llvm/MC/MCInstBuilder.h" using namespace llvm; @@ -39,7 +40,9 @@ MCInst LoongArchInstrInfo::getNop() const { void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, - MCRegister SrcReg, bool KillSrc) const { + MCRegister SrcReg, bool KillSrc, + bool RenamableDest, + bool RenamableSrc) const { if (LoongArch::GPRRegClass.contains(DstReg, SrcReg)) { BuildMI(MBB, MBBI, DL, get(LoongArch::OR), DstReg) .addReg(SrcReg, getKillRegState(KillSrc)) @@ -110,7 +113,8 @@ void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB, void LoongArchInstrInfo::storeRegToStackSlot( MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register SrcReg, bool IsKill, int FI, const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, Register VReg) const { + const TargetRegisterInfo *TRI, Register VReg, + MachineInstr::MIFlag Flags) const { MachineFunction *MF = MBB.getParent(); MachineFrameInfo &MFI = MF->getFrameInfo(); @@ -143,14 +147,15 @@ void LoongArchInstrInfo::storeRegToStackSlot( .addMemOperand(MMO); } -void LoongArchInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - Register DstReg, int FI, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - Register VReg) const { +void LoongArchInstrInfo::loadRegFromStackSlot( + MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register DstReg, + int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, + Register VReg, MachineInstr::MIFlag Flags) const { MachineFunction *MF = MBB.getParent(); MachineFrameInfo &MFI = MF->getFrameInfo(); + DebugLoc DL; + if (I != MBB.end()) + DL = I->getDebugLoc(); unsigned Opcode; if (LoongArch::GPRRegClass.hasSubClassEq(RC)) @@ -174,7 +179,7 @@ void LoongArchInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); - BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg) + BuildMI(MBB, I, DL, get(Opcode), DstReg) .addFrameIndex(FI) .addImm(0) .addMemOperand(MMO); @@ -208,6 +213,14 @@ void LoongArchInstrInfo::movImm(MachineBasicBlock &MBB, .addImm(Inst.Imm) .setMIFlag(Flag); break; + case LoongArch::BSTRINS_D: + BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg) + .addReg(SrcReg, RegState::Kill) + .addReg(SrcReg, RegState::Kill) + .addImm(Inst.Imm >> 32) + .addImm(Inst.Imm & 0xFF) + .setMIFlag(Flag); + break; default: assert(false && "Unknown insn emitted by LoongArchMatInt"); } @@ -226,7 +239,25 @@ unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI); } - return MI.getDesc().getSize(); + + unsigned NumBytes = 0; + const MCInstrDesc &Desc = MI.getDesc(); + + // Size should be preferably set in + // llvm/lib/Target/LoongArch/LoongArch*InstrInfo.td (default case). + // Specific cases handle instructions of variable sizes. + switch (Desc.getOpcode()) { + default: + return Desc.getSize(); + case TargetOpcode::STATEPOINT: + NumBytes = StatepointOpers(&MI).getNumPatchBytes(); + assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); + // No patch bytes means a normal call inst (i.e. `bl`) is emitted. + if (NumBytes == 0) + NumBytes = 4; + break; + } + return NumBytes; } bool LoongArchInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const { @@ -347,6 +378,162 @@ bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOp, } } +bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const { + if (TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF)) + return true; + + auto MII = MI.getIterator(); + auto MIE = MBB->end(); + + // According to psABI v2.30: + // + // https://github.com/loongson/la-abi-specs/releases/tag/v2.30 + // + // The following instruction patterns are prohibited from being reordered: + // + // * pcalau12i $a0, %pc_hi20(s) + // addi.d $a1, $zero, %pc_lo12(s) + // lu32i.d $a1, %pc64_lo20(s) + // lu52i.d $a1, $a1, %pc64_hi12(s) + // + // * pcalau12i $a0, %got_pc_hi20(s) | %ld_pc_hi20(s) | %gd_pc_hi20(s) + // addi.d $a1, $zero, %got_pc_lo12(s) + // lu32i.d $a1, %got64_pc_lo20(s) + // lu52i.d $a1, $a1, %got64_pc_hi12(s) + // + // * pcalau12i $a0, %ie_pc_hi20(s) + // addi.d $a1, $zero, %ie_pc_lo12(s) + // lu32i.d $a1, %ie64_pc_lo20(s) + // lu52i.d $a1, $a1, %ie64_pc_hi12(s) + // + // * pcalau12i $a0, %desc_pc_hi20(s) + // addi.d $a1, $zero, %desc_pc_lo12(s) + // lu32i.d $a1, %desc64_pc_lo20(s) + // lu52i.d $a1, $a1, %desc64_pc_hi12(s) + // + // For simplicity, only pcalau12i and lu52i.d are marked as scheduling + // boundaries, and the instructions between them are guaranteed to be + // ordered according to data dependencies. + switch (MI.getOpcode()) { + case LoongArch::PCALAU12I: { + auto AddI = std::next(MII); + if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D) + break; + auto Lu32I = std::next(AddI); + if (Lu32I == MIE || Lu32I->getOpcode() != LoongArch::LU32I_D) + break; + auto MO0 = MI.getOperand(1).getTargetFlags(); + auto MO1 = AddI->getOperand(2).getTargetFlags(); + auto MO2 = Lu32I->getOperand(2).getTargetFlags(); + if (MO0 == LoongArchII::MO_PCREL_HI && MO1 == LoongArchII::MO_PCREL_LO && + MO2 == LoongArchII::MO_PCREL64_LO) + return true; + if ((MO0 == LoongArchII::MO_GOT_PC_HI || MO0 == LoongArchII::MO_LD_PC_HI || + MO0 == LoongArchII::MO_GD_PC_HI) && + MO1 == LoongArchII::MO_GOT_PC_LO && MO2 == LoongArchII::MO_GOT_PC64_LO) + return true; + if (MO0 == LoongArchII::MO_IE_PC_HI && MO1 == LoongArchII::MO_IE_PC_LO && + MO2 == LoongArchII::MO_IE_PC64_LO) + return true; + if (MO0 == LoongArchII::MO_DESC_PC_HI && + MO1 == LoongArchII::MO_DESC_PC_LO && + MO2 == LoongArchII::MO_DESC64_PC_LO) + return true; + break; + } + case LoongArch::LU52I_D: { + auto MO = MI.getOperand(2).getTargetFlags(); + if (MO == LoongArchII::MO_PCREL64_HI || MO == LoongArchII::MO_GOT_PC64_HI || + MO == LoongArchII::MO_IE_PC64_HI || MO == LoongArchII::MO_DESC64_PC_HI) + return true; + break; + } + default: + break; + } + + const auto &STI = MF.getSubtarget<LoongArchSubtarget>(); + if (STI.hasFeature(LoongArch::FeatureRelax)) { + // When linker relaxation enabled, the following instruction patterns are + // prohibited from being reordered: + // + // * pcalau12i $a0, %pc_hi20(s) + // addi.w/d $a0, $a0, %pc_lo12(s) + // + // * pcalau12i $a0, %got_pc_hi20(s) + // ld.w/d $a0, $a0, %got_pc_lo12(s) + // + // * pcalau12i $a0, %ld_pc_hi20(s) | %gd_pc_hi20(s) + // addi.w/d $a0, $a0, %got_pc_lo12(s) + // + // * pcalau12i $a0, %desc_pc_hi20(s) + // addi.w/d $a0, $a0, %desc_pc_lo12(s) + // ld.w/d $ra, $a0, %desc_ld(s) + // jirl $ra, $ra, %desc_call(s) + unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; + unsigned LdOp = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; + switch (MI.getOpcode()) { + case LoongArch::PCALAU12I: { + auto MO0 = LoongArchII::getDirectFlags(MI.getOperand(1)); + auto SecondOp = std::next(MII); + if (MO0 == LoongArchII::MO_DESC_PC_HI) { + if (SecondOp == MIE || SecondOp->getOpcode() != AddiOp) + break; + auto Ld = std::next(SecondOp); + if (Ld == MIE || Ld->getOpcode() != LdOp) + break; + auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2)); + auto MO2 = LoongArchII::getDirectFlags(Ld->getOperand(2)); + if (MO1 == LoongArchII::MO_DESC_PC_LO && MO2 == LoongArchII::MO_DESC_LD) + return true; + break; + } + if (SecondOp == MIE || + (SecondOp->getOpcode() != AddiOp && SecondOp->getOpcode() != LdOp)) + break; + auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2)); + if (MO0 == LoongArchII::MO_PCREL_HI && SecondOp->getOpcode() == AddiOp && + MO1 == LoongArchII::MO_PCREL_LO) + return true; + if (MO0 == LoongArchII::MO_GOT_PC_HI && SecondOp->getOpcode() == LdOp && + MO1 == LoongArchII::MO_GOT_PC_LO) + return true; + if ((MO0 == LoongArchII::MO_LD_PC_HI || + MO0 == LoongArchII::MO_GD_PC_HI) && + SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_GOT_PC_LO) + return true; + break; + } + case LoongArch::ADDI_W: + case LoongArch::ADDI_D: { + auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); + if (MO == LoongArchII::MO_PCREL_LO || MO == LoongArchII::MO_GOT_PC_LO) + return true; + break; + } + case LoongArch::LD_W: + case LoongArch::LD_D: { + auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); + if (MO == LoongArchII::MO_GOT_PC_LO) + return true; + break; + } + case LoongArch::PseudoDESC_CALL: { + auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); + if (MO == LoongArchII::MO_DESC_CALL) + return true; + break; + } + default: + break; + } + } + + return false; +} + unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const { if (BytesRemoved) @@ -519,7 +706,8 @@ bool LoongArchInstrInfo::reverseBranchCondition( std::pair<unsigned, unsigned> LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { - return std::make_pair(TF, 0u); + const unsigned Mask = LoongArchII::MO_DIRECT_FLAG_MASK; + return std::make_pair(TF & Mask, TF & ~Mask); } ArrayRef<std::pair<unsigned, const char *>> @@ -545,14 +733,26 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { {MO_IE_PC_LO, "loongarch-ie-pc-lo"}, {MO_IE_PC64_LO, "loongarch-ie-pc64-lo"}, {MO_IE_PC64_HI, "loongarch-ie-pc64-hi"}, + {MO_LD_PC_HI, "loongarch-ld-pc-hi"}, + {MO_GD_PC_HI, "loongarch-gd-pc-hi"}, + {MO_CALL36, "loongarch-call36"}, {MO_DESC_PC_HI, "loongarch-desc-pc-hi"}, {MO_DESC_PC_LO, "loongarch-desc-pc-lo"}, {MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"}, {MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"}, {MO_DESC_LD, "loongarch-desc-ld"}, {MO_DESC_CALL, "loongarch-desc-call"}, - {MO_LD_PC_HI, "loongarch-ld-pc-hi"}, - {MO_GD_PC_HI, "loongarch-gd-pc-hi"}}; + {MO_LE_HI_R, "loongarch-le-hi-r"}, + {MO_LE_ADD_R, "loongarch-le-add-r"}, + {MO_LE_LO_R, "loongarch-le-lo-r"}}; + return ArrayRef(TargetFlags); +} + +ArrayRef<std::pair<unsigned, const char *>> +LoongArchInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { + using namespace LoongArchII; + static const std::pair<unsigned, const char *> TargetFlags[] = { + {MO_RELAX, "loongarch-relax"}}; return ArrayRef(TargetFlags); } |
