Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISCV] CodeGen of RVE and ilp32e/lp64e ABIs #76777

Merged
merged 1 commit into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,8 @@ RISC-V Support
^^^^^^^^^^^^^^
- Unaligned memory accesses can be toggled by ``-m[no-]unaligned-access`` or the
aliases ``-m[no-]strict-align``.
- CodeGen of RV32E/RV64E was supported experimentally.
- CodeGen of ilp32e/lp64e was supported experimentally.

- Default ABI with F but without D was changed to ilp32f for RV32 and to lp64f
for RV64.
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
else
Builder.defineMacro("__riscv_float_abi_soft");

if (ABIName == "ilp32e")
if (ABIName == "ilp32e" || ABIName == "lp64e")
Builder.defineMacro("__riscv_abi_rve");

Builder.defineMacro("__riscv_arch_test");
Expand Down Expand Up @@ -214,6 +214,13 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__riscv_misaligned_fast");
else
Builder.defineMacro("__riscv_misaligned_avoid");

if (ISAInfo->hasExtension("e")) {
if (Is64Bit)
Builder.defineMacro("__riscv_64e");
else
Builder.defineMacro("__riscv_32e");
}
}

static constexpr Builtin::Info BuiltinInfo[] = {
Expand Down Expand Up @@ -378,6 +385,11 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
if (llvm::is_contained(Features, "+experimental"))
HasExperimental = true;

if (ABI == "ilp32e" && ISAInfo->hasExtension("d")) {
Diags.Report(diag::err_invalid_feature_combination)
<< "ILP32E cannot be used with the D ISA extension";
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it also need to check ilp32e isn't compatible with zcmp?

Copy link
Contributor Author

@wangpc-pp wangpc-pp Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should!
(Sigh...even RISC-V International has forgotten RVE, as many new ISA extensions don't even think about impacts on RVE 😞).


There are still many problems to fix, I will leave this zcmp issue there and fix it after revising the psABI part.

return true;
}

Expand Down
12 changes: 12 additions & 0 deletions clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
}

bool setABI(const std::string &Name) override {
if (Name == "ilp32e") {
ABI = Name;
resetDataLayout("e-m:e-p:32:32-i64:64-n32-S32");
return true;
}

if (Name == "ilp32" || Name == "ilp32f" || Name == "ilp32d") {
ABI = Name;
return true;
Expand All @@ -156,6 +162,12 @@ class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo {
}

bool setABI(const std::string &Name) override {
if (Name == "lp64e") {
ABI = Name;
resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n32:64-S64");
return true;
}

if (Name == "lp64" || Name == "lp64f" || Name == "lp64d") {
ABI = Name;
return true;
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
ABIFLen = 32;
else if (ABIStr.ends_with("d"))
ABIFLen = 64;
return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen);
bool EABI = ABIStr.ends_with("e");
return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
}

case llvm::Triple::systemz: {
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,8 @@ createPPC64_SVR4_TargetCodeGenInfo(CodeGenModule &CGM, PPC64_SVR4_ABIKind Kind,
bool SoftFloatABI);

std::unique_ptr<TargetCodeGenInfo>
createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen, unsigned FLen);
createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen, unsigned FLen,
bool EABI);

std::unique_ptr<TargetCodeGenInfo>
createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM);
Expand Down
35 changes: 25 additions & 10 deletions clang/lib/CodeGen/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,20 @@ class RISCVABIInfo : public DefaultABIInfo {
// ISA might have a wider FLen than the selected ABI (e.g. an RV32IF target
// with soft float ABI has FLen==0).
unsigned FLen;
static const int NumArgGPRs = 8;
static const int NumArgFPRs = 8;
const int NumArgGPRs;
const int NumArgFPRs;
const bool EABI;
bool detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff,
llvm::Type *&Field1Ty,
CharUnits &Field1Off,
llvm::Type *&Field2Ty,
CharUnits &Field2Off) const;

public:
RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen)
: DefaultABIInfo(CGT), XLen(XLen), FLen(FLen) {}
RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen,
bool EABI)
: DefaultABIInfo(CGT), XLen(XLen), FLen(FLen), NumArgGPRs(EABI ? 6 : 8),
NumArgFPRs(FLen != 0 ? 8 : 0), EABI(EABI) {}

// DefaultABIInfo's classifyReturnType and classifyArgumentType are
// non-virtual, but computeInfo is virtual, so we overload it.
Expand Down Expand Up @@ -86,7 +89,7 @@ void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const {
}

