diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -103,6 +103,12 @@ /// Returns whether the instruction is a pre-indexed load/store. static bool isPreLdSt(const MachineInstr &MI); + /// Returns whether the instruction is FP or NEON. + static bool isFpOrNEON(const MachineInstr &MI); + + /// Returns whether the instruction is in Q form (128 bit operands) + static bool isQForm(const MachineInstr &MI); + /// Returns the index for the immediate for a given instruction. static unsigned getLoadStoreImmIdx(unsigned Opc); diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -3116,6 +3116,43 @@ return isPreLd(MI) || isPreSt(MI); } +static const TargetRegisterClass *getRegClass(const MachineInstr &MI, + Register Reg) { + if (MI.getParent() == nullptr) + return nullptr; + const MachineFunction *MF = MI.getParent()->getParent(); + return MF ? MF->getRegInfo().getRegClassOrNull(Reg) : nullptr; +} + +bool AArch64InstrInfo::isQForm(const MachineInstr &MI) { + if (!MI.getOperand(0).isReg()) + return false; + auto Reg = MI.getOperand(0).getReg(); + if (Reg.isPhysical()) + return AArch64::FPR128RegClass.contains(Reg); + + const TargetRegisterClass *TRC = ::getRegClass(MI, Reg); + return TRC == &AArch64::FPR128RegClass || TRC == &AArch64::FPR128_loRegClass; +} + +bool AArch64InstrInfo::isFpOrNEON(const MachineInstr &MI) { + if (!MI.getOperand(0).isReg()) + return false; + auto Reg = MI.getOperand(0).getReg(); + if (Reg.isPhysical()) + return AArch64::FPR128RegClass.contains(Reg) || + AArch64::FPR64RegClass.contains(Reg) || + AArch64::FPR32RegClass.contains(Reg) || + AArch64::FPR16RegClass.contains(Reg) || + AArch64::FPR8RegClass.contains(Reg); + + const TargetRegisterClass *TRC = ::getRegClass(MI, Reg); + return TRC == &AArch64::FPR128RegClass || + TRC == &AArch64::FPR128_loRegClass || TRC == &AArch64::FPR64RegClass || + TRC == &AArch64::FPR64_loRegClass || TRC == &AArch64::FPR32RegClass || + TRC == &AArch64::FPR16RegClass || TRC == &AArch64::FPR8RegClass; +} + // Scale the unscaled offsets. Returns false if the unscaled offset can't be // scaled. static bool scaleOffset(unsigned Opc, int64_t &Offset) { diff --git a/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td b/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td --- a/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td +++ b/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td @@ -109,10 +109,7 @@ def ExynosScaledIdxPred : MCSchedPredicate; // Identify FP instructions. -def ExynosFPPred : MCSchedPredicate>; +def ExynosFPPred : MCSchedPredicate; // Identify 128-bit NEON instructions. def ExynosQFormPred : MCSchedPredicate; diff --git a/llvm/lib/Target/AArch64/AArch64SchedPredicates.td b/llvm/lib/Target/AArch64/AArch64SchedPredicates.td --- a/llvm/lib/Target/AArch64/AArch64SchedPredicates.td +++ b/llvm/lib/Target/AArch64/AArch64SchedPredicates.td @@ -59,146 +59,17 @@ } // Generic predicates. - -// Identify whether an instruction is the 16-bit NEON form based on its result. -def CheckHForm : CheckAll<[CheckIsRegOperand<0>, - CheckAny<[CheckRegOperand<0, H0>, - CheckRegOperand<0, H1>, - CheckRegOperand<0, H2>, - CheckRegOperand<0, H3>, - CheckRegOperand<0, H4>, - CheckRegOperand<0, H5>, - CheckRegOperand<0, H6>, - CheckRegOperand<0, H7>, - CheckRegOperand<0, H8>, - CheckRegOperand<0, H9>, - CheckRegOperand<0, H10>, - CheckRegOperand<0, H11>, - CheckRegOperand<0, H12>, - CheckRegOperand<0, H13>, - CheckRegOperand<0, H14>, - CheckRegOperand<0, H15>, - CheckRegOperand<0, H16>, - CheckRegOperand<0, H17>, - CheckRegOperand<0, H18>, - CheckRegOperand<0, H19>, - CheckRegOperand<0, H20>, - CheckRegOperand<0, H21>, - CheckRegOperand<0, H22>, - CheckRegOperand<0, H23>, - CheckRegOperand<0, H24>, - CheckRegOperand<0, H25>, - CheckRegOperand<0, H26>, - CheckRegOperand<0, H27>, - CheckRegOperand<0, H28>, - CheckRegOperand<0, H29>, - CheckRegOperand<0, H30>, - CheckRegOperand<0, H31>]>]>; - -// Identify whether an instruction is the 32-bit NEON form based on its result. -def CheckSForm : CheckAll<[CheckIsRegOperand<0>, - CheckAny<[CheckRegOperand<0, S0>, - CheckRegOperand<0, S1>, - CheckRegOperand<0, S2>, - CheckRegOperand<0, S3>, - CheckRegOperand<0, S4>, - CheckRegOperand<0, S5>, - CheckRegOperand<0, S6>, - CheckRegOperand<0, S7>, - CheckRegOperand<0, S8>, - CheckRegOperand<0, S9>, - CheckRegOperand<0, S10>, - CheckRegOperand<0, S11>, - CheckRegOperand<0, S12>, - CheckRegOperand<0, S13>, - CheckRegOperand<0, S14>, - CheckRegOperand<0, S15>, - CheckRegOperand<0, S16>, - CheckRegOperand<0, S17>, - CheckRegOperand<0, S18>, - CheckRegOperand<0, S19>, - CheckRegOperand<0, S20>, - CheckRegOperand<0, S21>, - CheckRegOperand<0, S22>, - CheckRegOperand<0, S23>, - CheckRegOperand<0, S24>, - CheckRegOperand<0, S25>, - CheckRegOperand<0, S26>, - CheckRegOperand<0, S27>, - CheckRegOperand<0, S28>, - CheckRegOperand<0, S29>, - CheckRegOperand<0, S30>, - CheckRegOperand<0, S31>]>]>; - -// Identify whether an instruction is the 64-bit NEON form based on its result. -def CheckDForm : CheckAll<[CheckIsRegOperand<0>, - CheckAny<[CheckRegOperand<0, D0>, - CheckRegOperand<0, D1>, - CheckRegOperand<0, D2>, - CheckRegOperand<0, D3>, - CheckRegOperand<0, D4>, - CheckRegOperand<0, D5>, - CheckRegOperand<0, D6>, - CheckRegOperand<0, D7>, - CheckRegOperand<0, D8>, - CheckRegOperand<0, D9>, - CheckRegOperand<0, D10>, - CheckRegOperand<0, D11>, - CheckRegOperand<0, D12>, - CheckRegOperand<0, D13>, - CheckRegOperand<0, D14>, - CheckRegOperand<0, D15>, - CheckRegOperand<0, D16>, - CheckRegOperand<0, D17>, - CheckRegOperand<0, D18>, - CheckRegOperand<0, D19>, - CheckRegOperand<0, D20>, - CheckRegOperand<0, D21>, - CheckRegOperand<0, D22>, - CheckRegOperand<0, D23>, - CheckRegOperand<0, D24>, - CheckRegOperand<0, D25>, - CheckRegOperand<0, D26>, - CheckRegOperand<0, D27>, - CheckRegOperand<0, D28>, - CheckRegOperand<0, D29>, - CheckRegOperand<0, D30>, - CheckRegOperand<0, D31>]>]>; +// Identify whether an instruction is NEON or floating point +def CheckFpOrNEON : CheckFunctionPredicateWithTII< + "AArch64_MC::isFpOrNEON", + "AArch64InstrInfo::isFpOrNEON" +>; // Identify whether an instruction is the 128-bit NEON form based on its result. -def CheckQForm : CheckAll<[CheckIsRegOperand<0>, - CheckAny<[CheckRegOperand<0, Q0>, - CheckRegOperand<0, Q1>, - CheckRegOperand<0, Q2>, - CheckRegOperand<0, Q3>, - CheckRegOperand<0, Q4>, - CheckRegOperand<0, Q5>, - CheckRegOperand<0, Q6>, - CheckRegOperand<0, Q7>, - CheckRegOperand<0, Q8>, - CheckRegOperand<0, Q9>, - CheckRegOperand<0, Q10>, - CheckRegOperand<0, Q11>, - CheckRegOperand<0, Q12>, - CheckRegOperand<0, Q13>, - CheckRegOperand<0, Q14>, - CheckRegOperand<0, Q15>, - CheckRegOperand<0, Q16>, - CheckRegOperand<0, Q17>, - CheckRegOperand<0, Q18>, - CheckRegOperand<0, Q19>, - CheckRegOperand<0, Q20>, - CheckRegOperand<0, Q21>, - CheckRegOperand<0, Q22>, - CheckRegOperand<0, Q23>, - CheckRegOperand<0, Q24>, - CheckRegOperand<0, Q25>, - CheckRegOperand<0, Q26>, - CheckRegOperand<0, Q27>, - CheckRegOperand<0, Q28>, - CheckRegOperand<0, Q29>, - CheckRegOperand<0, Q30>, - CheckRegOperand<0, Q31>]>]>; +def CheckQForm : CheckFunctionPredicateWithTII< + "AArch64_MC::isQForm", + "AArch64InstrInfo::isQForm" +>; // Identify arithmetic instructions with extend. def IsArithExtOp : CheckOpcode<[ADDWrx, ADDXrx, ADDSWrx, ADDSXrx, diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h @@ -22,6 +22,7 @@ class MCAsmBackend; class MCCodeEmitter; class MCContext; +class MCInst; class MCInstrInfo; class MCInstPrinter; class MCRegisterInfo; @@ -60,6 +61,8 @@ namespace AArch64_MC { void initLLVMToCVRegMapping(MCRegisterInfo *MRI); +bool isQForm(const MCInst &MI, const MCInstrInfo *MCII); +bool isFpOrNEON(const MCInst &MI, const MCInstrInfo *MCII); } } // End llvm namespace diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp @@ -243,6 +243,26 @@ MRI->mapLLVMRegToCVReg(I.Reg, static_cast(I.CVReg)); } +bool AArch64_MC::isQForm(const MCInst &MI, const MCInstrInfo *MCII) { + if (!MI.getOperand(0).isReg()) + return false; + const auto &FPR128 = AArch64MCRegisterClasses[AArch64::FPR128RegClassID]; + return FPR128.contains(MI.getOperand(0).getReg()); +} + +bool AArch64_MC::isFpOrNEON(const MCInst &MI, const MCInstrInfo *MCII) { + if (!MI.getOperand(0).isReg()) + return false; + auto Reg = MI.getOperand(0).getReg(); + const auto &FPR128 = AArch64MCRegisterClasses[AArch64::FPR128RegClassID]; + const auto &FPR64 = AArch64MCRegisterClasses[AArch64::FPR64RegClassID]; + const auto &FPR32 = AArch64MCRegisterClasses[AArch64::FPR32RegClassID]; + const auto &FPR16 = AArch64MCRegisterClasses[AArch64::FPR16RegClassID]; + const auto &FPR8 = AArch64MCRegisterClasses[AArch64::FPR8RegClassID]; + return FPR128.contains(Reg) || FPR64.contains(Reg) || FPR32.contains(Reg) || + FPR16.contains(Reg) || FPR8.contains(Reg); +} + static MCRegisterInfo *createAArch64MCRegisterInfo(const Triple &Triple) { MCRegisterInfo *X = new MCRegisterInfo(); InitAArch64MCRegisterInfo(X, AArch64::LR); diff --git a/llvm/test/CodeGen/AArch64/misched-predicate-virtreg.mir b/llvm/test/CodeGen/AArch64/misched-predicate-virtreg.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/misched-predicate-virtreg.mir @@ -0,0 +1,43 @@ +# RUN: llc -mcpu=exynos-m5 -mtriple=aarch64 -enable-misched -run-pass=machine-scheduler -debug-only=machine-scheduler %s -o /dev/null 2>&1 | FileCheck %s + +# CHECK-LABEL: ********** MI Scheduling ********** +# CHECK: SU(0): %0:fpr128 = COPY $q1 +# CHECK-NEXT: # preds left : 0 +# CHECK-NEXT: # succs left : 1 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 2 +# CHECK-NEXT: Depth : 0 +# CHECK-NEXT: Height : 6 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(1): Data Latency=2 Reg=%0 +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(1): %1:fpr128 = COPY %0:fpr128 +# CHECK-NEXT: # preds left : 1 +# CHECK-NEXT: # succs left : 1 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 2 +# CHECK-NEXT: Depth : 2 +# CHECK-NEXT: Height : 4 +# CHECK-NEXT: Predecessors: +# CHECK-NEXT: SU(0): Data Latency=2 Reg=%0 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(2): Data Latency=2 Reg=%1 +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(2): $q0 = COPY %1:fpr128 +# CHECK-NEXT: # preds left : 1 +# CHECK-NEXT: # succs left : 1 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 2 +# CHECK-NEXT: Depth : 4 +# CHECK-NEXT: Height : 2 + +name: copy +tracksRegLiveness: true +body: | + bb.0: + liveins: $q0, $q1 + %1:fpr128 = COPY $q1 + %2:fpr128 = COPY %1 + $q0 = COPY %2 + RET_ReallyLR implicit $q0 +