Skip to content

Commit 4b7d997

Browse files
committed
[RISCV] Implement RISCVInsrInfo::getConstValDefinedInReg
This helper function handles common cases where we can determine a constant value is being defined in a register. Although it looks like codegen changes are possible due to this being called in PeepholeOptimizer, my main motivation is to use this in describeLoadedValue.
1 parent 60bb5c5 commit 4b7d997

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,12 @@ RISCVInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
15801580
switch (MI.getOpcode()) {
15811581
default:
15821582
break;
1583+
case RISCV::ADD:
1584+
if (MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == RISCV::X0)
1585+
return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
1586+
if (MI.getOperand(2).isReg() && MI.getOperand(2).getReg() == RISCV::X0)
1587+
return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
1588+
break;
15831589
case RISCV::ADDI:
15841590
// Operand 1 can be a frameindex but callers expect registers
15851591
if (MI.getOperand(1).isReg() && MI.getOperand(2).isImm() &&
@@ -2555,6 +2561,33 @@ std::optional<RegImmPair> RISCVInstrInfo::isAddImmediate(const MachineInstr &MI,
25552561
return std::nullopt;
25562562
}
25572563

2564+
bool RISCVInstrInfo::getConstValDefinedInReg(const MachineInstr &MI,
2565+
const Register Reg,
2566+
int64_t &ImmVal) const {
2567+
// Handle moves of X0.
2568+
if (auto DestSrc = isCopyInstr(MI)) {
2569+
if (DestSrc->Source->getReg() != RISCV::X0)
2570+
return false;
2571+
const Register DstReg = DestSrc->Destination->getReg();
2572+
if (DstReg != Reg)
2573+
return false;
2574+
ImmVal = 0;
2575+
return true;
2576+
}
2577+
2578+
if (!(MI.getOpcode() == RISCV::ADDI || MI.getOpcode() == RISCV::ADDIW ||
2579+
MI.getOpcode() == RISCV::ORI))
2580+
return false;
2581+
if (MI.getOperand(0).getReg() != Reg)
2582+
return false;
2583+
if (!MI.getOperand(1).isReg() || MI.getOperand(1).getReg() != RISCV::X0)
2584+
return false;
2585+
if (!MI.getOperand(2).isImm())
2586+
return false;
2587+
ImmVal = MI.getOperand(2).getImm();
2588+
return true;
2589+
}
2590+
25582591
// MIR printer helper function to annotate Operands with a comment.
25592592
std::string RISCVInstrInfo::createMIROperandComment(
25602593
const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx,

llvm/lib/Target/RISCV/RISCVInstrInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
212212
std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
213213
Register Reg) const override;
214214

215+
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg,
216+
int64_t &ImmVal) const override;
217+
215218
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
216219
unsigned &SrcOpIdx2) const override;
217220
MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,

llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,52 @@ TEST_P(RISCVInstrInfoTest, IsAddImmediate) {
9494
}
9595
}
9696

97+
TEST_P(RISCVInstrInfoTest, GetConstValDefinedInReg) {
98+
const RISCVInstrInfo *TII = ST->getInstrInfo();
99+
DebugLoc DL;
100+
int64_t ImmVal;
101+
102+
auto *MI1 = BuildMI(*MF, DL, TII->get(RISCV::ADD), RISCV::X1)
103+
.addReg(RISCV::X2)
104+
.addReg(RISCV::X3)
105+
.getInstr();
106+
EXPECT_FALSE(TII->getConstValDefinedInReg(*MI1, RISCV::X1, ImmVal));
107+
108+
auto *MI2 = BuildMI(*MF, DL, TII->get(RISCV::ADDI), RISCV::X1)
109+
.addReg(RISCV::X0)
110+
.addImm(-128)
111+
.getInstr();
112+
EXPECT_FALSE(TII->getConstValDefinedInReg(*MI2, RISCV::X0, ImmVal));
113+
ASSERT_TRUE(TII->getConstValDefinedInReg(*MI2, RISCV::X1, ImmVal));
114+
EXPECT_EQ(ImmVal, -128);
115+
116+
auto *MI3 = BuildMI(*MF, DL, TII->get(RISCV::ORI), RISCV::X2)
117+
.addReg(RISCV::X0)
118+
.addImm(1024)
119+
.getInstr();
120+
EXPECT_FALSE(TII->getConstValDefinedInReg(*MI3, RISCV::X0, ImmVal));
121+
ASSERT_TRUE(TII->getConstValDefinedInReg(*MI3, RISCV::X2, ImmVal));
122+
EXPECT_EQ(ImmVal, 1024);
123+
124+
if (ST->is64Bit()) {
125+
auto *MI4 = BuildMI(*MF, DL, TII->get(RISCV::ADDIW), RISCV::X2)
126+
.addReg(RISCV::X0)
127+
.addImm(512)
128+
.getInstr();
129+
EXPECT_FALSE(TII->getConstValDefinedInReg(*MI4, RISCV::X0, ImmVal));
130+
ASSERT_TRUE(TII->getConstValDefinedInReg(*MI4, RISCV::X2, ImmVal));
131+
EXPECT_EQ(ImmVal, 512);
132+
}
133+
134+
auto *MI5 = BuildMI(*MF, DL, TII->get(RISCV::ADD), RISCV::X1)
135+
.addReg(RISCV::X0)
136+
.addReg(RISCV::X0)
137+
.getInstr();
138+
EXPECT_FALSE(TII->getConstValDefinedInReg(*MI5, RISCV::X0, ImmVal));
139+
ASSERT_TRUE(TII->getConstValDefinedInReg(*MI5, RISCV::X1, ImmVal));
140+
EXPECT_EQ(ImmVal, 0);
141+
}
142+
97143
TEST_P(RISCVInstrInfoTest, GetMemOperandsWithOffsetWidth) {
98144
const RISCVInstrInfo *TII = ST->getInstrInfo();
99145
const TargetRegisterInfo *TRI = ST->getRegisterInfo();

0 commit comments

Comments
 (0)