[llvm] [MachinePipeliner] Extract some process into a separate function (PR #137662)
Ryotaro Kasuga via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 28 09:11:48 PDT 2025
https://github.com/kasuga-fj created https://github.com/llvm/llvm-project/pull/137662
This patch moves a process in `addLoopCarriedDependences` that checks for a loop-carried dependency between two instructions to another function. This patch is preliminary to a later patch and is not intended to change current behavior.
Split off from #135148
>From cf61ef84a24513f17f87ee58478202383bb3ed4e Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Mon, 28 Apr 2025 10:55:07 +0000
Subject: [PATCH] [MachinePipeliner] Extract some process into a separate
function
This patch moves a process in `addLoopCarriedDependences` that checks
for a loop-carried dependency between two instructions to another
function. This patch is preliminary to a later patch and is not intended
to change current behavior.
Split off from #135148
---
llvm/lib/CodeGen/MachinePipeliner.cpp | 125 ++++++++++++--------------
1 file changed, 59 insertions(+), 66 deletions(-)
diff --git a/llvm/lib/CodeGen/MachinePipeliner.cpp b/llvm/lib/CodeGen/MachinePipeliner.cpp
index 07bffc6c3de90..3d161ffbe40a4 100644
--- a/llvm/lib/CodeGen/MachinePipeliner.cpp
+++ b/llvm/lib/CodeGen/MachinePipeliner.cpp
@@ -884,6 +884,63 @@ bool SUnitWithMemInfo::getUnderlyingObjects() {
return true;
}
+/// Returns true if there is a loop-carried order dependency from \p Src to \p
+/// Dst.
+static bool hasLoopCarriedMemDep(const SUnitWithMemInfo &Src,
+ const SUnitWithMemInfo &Dst,
+ BatchAAResults &BAA,
+ const TargetInstrInfo *TII,
+ const TargetRegisterInfo *TRI) {
+ if (Src.isTriviallyDisjoint(Dst))
+ return false;
+ if (isSuccOrder(Src.SU, Dst.SU))
+ return false;
+
+ MachineInstr &SrcMI = *Src.SU->getInstr();
+ MachineInstr &DstMI = *Dst.SU->getInstr();
+ // First, perform the cheaper check that compares the base register.
+ // If they are the same and the load offset is less than the store
+ // offset, then mark the dependence as loop carried potentially.
+ const MachineOperand *BaseOp1, *BaseOp2;
+ int64_t Offset1, Offset2;
+ bool Offset1IsScalable, Offset2IsScalable;
+ if (TII->getMemOperandWithOffset(SrcMI, BaseOp1, Offset1, Offset1IsScalable,
+ TRI) &&
+ TII->getMemOperandWithOffset(DstMI, BaseOp2, Offset2, Offset2IsScalable,
+ TRI)) {
+ if (BaseOp1->isIdenticalTo(*BaseOp2) &&
+ Offset1IsScalable == Offset2IsScalable && (int)Offset1 < (int)Offset2) {
+ assert(TII->areMemAccessesTriviallyDisjoint(SrcMI, DstMI) &&
+ "What happened to the chain edge?");
+ return true;
+ }
+ }
+
+ // Second, the more expensive check that uses alias analysis on the
+ // base registers. If they alias, and the load offset is less than
+ // the store offset, the mark the dependence as loop carried.
+ if (Src.isUnknown() || Dst.isUnknown())
+ return true;
+ if (Src.MemOpValue == Dst.MemOpValue && Src.MemOpOffset <= Dst.MemOpOffset)
+ return true;
+
+ if (BAA.isNoAlias(
+ MemoryLocation::getBeforeOrAfter(Src.MemOpValue, Src.AATags),
+ MemoryLocation::getBeforeOrAfter(Dst.MemOpValue, Dst.AATags)))
+ return false;
+
+ // AliasAnalysis sometimes gives up on following the underlying
+ // object. In such a case, separate checks for underlying objects may
+ // prove that there are no aliases between two accesses.
+ for (const Value *SrcObj : Src.UnderlyingObjs)
+ for (const Value *DstObj : Dst.UnderlyingObjs)
+ if (!BAA.isNoAlias(MemoryLocation::getBeforeOrAfter(SrcObj, Src.AATags),
+ MemoryLocation::getBeforeOrAfter(DstObj, Dst.AATags)))
+ return true;
+
+ return false;
+}
+
/// Add a chain edge between a load and store if the store can be an
/// alias of the load on a subsequent iteration, i.e., a loop carried
/// dependence. This code is very similar to the code in ScheduleDAGInstrs
@@ -898,76 +955,12 @@ void SwingSchedulerDAG::addLoopCarriedDependences() {
PendingLoads.emplace_back(&SU);
} else if (MI.mayStore()) {
SUnitWithMemInfo Store(&SU);
- for (const SUnitWithMemInfo &Load : PendingLoads) {
- if (Load.isTriviallyDisjoint(Store))
- continue;
- if (isSuccOrder(Load.SU, Store.SU))
- continue;
- MachineInstr &LdMI = *Load.SU->getInstr();
- // First, perform the cheaper check that compares the base register.
- // If they are the same and the load offset is less than the store
- // offset, then mark the dependence as loop carried potentially.
- const MachineOperand *BaseOp1, *BaseOp2;
- int64_t Offset1, Offset2;
- bool Offset1IsScalable, Offset2IsScalable;
- if (TII->getMemOperandWithOffset(LdMI, BaseOp1, Offset1,
- Offset1IsScalable, TRI) &&
- TII->getMemOperandWithOffset(MI, BaseOp2, Offset2,
- Offset2IsScalable, TRI)) {
- if (BaseOp1->isIdenticalTo(*BaseOp2) &&
- Offset1IsScalable == Offset2IsScalable &&
- (int)Offset1 < (int)Offset2) {
- assert(TII->areMemAccessesTriviallyDisjoint(LdMI, MI) &&
- "What happened to the chain edge?");
- SDep Dep(Load.SU, SDep::Barrier);
- Dep.setLatency(1);
- SU.addPred(Dep);
- continue;
- }
- }
- // Second, the more expensive check that uses alias analysis on the
- // base registers. If they alias, and the load offset is less than
- // the store offset, the mark the dependence as loop carried.
- if (Load.isUnknown() || Store.isUnknown()) {
- SDep Dep(Load.SU, SDep::Barrier);
- Dep.setLatency(1);
- SU.addPred(Dep);
- continue;
- }
- if (Load.MemOpValue == Store.MemOpValue &&
- Load.MemOpOffset <= Store.MemOpOffset) {
- SDep Dep(Load.SU, SDep::Barrier);
- Dep.setLatency(1);
- SU.addPred(Dep);
- continue;
- }
-
- bool IsNoAlias = [&] {
- if (BAA.isNoAlias(MemoryLocation::getBeforeOrAfter(Load.MemOpValue,
- Load.AATags),
- MemoryLocation::getBeforeOrAfter(Store.MemOpValue,
- Store.AATags)))
- return true;
-
- // AliasAnalysis sometimes gives up on following the underlying
- // object. In such a case, separate checks for underlying objects may
- // prove that there are no aliases between two accesses.
- for (const Value *LoadObj : Load.UnderlyingObjs)
- for (const Value *StoreObj : Store.UnderlyingObjs)
- if (!BAA.isNoAlias(
- MemoryLocation::getBeforeOrAfter(LoadObj, Load.AATags),
- MemoryLocation::getBeforeOrAfter(StoreObj, Store.AATags)))
- return false;
-
- return true;
- }();
-
- if (!IsNoAlias) {
+ for (const SUnitWithMemInfo &Load : PendingLoads)
+ if (hasLoopCarriedMemDep(Load, Store, BAA, TII, TRI)) {
SDep Dep(Load.SU, SDep::Barrier);
Dep.setLatency(1);
SU.addPred(Dep);
}
- }
}
}
}
More information about the llvm-commits
mailing list