-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[CodeGen] Allow negative frame indicies in Register class. #164459
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
base: main
Are you sure you want to change the base?
Conversation
|
@llvm/pr-subscribers-llvm-regalloc Author: Mikhail Gudim (mgudim) ChangesThis is used by reaching definitions analysis in order to track stores / loads from negative frame indices. Full diff: https://github.com/llvm/llvm-project/pull/164459.diff 2 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/Register.h b/llvm/include/llvm/CodeGen/Register.h
index e462a814562dc..961d6fe744b15 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,9 @@ 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 +49,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 +90,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())
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
|
this is part of work for: #90819 |
This is used by reaching definitions analysis in order to track stores / loads from negative frame indices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the title. Can you rephrase an elaborate in the description
Simplified the definition of "StackSlotMask" Fixed wrong assertion. Added unit test.
|
I tried to make the title better. |
llvm/include/llvm/CodeGen/Register.h
Outdated
| assert(isStack() && "Not a stack slot"); | ||
| return static_cast<int>(Reg - Register::FirstStackSlot); | ||
| return static_cast<int>( | ||
| SignExtend64<MaxFrameIndexBitwidth>(Reg & Register::StackSlotMask)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use SignExtend32 so you don't need the static_cast?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought int could be smaller then int32_t in theory.
Actually, to me it looks like stackSlotIndex should return int32_t. If int is not 32 bits, the result may not be able to fit, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this OK to merge?
|
Edit: Apparently it does make sense. |
From MachineFrameInfo.h |
@MatzeB @topperc @arsenm |
I don't think its necessary. Having more than 2^29 frame indices in either direction seems unlikely. The amount of memory consumed by MachineFrameInfo just to track that would be excessive. |
|
does this look OK to merge? |
| EXPECT_EQ(Register::index2StackSlot(-1), | ||
| Register::StackSlotZero | Register::StackSlotMask); | ||
| // check that we do not crash on the highest possible value of frame index. | ||
| EXPECT_NO_FATAL_FAILURE(Register::index2StackSlot((1 << 29) - 1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use named constants for 29 here and the line below?
| EXPECT_EQ(Register::index2StackSlot(0), Register::StackSlotZero); | ||
| EXPECT_EQ(Register::index2StackSlot(1), Register::StackSlotZero | 1); | ||
| EXPECT_EQ(Register::index2StackSlot(-1), | ||
| Register::StackSlotZero | Register::StackSlotMask); | ||
| // check that we do not crash on the highest possible value of frame index. | ||
| EXPECT_NO_FATAL_FAILURE(Register::index2StackSlot((1 << 29) - 1)); | ||
| // check that we do not crash on the lowest possible value of frame index. | ||
| EXPECT_NO_FATAL_FAILURE(Register::index2StackSlot(-(1 << 29))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| EXPECT_EQ(Register::index2StackSlot(0), Register::StackSlotZero); | |
| EXPECT_EQ(Register::index2StackSlot(1), Register::StackSlotZero | 1); | |
| EXPECT_EQ(Register::index2StackSlot(-1), | |
| Register::StackSlotZero | Register::StackSlotMask); | |
| // check that we do not crash on the highest possible value of frame index. | |
| EXPECT_NO_FATAL_FAILURE(Register::index2StackSlot((1 << 29) - 1)); | |
| // check that we do not crash on the lowest possible value of frame index. | |
| EXPECT_NO_FATAL_FAILURE(Register::index2StackSlot(-(1 << 29))); | |
| int MaxPowOf2 = 1 << 29; | |
| EXPECT_EQ(Register::index2StackSlot(0), Register::StackSlotZero); | |
| EXPECT_EQ(Register::index2StackSlot(1), Register::StackSlotZero | 1); | |
| EXPECT_EQ(Register::index2StackSlot(-1), | |
| Register::StackSlotZero | Register::StackSlotMask); | |
| // check that we do not crash on the highest possible value of frame index. | |
| EXPECT_NO_FATAL_FAILURE(Register::index2StackSlot(MaxPowOf2 - 1)); | |
| // check that we do not crash on the lowest possible value of frame index. | |
| EXPECT_NO_FATAL_FAILURE(Register::index2StackSlot(-MaxPowOf2)); |
Or just MaxBits = 29 or something like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should use Register::MaxFrameIndexBitwidth - 1 instead of putting 29 anywhere in the test.
The register values between
2 << 30(inclusive) and2 << 31(exclusive) correspond to frame indices. To obtain the frame index from the given register value we interpret first 30 bits as an unsigned integer. Thus, currently only non-negative frame indices can be represented.However, we should also be able to represent negative frame indices as register values as well. This is used by reaching definitions analysis for example.
In order to do that, we interpret the first 30 bits of the register value as a signed integer.