int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
int ArgFPRsLeft = FLen ? NumArgFPRs : 0;
int ArgFPRsLeft = NumArgFPRs;
int NumFixedArgs = FI.getNumRequiredArgs();

int ArgNum = 0;
Expand Down Expand Up @@ -396,9 +399,12 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
// Determine the number of GPRs needed to pass the current argument
// according to the ABI. 2*XLen-aligned varargs are passed in "aligned"
// register pairs, so may consume 3 registers.
// TODO: To be compatible with GCC's behaviors, we don't align registers
// currently if we are using ILP32E calling convention. This behavior may be
// changed when RV32E/ILP32E is ratified.
int NeededArgGPRs = 1;
if (!IsFixed && NeededAlign == 2 * XLen)
NeededArgGPRs = 2 + (ArgGPRsLeft % 2);
NeededArgGPRs = 2 + (EABI && XLen == 32 ? 0 : (ArgGPRsLeft % 2));
else if (Size > XLen && Size <= 2 * XLen)
NeededArgGPRs = 2;

Expand Down Expand Up @@ -480,6 +486,13 @@ Address RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,

auto TInfo = getContext().getTypeInfoInChars(Ty);

// TODO: To be compatible with GCC's behaviors, we force arguments with
// 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`,
// `unsigned long long` and `double` to have 4-byte alignment. This
// behavior may be changed when RV32E/ILP32E is ratified.
if (EABI && XLen == 32)
TInfo.Align = std::min(TInfo.Align, CharUnits::fromQuantity(4));

// Arguments bigger than 2*Xlen bytes are passed indirectly.
bool IsIndirect = TInfo.Width > 2 * SlotSize;

Expand All @@ -499,8 +512,9 @@ namespace {
class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
public:
RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen,
unsigned FLen)
: TargetCodeGenInfo(std::make_unique<RISCVABIInfo>(CGT, XLen, FLen)) {}
unsigned FLen, bool EABI)
: TargetCodeGenInfo(
std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {}

void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
Expand All @@ -526,6 +540,7 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {

std::unique_ptr<TargetCodeGenInfo>
CodeGen::createRISCVTargetCodeGenInfo(CodeGenModule &CGM, unsigned XLen,
unsigned FLen) {
return std::make_unique<RISCVTargetCodeGenInfo>(CGM.getTypes(), XLen, FLen);
unsigned FLen, bool EABI) {
return std::make_unique<RISCVTargetCodeGenInfo>(CGM.getTypes(), XLen, FLen,
EABI);
}
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
// rv32e -> ilp32e
// rv32* -> ilp32
// rv64g | rv64*d -> lp64d
// rv64e -> lp64e
// rv64* -> lp64
StringRef Arch = getRISCVArch(Args, Triple);

Expand Down Expand Up @@ -285,13 +286,16 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
// 3. Choose a default based on `-mabi=`
//
// ilp32e -> rv32e
// lp64e -> rv64e
// ilp32 | ilp32f | ilp32d -> rv32imafdc
// lp64 | lp64f | lp64d -> rv64imafdc
if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
StringRef MABI = A->getValue();

if (MABI.equals_insensitive("ilp32e"))
return "rv32e";
else if (MABI.equals_insensitive("lp64e"))
return "rv64e";
else if (MABI.starts_with_insensitive("ilp32"))
return "rv32imafdc";
else if (MABI.starts_with_insensitive("lp64")) {
Expand Down
3 changes: 3 additions & 0 deletions clang/test/CodeGen/RISCV/riscv32-abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// RUN: | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32F-ILP32D,ILP32-ILP32F,ILP32F %s
// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \
// RUN: | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32F-ILP32D,ILP32D %s
// RUN: %clang_cc1 -triple riscv32 -emit-llvm -target-abi ilp32e %s -o - \
// RUN: | FileCheck -check-prefixes=ILP32-ILP32F-ILP32D,ILP32-ILP32F,ILP32,ILP32E %s

#include <stddef.h>
#include <stdint.h>
Expand Down Expand Up @@ -2064,4 +2066,5 @@ union float16_u f_ret_float16_u(void) {
}

//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
// ILP32E: {{.*}}
// ILP32F: {{.*}}
4 changes: 4 additions & 0 deletions clang/test/CodeGen/RISCV/riscv32-ilp32e-error.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: not %clang_cc1 -triple riscv32 -target-feature +d -emit-llvm -target-abi ilp32e %s 2>&1 \
// RUN: | FileCheck -check-prefix=ILP32E-WITH-FD %s

// ILP32E-WITH-FD: error: invalid feature combination: ILP32E cannot be used with the D ISA extension
Loading