Skip to content

Commit 050cbd2

Browse files
mgudimMikhail Gudimppenzin
authored
[CodeGen] Allow negative frame indicies in Register class. (#164459)
The register values between `2 << 30` (inclusive) and `2 << 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. --------- Co-authored-by: Mikhail Gudim <[email protected]> Co-authored-by: Petr Penzin <[email protected]>
1 parent 3b010c9 commit 050cbd2

File tree

4 files changed

+50
-9
lines changed

4 files changed

+50
-9
lines changed

llvm/include/llvm/CodeGen/Register.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_CODEGEN_REGISTER_H
1111

1212
#include "llvm/MC/MCRegister.h"
13+
#include "llvm/Support/MathExtras.h"
1314
#include <cassert>
1415

1516
namespace llvm {
@@ -35,19 +36,23 @@ class Register {
3536
// DenseMapInfo<unsigned> uses -1u and -2u.
3637
static_assert(std::numeric_limits<decltype(Reg)>::max() >= 0xFFFFFFFF,
3738
"Reg isn't large enough to hold full range.");
38-
static constexpr unsigned FirstStackSlot = 1u << 30;
39-
static_assert(FirstStackSlot >= MCRegister::LastPhysicalReg);
39+
static constexpr unsigned MaxFrameIndexBitwidth = 30;
40+
static constexpr unsigned StackSlotZero = 1u << MaxFrameIndexBitwidth;
41+
static constexpr const unsigned StackSlotMask = StackSlotZero - 1;
42+
static_assert(StackSlotZero >= MCRegister::LastPhysicalReg);
4043
static constexpr unsigned VirtualRegFlag = 1u << 31;
4144

4245
/// Return true if this is a stack slot.
4346
constexpr bool isStack() const {
44-
return Register::FirstStackSlot <= Reg && Reg < Register::VirtualRegFlag;
47+
return Register::StackSlotZero <= Reg && Reg < Register::VirtualRegFlag;
4548
}
4649

4750
/// Convert a non-negative frame index to a stack slot register value.
4851
static Register index2StackSlot(int FI) {
49-
assert(FI >= 0 && "Cannot hold a negative frame index.");
50-
return Register(FI + Register::FirstStackSlot);
52+
assert(isInt<MaxFrameIndexBitwidth>(FI) &&
53+
"Frame index must be at most 30 bits.");
54+
unsigned FIMasked = FI & Register::StackSlotMask;
55+
return Register(FIMasked | Register::StackSlotZero);
5156
}
5257

5358
/// Return true if the specified register number is in
@@ -87,7 +92,7 @@ class Register {
8792
/// Compute the frame index from a register value representing a stack slot.
8893
int stackSlotIndex() const {
8994
assert(isStack() && "Not a stack slot");
90-
return static_cast<int>(Reg - Register::FirstStackSlot);
95+
return SignExtend32<MaxFrameIndexBitwidth>(Reg & Register::StackSlotMask);
9196
}
9297

9398
constexpr operator unsigned() const { return Reg; }

llvm/lib/CodeGen/ReachingDefAnalysis.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ void ReachingDefInfo::processDefs(MachineInstr *MI) {
193193
for (auto &MO : MI->operands()) {
194194
if (MO.isFI()) {
195195
int FrameIndex = MO.getIndex();
196-
assert(FrameIndex >= 0 && "Can't handle negative frame indicies yet!");
197196
if (!isFIDef(*MI, FrameIndex, TII))
198197
continue;
199198
MBBFrameObjsReachingDefs[{MBBNumber, FrameIndex}].push_back(CurInstr);
@@ -302,8 +301,6 @@ void ReachingDefInfo::print(raw_ostream &OS) {
302301
Register Reg;
303302
if (MO.isFI()) {
304303
int FrameIndex = MO.getIndex();
305-
assert(FrameIndex >= 0 &&
306-
"Can't handle negative frame indicies yet!");
307304
Reg = Register::index2StackSlot(FrameIndex);
308305
} else if (MO.isReg()) {
309306
if (MO.isDef())

llvm/unittests/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ add_llvm_unittest(CodeGenTests
3939
MachineOperandTest.cpp
4040
MIR2VecTest.cpp
4141
RegAllocScoreTest.cpp
42+
RegisterTest.cpp
4243
PassManagerTest.cpp
4344
ScalableVectorMVTsTest.cpp
4445
SchedBoundary.cpp
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===- RegisterTest.cpp -----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/CodeGen/Register.h"
10+
#include "gtest/gtest.h"
11+
12+
using namespace llvm;
13+
14+
namespace {
15+
TEST(RegisterTest, Idx2StackSlot) {
16+
EXPECT_EQ(Register::index2StackSlot(0), Register::StackSlotZero);
17+
EXPECT_EQ(Register::index2StackSlot(1), Register::StackSlotZero | 1);
18+
EXPECT_EQ(Register::index2StackSlot(-1),
19+
Register::StackSlotZero | Register::StackSlotMask);
20+
int MaxPowOf2 = 1 << (Register::MaxFrameIndexBitwidth - 1);
21+
// Check the highest possible value of frame index
22+
EXPECT_EQ(Register::index2StackSlot(MaxPowOf2 - 1),
23+
Register::StackSlotZero | (MaxPowOf2 - 1));
24+
// Check the lowest possible value of frame index
25+
EXPECT_EQ(Register::index2StackSlot(-MaxPowOf2),
26+
Register::StackSlotZero | (-MaxPowOf2 & Register::StackSlotMask));
27+
}
28+
29+
TEST(RegisterTest, StackSlotIndex) {
30+
int MaxPowOf2 = 1 << (Register::MaxFrameIndexBitwidth - 1);
31+
std::vector<int> FIs = {0, 1 - 1, MaxPowOf2 - 1, -MaxPowOf2};
32+
33+
for (int FI : FIs) {
34+
Register Reg = Register::index2StackSlot(FI);
35+
EXPECT_EQ(Reg.stackSlotIndex(), FI);
36+
}
37+
}
38+
} // end namespace

0 commit comments

Comments
 (0)