[llvm] f3809b2 - [AArch64][SchedModels] Handle virtual registers in FP/NEON predicates
Pavel Kosov via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 17 02:43:32 PST 2022
Author: Pavel Kosov
Date: 2022-02-17T13:41:05+03:00
New Revision: f3809b20f2d97d0abdcdc5628c7093758aefc530
URL: https://github.com/llvm/llvm-project/commit/f3809b20f2d97d0abdcdc5628c7093758aefc530
DIFF: https://github.com/llvm/llvm-project/commit/f3809b20f2d97d0abdcdc5628c7093758aefc530.diff
LOG: [AArch64][SchedModels] Handle virtual registers in FP/NEON predicates
Current implementation of Check[HSDQ]Form predicates doesn’t handle virtual registers and therefore isn’t useful for pre-RA scheduling. Patch fixes this implementing two function predicates: CheckQForm for checking that instruction writes 128-bit NEON register and CheckFpOrNEON which checks that instruction writes FP register (any width). The latter supersedes Check[HSD]Form predicates which are not used individually.
OS Laboratory. Huawei Russian Research Institute. Saint-Petersburg
Reviewed By: dmgreen
Differential Revision: https://reviews.llvm.org/D114642
Added:
llvm/test/CodeGen/AArch64/misched-predicate-virtreg.mir
Modified:
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.h
llvm/lib/Target/AArch64/AArch64SchedPredExynos.td
llvm/lib/Target/AArch64/AArch64SchedPredicates.td
llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 153b176ad418..b2689e900f62 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -3105,6 +3105,51 @@ bool AArch64InstrInfo::isPreLdSt(const MachineInstr &MI) {
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) {
+ auto IsQFPR = [&](const MachineOperand &Op) {
+ if (!Op.isReg())
+ return false;
+ auto Reg = Op.getReg();
+ if (Reg.isPhysical())
+ return AArch64::FPR128RegClass.contains(Reg);
+ const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
+ return TRC == &AArch64::FPR128RegClass ||
+ TRC == &AArch64::FPR128_loRegClass;
+ };
+ return llvm::any_of(MI.operands(), IsQFPR);
+}
+
+bool AArch64InstrInfo::isFpOrNEON(const MachineInstr &MI) {
+ auto IsFPR = [&](const MachineOperand &Op) {
+ if (!Op.isReg())
+ return false;
+ auto Reg = Op.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;
+ };
+ return llvm::any_of(MI.operands(), IsFPR);
+}
+
// 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/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 75d2eb0169ea..b522230496d2 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -103,6 +103,12 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
/// 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/AArch64SchedPredExynos.td b/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td
index fcda2394bacf..ee7cc1f5095b 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td
@@ -109,10 +109,7 @@ def ExynosScaledIdxFn : TIIPredicate<"isExynosScaledAddr",
def ExynosScaledIdxPred : MCSchedPredicate<ExynosScaledIdxFn>;
// Identify FP instructions.
-def ExynosFPPred : MCSchedPredicate<CheckAny<[CheckHForm,
- CheckSForm,
- CheckDForm,
- CheckQForm]>>;
+def ExynosFPPred : MCSchedPredicate<CheckFpOrNEON>;
// Identify 128-bit NEON instructions.
def ExynosQFormPred : MCSchedPredicate<CheckQForm>;
diff --git a/llvm/lib/Target/AArch64/AArch64SchedPredicates.td b/llvm/lib/Target/AArch64/AArch64SchedPredicates.td
index fc13b23b4cf8..5402b8bf09e5 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedPredicates.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedPredicates.td
@@ -59,146 +59,17 @@ foreach I = {0-3, 8} in {
}
// 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.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
index c1186ae804d2..61ec1de55b9c 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
@@ -243,6 +243,31 @@ void AArch64_MC::initLLVMToCVRegMapping(MCRegisterInfo *MRI) {
MRI->mapLLVMRegToCVReg(I.Reg, static_cast<int>(I.CVReg));
}
+bool AArch64_MC::isQForm(const MCInst &MI, const MCInstrInfo *MCII) {
+ const auto &FPR128 = AArch64MCRegisterClasses[AArch64::FPR128RegClassID];
+ return llvm::any_of(MI, [](const MCOperand &Op) {
+ return Op.isReg() && FPR128.contains(Op.getReg());
+ });
+}
+
+bool AArch64_MC::isFpOrNEON(const MCInst &MI, const MCInstrInfo *MCII) {
+ 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];
+
+ auto IsFPR = [&](const MCOperand &Op) {
+ if (!Op.isReg())
+ return false;
+ auto Reg = Op.getReg();
+ return FPR128.contains(Reg) || FPR64.contains(Reg) || FPR32.contains(Reg) ||
+ FPR16.contains(Reg) || FPR8.contains(Reg);
+ };
+
+ return llvm::any_of(MI, IsFPR);
+}
+
static MCRegisterInfo *createAArch64MCRegisterInfo(const Triple &Triple) {
MCRegisterInfo *X = new MCRegisterInfo();
InitAArch64MCRegisterInfo(X, AArch64::LR);
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h
index 436648b67f8b..ad2dc1027a5e 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h
@@ -22,6 +22,7 @@ class formatted_raw_ostream;
class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
+class MCInst;
class MCInstrInfo;
class MCInstPrinter;
class MCRegisterInfo;
@@ -59,6 +60,8 @@ MCTargetStreamer *createAArch64AsmTargetStreamer(MCStreamer &S,
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/test/CodeGen/AArch64/misched-predicate-virtreg.mir b/llvm/test/CodeGen/AArch64/misched-predicate-virtreg.mir
new file mode 100644
index 000000000000..95e58a48b424
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/misched-predicate-virtreg.mir
@@ -0,0 +1,36 @@
+# 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 : 12
+# CHECK-NEXT: Successors:
+# CHECK-NEXT: SU(1): Data Latency=2 Reg=%0
+# CHECK-NEXT: Single Issue : false;
+# CHECK-NEXT: SU(1): %1:fpr32 = FMINVv4i32v %0:fpr128
+# CHECK-NEXT: # preds left : 1
+# CHECK-NEXT: # succs left : 1
+# CHECK-NEXT: # rdefs left : 0
+# CHECK-NEXT: Latency : 8
+# CHECK-NEXT: Depth : 2
+# CHECK-NEXT: Height : 10
+# CHECK-NEXT: Predecessors:
+# CHECK-NEXT: SU(0): Data Latency=2 Reg=%0
+# CHECK-NEXT: Successors:
+# CHECK-NEXT: SU(2): Data Latency=8 Reg=%1
+# CHECK-NEXT: Single Issue : false;
+
+name: test_qform_virtreg
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $s0, $q1
+ %0:fpr128 = COPY $q1
+ %1:fpr32 = FMINVv4i32v %0:fpr128
+ $s0 = COPY %1
+ RET_ReallyLR implicit $s0
+
More information about the llvm-commits
mailing list