Skip to content

Commit 068a6bd

Browse files
tclin914Kuan-Lin Chen
authored andcommitted
[RISCV] Support the large code model. (llvm#70308)
Implement large code model for GlobalAddressSDNode and ExternalSymbolSDNode. See discussion on riscv-non-isa/riscv-elf-psabi-doc#388. --------- Co-authored-by: Kuan-Lin Chen <[email protected]>
1 parent fa269ce commit 068a6bd

File tree

10 files changed

+1774
-2
lines changed

10 files changed

+1774
-2
lines changed

llvm/lib/Target/RISCV/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ add_public_tablegen_target(RISCVCommonTableGen)
3030
add_llvm_target(RISCVCodeGen
3131
RISCVAsmPrinter.cpp
3232
RISCVCodeGenPrepare.cpp
33+
RISCVConstantPoolValue.cpp
3334
RISCVDeadRegisterDefinitions.cpp
3435
RISCVMakeCompressible.cpp
3536
RISCVExpandAtomicPseudoInsts.cpp

llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "MCTargetDesc/RISCVMatInt.h"
1818
#include "MCTargetDesc/RISCVTargetStreamer.h"
1919
#include "RISCV.h"
20+
#include "RISCVConstantPoolValue.h"
2021
#include "RISCVMachineFunctionInfo.h"
2122
#include "RISCVTargetMachine.h"
2223
#include "TargetInfo/RISCVTargetInfo.h"
@@ -77,6 +78,8 @@ class RISCVAsmPrinter : public AsmPrinter {
7778

7879
void emitInstruction(const MachineInstr *MI) override;
7980

81+
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
82+
8083
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
8184
const char *ExtraCode, raw_ostream &OS) override;
8285
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
@@ -1085,3 +1088,23 @@ bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
10851088
}
10861089
return false;
10871090
}
1091+
1092+
void RISCVAsmPrinter::emitMachineConstantPoolValue(
1093+
MachineConstantPoolValue *MCPV) {
1094+
auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);
1095+
MCSymbol *MCSym;
1096+
1097+
if (RCPV->isGlobalValue()) {
1098+
auto *GV = RCPV->getGlobalValue();
1099+
MCSym = getSymbol(GV);
1100+
} else {
1101+
assert(RCPV->isExtSymbol() && "unrecognized constant pool type");
1102+
auto Sym = RCPV->getSymbol();
1103+
MCSym = GetExternalSymbolSymbol(Sym);
1104+
}
1105+
1106+
const MCExpr *Expr =
1107+
MCSymbolRefExpr::create(MCSym, MCSymbolRefExpr::VK_None, OutContext);
1108+
uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1109+
OutStreamer->emitValue(Expr, Size);
1110+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//===------- RISCVConstantPoolValue.cpp - RISC-V constantpool value -------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file implements the RISC-V specific constantpool value class.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "RISCVConstantPoolValue.h"
14+
#include "llvm/ADT/FoldingSet.h"
15+
#include "llvm/IR/Constants.h"
16+
#include "llvm/IR/DerivedTypes.h"
17+
#include "llvm/IR/GlobalValue.h"
18+
#include "llvm/IR/Type.h"
19+
#include "llvm/Support/Casting.h"
20+
#include "llvm/Support/raw_ostream.h"
21+
22+
using namespace llvm;
23+
24+
RISCVConstantPoolValue::RISCVConstantPoolValue(Type *Ty, const GlobalValue *GV)
25+
: MachineConstantPoolValue(Ty), GV(GV), Kind(RISCVCPKind::GlobalValue) {}
26+
27+
RISCVConstantPoolValue::RISCVConstantPoolValue(LLVMContext &C, StringRef S)
28+
: MachineConstantPoolValue(Type::getInt64Ty(C)), S(S),
29+
Kind(RISCVCPKind::ExtSymbol) {}
30+
31+
RISCVConstantPoolValue *RISCVConstantPoolValue::Create(const GlobalValue *GV) {
32+
return new RISCVConstantPoolValue(GV->getType(), GV);
33+
}
34+
35+
RISCVConstantPoolValue *RISCVConstantPoolValue::Create(LLVMContext &C,
36+
StringRef S) {
37+
return new RISCVConstantPoolValue(C, S);
38+
}
39+
40+
int RISCVConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
41+
Align Alignment) {
42+
const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
43+
for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
44+
if (Constants[i].isMachineConstantPoolEntry() &&
45+
Constants[i].getAlign() >= Alignment) {
46+
auto *CPV =
47+
static_cast<RISCVConstantPoolValue *>(Constants[i].Val.MachineCPVal);
48+
if (equals(CPV))
49+
return i;
50+
}
51+
}
52+
53+
return -1;
54+
}
55+
56+
void RISCVConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
57+
if (isGlobalValue())
58+
ID.AddPointer(GV);
59+
else {
60+
assert(isExtSymbol() && "unrecognized constant pool type");
61+
ID.AddString(S);
62+
}
63+
}
64+
65+
void RISCVConstantPoolValue::print(raw_ostream &O) const {
66+
if (isGlobalValue())
67+
O << GV->getName();
68+
else {
69+
assert(isExtSymbol() && "unrecognized constant pool type");
70+
O << S;
71+
}
72+
}
73+
74+
bool RISCVConstantPoolValue::equals(const RISCVConstantPoolValue *A) const {
75+
if (isGlobalValue() && A->isGlobalValue())
76+
return GV == A->GV;
77+
if (isExtSymbol() && A->isExtSymbol())
78+
return S == A->S;
79+
80+
return false;
81+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===--- RISCVConstantPoolValue.h - RISC-V constantpool value ---*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file implements the RISC-V specific constantpool value class.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_LIB_TARGET_RISCV_RISCVCONSTANTPOOLVALUE_H
14+
#define LLVM_LIB_TARGET_RISCV_RISCVCONSTANTPOOLVALUE_H
15+
16+
#include "llvm/ADT/StringRef.h"
17+
#include "llvm/CodeGen/MachineConstantPool.h"
18+
#include "llvm/Support/Casting.h"
19+
#include "llvm/Support/ErrorHandling.h"
20+
21+
namespace llvm {
22+
23+
class BlockAddress;
24+
class GlobalValue;
25+
class LLVMContext;
26+
27+
/// A RISCV-specific constant pool value.
28+
class RISCVConstantPoolValue : public MachineConstantPoolValue {
29+
const GlobalValue *GV;
30+
const StringRef S;
31+
32+
RISCVConstantPoolValue(Type *Ty, const GlobalValue *GV);
33+
RISCVConstantPoolValue(LLVMContext &C, StringRef S);
34+
35+
private:
36+
enum class RISCVCPKind { ExtSymbol, GlobalValue };
37+
RISCVCPKind Kind;
38+
39+
public:
40+
~RISCVConstantPoolValue() = default;
41+
42+
static RISCVConstantPoolValue *Create(const GlobalValue *GV);
43+
static RISCVConstantPoolValue *Create(LLVMContext &C, StringRef S);
44+
45+
bool isGlobalValue() const { return Kind == RISCVCPKind::GlobalValue; }
46+
bool isExtSymbol() const { return Kind == RISCVCPKind::ExtSymbol; }
47+
48+
const GlobalValue *getGlobalValue() const { return GV; }
49+
StringRef getSymbol() const { return S; }
50+
51+
int getExistingMachineCPValue(MachineConstantPool *CP,
52+
Align Alignment) override;
53+
54+
void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
55+
56+
void print(raw_ostream &O) const override;
57+
58+
bool equals(const RISCVConstantPoolValue *A) const;
59+
};
60+
61+
} // end namespace llvm
62+
63+
#endif

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "RISCVISelLowering.h"
1515
#include "MCTargetDesc/RISCVMatInt.h"
1616
#include "RISCV.h"
17+
#include "RISCVConstantPoolValue.h"
1718
#include "RISCVMachineFunctionInfo.h"
1819
#include "RISCVRegisterInfo.h"
1920
#include "RISCVSubtarget.h"
@@ -7407,6 +7408,27 @@ static SDValue getTargetNode(JumpTableSDNode *N, const SDLoc &DL, EVT Ty,
74077408
return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
74087409
}
74097410

7411+
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL,
7412+
EVT Ty, SelectionDAG &DAG) {
7413+
RISCVConstantPoolValue *CPV = RISCVConstantPoolValue::Create(N->getGlobal());
7414+
SDValue CPAddr = DAG.getTargetConstantPool(CPV, Ty, Align(8));
7415+
SDValue LC = DAG.getNode(RISCVISD::LLA, DL, Ty, CPAddr);
7416+
return DAG.getLoad(
7417+
Ty, DL, DAG.getEntryNode(), LC,
7418+
MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
7419+
}
7420+
7421+
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL,
7422+
EVT Ty, SelectionDAG &DAG) {
7423+
RISCVConstantPoolValue *CPV =
7424+
RISCVConstantPoolValue::Create(*DAG.getContext(), N->getSymbol());
7425+
SDValue CPAddr = DAG.getTargetConstantPool(CPV, Ty, Align(8));
7426+
SDValue LC = DAG.getNode(RISCVISD::LLA, DL, Ty, CPAddr);
7427+
return DAG.getLoad(
7428+
Ty, DL, DAG.getEntryNode(), LC,
7429+
MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
7430+
}
7431+
74107432
template <class NodeTy>
74117433
SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
74127434
bool IsLocal, bool IsExternWeak) const {
@@ -7475,6 +7497,14 @@ SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
74757497
// expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
74767498
return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
74777499
}
7500+
case CodeModel::Large: {
7501+
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N))
7502+
return getLargeGlobalAddress(G, DL, Ty, DAG);
7503+
7504+
// Using pc-relative mode for other node type.
7505+
SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
7506+
return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
7507+
}
74787508
}
74797509
}
74807510

@@ -20150,7 +20180,12 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
2015020180
// If the callee is a GlobalAddress/ExternalSymbol node, turn it into a
2015120181
// TargetGlobalAddress/TargetExternalSymbol node so that legalize won't
2015220182
// split it and then direct call can be matched by PseudoCALL.
20153-
if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
20183+
if (getTargetMachine().getCodeModel() == CodeModel::Large) {
20184+
if (auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
20185+
Callee = getLargeGlobalAddress(S, DL, PtrVT, DAG);
20186+
else if (auto *S = dyn_cast<ExternalSymbolSDNode>(Callee))
20187+
Callee = getLargeExternalSymbol(S, DL, PtrVT, DAG);
20188+
} else if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
2015420189
const GlobalValue *GV = S->getGlobal();
2015520190
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, RISCVII::MO_CALL);
2015620191
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {

llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ bool RISCVELFTargetObjectFile::isConstantInSmallSection(
161161
MCSection *RISCVELFTargetObjectFile::getSectionForConstant(
162162
const DataLayout &DL, SectionKind Kind, const Constant *C,
163163
Align &Alignment) const {
164-
if (isConstantInSmallSection(DL, C)) {
164+
if (C && isConstantInSmallSection(DL, C)) {
165165
if (Kind.isMergeableConst4())
166166
return SmallROData4Section;
167167
if (Kind.isMergeableConst8())

0 commit comments

Comments
 (0)