[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