[llvm] [CodeGen][RISCV] Make default describeLoadedValue implementation call getConstValDefinedInReg (PR #77611)

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 10 06:13:25 PST 2024


https://github.com/asb created https://github.com/llvm/llvm-project/pull/77611

This handles the same case that's supported in MipsInstrInfo::describeLoadedValue - allowing a simplified dwarf expression to be produced for when a register is set to a known constant value.

Stacks on top of #77610

>From 4b7d997aaed7a2399d5e73fc3adfaaa6a3d35d1f Mon Sep 17 00:00:00 2001
From: Alex Bradbury <asb at igalia.com>
Date: Wed, 10 Jan 2024 13:34:52 +0000
Subject: [PATCH 1/2] [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.
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp      | 33 +++++++++++++
 llvm/lib/Target/RISCV/RISCVInstrInfo.h        |  3 ++
 .../Target/RISCV/RISCVInstrInfoTest.cpp       | 46 +++++++++++++++++++
 3 files changed, 82 insertions(+)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 9813c7a70dfc31..857e8979762cdc 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1580,6 +1580,12 @@ RISCVInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
   switch (MI.getOpcode()) {
   default:
     break;
+  case RISCV::ADD:
+    if (MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == RISCV::X0)
+      return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
+    if (MI.getOperand(2).isReg() && MI.getOperand(2).getReg() == RISCV::X0)
+      return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
+    break;
   case RISCV::ADDI:
     // Operand 1 can be a frameindex but callers expect registers
     if (MI.getOperand(1).isReg() && MI.getOperand(2).isImm() &&
@@ -2555,6 +2561,33 @@ std::optional<RegImmPair> RISCVInstrInfo::isAddImmediate(const MachineInstr &MI,
   return std::nullopt;
 }
 
+bool RISCVInstrInfo::getConstValDefinedInReg(const MachineInstr &MI,
+                                             const Register Reg,
+                                             int64_t &ImmVal) const {
+  // Handle moves of X0.
+  if (auto DestSrc = isCopyInstr(MI)) {
+    if (DestSrc->Source->getReg() != RISCV::X0)
+      return false;
+    const Register DstReg = DestSrc->Destination->getReg();
+    if (DstReg != Reg)
+      return false;
+    ImmVal = 0;
+    return true;
+  }
+
+  if (!(MI.getOpcode() == RISCV::ADDI || MI.getOpcode() == RISCV::ADDIW ||
+        MI.getOpcode() == RISCV::ORI))
+    return false;
+  if (MI.getOperand(0).getReg() != Reg)
+    return false;
+  if (!MI.getOperand(1).isReg() || MI.getOperand(1).getReg() != RISCV::X0)
+    return false;
+  if (!MI.getOperand(2).isImm())
+    return false;
+  ImmVal = MI.getOperand(2).getImm();
+  return true;
+}
+
 // MIR printer helper function to annotate Operands with a comment.
 std::string RISCVInstrInfo::createMIROperandComment(
     const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 7e1d3f31180650..84015a66fb23a4 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -212,6 +212,9 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
   std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
                                            Register Reg) const override;
 
+  bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg,
+                               int64_t &ImmVal) const override;
+
   bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
                              unsigned &SrcOpIdx2) const override;
   MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
diff --git a/llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp b/llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp
index 5836239bc56fd6..4b1754cd4fcdcf 100644
--- a/llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp
+++ b/llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp
@@ -94,6 +94,52 @@ TEST_P(RISCVInstrInfoTest, IsAddImmediate) {
   }
 }
 
+TEST_P(RISCVInstrInfoTest, GetConstValDefinedInReg) {
+  const RISCVInstrInfo *TII = ST->getInstrInfo();
+  DebugLoc DL;
+  int64_t ImmVal;
+
+  auto *MI1 = BuildMI(*MF, DL, TII->get(RISCV::ADD), RISCV::X1)
+                  .addReg(RISCV::X2)
+                  .addReg(RISCV::X3)
+                  .getInstr();
+  EXPECT_FALSE(TII->getConstValDefinedInReg(*MI1, RISCV::X1, ImmVal));
+
+  auto *MI2 = BuildMI(*MF, DL, TII->get(RISCV::ADDI), RISCV::X1)
+                  .addReg(RISCV::X0)
+                  .addImm(-128)
+                  .getInstr();
+  EXPECT_FALSE(TII->getConstValDefinedInReg(*MI2, RISCV::X0, ImmVal));
+  ASSERT_TRUE(TII->getConstValDefinedInReg(*MI2, RISCV::X1, ImmVal));
+  EXPECT_EQ(ImmVal, -128);
+
+  auto *MI3 = BuildMI(*MF, DL, TII->get(RISCV::ORI), RISCV::X2)
+                  .addReg(RISCV::X0)
+                  .addImm(1024)
+                  .getInstr();
+  EXPECT_FALSE(TII->getConstValDefinedInReg(*MI3, RISCV::X0, ImmVal));
+  ASSERT_TRUE(TII->getConstValDefinedInReg(*MI3, RISCV::X2, ImmVal));
+  EXPECT_EQ(ImmVal, 1024);
+
+  if (ST->is64Bit()) {
+    auto *MI4 = BuildMI(*MF, DL, TII->get(RISCV::ADDIW), RISCV::X2)
+                    .addReg(RISCV::X0)
+                    .addImm(512)
+                    .getInstr();
+    EXPECT_FALSE(TII->getConstValDefinedInReg(*MI4, RISCV::X0, ImmVal));
+    ASSERT_TRUE(TII->getConstValDefinedInReg(*MI4, RISCV::X2, ImmVal));
+    EXPECT_EQ(ImmVal, 512);
+  }
+
+  auto *MI5 = BuildMI(*MF, DL, TII->get(RISCV::ADD), RISCV::X1)
+                  .addReg(RISCV::X0)
+                  .addReg(RISCV::X0)
+                  .getInstr();
+  EXPECT_FALSE(TII->getConstValDefinedInReg(*MI5, RISCV::X0, ImmVal));
+  ASSERT_TRUE(TII->getConstValDefinedInReg(*MI5, RISCV::X1, ImmVal));
+  EXPECT_EQ(ImmVal, 0);
+}
+
 TEST_P(RISCVInstrInfoTest, GetMemOperandsWithOffsetWidth) {
   const RISCVInstrInfo *TII = ST->getInstrInfo();
   const TargetRegisterInfo *TRI = ST->getRegisterInfo();

>From 93a5b690eda26ea71bd4b6f2e50236881cc09864 Mon Sep 17 00:00:00 2001
From: Alex Bradbury <asb at igalia.com>
Date: Wed, 10 Jan 2024 14:10:23 +0000
Subject: [PATCH 2/2] [CodeGen][RISCV] Make default describeLoadedValue
 implementation call getConstValDefinedInReg

This handles the same case that's supported in
MipsInstrInfo::describeLoadedValue - allowing a simplified dwarf
expression to be produced for when a register is set to a known constant
value.
---
 llvm/lib/CodeGen/TargetInstrInfo.cpp               | 6 ++++++
 llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp | 8 +++-----
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 4783742a14ad7d..43edbc08e9039f 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -1499,6 +1499,12 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI,
   assert(MF->getProperties().hasProperty(
       MachineFunctionProperties::Property::NoVRegs));
 
+  int64_t ImmVal;
+  // A simplified DIExpression can be produced if the register is being set to
+  // a known constant value.
+  if (getConstValDefinedInReg(MI, Reg, ImmVal))
+    return ParamLoadedValue(MachineOperand::CreateImm(ImmVal), Expr);
+
   if (auto DestSrc = isCopyInstr(MI)) {
     Register DestReg = DestSrc->Destination->getReg();
 
diff --git a/llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp b/llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp
index 4b1754cd4fcdcf..ca9040f17bf043 100644
--- a/llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp
+++ b/llvm/unittests/Target/RISCV/RISCVInstrInfoTest.cpp
@@ -257,11 +257,9 @@ TEST_P(RISCVInstrInfoTest, DescribeLoadedValue) {
   std::optional<ParamLoadedValue> MI2Res =
       TII->describeLoadedValue(*MI2, RISCV::X3);
   ASSERT_TRUE(MI2Res.has_value());
-  ASSERT_TRUE(MI2Res->first.isReg());
-  EXPECT_EQ(MI2Res->first.getReg(), RISCV::X0);
-  // TODO: Could be a DW_OP_constu if this is recognised as a immediate load
-  // rather than just an addi.
-  expectDIEPrintResult(MI2Res->second, "!DIExpression(DW_OP_plus_uconst, 111)");
+  ASSERT_TRUE(MI2Res->first.isImm());
+  EXPECT_EQ(MI2Res->first.getImm(), 111);
+  expectDIEPrintResult(MI2Res->second, "!DIExpression()");
 
   // Add immediate.
   auto *MI3 = BuildMI(*MBB, MBB->begin(), DL, TII->get(RISCV::ADDI), RISCV::X2)



More information about the llvm-commits mailing list