[llvm] [MachineLoopInfo] Implement `isLoopInvariant` recursively. (PR #95285)

Mikhail Gudim via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 12 11:27:48 PDT 2024


https://github.com/mgudim created https://github.com/llvm/llvm-project/pull/95285

In order for the instruction to be loop invariant, each of its operands has to be defined outside of the loop or be loop invariant itself.

>From d15dec103ae1653139bd3b6896a016b9eb6ad50f Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Fri, 31 May 2024 13:56:28 -0400
Subject: [PATCH] [MachineLoopInfo] Implement `isLoopInvariant` recursively.

In order for the instruction to be loop invariant, each of its operands
has to be defined outside of the loop or be loop invariant itself.
---
 llvm/include/llvm/CodeGen/MachineLoopInfo.h |  6 ++--
 llvm/lib/CodeGen/MachineLoopInfo.cpp        | 32 +++++++++++++--------
 2 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineLoopInfo.h b/llvm/include/llvm/CodeGen/MachineLoopInfo.h
index 967c4a70ca469..dcc9f699575ad 100644
--- a/llvm/include/llvm/CodeGen/MachineLoopInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineLoopInfo.h
@@ -82,7 +82,8 @@ class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> {
   /// ExcludeReg can be used to exclude the given register from the check
   /// i.e. when we're considering hoisting it's definition but not hoisted it
   /// yet
-  bool isLoopInvariant(MachineInstr &I, const Register ExcludeReg = 0) const;
+  bool isLoopInvariant(const MachineInstr &I, const Register ExcludeReg = 0,
+                       unsigned RecursionDepth = 1) const;
 
   void dump() const;
 
@@ -90,7 +91,8 @@ class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> {
   friend class LoopInfoBase<MachineBasicBlock, MachineLoop>;
 
   /// Returns true if the given physreg has no defs inside the loop.
-  bool isLoopInvariantImplicitPhysReg(Register Reg) const;
+  bool isLoopInvariantImplicitPhysReg(Register Reg, Register ExcludeReg,
+                                      unsigned RecursionDepth = 0) const;
 
   explicit MachineLoop(MachineBasicBlock *MBB)
     : LoopBase<MachineBasicBlock, MachineLoop>(MBB) {}
diff --git a/llvm/lib/CodeGen/MachineLoopInfo.cpp b/llvm/lib/CodeGen/MachineLoopInfo.cpp
index 1019c53e57c6f..4f8245a35c9ab 100644
--- a/llvm/lib/CodeGen/MachineLoopInfo.cpp
+++ b/llvm/lib/CodeGen/MachineLoopInfo.cpp
@@ -198,7 +198,8 @@ MDNode *MachineLoop::getLoopID() const {
   return LoopID;
 }
 
-bool MachineLoop::isLoopInvariantImplicitPhysReg(Register Reg) const {
+bool MachineLoop::isLoopInvariantImplicitPhysReg(
+    Register Reg, Register ExcludeReg, unsigned RecursionDepth) const {
   MachineFunction *MF = getHeader()->getParent();
   MachineRegisterInfo *MRI = &MF->getRegInfo();
 
@@ -210,15 +211,20 @@ bool MachineLoop::isLoopInvariantImplicitPhysReg(Register Reg) const {
            ->shouldAnalyzePhysregInMachineLoopInfo(Reg))
     return false;
 
-  return !llvm::any_of(
-      MRI->def_instructions(Reg),
-      [this](const MachineInstr &MI) { return this->contains(&MI); });
+  return !llvm::any_of(MRI->def_instructions(Reg), [=](const MachineInstr &MI) {
+    return (this->contains(&MI) &&
+            !isLoopInvariant(MI, ExcludeReg, RecursionDepth - 1));
+  });
 }
 
-bool MachineLoop::isLoopInvariant(MachineInstr &I,
-                                  const Register ExcludeReg) const {
-  MachineFunction *MF = I.getParent()->getParent();
-  MachineRegisterInfo *MRI = &MF->getRegInfo();
+bool MachineLoop::isLoopInvariant(const MachineInstr &I,
+                                  const Register ExcludeReg,
+                                  unsigned RecursionDepth) const {
+  if (RecursionDepth == 0)
+    return false;
+
+  const MachineFunction *MF = I.getParent()->getParent();
+  const MachineRegisterInfo *MRI = &MF->getRegInfo();
   const TargetSubtargetInfo &ST = MF->getSubtarget();
   const TargetRegisterInfo *TRI = ST.getRegisterInfo();
   const TargetInstrInfo *TII = ST.getInstrInfo();
@@ -243,7 +249,7 @@ bool MachineLoop::isLoopInvariant(MachineInstr &I,
         // it could get allocated to something with a def during allocation.
         // However, if the physreg is known to always be caller saved/restored
         // then this use is safe to hoist.
-        if (!isLoopInvariantImplicitPhysReg(Reg) &&
+        if (!isLoopInvariantImplicitPhysReg(Reg, ExcludeReg, RecursionDepth) &&
             !(TRI->isCallerPreservedPhysReg(Reg.asMCReg(), *I.getMF())) &&
             !TII->isIgnorableUse(MO))
           return false;
@@ -265,9 +271,11 @@ bool MachineLoop::isLoopInvariant(MachineInstr &I,
     assert(MRI->getVRegDef(Reg) &&
            "Machine instr not mapped for this vreg?!");
 
-    // If the loop contains the definition of an operand, then the instruction
-    // isn't loop invariant.
-    if (contains(MRI->getVRegDef(Reg)))
+    // If the loop contains the definition of an operand, then it must be loop
+    // invariant
+    MachineInstr *VRegDefMI = MRI->getVRegDef(Reg);
+    if (contains(VRegDefMI) &&
+        !isLoopInvariant(*VRegDefMI, ExcludeReg, RecursionDepth - 1))
       return false;
   }
 



More information about the llvm-commits mailing list