Skip to content

Commit fef84c5

Browse files
tclin914Kuan-Lin Chen
and
Kuan-Lin Chen
authored
[RISCV] Support the large code model. (#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 9d8950a commit fef84c5

10 files changed

+1774
-2
lines changed

llvm/lib/Target/RISCV/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ add_llvm_target(RISCVCodeGen
3131
RISCVAsmPrinter.cpp
3232
RISCVCallingConv.cpp
3333
RISCVCodeGenPrepare.cpp
34+
RISCVConstantPoolValue.cpp
3435
RISCVDeadRegisterDefinitions.cpp
3536
RISCVMakeCompressible.cpp
3637
RISCVExpandAtomicPseudoInsts.cpp

llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp

+23
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,
@@ -1080,3 +1083,23 @@ bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
10801083
}
10811084
return false;
10821085
}
1086+
1087+
void RISCVAsmPrinter::emitMachineConstantPoolValue(
1088+
MachineConstantPoolValue *MCPV) {
1089+
auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);
1090+
MCSymbol *MCSym;
1091+
1092+
if (RCPV->isGlobalValue()) {
1093+
auto *GV = RCPV->getGlobalValue();
1094+
MCSym = getSymbol(GV);
1095+
} else {
1096+
assert(RCPV->isExtSymbol() && "unrecognized constant pool type");
1097+
auto Sym = RCPV->getSymbol();
1098+
MCSym = GetExternalSymbolSymbol(Sym);
1099+
}
1100+
1101+
const MCExpr *Expr =
1102+
MCSymbolRefExpr::create(MCSym, MCSymbolRefExpr::VK_None, OutContext);
1103+
uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1104+
OutStreamer->emitValue(Expr, Size);
1105+
}
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+
}
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

+36-1
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"
@@ -7518,6 +7519,27 @@ static SDValue getTargetNode(JumpTableSDNode *N, const SDLoc &DL, EVT Ty,
75187519
return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
75197520
}
75207521

7522+
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL,
7523+
EVT Ty, SelectionDAG &DAG) {
7524+
RISCVConstantPoolValue *CPV = RISCVConstantPoolValue::Create(N->getGlobal());
7525+
SDValue CPAddr = DAG.getTargetConstantPool(CPV, Ty, Align(8));
7526+
SDValue LC = DAG.getNode(RISCVISD::LLA, DL, Ty, CPAddr);
7527+
return DAG.getLoad(
7528+
Ty, DL, DAG.getEntryNode(), LC,
7529+
MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
7530+
}
7531+
7532+
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL,
7533+
EVT Ty, SelectionDAG &DAG) {
7534+
RISCVConstantPoolValue *CPV =
7535+
RISCVConstantPoolValue::Create(*DAG.getContext(), N->getSymbol());
7536+
SDValue CPAddr = DAG.getTargetConstantPool(CPV, Ty, Align(8));
7537+
SDValue LC = DAG.getNode(RISCVISD::LLA, DL, Ty, CPAddr);
7538+
return DAG.getLoad(
7539+
Ty, DL, DAG.getEntryNode(), LC,
7540+
MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
7541+
}
7542+
75217543
template <class NodeTy>
75227544
SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
75237545
bool IsLocal, bool IsExternWeak) const {
@@ -7586,6 +7608,14 @@ SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
75867608
// expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
75877609
return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
75887610
}
7611+
case CodeModel::Large: {
7612+
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N))
7613+
return getLargeGlobalAddress(G, DL, Ty, DAG);
7614+
7615+
// Using pc-relative mode for other node type.
7616+
SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
7617+
return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
7618+
}
75897619
}
75907620
}
75917621

@@ -19590,7 +19620,12 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
1959019620
// If the callee is a GlobalAddress/ExternalSymbol node, turn it into a
1959119621
// TargetGlobalAddress/TargetExternalSymbol node so that legalize won't
1959219622
// split it and then direct call can be matched by PseudoCALL.
19593-
if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
19623+
if (getTargetMachine().getCodeModel() == CodeModel::Large) {
19624+
if (auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
19625+
Callee = getLargeGlobalAddress(S, DL, PtrVT, DAG);
19626+
else if (auto *S = dyn_cast<ExternalSymbolSDNode>(Callee))
19627+
Callee = getLargeExternalSymbol(S, DL, PtrVT, DAG);
19628+
} else if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
1959419629
const GlobalValue *GV = S->getGlobal();
1959519630
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, RISCVII::MO_CALL);
1959619631
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {

llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp

+1-1
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)