Skip to content

[CallingConv] Return ArrayRef from AllocateRegBlock() (NFC) #124120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 23, 2025

Conversation

nikic
Copy link
Contributor

@nikic nikic commented Jan 23, 2025

Instead of returning the first register, return the ArrayRef containing the whole block.

Existing users rely on the fact that the register block only contains adjacently-numbered registers and it's possible to get the remaining registers in the block by just incrementing the register. Returning an ArrayRef allows more generic usage with non-adjacent registers.

@llvmbot
Copy link
Member

llvmbot commented Jan 23, 2025

@llvm/pr-subscribers-backend-arm

Author: Nikita Popov (nikic)

Changes

Instead of returning the first register, return the ArrayRef containing the whole block.

Existing users rely on the fact that the register block only contains adjacently-numbered registers and it's possible to get the remaining registers in the block by just incrementing the register. Returning an ArrayRef allows more generic usage with non-adjacent registers.


Full diff: https://github.com/llvm/llvm-project/pull/124120.diff

3 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/CallingConvLower.h (+8-7)
  • (modified) llvm/lib/Target/AArch64/AArch64CallingConvention.cpp (+9-9)
  • (modified) llvm/lib/Target/ARM/ARMCallingConv.cpp (+4-5)
diff --git a/llvm/include/llvm/CodeGen/CallingConvLower.h b/llvm/include/llvm/CodeGen/CallingConvLower.h
index 85171138d1eb9d..7ad27cd01336a6 100644
--- a/llvm/include/llvm/CodeGen/CallingConvLower.h
+++ b/llvm/include/llvm/CodeGen/CallingConvLower.h
@@ -357,12 +357,13 @@ class CCState {
     return Reg;
   }
 
-  /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive
-  /// registers. If this is not possible, return zero. Otherwise, return the first
-  /// register of the block that were allocated, marking the entire block as allocated.
-  MCPhysReg AllocateRegBlock(ArrayRef<MCPhysReg> Regs, unsigned RegsRequired) {
+  /// Attempt to allocate a block of RegsRequired consecutive registers.
+  /// If this is not possible, return an empty range. Otherwise, return a
+  /// range of consecutive registers, marking the entire block as allocated.
+  ArrayRef<MCPhysReg> AllocateRegBlock(ArrayRef<MCPhysReg> Regs,
+                                       unsigned RegsRequired) {
     if (RegsRequired > Regs.size())
-      return 0;
+      return {};
 
     for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired;
          ++StartIdx) {
@@ -379,11 +380,11 @@ class CCState {
         for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) {
           MarkAllocated(Regs[StartIdx + BlockIdx]);
         }
-        return Regs[StartIdx];
+        return Regs.slice(StartIdx, RegsRequired);
       }
     }
     // No block was available
-    return 0;
+    return {};
   }
 
   /// Version of AllocateReg with list of registers to be shadowed.
diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp b/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
index fa04ccfba30f06..991d710c979b9e 100644
--- a/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
+++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
@@ -176,27 +176,27 @@ static bool CC_AArch64_Custom_Block(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
   // [N x i32] arguments get packed into x-registers on Darwin's arm64_32
   // because that's how the armv7k Clang front-end emits small structs.
   unsigned EltsPerReg = (IsDarwinILP32 && LocVT.SimpleTy == MVT::i32) ? 2 : 1;
-  unsigned RegResult = State.AllocateRegBlock(
+  ArrayRef<MCPhysReg> RegResult = State.AllocateRegBlock(
       RegList, alignTo(PendingMembers.size(), EltsPerReg) / EltsPerReg);
-  if (RegResult && EltsPerReg == 1) {
-    for (auto &It : PendingMembers) {
-      It.convertToReg(RegResult);
+  if (!RegResult.empty() && EltsPerReg == 1) {
+    for (const auto &[It, Reg] : zip(PendingMembers, RegResult)) {
+      It.convertToReg(Reg);
       State.addLoc(It);
-      ++RegResult;
     }
     PendingMembers.clear();
     return true;
-  } else if (RegResult) {
+  } else if (!RegResult.empty()) {
     assert(EltsPerReg == 2 && "unexpected ABI");
     bool UseHigh = false;
     CCValAssign::LocInfo Info;
+    unsigned RegIdx = 0;
     for (auto &It : PendingMembers) {
       Info = UseHigh ? CCValAssign::AExtUpper : CCValAssign::ZExt;
-      State.addLoc(CCValAssign::getReg(It.getValNo(), MVT::i32, RegResult,
-                                       MVT::i64, Info));
+      State.addLoc(CCValAssign::getReg(It.getValNo(), MVT::i32,
+                                       RegResult[RegIdx], MVT::i64, Info));
       UseHigh = !UseHigh;
       if (!UseHigh)
-        ++RegResult;
+        ++RegIdx;
     }
     PendingMembers.clear();
     return true;
diff --git a/llvm/lib/Target/ARM/ARMCallingConv.cpp b/llvm/lib/Target/ARM/ARMCallingConv.cpp
index 5a88fff41aeb1d..2c429d7ea1a8b2 100644
--- a/llvm/lib/Target/ARM/ARMCallingConv.cpp
+++ b/llvm/lib/Target/ARM/ARMCallingConv.cpp
@@ -228,12 +228,11 @@ static bool CC_ARM_AAPCS_Custom_Aggregate(unsigned ValNo, MVT ValVT,
     break;
   }
 
-  unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size());
-  if (RegResult) {
-    for (CCValAssign &PendingMember : PendingMembers) {
-      PendingMember.convertToReg(RegResult);
+  ArrayRef<MCPhysReg> RegResult = State.AllocateRegBlock(RegList, PendingMembers.size());
+  if (!RegResult.empty()) {
+    for (const auto &[PendingMember, Reg] : zip(PendingMembers, RegResult)) {
+      PendingMember.convertToReg(Reg);
       State.addLoc(PendingMember);
-      ++RegResult;
     }
     PendingMembers.clear();
     return true;

@llvmbot
Copy link
Member

llvmbot commented Jan 23, 2025

@llvm/pr-subscribers-backend-aarch64

Author: Nikita Popov (nikic)

Changes

Instead of returning the first register, return the ArrayRef containing the whole block.

Existing users rely on the fact that the register block only contains adjacently-numbered registers and it's possible to get the remaining registers in the block by just incrementing the register. Returning an ArrayRef allows more generic usage with non-adjacent registers.


Full diff: https://github.com/llvm/llvm-project/pull/124120.diff

3 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/CallingConvLower.h (+8-7)
  • (modified) llvm/lib/Target/AArch64/AArch64CallingConvention.cpp (+9-9)
  • (modified) llvm/lib/Target/ARM/ARMCallingConv.cpp (+4-5)
diff --git a/llvm/include/llvm/CodeGen/CallingConvLower.h b/llvm/include/llvm/CodeGen/CallingConvLower.h
index 85171138d1eb9d..7ad27cd01336a6 100644
--- a/llvm/include/llvm/CodeGen/CallingConvLower.h
+++ b/llvm/include/llvm/CodeGen/CallingConvLower.h
@@ -357,12 +357,13 @@ class CCState {
     return Reg;
   }
 
-  /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive
-  /// registers. If this is not possible, return zero. Otherwise, return the first
-  /// register of the block that were allocated, marking the entire block as allocated.
-  MCPhysReg AllocateRegBlock(ArrayRef<MCPhysReg> Regs, unsigned RegsRequired) {
+  /// Attempt to allocate a block of RegsRequired consecutive registers.
+  /// If this is not possible, return an empty range. Otherwise, return a
+  /// range of consecutive registers, marking the entire block as allocated.
+  ArrayRef<MCPhysReg> AllocateRegBlock(ArrayRef<MCPhysReg> Regs,
+                                       unsigned RegsRequired) {
     if (RegsRequired > Regs.size())
-      return 0;
+      return {};
 
     for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired;
          ++StartIdx) {
@@ -379,11 +380,11 @@ class CCState {
         for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) {
           MarkAllocated(Regs[StartIdx + BlockIdx]);
         }
-        return Regs[StartIdx];
+        return Regs.slice(StartIdx, RegsRequired);
       }
     }
     // No block was available
-    return 0;
+    return {};
   }
 
   /// Version of AllocateReg with list of registers to be shadowed.
diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp b/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
index fa04ccfba30f06..991d710c979b9e 100644
--- a/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
+++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.cpp
@@ -176,27 +176,27 @@ static bool CC_AArch64_Custom_Block(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
   // [N x i32] arguments get packed into x-registers on Darwin's arm64_32
   // because that's how the armv7k Clang front-end emits small structs.
   unsigned EltsPerReg = (IsDarwinILP32 && LocVT.SimpleTy == MVT::i32) ? 2 : 1;
-  unsigned RegResult = State.AllocateRegBlock(
+  ArrayRef<MCPhysReg> RegResult = State.AllocateRegBlock(
       RegList, alignTo(PendingMembers.size(), EltsPerReg) / EltsPerReg);
-  if (RegResult && EltsPerReg == 1) {
-    for (auto &It : PendingMembers) {
-      It.convertToReg(RegResult);
+  if (!RegResult.empty() && EltsPerReg == 1) {
+    for (const auto &[It, Reg] : zip(PendingMembers, RegResult)) {
+      It.convertToReg(Reg);
       State.addLoc(It);
-      ++RegResult;
     }
     PendingMembers.clear();
     return true;
-  } else if (RegResult) {
+  } else if (!RegResult.empty()) {
     assert(EltsPerReg == 2 && "unexpected ABI");
     bool UseHigh = false;
     CCValAssign::LocInfo Info;
+    unsigned RegIdx = 0;
     for (auto &It : PendingMembers) {
       Info = UseHigh ? CCValAssign::AExtUpper : CCValAssign::ZExt;
-      State.addLoc(CCValAssign::getReg(It.getValNo(), MVT::i32, RegResult,
-                                       MVT::i64, Info));
+      State.addLoc(CCValAssign::getReg(It.getValNo(), MVT::i32,
+                                       RegResult[RegIdx], MVT::i64, Info));
       UseHigh = !UseHigh;
       if (!UseHigh)
-        ++RegResult;
+        ++RegIdx;
     }
     PendingMembers.clear();
     return true;
diff --git a/llvm/lib/Target/ARM/ARMCallingConv.cpp b/llvm/lib/Target/ARM/ARMCallingConv.cpp
index 5a88fff41aeb1d..2c429d7ea1a8b2 100644
--- a/llvm/lib/Target/ARM/ARMCallingConv.cpp
+++ b/llvm/lib/Target/ARM/ARMCallingConv.cpp
@@ -228,12 +228,11 @@ static bool CC_ARM_AAPCS_Custom_Aggregate(unsigned ValNo, MVT ValVT,
     break;
   }
 
-  unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size());
-  if (RegResult) {
-    for (CCValAssign &PendingMember : PendingMembers) {
-      PendingMember.convertToReg(RegResult);
+  ArrayRef<MCPhysReg> RegResult = State.AllocateRegBlock(RegList, PendingMembers.size());
+  if (!RegResult.empty()) {
+    for (const auto &[PendingMember, Reg] : zip(PendingMembers, RegResult)) {
+      PendingMember.convertToReg(Reg);
       State.addLoc(PendingMember);
-      ++RegResult;
     }
     PendingMembers.clear();
     return true;

Copy link

github-actions bot commented Jan 23, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Instead of returning the first register, return the ArrayRef
containing the whole block.

Existing users rely on the fact that the register block only
contains adjacently-numbered registers and it's possible to get
the remaining registers in the block by just incrementing the
register. Returning an ArrayRef allows more generic usage with
non-adjacent registers.
@nikic nikic merged commit 6fe0fc6 into llvm:main Jan 23, 2025
7 of 9 checks passed
@nikic nikic deleted the alloc-block branch January 23, 2025 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants