Skip to content
Open
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
8 changes: 8 additions & 0 deletions clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo {
ABI = Name;
return true;
}

if (Name == "ilp32") {
ABI = Name;
resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128");
LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
IntMaxType = SignedLongLong;
return true;
}
return false;
}

Expand Down
21 changes: 21 additions & 0 deletions clang/test/CodeGen/riscv64-ilp32-abi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// RUN: %clang_cc1 -triple riscv64 -target-abi ilp32 -emit-llvm -o - %s | FileCheck %s

struct Foo {
char a;
int b : 1;
};

int BitfieldOffset = sizeof(struct Foo);
// CHECK: @BitfieldOffset = global i32 4

int PointerSize = sizeof(void *);
// CHECK: @PointerSize = global i32 4

int PointerAlign = __alignof(void *);
// CHECK: @PointerAlign = global i32 4

int LongSize = sizeof(long);
// CHECK: @LongSize = global i32 4

int LongAlign = __alignof(long);
// CHECK: @LongAlign = global i32 4
5 changes: 0 additions & 5 deletions clang/test/Driver/riscv-abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,3 @@
// RUN: | FileCheck -check-prefix=CHECK-LP64D %s

// CHECK-LP64D: "-target-abi" "lp64d"

// RUN: not %clang --target=riscv64-unknown-elf %s -o %t.o -mabi=ilp32 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-RV64-ILP32 %s

// CHECK-RV64-ILP32: error: unknown target ABI 'ilp32'
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/InlineAsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,8 @@ class InlineAsm final : public Value {
return "ZS";
case InlineAsm::Constraint_ZT:
return "ZT";
case InlineAsm::Constraint_A:
return "A";
default:
llvm_unreachable("Unknown memory constraint");
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5299,11 +5299,11 @@ void TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
}
}
const unsigned OpCode = Op.getOpcode();
if (OpCode == ISD::ADD || OpCode == ISD::SUB) {
if (OpCode == ISD::ADD || OpCode == ISD::SUB || OpCode == ISD::AND) {
if ((C = dyn_cast<ConstantSDNode>(Op.getOperand(0))))
Op = Op.getOperand(1);
// Subtraction is not commutative.
else if (OpCode == ISD::ADD &&
else if ((OpCode == ISD::ADD || OpCode == ISD::AND) &&
(C = dyn_cast<ConstantSDNode>(Op.getOperand(1))))
Op = Op.getOperand(0);
else
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class RISCVAsmBackend : public MCAsmBackend {
const MCTargetOptions &Options)
: MCAsmBackend(support::little), STI(STI), OSABI(OSABI), Is64Bit(Is64Bit),
TargetOptions(Options) {
// Use ELF32 format for RV64 ILP32.
// FIXME: Here only handles ABI set from options. What to do with the ABI
// set from LLVM module flags ?
if (Options.getABIName() == "ilp32" && Is64Bit)
this->Is64Bit = false;
RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
}
~RISCVAsmBackend() override = default;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,
errs()
<< "'" << ABIName
<< "' is not a recognized ABI for this target (ignoring target-abi)\n";
} else if (ABIName.startswith("ilp32") && IsRV64) {

} else if ((ABIName != "ilp32" && ABIName.startswith("ilp32")) && IsRV64) {
errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring "
"target-abi)\n";
TargetABI = ABI_Unknown;
Expand Down
15 changes: 11 additions & 4 deletions llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,15 @@ bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(
RISCV::ADDI);
}

static unsigned getAddrLoadSecondOpcode(const RISCVSubtarget &STI) {
if (STI.is64Bit()) {
if (STI.getTargetABI() == RISCVABI::ABI_ILP32)
return RISCV::LWU;
return RISCV::LD;
}
return RISCV::LW;
}

bool RISCVPreRAExpandPseudo::expandLoadAddress(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI) {
Expand All @@ -401,9 +410,8 @@ bool RISCVPreRAExpandPseudo::expandLoadAddress(
// is incompatible with existing code models. This also applies to non-pic
// mode.
assert(MF->getTarget().isPositionIndependent() || STI.allowTaggedGlobals());
unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,
SecondOpcode);
getAddrLoadSecondOpcode(STI));
}

bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress(
Expand All @@ -412,9 +420,8 @@ bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress(
MachineFunction *MF = MBB.getParent();

const auto &STI = MF->getSubtarget<RISCVSubtarget>();
unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
SecondOpcode);
getAddrLoadSecondOpcode(STI));
}

