[llvm] [RISCV][GlobalISel] Select G_GLOBAL_VALUE (PR #70091)
Michael Maitland via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 24 18:11:26 PDT 2023
https://github.com/michaelmaitland updated https://github.com/llvm/llvm-project/pull/70091
>From a296eb27b2b5a2012c7f5ead2f2b9fb80511f496 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Tue, 24 Oct 2023 11:50:29 -0700
Subject: [PATCH 1/7] [RISCV][GlobalISel] Select G_GLOBAL_VALUE
G_GLOBAL_VALUE should be lowered into an absolute address if `-codemodel=small`
is used or into a PC-relative if `-codemodel=medium` is used.
PR #68380 tried to create special instructions to do this, but I don't
see why we need to do that.
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 66 +++++++++++++++++++
.../instruction-select/global-value.mir | 38 +++++++++++
2 files changed, 104 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 a7f18c04a190790..43da613a65dd60e 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -63,6 +63,8 @@ class RISCVInstructionSelector : public InstructionSelector {
bool selectCopy(MachineInstr &MI, MachineRegisterInfo &MRI) const;
bool selectConstant(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
+ bool selectGlobalValue(MachineInstr &MI, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) const;
bool selectSExtInreg(MachineInstr &MI, MachineIRBuilder &MIB) const;
bool selectSelect(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
@@ -95,6 +97,7 @@ class RISCVInstructionSelector : public InstructionSelector {
const RISCVInstrInfo &TII;
const RISCVRegisterInfo &TRI;
const RISCVRegisterBankInfo &RBI;
+ const RISCVTargetMachine &TM;
// FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
// uses "STI." in the code generated by TableGen. We need to unify the name of
@@ -120,6 +123,7 @@ RISCVInstructionSelector::RISCVInstructionSelector(
const RISCVTargetMachine &TM, const RISCVSubtarget &STI,
const RISCVRegisterBankInfo &RBI)
: STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI),
+ TM(TM),
#define GET_GLOBALISEL_PREDICATES_INIT
#include "RISCVGenGlobalISel.inc"
@@ -302,6 +306,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
return selectCopy(MI, MRI);
case TargetOpcode::G_CONSTANT:
return selectConstant(MI, MIB, MRI);
+ case TargetOpcode::G_GLOBAL_VALUE:
+ return selectGlobalValue(MI, MIB, MRI);
case TargetOpcode::G_BRCOND: {
// TODO: Fold with G_ICMP.
auto Bcc =
@@ -483,6 +489,66 @@ bool RISCVInstructionSelector::selectConstant(MachineInstr &MI,
return true;
}
+bool RISCVInstructionSelector::selectGlobalValue(
+ MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const {
+ assert(MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE &&
+ "Expected G_GLOBAL_VALUE");
+ auto GV = MI.getOperand(1).getGlobal();
+ if (GV->isThreadLocal()) {
+ // TODO: implement this case.
+ return false;
+ }
+
+ switch (TM.getCodeModel()) {
+ default:
+ report_fatal_error("Unsupported code model for lowering");
+ case CodeModel::Small: {
+ // Must lie within a single 2 GiB address range and must lie between
+ // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
+ // (lui %hi(sym)) %lo(sym)).
+ Register AddrHiDest = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ MachineInstr *AddrHi = MIB.buildInstr(RISCV::LUI)
+ .addDef(AddrHiDest)
+ .addGlobalAddress(GV, RISCVII::MO_HI);
+ if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
+ return false;
+
+ Register DstReg = MI.getOperand(0).getReg();
+ MachineInstr *Result = MIB.buildInstr(RISCV::ADDI)
+ .addDef(DstReg)
+ .addReg(AddrHiDest)
+ .addGlobalAddress(GV, 0, RISCVII::MO_LO);
+ if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+ }
+ case CodeModel::Medium: {
+ // Must lie within *any* 2GiB range. The generates (addi (auipc
+ // %pcrel_hi(sym)) %pcrel_lo(auipc)).
+ Register AddrHiDest = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ MachineInstr *AddrHi = MIB.buildInstr(RISCV::AUIPC)
+ .addDef(AddrHiDest)
+ .addGlobalAddress(GV, RISCVII::MO_PCREL_HI);
+ if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
+ return false;
+
+ Register DstReg = MI.getOperand(0).getReg();
+ MachineInstr *Result = MIB.buildInstr(RISCV::ADDI)
+ .addDef(DstReg)
+ .addReg(AddrHiDest)
+ .addGlobalAddress(GV, 0, RISCVII::MO_PCREL_LO);
+ if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+ }
+ }
+ return false;
+}
+
bool RISCVInstructionSelector::selectSExtInreg(MachineInstr &MI,
MachineIRBuilder &MIB) const {
if (!STI.isRV64())
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..0f986a82b14cf6f
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
@@ -0,0 +1,38 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
+# RUN: %s -o - | FileCheck --check-prefix=RV64-SMALL %s
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=medium \
+# RUN: %s -o - | FileCheck --check-prefix=RV64-MED %s
+
+--- |
+ @x = global i32 0, align 4
+ define ptr @global_addr() {
+ entry:
+ ret ptr @x
+ }
+...
+---
+name: global_addr
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: gprb, preferred-register: '' }
+body: |
+ bb.1.entry:
+ ; RV64-SMALL-LABEL: name: global_addr
+ ; RV64-SMALL: [[LUI:%[0-9]+]]:gpr = LUI @x + 4
+ ; RV64-SMALL-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @x
+ ; RV64-SMALL-NEXT: $x10 = COPY [[ADDI]]
+ ; RV64-SMALL-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-MED-LABEL: name: global_addr
+ ; RV64-MED: [[AUIPC:%[0-9]+]]:gpr = AUIPC @x + 6
+ ; RV64-MED-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[AUIPC]], target-flags(riscv-pcrel-lo) @x
+ ; RV64-MED-NEXT: $x10 = COPY [[ADDI]]
+ ; RV64-MED-NEXT: PseudoRET implicit $x10
+ %0:gprb(p0) = G_GLOBAL_VALUE @x
+ $x10 = COPY %0(p0)
+ PseudoRET implicit $x10
+...
+
>From e81d9cff26029dbabf7f5ce209229f4d2efe8cf3 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Tue, 24 Oct 2023 12:56:11 -0700
Subject: [PATCH 2/7] [GISel] Add support for reportGISelFailure in target
selector
---
.../include/llvm/CodeGen/GlobalISel/InstructionSelector.h | 8 ++++++++
llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp | 2 ++
llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 7 +++++--
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
index 1662136cfa94afb..8331cb58a0991a4 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
@@ -31,6 +31,14 @@ class InstructionSelector : public GIMatchTableExecutor {
/// for I in all mutated/inserted instructions:
/// !isPreISelGenericOpcode(I.getOpcode())
virtual bool select(MachineInstr &I) = 0;
+
+ void setTargetPassConfig(const TargetPassConfig *T) { TPC = T; }
+
+ void setRemarkEmitter(MachineOptimizationRemarkEmitter *M) { MORE = M; }
+
+protected:
+ const TargetPassConfig *TPC = nullptr;
+ MachineOptimizationRemarkEmitter *MORE = nullptr;
};
} // namespace llvm
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
index 75f1fbc3b2d1b3c..baea773cf528e92 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp
@@ -90,6 +90,7 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
InstructionSelector *ISel = MF.getSubtarget().getInstructionSelector();
+ ISel->setTargetPassConfig(&TPC);
CodeGenOptLevel OldOptLevel = OptLevel;
auto RestoreOptLevel = make_scope_exit([=]() { OptLevel = OldOptLevel; });
@@ -109,6 +110,7 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
// An optimization remark emitter. Used to report failures.
MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
+ ISel->setRemarkEmitter(&MORE);
// FIXME: There are many other MF/MFI fields we need to initialize.
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 43da613a65dd60e..34d2eba499feb63 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -500,8 +500,11 @@ bool RISCVInstructionSelector::selectGlobalValue(
}
switch (TM.getCodeModel()) {
- default:
- report_fatal_error("Unsupported code model for lowering");
+ default: {
+ reportGISelFailure(const_cast<MachineFunction &>(*MF), *TPC, *MORE,
+ getName(), "Unsupported code model for lowering", MI);
+ return false;
+ }
case CodeModel::Small: {
// Must lie within a single 2 GiB address range and must lie between
// absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
>From 96ce233fb29a30ea1b0882b3e54995c784295229 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Tue, 24 Oct 2023 13:17:33 -0700
Subject: [PATCH 3/7] Add support for PIE/PIC
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 35 ++++++++++++-------
.../instruction-select/global-value.mir | 33 +++++++++++++++--
2 files changed, 52 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 34d2eba499feb63..60a7791fcf45215 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -528,20 +528,29 @@ bool RISCVInstructionSelector::selectGlobalValue(
return true;
}
case CodeModel::Medium: {
- // Must lie within *any* 2GiB range. The generates (addi (auipc
- // %pcrel_hi(sym)) %pcrel_lo(auipc)).
- Register AddrHiDest = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- MachineInstr *AddrHi = MIB.buildInstr(RISCV::AUIPC)
- .addDef(AddrHiDest)
- .addGlobalAddress(GV, RISCVII::MO_PCREL_HI);
- if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
- return false;
-
Register DstReg = MI.getOperand(0).getReg();
- MachineInstr *Result = MIB.buildInstr(RISCV::ADDI)
- .addDef(DstReg)
- .addReg(AddrHiDest)
- .addGlobalAddress(GV, 0, RISCVII::MO_PCREL_LO);
+ MachineInstr *Result = nullptr;
+
+ // Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
+ // relocation needs to reference a label that points to the auipc
+ // instruction itself, not the global. This cannot be done inside the
+ // instruction selector.
+ if (GV->hasExternalWeakLinkage())
+ // An extern weak symbol may be undefined, i.e. have value 0, which may
+ // not be within 2GiB of PC, so use GOT-indirect addressing to access the
+ // symbol. This generates the pattern (PseudoLGA sym), which expands to
+ // (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
+ Result = MIB.buildInstr(RISCV::PseudoLGA)
+ .addDef(DstReg)
+ .addGlobalAddress(GV, 0);
+ else
+ // Generate a sequence for accessing addresses within any 2GiB range
+ // within the address space. This generates the pattern (PseudoLLA sym),
+ // which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
+ Result = MIB.buildInstr(RISCV::PseudoLLA)
+ .addDef(DstReg)
+ .addGlobalAddress(GV, 0);
+
if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
return false;
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
index 0f986a82b14cf6f..9e725e0764289ee 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
@@ -10,6 +10,11 @@
entry:
ret ptr @x
}
+ @y = external global i32, align 4
+ define ptr @extern_global_addr() {
+ entry:
+ ret ptr @y
+ }
...
---
name: global_addr
@@ -27,12 +32,34 @@ body: |
; RV64-SMALL-NEXT: PseudoRET implicit $x10
;
; RV64-MED-LABEL: name: global_addr
- ; RV64-MED: [[AUIPC:%[0-9]+]]:gpr = AUIPC @x + 6
- ; RV64-MED-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[AUIPC]], target-flags(riscv-pcrel-lo) @x
- ; RV64-MED-NEXT: $x10 = COPY [[ADDI]]
+ ; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @x
+ ; RV64-MED-NEXT: $x10 = COPY [[PseudoLLA]]
; RV64-MED-NEXT: PseudoRET implicit $x10
%0:gprb(p0) = G_GLOBAL_VALUE @x
$x10 = COPY %0(p0)
PseudoRET implicit $x10
...
+---
+name: extern_global_addr
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: gprb, preferred-register: '' }
+body: |
+ bb.1.entry:
+ ; RV64-SMALL-LABEL: name: extern_global_addr
+ ; RV64-SMALL: [[LUI:%[0-9]+]]:gpr = LUI @y + 4
+ ; RV64-SMALL-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @y
+ ; RV64-SMALL-NEXT: $x10 = COPY [[ADDI]]
+ ; RV64-SMALL-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-MED-LABEL: name: extern_global_addr
+ ; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @y
+ ; RV64-MED-NEXT: $x10 = COPY [[PseudoLLA]]
+ ; RV64-MED-NEXT: PseudoRET implicit $x10
+ %0:gprb(p0) = G_GLOBAL_VALUE @y
+ $x10 = COPY %0(p0)
+ PseudoRET implicit $x10
+...
>From 7f2db7d46e45956faf4652dc0cd01281c6b8e652 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Tue, 24 Oct 2023 14:37:34 -0700
Subject: [PATCH 4/7] Really handle PIE, dso_local, and tagged globals
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 90 ++++++++++----
.../instruction-select/global-value.mir | 116 +++++++++++++++---
2 files changed, 168 insertions(+), 38 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 60a7791fcf45215..fa142a4dea68d6e 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -493,7 +493,8 @@ bool RISCVInstructionSelector::selectGlobalValue(
MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const {
assert(MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE &&
"Expected G_GLOBAL_VALUE");
- auto GV = MI.getOperand(1).getGlobal();
+
+ auto *GV = MI.getOperand(1).getGlobal();
if (GV->isThreadLocal()) {
// TODO: implement this case.
return false;
@@ -506,21 +507,58 @@ bool RISCVInstructionSelector::selectGlobalValue(
return false;
}
case CodeModel::Small: {
- // Must lie within a single 2 GiB address range and must lie between
- // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
- // (lui %hi(sym)) %lo(sym)).
- Register AddrHiDest = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- MachineInstr *AddrHi = MIB.buildInstr(RISCV::LUI)
- .addDef(AddrHiDest)
- .addGlobalAddress(GV, RISCVII::MO_HI);
- if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
- return false;
+ Register DefReg = MI.getOperand(0).getReg();
+ const LLT DefTy = MRI.getType(DefReg);
+ MachineInstr *Result = nullptr;
+
+ // When HWASAN is used and tagging of global variables is enabled
+ // they should be accessed via the GOT, since the tagged address of a global
+ // is incompatible with existing code models. This also applies to non-pic
+ // mode.
+ if (TM.isPositionIndependent() && GV->isDSOLocal() &&
+ !Subtarget->allowTaggedGlobals()) {
+ // Use PC-relative addressing to access the symbol. This generates the
+ // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
+ // %pcrel_lo(auipc)).
+ Result = MIB.buildInstr(RISCV::PseudoLLA)
+ .addDef(DefReg)
+ .addGlobalAddress(GV, 0);
+ } else if (Subtarget->allowTaggedGlobals() ||
+ (TM.isPositionIndependent() && !GV->isDSOLocal())) {
+ // Use PC-relative addressing to access the GOT for this symbol, then
+ // load the address from the GOT. This generates the pattern (PseudoLGA
+ // sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
+ // %pcrel_lo(auipc))).
+ MachineFunction &MF = *MI.getParent()->getParent();
+ MachineMemOperand *MemOp =
+ MI.getParent()->getParent()->getMachineMemOperand(
+ MachinePointerInfo::getGOT(MF),
+ MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
+ MachineMemOperand::MOInvariant,
+ DefTy, Align(DefTy.getSizeInBits() / 8));
+
+ Result = MIB.buildInstr(RISCV::PseudoLGA)
+ .addDef(DefReg)
+ .addGlobalAddress(GV, 0)
+ .addMemOperand(MemOp);
+ } else {
+ // Must lie within a single 2 GiB address range and must lie between
+ // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
+ // (lui %hi(sym)) %lo(sym)).
+ Register AddrHiDest = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ MachineInstr *AddrHi = MIB.buildInstr(RISCV::LUI)
+ .addDef(AddrHiDest)
+ .addGlobalAddress(GV, RISCVII::MO_HI);
+
+ if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
+ return false;
+
+ Result = MIB.buildInstr(RISCV::ADDI)
+ .addDef(DefReg)
+ .addReg(AddrHiDest)
+ .addGlobalAddress(GV, 0, RISCVII::MO_LO);
+ }
- Register DstReg = MI.getOperand(0).getReg();
- MachineInstr *Result = MIB.buildInstr(RISCV::ADDI)
- .addDef(DstReg)
- .addReg(AddrHiDest)
- .addGlobalAddress(GV, 0, RISCVII::MO_LO);
if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
return false;
@@ -528,28 +566,38 @@ bool RISCVInstructionSelector::selectGlobalValue(
return true;
}
case CodeModel::Medium: {
- Register DstReg = MI.getOperand(0).getReg();
+ Register DefReg = MI.getOperand(0).getReg();
+ const LLT DefTy = MRI.getType(DefReg);
MachineInstr *Result = nullptr;
// Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
// relocation needs to reference a label that points to the auipc
// instruction itself, not the global. This cannot be done inside the
// instruction selector.
- if (GV->hasExternalWeakLinkage())
+ if (GV->hasExternalWeakLinkage()) {
// An extern weak symbol may be undefined, i.e. have value 0, which may
// not be within 2GiB of PC, so use GOT-indirect addressing to access the
// symbol. This generates the pattern (PseudoLGA sym), which expands to
// (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
+ MachineFunction &MF = *MI.getParent()->getParent();
+ MachineMemOperand *MemOp = MF.getMachineMemOperand(
+ MachinePointerInfo::getGOT(MF),
+ MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
+ MachineMemOperand::MOInvariant,
+ DefTy, Align(DefTy.getSizeInBits() / 8));
+
Result = MIB.buildInstr(RISCV::PseudoLGA)
- .addDef(DstReg)
- .addGlobalAddress(GV, 0);
- else
+ .addDef(DefReg)
+ .addGlobalAddress(GV, 0)
+ .addMemOperand(MemOp);
+ } else {
// Generate a sequence for accessing addresses within any 2GiB range
// within the address space. This generates the pattern (PseudoLLA sym),
// which expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
Result = MIB.buildInstr(RISCV::PseudoLLA)
- .addDef(DstReg)
+ .addDef(DefReg)
.addGlobalAddress(GV, 0);
+ }
if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
return false;
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
index 9e725e0764289ee..07329eb0453919e 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
@@ -1,6 +1,15 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
-# RUN: %s -o - | FileCheck --check-prefix=RV64-SMALL %s
+# RUN: %s -o - | FileCheck --check-prefix=RV64-SMALL-NOPIE-NOTAG %s
+
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
+# RUN: -mattr=+tagged-globals %s -o - | FileCheck --check-prefix=RV64-SMALL-TAGGED %s
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
+# RUN: -relocation-model=pic %s -o - | FileCheck --check-prefix=RV64-SMALL-PIE %s
+
+# RUN: llc -mtriple=riscv64 -mattr=+tagged-globals -run-pass=instruction-select -code-model=small \
+# RUN: -relocation-model=pic %s -o - | FileCheck --check-prefix=RV64-SMALL-PIEANDLOCAL %s
+
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=medium \
# RUN: %s -o - | FileCheck --check-prefix=RV64-MED %s
@@ -10,11 +19,16 @@
entry:
ret ptr @x
}
- @y = external global i32, align 4
- define ptr @extern_global_addr() {
+ @y = extern_weak global i32, align 4
+ define ptr @extern_weak_global_addr() {
entry:
ret ptr @y
}
+ @z = dso_local global i32 0, align 4
+ define ptr @local_global_addr() {
+ entry:
+ ret ptr @z
+ }
...
---
name: global_addr
@@ -25,11 +39,26 @@ registers:
- { id: 0, class: gprb, preferred-register: '' }
body: |
bb.1.entry:
- ; RV64-SMALL-LABEL: name: global_addr
- ; RV64-SMALL: [[LUI:%[0-9]+]]:gpr = LUI @x + 4
- ; RV64-SMALL-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @x
- ; RV64-SMALL-NEXT: $x10 = COPY [[ADDI]]
- ; RV64-SMALL-NEXT: PseudoRET implicit $x10
+ ; RV64-SMALL-NOPIE-NOTAG-LABEL: name: global_addr
+ ; RV64-SMALL-NOPIE-NOTAG: [[LUI:%[0-9]+]]:gpr = LUI @x + 4
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @x
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: $x10 = COPY [[ADDI]]
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-SMALL-TAGGED-LABEL: name: global_addr
+ ; RV64-SMALL-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-TAGGED-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-SMALL-PIE-LABEL: name: global_addr
+ ; RV64-SMALL-PIE: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-SMALL-PIEANDLOCAL-LABEL: name: global_addr
+ ; RV64-SMALL-PIEANDLOCAL: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-PIEANDLOCAL-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-PIEANDLOCAL-NEXT: PseudoRET implicit $x10
;
; RV64-MED-LABEL: name: global_addr
; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @x
@@ -40,7 +69,7 @@ body: |
PseudoRET implicit $x10
...
---
-name: extern_global_addr
+name: extern_weak_global_addr
legalized: true
regBankSelected: true
tracksRegLiveness: true
@@ -48,18 +77,71 @@ registers:
- { id: 0, class: gprb, preferred-register: '' }
body: |
bb.1.entry:
- ; RV64-SMALL-LABEL: name: extern_global_addr
- ; RV64-SMALL: [[LUI:%[0-9]+]]:gpr = LUI @y + 4
- ; RV64-SMALL-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @y
- ; RV64-SMALL-NEXT: $x10 = COPY [[ADDI]]
- ; RV64-SMALL-NEXT: PseudoRET implicit $x10
+ ; RV64-SMALL-NOPIE-NOTAG-LABEL: name: extern_weak_global_addr
+ ; RV64-SMALL-NOPIE-NOTAG: [[LUI:%[0-9]+]]:gpr = LUI @y + 4
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @y
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: $x10 = COPY [[ADDI]]
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: PseudoRET implicit $x10
;
- ; RV64-MED-LABEL: name: extern_global_addr
- ; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @y
- ; RV64-MED-NEXT: $x10 = COPY [[PseudoLLA]]
+ ; RV64-SMALL-TAGGED-LABEL: name: extern_weak_global_addr
+ ; RV64-SMALL-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-TAGGED-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-SMALL-PIE-LABEL: name: extern_weak_global_addr
+ ; RV64-SMALL-PIE: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-SMALL-PIEANDLOCAL-LABEL: name: extern_weak_global_addr
+ ; RV64-SMALL-PIEANDLOCAL: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-PIEANDLOCAL-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-PIEANDLOCAL-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-MED-LABEL: name: extern_weak_global_addr
+ ; RV64-MED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
+ ; RV64-MED-NEXT: $x10 = COPY [[PseudoLGA]]
; RV64-MED-NEXT: PseudoRET implicit $x10
%0:gprb(p0) = G_GLOBAL_VALUE @y
$x10 = COPY %0(p0)
PseudoRET implicit $x10
...
+---
+name: local_global_addr
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: gprb, preferred-register: '' }
+body: |
+ bb.1.entry:
+ ; RV64-SMALL-NOPIE-NOTAG-LABEL: name: local_global_addr
+ ; RV64-SMALL-NOPIE-NOTAG: [[LUI:%[0-9]+]]:gpr = LUI @z + 4
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @z
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: $x10 = COPY [[ADDI]]
+ ; RV64-SMALL-NOPIE-NOTAG-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-SMALL-TAGGED-LABEL: name: local_global_addr
+ ; RV64-SMALL-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @z :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-TAGGED-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-SMALL-PIE-LABEL: name: local_global_addr
+ ; RV64-SMALL-PIE: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @z
+ ; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLLA]]
+ ; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-SMALL-PIEANDLOCAL-LABEL: name: local_global_addr
+ ; RV64-SMALL-PIEANDLOCAL: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @z :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-PIEANDLOCAL-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-PIEANDLOCAL-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-MED-LABEL: name: local_global_addr
+ ; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @z
+ ; RV64-MED-NEXT: $x10 = COPY [[PseudoLLA]]
+ ; RV64-MED-NEXT: PseudoRET implicit $x10
+ %0:gprb(p0) = G_GLOBAL_VALUE @z
+ $x10 = COPY %0(p0)
+ PseudoRET implicit $x10
+...
>From 7d88c5eac50e47b80a0d8765700f2ed120487eac Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Tue, 24 Oct 2023 15:03:47 -0700
Subject: [PATCH 5/7] update test naming and movie common code outside switch
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 12 +++-----
.../instruction-select/global-value.mir | 29 +++++++++----------
2 files changed, 17 insertions(+), 24 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index fa142a4dea68d6e..5a7ef10e4109b41 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -500,6 +500,10 @@ bool RISCVInstructionSelector::selectGlobalValue(
return false;
}
+ Register DefReg = MI.getOperand(0).getReg();
+ const LLT DefTy = MRI.getType(DefReg);
+ MachineInstr *Result = nullptr;
+
switch (TM.getCodeModel()) {
default: {
reportGISelFailure(const_cast<MachineFunction &>(*MF), *TPC, *MORE,
@@ -507,10 +511,6 @@ bool RISCVInstructionSelector::selectGlobalValue(
return false;
}
case CodeModel::Small: {
- Register DefReg = MI.getOperand(0).getReg();
- const LLT DefTy = MRI.getType(DefReg);
- MachineInstr *Result = nullptr;
-
// When HWASAN is used and tagging of global variables is enabled
// they should be accessed via the GOT, since the tagged address of a global
// is incompatible with existing code models. This also applies to non-pic
@@ -566,10 +566,6 @@ bool RISCVInstructionSelector::selectGlobalValue(
return true;
}
case CodeModel::Medium: {
- Register DefReg = MI.getOperand(0).getReg();
- const LLT DefTy = MRI.getType(DefReg);
- MachineInstr *Result = nullptr;
-
// Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
// relocation needs to reference a label that points to the auipc
// instruction itself, not the global. This cannot be done inside the
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
index 07329eb0453919e..c404c1b404d12a2 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
@@ -1,15 +1,12 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
# RUN: %s -o - | FileCheck --check-prefix=RV64-SMALL-NOPIE-NOTAG %s
-
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
# RUN: -mattr=+tagged-globals %s -o - | FileCheck --check-prefix=RV64-SMALL-TAGGED %s
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
# RUN: -relocation-model=pic %s -o - | FileCheck --check-prefix=RV64-SMALL-PIE %s
-
# RUN: llc -mtriple=riscv64 -mattr=+tagged-globals -run-pass=instruction-select -code-model=small \
-# RUN: -relocation-model=pic %s -o - | FileCheck --check-prefix=RV64-SMALL-PIEANDLOCAL %s
-
+# RUN: -relocation-model=pic %s -o - | FileCheck --check-prefix=RV64-SMALL-PIE-TAGGED %s
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=medium \
# RUN: %s -o - | FileCheck --check-prefix=RV64-MED %s
@@ -55,10 +52,10 @@ body: |
; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLGA]]
; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
;
- ; RV64-SMALL-PIEANDLOCAL-LABEL: name: global_addr
- ; RV64-SMALL-PIEANDLOCAL: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-PIEANDLOCAL-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-PIEANDLOCAL-NEXT: PseudoRET implicit $x10
+ ; RV64-SMALL-PIE-TAGGED-LABEL: name: global_addr
+ ; RV64-SMALL-PIE-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-PIE-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-PIE-TAGGED-NEXT: PseudoRET implicit $x10
;
; RV64-MED-LABEL: name: global_addr
; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @x
@@ -93,10 +90,10 @@ body: |
; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLGA]]
; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
;
- ; RV64-SMALL-PIEANDLOCAL-LABEL: name: extern_weak_global_addr
- ; RV64-SMALL-PIEANDLOCAL: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-PIEANDLOCAL-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-PIEANDLOCAL-NEXT: PseudoRET implicit $x10
+ ; RV64-SMALL-PIE-TAGGED-LABEL: name: extern_weak_global_addr
+ ; RV64-SMALL-PIE-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-PIE-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-PIE-TAGGED-NEXT: PseudoRET implicit $x10
;
; RV64-MED-LABEL: name: extern_weak_global_addr
; RV64-MED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
@@ -131,10 +128,10 @@ body: |
; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLLA]]
; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
;
- ; RV64-SMALL-PIEANDLOCAL-LABEL: name: local_global_addr
- ; RV64-SMALL-PIEANDLOCAL: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @z :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-PIEANDLOCAL-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-PIEANDLOCAL-NEXT: PseudoRET implicit $x10
+ ; RV64-SMALL-PIE-TAGGED-LABEL: name: local_global_addr
+ ; RV64-SMALL-PIE-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @z :: (dereferenceable invariant load (p0) from got)
+ ; RV64-SMALL-PIE-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-SMALL-PIE-TAGGED-NEXT: PseudoRET implicit $x10
;
; RV64-MED-LABEL: name: local_global_addr
; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @z
>From c6d265bb4b4c50e4f8f18b650e7c435deda15743 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Tue, 24 Oct 2023 15:11:22 -0700
Subject: [PATCH 6/7] clang-format
---
llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 5a7ef10e4109b41..cb2592ac87e1a78 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -577,10 +577,10 @@ bool RISCVInstructionSelector::selectGlobalValue(
// (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
MachineFunction &MF = *MI.getParent()->getParent();
MachineMemOperand *MemOp = MF.getMachineMemOperand(
- MachinePointerInfo::getGOT(MF),
- MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
- MachineMemOperand::MOInvariant,
- DefTy, Align(DefTy.getSizeInBits() / 8));
+ MachinePointerInfo::getGOT(MF),
+ MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
+ MachineMemOperand::MOInvariant,
+ DefTy, Align(DefTy.getSizeInBits() / 8));
Result = MIB.buildInstr(RISCV::PseudoLGA)
.addDef(DefReg)
>From c9b587e7fbeb94bd6af131d7eff4e8d81ca1c6c7 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Tue, 24 Oct 2023 18:11:06 -0700
Subject: [PATCH 7/7] move PIE part out of switch
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 68 ++++++++-------
.../instruction-select/global-value.mir | 86 ++++++++-----------
2 files changed, 72 insertions(+), 82 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index cb2592ac87e1a78..dd4f2f646b3f04c 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -504,27 +504,19 @@ bool RISCVInstructionSelector::selectGlobalValue(
const LLT DefTy = MRI.getType(DefReg);
MachineInstr *Result = nullptr;
- switch (TM.getCodeModel()) {
- default: {
- reportGISelFailure(const_cast<MachineFunction &>(*MF), *TPC, *MORE,
- getName(), "Unsupported code model for lowering", MI);
- return false;
- }
- case CodeModel::Small: {
- // When HWASAN is used and tagging of global variables is enabled
- // they should be accessed via the GOT, since the tagged address of a global
- // is incompatible with existing code models. This also applies to non-pic
- // mode.
- if (TM.isPositionIndependent() && GV->isDSOLocal() &&
- !Subtarget->allowTaggedGlobals()) {
+ // When HWASAN is used and tagging of global variables is enabled
+ // they should be accessed via the GOT, since the tagged address of a global
+ // is incompatible with existing code models. This also applies to non-pic
+ // mode.
+ if (TM.isPositionIndependent() || Subtarget->allowTaggedGlobals()) {
+ if (GV->isDSOLocal() && !Subtarget->allowTaggedGlobals()) {
// Use PC-relative addressing to access the symbol. This generates the
// pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
// %pcrel_lo(auipc)).
Result = MIB.buildInstr(RISCV::PseudoLLA)
.addDef(DefReg)
.addGlobalAddress(GV, 0);
- } else if (Subtarget->allowTaggedGlobals() ||
- (TM.isPositionIndependent() && !GV->isDSOLocal())) {
+ } else {
// Use PC-relative addressing to access the GOT for this symbol, then
// load the address from the GOT. This generates the pattern (PseudoLGA
// sym), which expands to (ld (addi (auipc %got_pcrel_hi(sym))
@@ -541,22 +533,6 @@ bool RISCVInstructionSelector::selectGlobalValue(
.addDef(DefReg)
.addGlobalAddress(GV, 0)
.addMemOperand(MemOp);
- } else {
- // Must lie within a single 2 GiB address range and must lie between
- // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
- // (lui %hi(sym)) %lo(sym)).
- Register AddrHiDest = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- MachineInstr *AddrHi = MIB.buildInstr(RISCV::LUI)
- .addDef(AddrHiDest)
- .addGlobalAddress(GV, RISCVII::MO_HI);
-
- if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
- return false;
-
- Result = MIB.buildInstr(RISCV::ADDI)
- .addDef(DefReg)
- .addReg(AddrHiDest)
- .addGlobalAddress(GV, 0, RISCVII::MO_LO);
}
if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
@@ -565,6 +541,36 @@ bool RISCVInstructionSelector::selectGlobalValue(
MI.eraseFromParent();
return true;
}
+
+ switch (TM.getCodeModel()) {
+ default: {
+ reportGISelFailure(const_cast<MachineFunction &>(*MF), *TPC, *MORE,
+ getName(), "Unsupported code model for lowering", MI);
+ return false;
+ }
+ case CodeModel::Small: {
+ // Must lie within a single 2 GiB address range and must lie between
+ // absolute addresses -2 GiB and +2 GiB. This generates the pattern (addi
+ // (lui %hi(sym)) %lo(sym)).
+ Register AddrHiDest = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ MachineInstr *AddrHi = MIB.buildInstr(RISCV::LUI)
+ .addDef(AddrHiDest)
+ .addGlobalAddress(GV, RISCVII::MO_HI);
+
+ if (!constrainSelectedInstRegOperands(*AddrHi, TII, TRI, RBI))
+ return false;
+
+ Result = MIB.buildInstr(RISCV::ADDI)
+ .addDef(DefReg)
+ .addReg(AddrHiDest)
+ .addGlobalAddress(GV, 0, RISCVII::MO_LO);
+
+ if (!constrainSelectedInstRegOperands(*Result, TII, TRI, RBI))
+ return false;
+
+ MI.eraseFromParent();
+ return true;
+ }
case CodeModel::Medium: {
// Emit LGA/LLA instead of the sequence it expands to because the pcrel_lo
// relocation needs to reference a label that points to the auipc
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
index c404c1b404d12a2..440afaab7b28efe 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/global-value.mir
@@ -1,12 +1,11 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -relocation-model=pic \
+# RUN: %s -o - | FileCheck --check-prefix=RV64-PIE %s
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select \
+# RUN: -mattr=+tagged-globals %s -o - | FileCheck \
+# RUN: --check-prefix=RV64-NOPIE-TAG %s
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
# RUN: %s -o - | FileCheck --check-prefix=RV64-SMALL-NOPIE-NOTAG %s
-# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
-# RUN: -mattr=+tagged-globals %s -o - | FileCheck --check-prefix=RV64-SMALL-TAGGED %s
-# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=small \
-# RUN: -relocation-model=pic %s -o - | FileCheck --check-prefix=RV64-SMALL-PIE %s
-# RUN: llc -mtriple=riscv64 -mattr=+tagged-globals -run-pass=instruction-select -code-model=small \
-# RUN: -relocation-model=pic %s -o - | FileCheck --check-prefix=RV64-SMALL-PIE-TAGGED %s
# RUN: llc -mtriple=riscv64 -run-pass=instruction-select -code-model=medium \
# RUN: %s -o - | FileCheck --check-prefix=RV64-MED %s
@@ -36,27 +35,22 @@ registers:
- { id: 0, class: gprb, preferred-register: '' }
body: |
bb.1.entry:
+ ; RV64-PIE-LABEL: name: global_addr
+ ; RV64-PIE: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
+ ; RV64-PIE-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-PIE-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-NOPIE-TAG-LABEL: name: global_addr
+ ; RV64-NOPIE-TAG: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
+ ; RV64-NOPIE-TAG-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-NOPIE-TAG-NEXT: PseudoRET implicit $x10
+ ;
; RV64-SMALL-NOPIE-NOTAG-LABEL: name: global_addr
; RV64-SMALL-NOPIE-NOTAG: [[LUI:%[0-9]+]]:gpr = LUI @x + 4
; RV64-SMALL-NOPIE-NOTAG-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @x
; RV64-SMALL-NOPIE-NOTAG-NEXT: $x10 = COPY [[ADDI]]
; RV64-SMALL-NOPIE-NOTAG-NEXT: PseudoRET implicit $x10
;
- ; RV64-SMALL-TAGGED-LABEL: name: global_addr
- ; RV64-SMALL-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-TAGGED-NEXT: PseudoRET implicit $x10
- ;
- ; RV64-SMALL-PIE-LABEL: name: global_addr
- ; RV64-SMALL-PIE: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
- ;
- ; RV64-SMALL-PIE-TAGGED-LABEL: name: global_addr
- ; RV64-SMALL-PIE-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @x :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-PIE-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-PIE-TAGGED-NEXT: PseudoRET implicit $x10
- ;
; RV64-MED-LABEL: name: global_addr
; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @x
; RV64-MED-NEXT: $x10 = COPY [[PseudoLLA]]
@@ -74,27 +68,22 @@ registers:
- { id: 0, class: gprb, preferred-register: '' }
body: |
bb.1.entry:
+ ; RV64-PIE-LABEL: name: extern_weak_global_addr
+ ; RV64-PIE: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
+ ; RV64-PIE-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-PIE-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-NOPIE-TAG-LABEL: name: extern_weak_global_addr
+ ; RV64-NOPIE-TAG: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
+ ; RV64-NOPIE-TAG-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-NOPIE-TAG-NEXT: PseudoRET implicit $x10
+ ;
; RV64-SMALL-NOPIE-NOTAG-LABEL: name: extern_weak_global_addr
; RV64-SMALL-NOPIE-NOTAG: [[LUI:%[0-9]+]]:gpr = LUI @y + 4
; RV64-SMALL-NOPIE-NOTAG-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @y
; RV64-SMALL-NOPIE-NOTAG-NEXT: $x10 = COPY [[ADDI]]
; RV64-SMALL-NOPIE-NOTAG-NEXT: PseudoRET implicit $x10
;
- ; RV64-SMALL-TAGGED-LABEL: name: extern_weak_global_addr
- ; RV64-SMALL-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-TAGGED-NEXT: PseudoRET implicit $x10
- ;
- ; RV64-SMALL-PIE-LABEL: name: extern_weak_global_addr
- ; RV64-SMALL-PIE: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
- ;
- ; RV64-SMALL-PIE-TAGGED-LABEL: name: extern_weak_global_addr
- ; RV64-SMALL-PIE-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-PIE-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-PIE-TAGGED-NEXT: PseudoRET implicit $x10
- ;
; RV64-MED-LABEL: name: extern_weak_global_addr
; RV64-MED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @y :: (dereferenceable invariant load (p0) from got)
; RV64-MED-NEXT: $x10 = COPY [[PseudoLGA]]
@@ -112,27 +101,22 @@ registers:
- { id: 0, class: gprb, preferred-register: '' }
body: |
bb.1.entry:
+ ; RV64-PIE-LABEL: name: local_global_addr
+ ; RV64-PIE: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @z
+ ; RV64-PIE-NEXT: $x10 = COPY [[PseudoLLA]]
+ ; RV64-PIE-NEXT: PseudoRET implicit $x10
+ ;
+ ; RV64-NOPIE-TAG-LABEL: name: local_global_addr
+ ; RV64-NOPIE-TAG: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @z :: (dereferenceable invariant load (p0) from got)
+ ; RV64-NOPIE-TAG-NEXT: $x10 = COPY [[PseudoLGA]]
+ ; RV64-NOPIE-TAG-NEXT: PseudoRET implicit $x10
+ ;
; RV64-SMALL-NOPIE-NOTAG-LABEL: name: local_global_addr
; RV64-SMALL-NOPIE-NOTAG: [[LUI:%[0-9]+]]:gpr = LUI @z + 4
; RV64-SMALL-NOPIE-NOTAG-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], target-flags(riscv-lo) @z
; RV64-SMALL-NOPIE-NOTAG-NEXT: $x10 = COPY [[ADDI]]
; RV64-SMALL-NOPIE-NOTAG-NEXT: PseudoRET implicit $x10
;
- ; RV64-SMALL-TAGGED-LABEL: name: local_global_addr
- ; RV64-SMALL-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @z :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-TAGGED-NEXT: PseudoRET implicit $x10
- ;
- ; RV64-SMALL-PIE-LABEL: name: local_global_addr
- ; RV64-SMALL-PIE: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @z
- ; RV64-SMALL-PIE-NEXT: $x10 = COPY [[PseudoLLA]]
- ; RV64-SMALL-PIE-NEXT: PseudoRET implicit $x10
- ;
- ; RV64-SMALL-PIE-TAGGED-LABEL: name: local_global_addr
- ; RV64-SMALL-PIE-TAGGED: [[PseudoLGA:%[0-9]+]]:gpr = PseudoLGA @z :: (dereferenceable invariant load (p0) from got)
- ; RV64-SMALL-PIE-TAGGED-NEXT: $x10 = COPY [[PseudoLGA]]
- ; RV64-SMALL-PIE-TAGGED-NEXT: PseudoRET implicit $x10
- ;
; RV64-MED-LABEL: name: local_global_addr
; RV64-MED: [[PseudoLLA:%[0-9]+]]:gpr = PseudoLLA @z
; RV64-MED-NEXT: $x10 = COPY [[PseudoLLA]]
More information about the llvm-commits
mailing list