Support for "zicsr" and "zifencei" extensions

Hello,

I’ve just merged locally my toolchain from LLVM15 to 16rc1 and noticed that there were recently enabled restrictive checks which verifies .riscv.attributes of ELF files.

Currently during building anything with clang I use sys-root built by gcc.

It occurred that I’ve got issues with linking.

When I run for example:

llvm-readobj -A /usr/lib/gcc-cross/riscv64-linux-gnu/12/crtendS.o

I see following attributes:

rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0

Attributes like icsr or ifencei aren’t accepted by LLVM binutils from branch release _16.x.

As a wrorkaround I’ve added locally:

{“zicsr”, RISCVExtensionVersion{2, 0}},
{“zifencei”, RISCVExtensionVersion{2, 0}},

This works, but I wanted to ask why RISCV LLVM backend doesn’t reports that extensions ziscr and zifencei are supported.

Are there still any gaps regarding full support of zicsr and zifencei extensions?

CSR instructions are for example defined:

def CSRRW : CSR_ir<0b001, “csrrw”>;
def CSRRS : CSR_ir<0b010, “csrrs”>;
def CSRRC : CSR_ir<0b011, “csrrc”>;
def CSRRWI : CSR_ii<0b101, “csrrwi”>;
def CSRRSI : CSR_ii<0b110, “csrrsi”>;
def CSRRCI : CSR_ii<0b111, “csrrci”>;

Similarly FENCE_I:
def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), “fence.i”, “”>, Sched<[]> {
let rs1 = 0;
let rd = 0;
let imm12 = 0;
}

Or in LLVM we don’t want to separately indicate support for these extensions?

Moreover, other parts of attributes also aren’t accepted, for example rv64i2p1

LLVM reports that doesn’t support version 2.1 for rv64i2p1

So regarding Base Integer instruction set and other Standard extensions are there still any gaps between 2.0 and 2.1 in LLVM?

Thanks,
PrzemekO

It’s a matter of not having moved the default in Clang/LLVM to 2.1 like GCC has, though we’re hoping to address that soon. Unfortunately the decision to break backwards compatibility in the RISC-V spec by moving fence.i and the CSR instructions out of the base ‘I’ instruction set means this ends up being rather user hostile.

If you’re able to build your GCC sysroot with an earlier -misa-spec, that might provide an easy workaround.

Could you please clarify the issues you’re seeing around “restrictive checks” of .riscv.attributes in ELF files though? I’m curious if we’re doing something there that makes it more difficult than necessary.

Thanks for explanation and hint regarding -misa-spec.
So it means that LLVM supports zicsr 2.0 and zifencei 2.0 but simply doesn’t reports that fact and there will not be defined dedicated features for zicsr and zifencei to handle them separately?

Regarding “restrictive checks” I didn’t mean these checks are too restrictive. I think they are proper but compering to previous version 15.0, where binutils worked for me, it was surprising.
Earlier I didn’t have issues with llvm-objdump and lld.
In these two changes RISCVISAInfo::parseArchString method started to be used:
objdump:

lld:

Using LLVM15.0 I wasn’t aware that I’m using incompatible binary version of crt files. Now I am.
So the checks are fine, but I think there might others which are going to be surprised like me after switching to LLVM16 :slight_smile:

LLVM supports i2p0, which is equivalent to i2p1_zicsr2p0_zifencei2p0.

Thank you @jrtc27 for clarification.

Since this has come up a couple times recently, I made an attempt to document this: ⚙ D143924 [RISCV][docs] Describe status of zicsr and zifencei.