Skip to content

Commit

Permalink
[RISCV] Support the large code model. (#70308)
Browse files Browse the repository at this point in the history
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 <rufus@andestech.com>
  • Loading branch information
tclin914 and Kuan-Lin Chen authored Sep 9, 2024
1 parent 9d8950a commit fef84c5
Show file tree
Hide file tree
Showing 10 changed files with 1,774 additions and 2 deletions.
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_llvm_target(RISCVCodeGen
RISCVAsmPrinter.cpp
RISCVCallingConv.cpp
RISCVCodeGenPrepare.cpp
RISCVConstantPoolValue.cpp
RISCVDeadRegisterDefinitions.cpp
RISCVMakeCompressible.cpp
RISCVExpandAtomicPseudoInsts.cpp
Expand Down
23 changes: 23 additions & 0 deletions llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "MCTargetDesc/RISCVMatInt.h"
#include "MCTargetDesc/RISCVTargetStreamer.h"
#include "RISCV.h"
#include "RISCVConstantPoolValue.h"
#include "RISCVMachineFunctionInfo.h"
#include "RISCVTargetMachine.h"
#include "TargetInfo/RISCVTargetInfo.h"
Expand Down Expand Up @@ -77,6 +78,8 @@ class RISCVAsmPrinter : public AsmPrinter {

void emitInstruction(const MachineInstr *MI) override;

void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;

bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode, raw_ostream &OS) override;
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
Expand Down Expand Up @@ -1080,3 +1083,23 @@ bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
}
return false;
}

void RISCVAsmPrinter::emitMachineConstantPoolValue(
MachineConstantPoolValue *MCPV) {
auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);
MCSymbol *MCSym;

if (RCPV->isGlobalValue()) {
auto *GV = RCPV->getGlobalValue();
MCSym = getSymbol(GV);
} else {
assert(RCPV->isExtSymbol() && "unrecognized constant pool type");
auto Sym = RCPV->getSymbol();
MCSym = GetExternalSymbolSymbol(Sym);
}

const MCExpr *Expr =
MCSymbolRefExpr::create(MCSym, MCSymbolRefExpr::VK_None, OutContext);
uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());
OutStreamer->emitValue(Expr, Size);
}
81 changes: 81 additions & 0 deletions llvm/lib/Target/RISCV/RISCVConstantPoolValue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//===------- RISCVConstantPoolValue.cpp - RISC-V constantpool value -------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the RISC-V specific constantpool value class.
//
//===----------------------------------------------------------------------===//

#include "RISCVConstantPoolValue.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

RISCVConstantPoolValue::RISCVConstantPoolValue(Type *Ty, const GlobalValue *GV)
: MachineConstantPoolValue(Ty), GV(GV), Kind(RISCVCPKind::GlobalValue) {}

RISCVConstantPoolValue::RISCVConstantPoolValue(LLVMContext &C, StringRef S)
: MachineConstantPoolValue(Type::getInt64Ty(C)), S(S),
Kind(RISCVCPKind::ExtSymbol) {}

RISCVConstantPoolValue *RISCVConstantPoolValue::Create(const GlobalValue *GV) {
return new RISCVConstantPoolValue(GV->getType(), GV);
}

RISCVConstantPoolValue *RISCVConstantPoolValue::Create(LLVMContext &C,
StringRef S) {
return new RISCVConstantPoolValue(C, S);
}

int RISCVConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
Align Alignment) {
const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
if (Constants[i].isMachineConstantPoolEntry() &&
Constants[i].getAlign() >= Alignment) {
auto *CPV =
static_cast<RISCVConstantPoolValue *>(Constants[i].Val.MachineCPVal);
if (equals(CPV))
return i;
}
}

return -1;
}

void RISCVConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
if (isGlobalValue())
ID.AddPointer(GV);
else {
assert(isExtSymbol() && "unrecognized constant pool type");
ID.AddString(S);
}
}

void RISCVConstantPoolValue::print(raw_ostream &O) const {
if (isGlobalValue())
O << GV->getName();
else {
assert(isExtSymbol() && "unrecognized constant pool type");
O << S;
}
}

bool RISCVConstantPoolValue::equals(const RISCVConstantPoolValue *A) const {
if (isGlobalValue() && A->isGlobalValue())
return GV == A->GV;
if (isExtSymbol() && A->isExtSymbol())
return S == A->S;

return false;
}
63 changes: 63 additions & 0 deletions llvm/lib/Target/RISCV/RISCVConstantPoolValue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===--- RISCVConstantPoolValue.h - RISC-V constantpool value ---*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the RISC-V specific constantpool value class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_RISCV_RISCVCONSTANTPOOLVALUE_H
#define LLVM_LIB_TARGET_RISCV_RISCVCONSTANTPOOLVALUE_H

#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"

namespace llvm {

class BlockAddress;
class GlobalValue;
class LLVMContext;

/// A RISCV-specific constant pool value.
class RISCVConstantPoolValue : public MachineConstantPoolValue {
const GlobalValue *GV;
const StringRef S;

RISCVConstantPoolValue(Type *Ty, const GlobalValue *GV);
RISCVConstantPoolValue(LLVMContext &C, StringRef S);

private:
enum class RISCVCPKind { ExtSymbol, GlobalValue };
RISCVCPKind Kind;

public:
~RISCVConstantPoolValue() = default;

static RISCVConstantPoolValue *Create(const GlobalValue *GV);
static RISCVConstantPoolValue *Create(LLVMContext &C, StringRef S);

bool isGlobalValue() const { return Kind == RISCVCPKind::GlobalValue; }
bool isExtSymbol() const { return Kind == RISCVCPKind::ExtSymbol; }

const GlobalValue *getGlobalValue() const { return GV; }
StringRef getSymbol() const { return S; }

int getExistingMachineCPValue(MachineConstantPool *CP,
Align Alignment) override;

void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;

void print(raw_ostream &O) const override;

bool equals(const RISCVConstantPoolValue *A) const;
};

} // end namespace llvm

#endif
37 changes: 36 additions & 1 deletion llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "RISCVISelLowering.h"
#include "MCTargetDesc/RISCVMatInt.h"
#include "RISCV.h"
#include "RISCVConstantPoolValue.h"
#include "RISCVMachineFunctionInfo.h"
#include "RISCVRegisterInfo.h"
#include "RISCVSubtarget.h"
Expand Down Expand Up @@ -7518,6 +7519,27 @@ static SDValue getTargetNode(JumpTableSDNode *N, const SDLoc &DL, EVT Ty,
return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
}

static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL,
EVT Ty, SelectionDAG &DAG) {
RISCVConstantPoolValue *CPV = RISCVConstantPoolValue::Create(N->getGlobal());
SDValue CPAddr = DAG.getTargetConstantPool(CPV, Ty, Align(8));
SDValue LC = DAG.getNode(RISCVISD::LLA, DL, Ty, CPAddr);
return DAG.getLoad(
Ty, DL, DAG.getEntryNode(), LC,
MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
}

static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL,
EVT Ty, SelectionDAG &DAG) {
RISCVConstantPoolValue *CPV =
RISCVConstantPoolValue::Create(*DAG.getContext(), N->getSymbol());
SDValue CPAddr = DAG.getTargetConstantPool(CPV, Ty, Align(8));
SDValue LC = DAG.getNode(RISCVISD::LLA, DL, Ty, CPAddr);
return DAG.getLoad(
Ty, DL, DAG.getEntryNode(), LC,
MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
}

template <class NodeTy>
SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
bool IsLocal, bool IsExternWeak) const {
Expand Down Expand Up @@ -7586,6 +7608,14 @@ SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
// expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
}
case CodeModel::Large: {
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N))
return getLargeGlobalAddress(G, DL, Ty, DAG);

// Using pc-relative mode for other node type.
SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
}
}
}

Expand Down Expand Up @@ -19590,7 +19620,12 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
// If the callee is a GlobalAddress/ExternalSymbol node, turn it into a
// TargetGlobalAddress/TargetExternalSymbol node so that legalize won't
// split it and then direct call can be matched by PseudoCALL.
if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
if (getTargetMachine().getCodeModel() == CodeModel::Large) {
if (auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
Callee = getLargeGlobalAddress(S, DL, PtrVT, DAG);
else if (auto *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Callee = getLargeExternalSymbol(S, DL, PtrVT, DAG);
} else if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
const GlobalValue *GV = S->getGlobal();
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, RISCVII::MO_CALL);
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ bool RISCVELFTargetObjectFile::isConstantInSmallSection(
MCSection *RISCVELFTargetObjectFile::getSectionForConstant(
const DataLayout &DL, SectionKind Kind, const Constant *C,
Align &Alignment) const {
if (isConstantInSmallSection(DL, C)) {
if (C && isConstantInSmallSection(DL, C)) {
if (Kind.isMergeableConst4())
return SmallROData4Section;
if (Kind.isMergeableConst8())
Expand Down
Loading

0 comments on commit fef84c5

Please sign in to comment.