[llvm] [RISCV][GlobalISel] Create generic instructions to handle legalization and selection of G_GLOBAL_VALUE for medlow code model (PR #69562)

Nitin John Raj via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 18 22:32:25 PDT 2023


https://github.com/nitinjohnraj created https://github.com/llvm/llvm-project/pull/69562

We create generic instructions G_RISCV_HI and G_RISCV_ADD_LO. We lower G_GLOBAL_VALUE to these instructions during legalization, and we use pre-existing tablegen rules to select these instructions.

>From 29f3936a1711c1b9187de456610a8a2e1b097c30 Mon Sep 17 00:00:00 2001
From: Nitin John Raj <nitin.raj at sifive.com>
Date: Wed, 18 Oct 2023 11:07:34 -0700
Subject: [PATCH 1/5] [RISCV][GlobalISel] Create generic instructions
 G_RISCV_ADD_LO and G_RISCV_HI

---
 llvm/lib/Target/RISCV/RISCVInstrGISel.td | 36 ++++++++++++++++++++++++
 llvm/lib/Target/RISCV/RISCVInstrInfo.td  |  2 ++
 2 files changed, 38 insertions(+)
 create mode 100644 llvm/lib/Target/RISCV/RISCVInstrGISel.td

diff --git a/llvm/lib/Target/RISCV/RISCVInstrGISel.td b/llvm/lib/Target/RISCV/RISCVInstrGISel.td
new file mode 100644
index 000000000000000..24e7be03b0c8f07
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrGISel.td
@@ -0,0 +1,36 @@
+//=----- RISCVInstrGISel.td - RISCV GISel target pseudos -*- tablegen -*-=//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// RISCV GlobalISel target pseudo instruction definitions. This is kept
+// separately from the other tablegen files for organizational purposes, but
+// share the same infrastructure.
+//
+//===----------------------------------------------------------------------===//
+
+class RISCVGenericInstruction : GenericInstruction {
+  let Namespace = "RISCV";
+}
+
+// A pseudo to represent a relocatable add instruction as part of address
+// computation.
+// FIXME: Copy the type from SelectionDAG
+def G_RISCV_ADD_LO : RISCVGenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type1:$src, type2:$imm);
+  let hasSideEffects = 0;
+}
+
+// FIXME: Copy the type from SelectionDAG
+def G_RISCV_HI : RISCVGenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type1:$imm);
+  let hasSideEffects = 0;
+}
+
+def : GINodeEquiv<G_RISCV_ADD_LO, riscv_add_lo>;
+def : GINodeEquiv<G_RISCV_HI, riscv_hi>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 54efe67f600a92d..54482c5a37259cf 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2036,3 +2036,5 @@ include "RISCVInstrInfoXVentana.td"
 include "RISCVInstrInfoXTHead.td"
 include "RISCVInstrInfoXSf.td"
 include "RISCVInstrInfoXCV.td"
+
+include "RISCVInstrGISel.td"

>From 3367e7158e358955af96e5bfd7a639404d48b2e3 Mon Sep 17 00:00:00 2001
From: Nitin John Raj <nitin.raj at sifive.com>
Date: Wed, 18 Oct 2023 11:08:48 -0700
Subject: [PATCH 2/5] [RISCV][GlobalISel] Legalize G_RISCV_ADD_LO, G_RISCV_HI

---
 .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 35 +++++++++++++++++--
 .../Target/RISCV/GISel/RISCVLegalizerInfo.h   |  3 ++
 .../legalizer/rv32/legalize-global.mir        | 10 ++----
 .../legalizer/rv64/legalize-global.mir        |  5 +--
 4 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 4479bccfd45e396..022c092b8c26f3d 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -13,6 +13,7 @@
 #include "RISCVLegalizerInfo.h"
 #include "RISCVSubtarget.h"
 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/TargetOpcodes.h"
 #include "llvm/CodeGen/ValueTypes.h"
 #include "llvm/IR/DerivedTypes.h"
@@ -20,7 +21,7 @@
 
 using namespace llvm;
 
-RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
+RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) : ST(&ST) {
   const unsigned XLen = ST.getXLen();
   const LLT XLenLLT = LLT::scalar(XLen);
   const LLT DoubleXLenLLT = LLT::scalar(2 * XLen);
@@ -29,6 +30,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
   const LLT s16 = LLT::scalar(16);
   const LLT s32 = LLT::scalar(32);
 
+  const TargetMachine &TM = ST.getTargetLowering()->getTargetMachine();
+
   using namespace TargetOpcode;
 
   getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
@@ -131,8 +134,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
       .widenScalarToNextPow2(0)
       .clampScalar(0, XLenLLT, XLenLLT);
 
-  getActionDefinitionsBuilder(G_GLOBAL_VALUE)
-      .legalFor({p0});
+  if (TM.getCodeModel() == CodeModel::Small)
+    getActionDefinitionsBuilder(G_GLOBAL_VALUE).custom();
+  else
+    getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
 
   if (ST.hasStdExtM() || ST.hasStdExtZmmul()) {
     getActionDefinitionsBuilder(G_MUL)
@@ -176,10 +181,34 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
 
 bool RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
                                         MachineInstr &MI) const {
+  MachineIRBuilder &MIB = Helper.MIRBuilder;
+
   switch (MI.getOpcode()) {
   default:
     // No idea what to do.
     return false;
+  case TargetOpcode::G_GLOBAL_VALUE: {
+    Register DstReg = MI.getOperand(0).getReg();
+    MachineOperand &GlobalOp = MI.getOperand(1);
+    const GlobalValue *GV = GlobalOp.getGlobal();
+    auto &TM = ST->getTargetLowering()->getTargetMachine();
+    int64_t Offset = GlobalOp.getOffset();
+
+    switch (TM.getCodeModel()) {
+    case CodeModel::Small: {
+      auto AddrHi = MIB.buildInstr(RISCV::G_RISCV_HI, {LLT::pointer(0, 64)}, {})
+                        .addGlobalAddress(GV, Offset, RISCVII::MO_HI);
+
+      MIB.buildInstr(RISCV::G_RISCV_ADD_LO, {DstReg}, {AddrHi})
+                      .addGlobalAddress(GV, Offset, RISCVII::MO_LO);
+
+      MI.eraseFromParent();
+      return true;
+    }
+    default:
+      llvm_unreachable("Code model not handled!");
+    }
+  }
   case TargetOpcode::G_SEXT_INREG: {
     // Source size of 32 is sext.w.
     int64_t SizeInBits = MI.getOperand(2).getImm();
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h
index 4061c553b6496ae..77b5e163ec5b5d8 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h
@@ -25,6 +25,9 @@ class RISCVLegalizerInfo : public LegalizerInfo {
   RISCVLegalizerInfo(const RISCVSubtarget &ST);
 
   bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI) const override;
+
+private:
+  const RISCVSubtarget *ST;
 };
 } // end namespace llvm
 #endif
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-global.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-global.mir
index 8e7daa60aa8deb0..d16f22006f30836 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-global.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv32/legalize-global.mir
@@ -15,16 +15,12 @@ alignment:       4
 tracksRegLiveness: true
 registers:
   - { id: 0, class: _ }
-frameInfo:
-  maxAlignment:    1
-machineFunctionInfo:
-  varArgsFrameIndex: 0
-  varArgsSaveSize: 0
 body:             |
   bb.1 (%ir-block.0):
     ; CHECK-LABEL: name: test_global
-    ; CHECK: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @var
-    ; CHECK-NEXT: $x10 = COPY [[GV]](p0)
+    ; CHECK: [[RISCV_HI:%[0-9]+]]:_(p0) = G_RISCV_HI target-flags(riscv-hi) @var
+    ; CHECK-NEXT: [[RISCV_ADD_LO:%[0-9]+]]:_(p0) = G_RISCV_ADD_LO [[RISCV_HI]](p0), target-flags(riscv-lo) @var
+    ; CHECK-NEXT: $x10 = COPY [[RISCV_ADD_LO]](p0)
     ; CHECK-NEXT: PseudoRET implicit $x10
     %0:_(p0) = G_GLOBAL_VALUE @var
     $x10 = COPY %0(p0)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-global.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-global.mir
index 9e501214083864f..3e8d7da138ac332 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-global.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rv64/legalize-global.mir
@@ -23,8 +23,9 @@ machineFunctionInfo:
 body:             |
   bb.1 (%ir-block.0):
     ; CHECK-LABEL: name: test_global
-    ; CHECK: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @var
-    ; CHECK-NEXT: $x10 = COPY [[GV]](p0)
+    ; CHECK: [[RISCV_HI:%[0-9]+]]:_(p0) = G_RISCV_HI target-flags(riscv-hi) @var
+    ; CHECK-NEXT: [[RISCV_ADD_LO:%[0-9]+]]:_(p0) = G_RISCV_ADD_LO [[RISCV_HI]](p0), target-flags(riscv-lo) @var
+    ; CHECK-NEXT: $x10 = COPY [[RISCV_ADD_LO]](p0)
     ; CHECK-NEXT: PseudoRET implicit $x10
     %0:_(p0) = G_GLOBAL_VALUE @var
     $x10 = COPY %0(p0)

>From 3f5cfa66f707d235c3e211bd6e0db569f48093d1 Mon Sep 17 00:00:00 2001
From: Nitin John Raj <nitin.raj at sifive.com>
Date: Wed, 18 Oct 2023 11:09:37 -0700
Subject: [PATCH 3/5] [RISCV][GlobalISel] Register bank selection
 G_RISCV_ADD_LO, G_RISCV_HI

---
 .../RISCV/GISel/RISCVRegisterBankInfo.cpp     |  2 ++
 .../RISCV/GlobalISel/regbankselect/global.mir | 33 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/global.mir

diff --git a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
index e2cf461a1eb8e22..9a9f9d0b4485b00 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp
@@ -136,6 +136,7 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
     break;
   case TargetOpcode::G_CONSTANT:
   case TargetOpcode::G_GLOBAL_VALUE:
+  case RISCV::G_RISCV_HI:
   case TargetOpcode::G_BRCOND:
     OperandsMapping = getOperandsMapping({GPRValueMapping, nullptr});
     break;
@@ -146,6 +147,7 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
     OperandsMapping = getOperandsMapping(
         {GPRValueMapping, nullptr, GPRValueMapping, GPRValueMapping});
     break;
+  case RISCV::G_RISCV_ADD_LO:
   case TargetOpcode::G_SEXT_INREG:
     OperandsMapping =
         getOperandsMapping({GPRValueMapping, GPRValueMapping, nullptr});
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/global.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/global.mir
new file mode 100644
index 000000000000000..2afe29420747a48
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/global.mir
@@ -0,0 +1,33 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -run-pass=regbankselect \
+# RUN:   -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \
+# RUN:   -o - | FileCheck %s
+# RUN: llc -mtriple=riscv64 -run-pass=regbankselect \
+# RUN:   -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \
+# RUN:   -o - | FileCheck %s
+
+--- |
+  @var = global i32 0
+
+  define ptr @test_global() {
+    ret ptr @var
+  }
+
+...
+---
+name:            test_global
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.0 (%ir-block.0):
+    ; CHECK-LABEL: name: test_global
+    ; CHECK: [[RISCV_HI:%[0-9]+]]:gprb(p0) = G_RISCV_HI target-flags(riscv-hi) @var
+    ; CHECK-NEXT: [[RISCV_ADD_LO:%[0-9]+]]:gprb(p0) = G_RISCV_ADD_LO [[RISCV_HI]](p0), target-flags(riscv-lo) @var
+    ; CHECK-NEXT: $x10 = COPY [[RISCV_ADD_LO]](p0)
+    ; CHECK-NEXT: PseudoRET implicit $x10
+    %1:_(p0) = G_RISCV_HI target-flags(riscv-hi) @var
+    %0:_(p0) = G_RISCV_ADD_LO %1(p0), target-flags(riscv-lo) @var
+    $x10 = COPY %0(p0)
+    PseudoRET implicit $x10
+
+...

>From 11bc99a9384f50bd1cbba349b52f133ac74293df Mon Sep 17 00:00:00 2001
From: Nitin John Raj <nitin.raj at sifive.com>
Date: Wed, 18 Oct 2023 11:11:21 -0700
Subject: [PATCH 4/5] [RISCV][GlobalISel] Instruction selection for
 G_RISCV_ADD_LO, G_RISCV_H

---
 .../RISCV/GISel/RISCVInstructionSelector.cpp  | 21 +++++++++++++
 .../instruction-select/global-value.mir       | 31 +++++++++++++++++++
 2 files changed, 52 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir

diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 59c95f9c740b5a3..757298f76fbe4fe 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -164,6 +164,25 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
   preISelLower(MI, MIB, MRI);
   const unsigned Opc = MI.getOpcode();
 
+  switch(Opc) {
+  case RISCV::G_RISCV_ADD_LO: {
+    Register DstReg = MI.getOperand(0).getReg();
+    const LLT XLenLLT = LLT::scalar(STI.getXLen());
+    RBI.constrainGenericRegister(DstReg, RISCV::GPRRegClass, MRI);
+    MI.setDesc(TII.get(RISCV::ADDI));
+    MRI.setType(DstReg, XLenLLT);
+    return true;
+  }
+  case RISCV::G_RISCV_HI: {
+    Register DstReg = MI.getOperand(0).getReg();
+    const LLT XLenLLT = LLT::scalar(STI.getXLen());
+    RBI.constrainGenericRegister(DstReg, RISCV::GPRRegClass, MRI);
+    MI.setDesc(TII.get(RISCV::LUI));
+    MRI.setType(DstReg, XLenLLT);
+    return true;
+  }
+  }
+
   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
     if (Opc == TargetOpcode::PHI || Opc == TargetOpcode::G_PHI) {
       const Register DefReg = MI.getOperand(0).getReg();
@@ -248,6 +267,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
     break;
   }
 
+  errs() << "HERE\n";
+
   if (selectImpl(MI, *CoverageInfo))
     return true;
 
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
new file mode 100644
index 000000000000000..690539cb0b796e0
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
@@ -0,0 +1,31 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -march=riscv32 -run-pass=instruction-select -simplify-mir \
+# RUN:   -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -march=riscv64 -run-pass=instruction-select -simplify-mir \
+# RUN:   -verify-machineinstrs %s -o - | FileCheck %s
+--- |
+  @var = global i32 0
+
+  define ptr @test_global() {
+    ret ptr @var
+  }
+
+...
+---
+name:            test_global
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.0 (%ir-block.0):
+    ; CHECK-LABEL: name: test_global
+    ; CHECK: [[LUI:%[0-9]+]]:gpr = LUI target-flags(riscv-hi) @var
+    ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @var
+    ; CHECK-NEXT: $x10 = COPY [[ADDI]]
+    ; CHECK-NEXT: PseudoRET implicit $x10
+    %0:gprb(p0) = G_RISCV_HI target-flags(riscv-hi) @var
+    %1:gprb(p0) = G_RISCV_ADD_LO %0(p0), target-flags(riscv-lo) @var
+    $x10 = COPY %1(p0)
+    PseudoRET implicit $x10
+
+...

>From 6144541a6d3c515cc3d2b6cab7090a5e3b145708 Mon Sep 17 00:00:00 2001
From: Nitin John Raj <nitin.raj at sifive.com>
Date: Wed, 18 Oct 2023 16:36:20 -0700
Subject: [PATCH 5/5] Add FIXME for position independent code

---
 llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 022c092b8c26f3d..69ae0266cdc1592 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -188,10 +188,15 @@ bool RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
     // No idea what to do.
     return false;
   case TargetOpcode::G_GLOBAL_VALUE: {
+    auto &TM = ST->getTargetLowering()->getTargetMachine();
+
+    // FIXME: Handle position independent code.
+    if (TM.isPositionIndependent())
+      return false;
+
     Register DstReg = MI.getOperand(0).getReg();
     MachineOperand &GlobalOp = MI.getOperand(1);
     const GlobalValue *GV = GlobalOp.getGlobal();
-    auto &TM = ST->getTargetLowering()->getTargetMachine();
     int64_t Offset = GlobalOp.getOffset();
 
     switch (TM.getCodeModel()) {



More information about the llvm-commits mailing list