[llvm] [CodeGen] Negative frame indicies as register. (PR #164459)
Mikhail Gudim via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 22 11:35:20 PDT 2025
https://github.com/mgudim updated https://github.com/llvm/llvm-project/pull/164459
>From dc953025b85361a975fdf9fc78cd4d37adc01247 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at ventanamicro.com>
Date: Sat, 23 Aug 2025 14:58:03 -0700
Subject: [PATCH 1/3] Negative frame indicies as register.
This is used by reaching definitions analysis in order to track stores /
loads from negative frame indices.
---
llvm/include/llvm/CodeGen/Register.h | 12 ++++++++----
llvm/lib/CodeGen/ReachingDefAnalysis.cpp | 3 ---
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/Register.h b/llvm/include/llvm/CodeGen/Register.h
index e462a814562dc..9aa30e9f3513a 100644
--- a/llvm/include/llvm/CodeGen/Register.h
+++ b/llvm/include/llvm/CodeGen/Register.h
@@ -10,6 +10,7 @@
#define LLVM_CODEGEN_REGISTER_H
#include "llvm/MC/MCRegister.h"
+#include "llvm/Support/MathExtras.h"
#include <cassert>
namespace llvm {
@@ -35,7 +36,10 @@ class Register {
// DenseMapInfo<unsigned> uses -1u and -2u.
static_assert(std::numeric_limits<decltype(Reg)>::max() >= 0xFFFFFFFF,
"Reg isn't large enough to hold full range.");
- static constexpr unsigned FirstStackSlot = 1u << 30;
+ static constexpr unsigned MaxFrameIndexBitwidth = 30;
+ static constexpr unsigned FirstStackSlot = 1u << MaxFrameIndexBitwidth;
+ static const unsigned StackSlotMask =
+ (unsigned)(-1) >> (CHAR_BIT * sizeof(unsigned) - MaxFrameIndexBitwidth);
static_assert(FirstStackSlot >= MCRegister::LastPhysicalReg);
static constexpr unsigned VirtualRegFlag = 1u << 31;
@@ -46,8 +50,8 @@ class Register {
/// Convert a non-negative frame index to a stack slot register value.
static Register index2StackSlot(int FI) {
- assert(FI >= 0 && "Cannot hold a negative frame index.");
- return Register(FI + Register::FirstStackSlot);
+ assert(isInt<30>(FI) && "Frame index must be at most 30 bit integer");
+ return Register((FI & Register::StackSlotMask) | Register::FirstStackSlot);
}
/// Return true if the specified register number is in
@@ -87,7 +91,7 @@ class Register {
/// Compute the frame index from a register value representing a stack slot.
int stackSlotIndex() const {
assert(isStack() && "Not a stack slot");
- return static_cast<int>(Reg - Register::FirstStackSlot);
+ return static_cast<int>(SignExtend64(Reg & Register::StackSlotMask, 30));
}
constexpr operator unsigned() const { return Reg; }
diff --git a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
index 40a89078bcf59..61706e13b8e91 100644
--- a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
+++ b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
@@ -193,7 +193,6 @@ void ReachingDefInfo::processDefs(MachineInstr *MI) {
for (auto &MO : MI->operands()) {
if (MO.isFI()) {
int FrameIndex = MO.getIndex();
- assert(FrameIndex >= 0 && "Can't handle negative frame indicies yet!");
if (!isFIDef(*MI, FrameIndex, TII))
continue;
MBBFrameObjsReachingDefs[{MBBNumber, FrameIndex}].push_back(CurInstr);
@@ -302,8 +301,6 @@ void ReachingDefInfo::print(raw_ostream &OS) {
Register Reg;
if (MO.isFI()) {
int FrameIndex = MO.getIndex();
- assert(FrameIndex >= 0 &&
- "Can't handle negative frame indicies yet!");
Reg = Register::index2StackSlot(FrameIndex);
} else if (MO.isReg()) {
if (MO.isDef())
>From 7b2fcda9ba02b5aa5605782a365d7683ff238a1e Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at ventanamicro.com>
Date: Tue, 21 Oct 2025 13:59:03 -0700
Subject: [PATCH 2/3] addressed review comments.
---
llvm/include/llvm/CodeGen/Register.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/Register.h b/llvm/include/llvm/CodeGen/Register.h
index 9aa30e9f3513a..048366159cb2f 100644
--- a/llvm/include/llvm/CodeGen/Register.h
+++ b/llvm/include/llvm/CodeGen/Register.h
@@ -38,7 +38,7 @@ class Register {
"Reg isn't large enough to hold full range.");
static constexpr unsigned MaxFrameIndexBitwidth = 30;
static constexpr unsigned FirstStackSlot = 1u << MaxFrameIndexBitwidth;
- static const unsigned StackSlotMask =
+ static constexpr const unsigned StackSlotMask =
(unsigned)(-1) >> (CHAR_BIT * sizeof(unsigned) - MaxFrameIndexBitwidth);
static_assert(FirstStackSlot >= MCRegister::LastPhysicalReg);
static constexpr unsigned VirtualRegFlag = 1u << 31;
@@ -91,7 +91,7 @@ class Register {
/// Compute the frame index from a register value representing a stack slot.
int stackSlotIndex() const {
assert(isStack() && "Not a stack slot");
- return static_cast<int>(SignExtend64(Reg & Register::StackSlotMask, 30));
+ return static_cast<int>(SignExtend64<30>(Reg & Register::StackSlotMask));
}
constexpr operator unsigned() const { return Reg; }
>From 478c945944a6348028213929b560a0207c28b87a Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at ventanamicro.com>
Date: Wed, 22 Oct 2025 10:45:08 -0700
Subject: [PATCH 3/3] Renamed "FirstStackSlot" to "StackSlotZero". Simplified
the definition of "StackSlotMask" Fixed wrong assertion. Added unit test.
---
llvm/include/llvm/CodeGen/Register.h | 18 ++++++++------
llvm/unittests/CodeGen/CMakeLists.txt | 1 +
llvm/unittests/CodeGen/RegisterTest.cpp | 33 +++++++++++++++++++++++++
3 files changed, 44 insertions(+), 8 deletions(-)
create mode 100644 llvm/unittests/CodeGen/RegisterTest.cpp
diff --git a/llvm/include/llvm/CodeGen/Register.h b/llvm/include/llvm/CodeGen/Register.h
index 048366159cb2f..83bf6c8ff2fa2 100644
--- a/llvm/include/llvm/CodeGen/Register.h
+++ b/llvm/include/llvm/CodeGen/Register.h
@@ -37,21 +37,22 @@ class Register {
static_assert(std::numeric_limits<decltype(Reg)>::max() >= 0xFFFFFFFF,
"Reg isn't large enough to hold full range.");
static constexpr unsigned MaxFrameIndexBitwidth = 30;
- static constexpr unsigned FirstStackSlot = 1u << MaxFrameIndexBitwidth;
- static constexpr const unsigned StackSlotMask =
- (unsigned)(-1) >> (CHAR_BIT * sizeof(unsigned) - MaxFrameIndexBitwidth);
- static_assert(FirstStackSlot >= MCRegister::LastPhysicalReg);
+ static constexpr unsigned StackSlotZero = 1u << MaxFrameIndexBitwidth;
+ static constexpr const unsigned StackSlotMask = StackSlotZero - 1;
+ static_assert(StackSlotZero >= MCRegister::LastPhysicalReg);
static constexpr unsigned VirtualRegFlag = 1u << 31;
/// Return true if this is a stack slot.
constexpr bool isStack() const {
- return Register::FirstStackSlot <= Reg && Reg < Register::VirtualRegFlag;
+ return Register::StackSlotZero <= Reg && Reg < Register::VirtualRegFlag;
}
/// Convert a non-negative frame index to a stack slot register value.
static Register index2StackSlot(int FI) {
- assert(isInt<30>(FI) && "Frame index must be at most 30 bit integer");
- return Register((FI & Register::StackSlotMask) | Register::FirstStackSlot);
+ unsigned FIMasked = FI & Register::StackSlotMask;
+ assert(isUInt<30>(FIMasked) &&
+ "Frame index must be at most 30 bit as an unsigned integer");
+ return Register(FIMasked | Register::StackSlotZero);
}
/// Return true if the specified register number is in
@@ -91,7 +92,8 @@ class Register {
/// Compute the frame index from a register value representing a stack slot.
int stackSlotIndex() const {
assert(isStack() && "Not a stack slot");
- return static_cast<int>(SignExtend64<30>(Reg & Register::StackSlotMask));
+ return static_cast<int>(
+ SignExtend64<MaxFrameIndexBitwidth>(Reg & Register::StackSlotMask));
}
constexpr operator unsigned() const { return Reg; }
diff --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt
index 18332d20bf8ff..4d07462babefa 100644
--- a/llvm/unittests/CodeGen/CMakeLists.txt
+++ b/llvm/unittests/CodeGen/CMakeLists.txt
@@ -39,6 +39,7 @@ add_llvm_unittest(CodeGenTests
MachineOperandTest.cpp
MIR2VecTest.cpp
RegAllocScoreTest.cpp
+ RegisterTest.cpp
PassManagerTest.cpp
ScalableVectorMVTsTest.cpp
SchedBoundary.cpp
diff --git a/llvm/unittests/CodeGen/RegisterTest.cpp b/llvm/unittests/CodeGen/RegisterTest.cpp
new file mode 100644
index 0000000000000..1f61aeaac7c68
--- /dev/null
+++ b/llvm/unittests/CodeGen/RegisterTest.cpp
@@ -0,0 +1,33 @@
+//===- RegisterTest.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/Register.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+TEST(RegisterTest, Idx2StackSlot) {
+ ASSERT_EQ(Register::index2StackSlot(0), Register::StackSlotZero);
+ ASSERT_EQ(Register::index2StackSlot(-1),
+ Register::StackSlotZero | Register::StackSlotMask);
+ ASSERT_EQ(Register::index2StackSlot(Register::StackSlotMask),
+ Register::StackSlotZero | Register::StackSlotMask);
+ ASSERT_EQ(Register::index2StackSlot(1), Register::StackSlotZero | 1);
+}
+
+TEST(RegisterTest, StackSlotIndex) {
+ Register Reg;
+ std::vector<int64_t> FIs = {0, 1 - 1, (1 << 29) - 1, -(1 << 29)};
+
+ for (int64_t FI : FIs) {
+ Reg = Register::index2StackSlot(FI);
+ ASSERT_EQ(Reg.stackSlotIndex(), FI);
+ }
+}
+} // end namespace
More information about the llvm-commits
mailing list