bool RISCVPreRAExpandPseudo::expandLoadTLSGDAddress(
Expand Down
26 changes: 25 additions & 1 deletion llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,

setOperationAction({ISD::UADDO, ISD::USUBO, ISD::UADDSAT, ISD::USUBSAT},
MVT::i32, Custom);
setOperationAction(ISD::READ_REGISTER, MVT::i32, Custom);
} else {
setLibcallName(
{RTLIB::SHL_I128, RTLIB::SRL_I128, RTLIB::SRA_I128, RTLIB::MUL_I128},
Expand Down Expand Up @@ -1176,6 +1177,21 @@ MVT RISCVTargetLowering::getVPExplicitVectorLengthTy() const {
return Subtarget.getXLenVT();
}

MVT RISCVTargetLowering::getPointerTy(const DataLayout &DL, uint32_t AS) const {
// Return i64 for ILP32. It will be truncated and extended when transferred to
// memory, but the 64-bit DAG allow us to use RISCV64's address modes much
// more easily.
if (Subtarget.is64Bit() && Subtarget.getTargetABI() == RISCVABI::ABI_ILP32)
return MVT::getIntegerVT(64);
return TargetLowering::getPointerTy(DL, AS);
}

MVT RISCVTargetLowering::getScalarShiftAmountTy(const DataLayout &DL, EVT VT) const {
if (Subtarget.is64Bit() && Subtarget.getTargetABI() == RISCVABI::ABI_ILP32)
return MVT::getIntegerVT(64);
return TargetLowering::getScalarShiftAmountTy(DL, VT);
}

bool RISCVTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
const CallInst &I,
MachineFunction &MF,
Expand Down Expand Up @@ -9226,6 +9242,14 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, EltLo, EltHi));
break;
}
case ISD::READ_REGISTER: {
SDValue Chain = N->getOperand(0);
SDValue SysRegName = N->getOperand(1);
SDValue Result = DAG.getNode(N->getOpcode(), DL, DAG.getVTList({MVT::i64, MVT::Other}), Chain, SysRegName);
Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Result));
Results.push_back(Result.getValue(1));
break;
}
case ISD::INTRINSIC_WO_CHAIN: {
unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
switch (IntNo) {
Expand Down Expand Up @@ -13904,7 +13928,7 @@ static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
MachineFrameInfo &MFI = MF.getFrameInfo();
EVT LocVT = VA.getLocVT();
EVT ValVT = VA.getValVT();
EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0));
EVT PtrVT = DAG.getTargetLoweringInfo().getFrameIndexTy(DAG.getDataLayout());
if (ValVT.isScalableVector()) {
// When the value is a scalable vector, we save the pointer which points to
// the scalable vector value in the stack. The ValVT will be the pointer
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@ class RISCVTargetLowering : public TargetLowering {

bool softPromoteHalfType() const override { return true; }

MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const override;

MVT getScalarShiftAmountTy(const DataLayout &DL, EVT) const override;

/// Return the register type for a given MVT, ensuring vectors are treated
/// as a series of gpr sized integers.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
Expand Down
12 changes: 9 additions & 3 deletions llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,15 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
initializeRISCVInitUndefPass(*PR);
}

static StringRef computeDataLayout(const Triple &TT) {
if (TT.isArch64Bit())
static StringRef computeDataLayout(const Triple &TT,
const TargetOptions &Options) {
if (TT.isArch64Bit()) {
// FIXME: Here only handles ABI set from option. What to do with ABI set
// from module flags?
if (Options.MCOptions.getABIName() == "ilp32")
return "e-m:e-p:32:32-i64:64-n32:64-S128";
return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
}
assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
return "e-m:e-p:32:32-i64:64-n32-S128";
}
Expand All @@ -106,7 +112,7 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
std::optional<Reloc::Model> RM,
std::optional<CodeModel::Model> CM,
CodeGenOpt::Level OL, bool JIT)
: LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
: LLVMTargetMachine(T, computeDataLayout(TT, Options), TT, CPU, FS, Options,
getEffectiveRelocModel(TT, RM),
getEffectiveCodeModel(CM, CodeModel::Small), OL),
TLOF(std::make_unique<RISCVELFTargetObjectFile>()) {
Expand Down
80 changes: 80 additions & 0 deletions llvm/test/CodeGen/RISCV/alloca.ll
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV32I
; RUN: llc -mtriple=riscv64 -target-abi=ilp32 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64-ILP32

declare void @notdead(ptr)

Expand All @@ -24,6 +26,25 @@ define void @simple_alloca(i32 %n) nounwind {
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64-ILP32-LABEL: simple_alloca:
; RV64-ILP32: # %bb.0:
; RV64-ILP32-NEXT: addi sp, sp, -16
; RV64-ILP32-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-ILP32-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
; RV64-ILP32-NEXT: addi s0, sp, 16
; RV64-ILP32-NEXT: slli a0, a0, 32
; RV64-ILP32-NEXT: srli a0, a0, 32
; RV64-ILP32-NEXT: addi a0, a0, 15
; RV64-ILP32-NEXT: andi a0, a0, -16
; RV64-ILP32-NEXT: sub a0, sp, a0
; RV64-ILP32-NEXT: mv sp, a0
; RV64-ILP32-NEXT: call notdead@plt
; RV64-ILP32-NEXT: addi sp, s0, -16
; RV64-ILP32-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-ILP32-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
; RV64-ILP32-NEXT: addi sp, sp, 16
; RV64-ILP32-NEXT: ret
%1 = alloca i8, i32 %n
call void @notdead(ptr %1)
ret void
Expand Down Expand Up @@ -53,6 +74,29 @@ define void @scoped_alloca(i32 %n) nounwind {
; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64-ILP32-LABEL: scoped_alloca:
; RV64-ILP32: # %bb.0:
; RV64-ILP32-NEXT: addi sp, sp, -32
; RV64-ILP32-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64-ILP32-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64-ILP32-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64-ILP32-NEXT: addi s0, sp, 32
; RV64-ILP32-NEXT: mv s1, sp
; RV64-ILP32-NEXT: slli a0, a0, 32
; RV64-ILP32-NEXT: srli a0, a0, 32
; RV64-ILP32-NEXT: addi a0, a0, 15
; RV64-ILP32-NEXT: andi a0, a0, -16
; RV64-ILP32-NEXT: sub a0, sp, a0
; RV64-ILP32-NEXT: mv sp, a0
; RV64-ILP32-NEXT: call notdead@plt
; RV64-ILP32-NEXT: mv sp, s1
; RV64-ILP32-NEXT: addi sp, s0, -32
; RV64-ILP32-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64-ILP32-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64-ILP32-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64-ILP32-NEXT: addi sp, sp, 32
; RV64-ILP32-NEXT: ret
%sp = call ptr @llvm.stacksave()
%addr = alloca i8, i32 %n
call void @notdead(ptr %addr)
Expand Down Expand Up @@ -98,6 +142,42 @@ define void @alloca_callframe(i32 %n) nounwind {
; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
; RV64-ILP32-LABEL: alloca_callframe:
; RV64-ILP32: # %bb.0:
; RV64-ILP32-NEXT: addi sp, sp, -16
; RV64-ILP32-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-ILP32-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
; RV64-ILP32-NEXT: addi s0, sp, 16
; RV64-ILP32-NEXT: slli a0, a0, 32
; RV64-ILP32-NEXT: srli a0, a0, 32
; RV64-ILP32-NEXT: addi a0, a0, 15
; RV64-ILP32-NEXT: andi a0, a0, -16
; RV64-ILP32-NEXT: sub a0, sp, a0
; RV64-ILP32-NEXT: mv sp, a0
; RV64-ILP32-NEXT: addi sp, sp, -32
; RV64-ILP32-NEXT: li a1, 12
; RV64-ILP32-NEXT: sd a1, 24(sp)
; RV64-ILP32-NEXT: li a1, 11
; RV64-ILP32-NEXT: sd a1, 16(sp)
; RV64-ILP32-NEXT: li a1, 10
; RV64-ILP32-NEXT: sd a1, 8(sp)
; RV64-ILP32-NEXT: li t0, 9
; RV64-ILP32-NEXT: li a1, 2
; RV64-ILP32-NEXT: li a2, 3
; RV64-ILP32-NEXT: li a3, 4
; RV64-ILP32-NEXT: li a4, 5
; RV64-ILP32-NEXT: li a5, 6
; RV64-ILP32-NEXT: li a6, 7
; RV64-ILP32-NEXT: li a7, 8
; RV64-ILP32-NEXT: sd t0, 0(sp)
; RV64-ILP32-NEXT: call func@plt
; RV64-ILP32-NEXT: addi sp, sp, 32
; RV64-ILP32-NEXT: addi sp, s0, -16
; RV64-ILP32-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-ILP32-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
; RV64-ILP32-NEXT: addi sp, sp, 16
; RV64-ILP32-NEXT: ret
%1 = alloca i8, i32 %n
call void @func(ptr %1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8,
i32 9, i32 10, i32 11, i32 12)
Expand Down
Loading