This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] add the MC layer support of Zfinx extension
ClosedPublic

Authored by achieveartificialintelligence on Dec 15 2020, 6:53 AM.

Details

Summary

This patch added the MC layer support of Zfinx extension.

Authored-by: StephenFan
Co-Authored-by: Shao-Ce Sun

Diff Detail

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
achieveartificialintelligence marked an inline comment as done.

Add arch info

MaskRay added inline comments.Oct 18 2021, 11:10 PM
llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
164

Use functionName.

There is inconsistency in the code base but functionName is used much more than FunctionName.

186
llvm/lib/Target/RISCV/RISCVInstrInfoD.td
175 ↗(On Diff #379273)

The indentation is inconsistent. Also applies to code above.

llvm/test/MC/RISCV/rv64zhinx-valid.s
4

llvm-mc can use %s instead of < %s

I heard that not using < is a bit more convenient for some Windows users. (They do suffer from llc and opt's prevailing < %s)

13

[[@LINE+1]] is a deprecated form.
Use [[#@LINE+1]]. Applies to many places elsewhere.

llvm/test/MC/RISCV/rvzhinx-aliases-valid.s
47

What is {{[[:space:]]}} used for?

achieveartificialintelligence marked 14 inline comments as done.Oct 25 2021, 11:14 PM
achieveartificialintelligence marked 6 inline comments as done.Oct 26 2021, 1:10 AM
achieveartificialintelligence added inline comments.
llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
164

I fix this in D112520

llvm/lib/Target/RISCV/RISCVRegisterInfo.td
539

After D95588 is accepted, we will reuse this.

achieveartificialintelligence marked an inline comment as done.

Address @MaskRay 's comments.

craig.topper added inline comments.Nov 24 2021, 12:39 PM
llvm/lib/Support/RISCVISAInfo.cpp
69 ↗(On Diff #388780)

Do we need to enforce that these can't be mixed with F, D, and Zfh?

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
1711

D and Zfh imply F. Is it enough to just check F?

llvm/lib/Target/RISCV/RISCVInstrInfoF.td
77 ↗(On Diff #388780)

Can we merge this with FPFMAD_rrr_frm_single and FPFMAH_rrr_frm_single by passing the 0b00/0b01/0b10 value from FPFMAS_rrr_frm/FPFMAD_rrr_frm/FPFMAH_rrr_frm?

This applies to most of the _single classes. We should share them if possible.

craig.topper added inline comments.Nov 24 2021, 12:47 PM
llvm/lib/Target/RISCV/RISCVInstrInfoD.td
489 ↗(On Diff #388780)

Aren't these aliases only valid for RV64. You need IN32X aliases for RV32 right?

achieveartificialintelligence marked 4 inline comments as done.

Address @craig.topper 's comments.

Gentle Ping and Rebase.

Update Part of Zfinx Codes

achieveartificialintelligence retitled this revision from [RISCV] add the MC layer support of Zfinx extension to [RISCV] add the part of MC layer support of Zfinx extension.Dec 27 2021, 10:17 PM

I'll finish the rest of code, if this patch is acceptable.

craig.topper added inline comments.
llvm/lib/Support/RISCVISAInfo.cpp
290 ↗(On Diff #396373)

@kito-cheng or @khchen is the right way to do this? Or should it be in updateImplication? Where do we have Zfhmin imply f or d imply f today?

llvm/lib/Target/RISCV/RISCVInstrInfoD.td
34 ↗(On Diff #396373)

Can you add let RenderMethod = "addRegOperands"; here. That should let you remove addGPRAsFPROperands from RISCVAsmParser.cpp. Similar for the other AsmOperandClasses.

craig.topper added inline comments.Jan 3 2022, 7:47 PM
llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
170

Can we make use of let DecoderMethod = on RegisterClass to avoid these aliases?

achieveartificialintelligence marked 2 inline comments as done.Jan 3 2022, 8:32 PM
craig.topper added inline comments.Jan 3 2022, 9:27 PM
llvm/lib/Target/RISCV/RISCVInstrInfoF.td
124 ↗(On Diff #397193)

Can we use DAGOperand instead of RegisterOperand? I think that should allow you to avoid adding GPROp, FPR32Op, FPR64Op, and FPR16Op. You can just use the RegisterClasses. Both RegisterClass and RegisterOperand inherit from DAGOperand.

craig.topper added inline comments.Jan 3 2022, 9:29 PM
llvm/lib/Target/RISCV/RISCVInstrInfoF.td
217 ↗(On Diff #397193)

Why do the aliases not apply to Zfinx?

llvm/lib/Target/RISCV/RISCVInstrInfoF.td
217 ↗(On Diff #397193)

Because the first argument is FPFMA_rrr_frm Inst, if we use multiclass here, it'll be FFPFMA_rrr_frm Inst, FFPFMA_rrr_frm Inst_INX. I don't know is there a better way?

Use DAGOperand instead of RegisterOperand

achieveartificialintelligence marked an inline comment as done.Jan 3 2022, 11:36 PM
achieveartificialintelligence marked an inline comment as done.

Fix issue in RISCVISAInfo.cpp

achieveartificialintelligence marked an inline comment as done.

Inspired by D116019, use multiclass in Alias

achieveartificialintelligence retitled this revision from [RISCV] add the part of MC layer support of Zfinx extension to [RISCV] add the MC layer support of Zfinx extension.Jan 10 2022, 8:21 PM

Ping. Zfinx has been ratified, could we spend some time on this patch?

craig.topper added inline comments.Jan 12 2022, 12:29 PM
llvm/lib/Support/RISCVISAInfo.cpp
687 ↗(On Diff #399270)

Do we need the equivalent of this for Zfinx and Zdinx?

llvm/lib/Target/RISCV/RISCVInstrInfoD.td
228 ↗(On Diff #399270)

Don't we need IN32X aliases too?

llvm/lib/Target/RISCV/RISCVRegisterInfo.td
552

Is possible to reference GPR here to avoid listing the allocation order again? Similar to how GPRNoX0 does (sub GPR, X0). Not sure if there is a way to be exactly another list.

achieveartificialintelligence marked 3 inline comments as done.

Address @craig.topper's comments

Ping. Any other suggestions?

craig.topper added inline comments.Jan 19 2022, 11:30 PM
llvm/lib/Target/RISCV/RISCVRegisterInfo.td
136

Does putting this back the way it was and using "(add GPR)" in GPRF16, GPRF32, and GPRF64 work?

asb added a comment.EditedJan 24 2022, 7:01 AM

Thanks for your work on this. The way you've managed to use multiclasses to handle this with the 'ExtInfo' definitions takes a bit of unpicking to follow, but it does a really good job of keeping the instruction definitions largely unmodified. Nice!

I've got a few requests/questions on the test coverage:

  • I'm not sure the inclusion of the load/store instructions in the z[d,f,h]inx test cases has much value, given those instructions are unmodified?
  • Given that the set of F/D/Zfh instructions that _aren't_ supported under z[d,f,h]inx is relatively short, it's probably worth being exhaustive in the *-invalid.s test cases. It's only 8 instructions for Zfinx for instance.
  • The *-invalid.s test cases should have coverage for using a floating point register with an operation that is supported by Z[d,f,h]inx
  • The zdinx test cases don't include any coverage for when odd registers are used, but I think it should
asb added a comment.Jan 24 2022, 7:10 AM

Not an issue for this MC-layer patch, but I've created https://github.com/riscv/riscv-zfinx/issues/14 to point out what seems to be an incorrect statement about the status quo on the ABI for 32-bit floating point types on RV64 in the Zfinx spec.

achieveartificialintelligence marked an inline comment as done.

@asb Thank you very much! Could you please take a look at what needs to be modified now?

Separate the Zhinxmin and Zhinx extensions. Inspired by D118581

Assuming this will be merged soon, do you want to submit a backport request for the 14.0 branch?

Assuming this will be merged soon, do you want to submit a backport request for the 14.0 branch?

Yes.

Jim added inline comments.Feb 8 2022, 7:34 PM
llvm/lib/Target/RISCV/RISCVRegisterInfo.td
556

Is XLenRI correct for GPRPF64? RV32 has size 32.

craig.topper added inline comments.Feb 9 2022, 7:31 PM
llvm/lib/Target/RISCV/RISCVRegisterInfo.td
556

I'm not sure the RegInfos are correct for the other classes either. The RegInfos override the register size, the spill size, and spill alignment. I think those should all be based on the FP type.

So I don't think any of these should have a RegInfos.

achieveartificialintelligence marked 2 inline comments as done.

Address comments.

llvm/lib/Target/RISCV/RISCVRegisterInfo.td
556

Without RegInfo, it would cause spill size to be changed for a large number of other tests.

Jim added inline comments.Feb 10 2022, 9:29 PM
llvm/lib/Target/RISCV/RISCVRegisterInfo.td
558

Is register pair only on RV32 for used as f64?

achieveartificialintelligence marked an inline comment as done.Feb 11 2022, 5:34 AM
achieveartificialintelligence added inline comments.
llvm/lib/Target/RISCV/RISCVRegisterInfo.td
558

Yes.

asb added a comment.Feb 16 2022, 6:50 AM

I think all my comments have been addressed. @craig.topper - are you happy your RegInfo question is addressed?

In D93298#3326230, @asb wrote:

I think all my comments have been addressed. @craig.topper - are you happy your RegInfo question is addressed?

I'm happy.

asb accepted this revision.Feb 17 2022, 5:36 AM

In that case, LGTM (needs a rebase though). Thanks for your patience on this @achieveartificialintelligence.

This revision is now accepted and ready to land.Feb 17 2022, 5:36 AM
This revision was landed with ongoing or failed builds.Feb 17 2022, 5:54 AM
This revision was automatically updated to reflect the committed changes.
achieveartificialintelligence marked an inline comment as done.

It appears that this is causing an assertion segfault in a rustc test over at our experimental rust + llvm@head bot:
https://buildkite.com/llvm-project/rust-llvm-integrate-prototype/builds/8430#167e6de5-2dd5-41c3-87d7-b6e3f3908371/262-706
The test is https://github.com/rust-lang/rust/blob/master/src/test/assembly/asm/riscv-types.rs. These two lines appear to cause it (code compiles fine when removed):

The assertion:

Impossible reg-to-reg copy
UNREACHABLE executed at [...]/rust/src/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp:350

The IR for riscv-types.rs:

; ModuleID = 'riscv_types.4cedf4b7-cgu.0'
source_filename = "riscv_types.4cedf4b7-cgu.0"
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
target triple = "riscv64"

@extern_static = external dso_local global i8
@alloc55 = private unnamed_addr constant <{ [6 x i8] }> <{ [6 x i8] c"reg_i8" }>, align 1
@alloc56 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"reg_i16" }>, align 1
@alloc57 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"reg_i32" }>, align 1
@alloc58 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"reg_f32" }>, align 1
@alloc59 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"reg_i64" }>, align 1
@alloc60 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"reg_f64" }>, align 1
@alloc61 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"reg_ptr" }>, align 1
@alloc62 = private unnamed_addr constant <{ [8 x i8] }> <{ [8 x i8] c"freg_f32" }>, align 1
@alloc63 = private unnamed_addr constant <{ [8 x i8] }> <{ [8 x i8] c"freg_f64" }>, align 1
@alloc64 = private unnamed_addr constant <{ [5 x i8] }> <{ [5 x i8] c"a0_i8" }>, align 1
@alloc65 = private unnamed_addr constant <{ [6 x i8] }> <{ [6 x i8] c"a0_i16" }>, align 1
@alloc66 = private unnamed_addr constant <{ [6 x i8] }> <{ [6 x i8] c"a0_i32" }>, align 1
@alloc67 = private unnamed_addr constant <{ [6 x i8] }> <{ [6 x i8] c"a0_f32" }>, align 1
@alloc68 = private unnamed_addr constant <{ [6 x i8] }> <{ [6 x i8] c"a0_i64" }>, align 1
@alloc69 = private unnamed_addr constant <{ [6 x i8] }> <{ [6 x i8] c"a0_f64" }>, align 1
@alloc70 = private unnamed_addr constant <{ [6 x i8] }> <{ [6 x i8] c"a0_ptr" }>, align 1
@alloc71 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"fa0_f32" }>, align 1
@alloc72 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"fa0_f64" }>, align 1

; Function Attrs: nounwind
define dso_local void @sym_fn() unnamed_addr #0 {
start:
  tail call void asm sideeffect alignstack "call ${0:c}", "s,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(void ()* nonnull @extern_func) #1, !srcloc !1
  ret void
}

; Function Attrs: nounwind
define dso_local void @sym_static() unnamed_addr #0 {
start:
  tail call void asm sideeffect alignstack "lb t0, ${0:c}", "s,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i8* nonnull @extern_static) #1, !srcloc !2
  ret void
}

; Function Attrs: nounwind
define dso_local i8 @reg_i8(i8 %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [6 x i8] }>* @alloc55 to [0 x i8]*), i64 6) #1
  %0 = tail call i8 asm sideeffect alignstack "mv ${0}, ${1}", "=&r,r,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i8 %x) #1, !srcloc !3
  ret i8 %0
}

; Function Attrs: nounwind
define dso_local i16 @reg_i16(i16 %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [7 x i8] }>* @alloc56 to [0 x i8]*), i64 7) #1
  %0 = tail call i16 asm sideeffect alignstack "mv ${0}, ${1}", "=&r,r,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i16 %x) #1, !srcloc !3
  ret i16 %0
}

; Function Attrs: nounwind
define dso_local i32 @reg_i32(i32 %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [7 x i8] }>* @alloc57 to [0 x i8]*), i64 7) #1
  %0 = tail call i32 asm sideeffect alignstack "mv ${0}, ${1}", "=&r,r,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i32 %x) #1, !srcloc !3
  ret i32 %0
}

; Function Attrs: nounwind
define dso_local float @reg_f32(float %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [7 x i8] }>* @alloc58 to [0 x i8]*), i64 7) #1
  %0 = tail call float asm sideeffect alignstack "mv ${0}, ${1}", "=&r,r,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(float %x) #1, !srcloc !3
  ret float %0
}

; Function Attrs: nounwind
define dso_local i64 @reg_i64(i64 %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [7 x i8] }>* @alloc59 to [0 x i8]*), i64 7) #1
  %0 = tail call i64 asm sideeffect alignstack "mv ${0}, ${1}", "=&r,r,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i64 %x) #1, !srcloc !3
  ret i64 %0
}

; Function Attrs: nounwind
define dso_local double @reg_f64(double %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [7 x i8] }>* @alloc60 to [0 x i8]*), i64 7) #1
  %0 = tail call double asm sideeffect alignstack "mv ${0}, ${1}", "=&r,r,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(double %x) #1, !srcloc !3
  ret double %0
}

; Function Attrs: nounwind
define dso_local i8* @reg_ptr(i8* %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [7 x i8] }>* @alloc61 to [0 x i8]*), i64 7) #1
  %0 = tail call i8* asm sideeffect alignstack "mv ${0}, ${1}", "=&r,r,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i8* %x) #1, !srcloc !3
  ret i8* %0
}

; Function Attrs: nounwind
define dso_local float @freg_f32(float %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [8 x i8] }>* @alloc62 to [0 x i8]*), i64 8) #1
  %0 = tail call float asm sideeffect alignstack "fmv.s ${0}, ${1}", "=&f,f,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(float %x) #1, !srcloc !3
  ret float %0
}

; Function Attrs: nounwind
define dso_local double @freg_f64(double %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [8 x i8] }>* @alloc63 to [0 x i8]*), i64 8) #1
  %0 = tail call double asm sideeffect alignstack "fmv.d ${0}, ${1}", "=&f,f,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(double %x) #1, !srcloc !3
  ret double %0
}

; Function Attrs: nounwind
define dso_local i8 @a0_i8(i8 %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [5 x i8] }>* @alloc64 to [0 x i8]*), i64 5) #1
  %0 = tail call i8 asm sideeffect alignstack "mv a0, a0", "={x10},{x10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i8 %x) #1, !srcloc !4
  ret i8 %0
}

; Function Attrs: nounwind
define dso_local i16 @a0_i16(i16 %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [6 x i8] }>* @alloc65 to [0 x i8]*), i64 6) #1
  %0 = tail call i16 asm sideeffect alignstack "mv a0, a0", "={x10},{x10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i16 %x) #1, !srcloc !4
  ret i16 %0
}

; Function Attrs: nounwind
define dso_local i32 @a0_i32(i32 %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [6 x i8] }>* @alloc66 to [0 x i8]*), i64 6) #1
  %0 = tail call i32 asm sideeffect alignstack "mv a0, a0", "={x10},{x10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i32 %x) #1, !srcloc !4
  ret i32 %0
}

; Function Attrs: nounwind
define dso_local float @a0_f32(float %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [6 x i8] }>* @alloc67 to [0 x i8]*), i64 6) #1
  %0 = tail call float asm sideeffect alignstack "mv a0, a0", "={x10},{x10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(float %x) #1, !srcloc !4
  ret float %0
}

; Function Attrs: nounwind
define dso_local i64 @a0_i64(i64 %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [6 x i8] }>* @alloc68 to [0 x i8]*), i64 6) #1
  %0 = tail call i64 asm sideeffect alignstack "mv a0, a0", "={x10},{x10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i64 %x) #1, !srcloc !4
  ret i64 %0
}

; Function Attrs: nounwind
define dso_local double @a0_f64(double %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [6 x i8] }>* @alloc69 to [0 x i8]*), i64 6) #1
  %0 = tail call double asm sideeffect alignstack "mv a0, a0", "={x10},{x10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(double %x) #1, !srcloc !4
  ret double %0
}

; Function Attrs: nounwind
define dso_local i8* @a0_ptr(i8* %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [6 x i8] }>* @alloc70 to [0 x i8]*), i64 6) #1
  %0 = tail call i8* asm sideeffect alignstack "mv a0, a0", "={x10},{x10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(i8* %x) #1, !srcloc !4
  ret i8* %0
}

; Function Attrs: nounwind
define dso_local float @fa0_f32(float %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [7 x i8] }>* @alloc71 to [0 x i8]*), i64 7) #1
  %0 = tail call float asm sideeffect alignstack "fmv.s fa0, fa0", "={f10},{f10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(float %x) #1, !srcloc !4
  ret float %0
}

; Function Attrs: nounwind
define dso_local double @fa0_f64(double %x) unnamed_addr #0 {
start:
  tail call void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1 bitcast (<{ [7 x i8] }>* @alloc72 to [0 x i8]*), i64 7) #1
  %0 = tail call double asm sideeffect alignstack "fmv.d fa0, fa0", "={f10},{f10},~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(double %x) #1, !srcloc !4
  ret double %0
}

; Function Attrs: nounwind
declare dso_local void @extern_func() unnamed_addr #0

; Function Attrs: nounwind
declare dso_local void @dont_merge([0 x i8]* noalias noundef nonnull readonly align 1, i64) unnamed_addr #0

attributes #0 = { nounwind "target-cpu"="generic-rv64" }
attributes #1 = { nounwind }

!llvm.module.flags = !{!0}

!0 = !{i32 1, !"Code Model", i32 3}
!1 = !{i32 1048}
!2 = !{i32 1281}
!3 = !{i32 1670}
!4 = !{i32 2113}

@achieveartificialintelligence could you please take a look? Any ideas what's going wrong here?

It appears that this is causing an assertion segfault in a rustc test over at our experimental rust + llvm@head bot:
https://buildkite.com/llvm-project/rust-llvm-integrate-prototype/builds/8430#167e6de5-2dd5-41c3-87d7-b6e3f3908371/262-706
The test is https://github.com/rust-lang/rust/blob/master/src/test/assembly/asm/riscv-types.rs. These two lines appear to cause it (code compiles fine when removed):

The assertion:

Impossible reg-to-reg copy
UNREACHABLE executed at [...]/rust/src/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp:350

...

This is just MC layer support. Inline assembly interacts with CodeGen; I assume the register classes/constraints still need updating to support Zfinx.

llvm/test/MC/RISCV/rv32i-invalid.s
1

This is an unrelated change

@krasimir Since I don't have a rust environment, can you help me to test if D120130 works?

@krasimir Since I don't have a rust environment, can you help me to test if D120130 works?

Hm, actually, looking at the log, it doesn't appear to be trying to use Zfinx? My guess is that putting a float in a GPR has broken as that's now legal but should only be legal for Zfinx?

It appears that this is causing an assertion segfault in a rustc test over at our experimental rust + llvm@head bot:

I dont think that patch author is required to debug this issue for "experimental rust + llvm@head" - downstream.

Since I don't have a rust environment

There is no requirement, indeed. LLVM devs are not responsible to keep ""experimental rust + llvm@head" working.

It appears that this is causing an assertion segfault in a rustc test over at our experimental rust + llvm@head bot:

I dont think that patch author is required to debug this issue for "experimental rust + llvm@head" - downstream.

Since I don't have a rust environment

There is no requirement, indeed. LLVM devs are not responsible to keep ""experimental rust + llvm@head" working.

They're required to assist with fixing regressions that show when compiling legitimate IR. An IR reproducer was given, so no Rust toolchain knowledge should be needed, at that point it's the LLVM dev's responsibility, and if they can't fix it in a timely manner then it should be backed out.

It appears that this is causing an assertion segfault in a rustc test over at our experimental rust + llvm@head bot:

I dont think that patch author is required to debug this issue for "experimental rust + llvm@head" - downstream.

Since I don't have a rust environment

There is no requirement, indeed. LLVM devs are not responsible to keep ""experimental rust + llvm@head" working.

They're required to assist with fixing regressions that show when compiling legitimate IR. An IR reproducer was given, so no Rust toolchain knowledge should be needed, at that point it's the LLVM dev's responsibility, and if they can't fix it in a timely manner then it should be backed out.

Then yeah, if IR is provided and is standard one, this is okay. Consider to add that IR as testcase for the fix.

nikic added a subscriber: nikic.Feb 21 2022, 2:45 AM

Because I happened to also run into this, reduced IR for -mtriple=riscv32 -mattr=+d is:

define float @test(float %x) {
  %1 = tail call float asm sideeffect alignstack "mv a0, a0", "={x10},{x10}"(float 0.000000e+00)
  ret float 0.000000e+00
}

@achieveartificialintelligence any progress with the problematic IR? Have you been able to reproduce using nikic's reduced example?

@achieveartificialintelligence any progress with the problematic IR? Have you been able to reproduce using nikic's reduced example?

Sorry, I don't have a solution right now.

@achieveartificialintelligence any progress with the problematic IR? Have you been able to reproduce using nikic's reduced example?

Sorry, I don't have a solution right now.

Could we revert this until then?

This revision is now accepted and ready to land.Feb 24 2022, 3:51 AM

Here's a fix that I tested on the original repreoduce. It detects that we picked one of the new register classes and tries to redirect back to the normal GPR register class if the GPR register class has the same width. I also checked for MVT::Other to use the GPR class if there was no type.

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 3daf2d03de03..4984872139c5 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -10893,7 +10893,28 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
     }
   }
 
-  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
+  std::pair<Register, const TargetRegisterClass*> Res;
+  Res = TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
+
+  if (Res.second == &RISCV::GPRF32RegClass) {
+    if (!Subtarget.is64Bit() || VT == MVT::Other)
+      return std::make_pair(Res.first, &RISCV::GPRRegClass);
+    return std::make_pair(0, nullptr);
+  }
+
+  if (Res.second == &RISCV::GPRF64RegClass) {
+    if (Subtarget.is64Bit() || VT == MVT::Other)
+      return std::make_pair(Res.first, &RISCV::GPRRegClass);
+    return std::make_pair(0, nullptr);
+  }
+
+  if (Res.second == &RISCV::GPRF16RegClass) {
+    if (VT == MVT::Other)
+      return std::make_pair(Res.first, &RISCV::GPRRegClass);
+    return std::make_pair(0, nullptr);
+  }
+
+  return Res;
 }

Can you help test if this patch works fine now? @krasimir

jrtc27 added inline comments.Feb 27 2022, 7:51 PM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
10923–10924 ↗(On Diff #411719)
achieveartificialintelligence marked an inline comment as done.

Address @jrtc27's comments

craig.topper added inline comments.Feb 28 2022, 7:29 PM
llvm/test/CodeGen/RISCV/zfinx-types.ll
5 ↗(On Diff #411375)

I'm not sure the Zfh or D RUN lines are really doing anything. Especially the Zfh.

The same bug did happen with double, D extension and RV64 so should probably test that.

achieveartificialintelligence marked an inline comment as done.

Address @craig.topper's comment

This revision was landed with ongoing or failed builds.Mar 1 2022, 10:25 PM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptMar 1 2022, 10:25 PM
craig.topper added inline comments.Mar 1 2022, 10:48 PM
llvm/test/CodeGen/RISCV/zfinx-types.ll
5 ↗(On Diff #411375)

I see you added rv64, but didn't add a test case that uses double instead of float.

@achieveartificialintelligence thank you for looking into this, sorry for the late reply!

It looks like the latest version addresses @nikic's IR reproducer with -mtriple=riscv32.

There seems to be an error trying this out with -mtriple=riscv64:

% cat test.ll
define float @test(float %x) {
  %1 = tail call float asm sideeffect alignstack "mv a0, a0", "={x10},{x10}"(float 0.000000e+00)
  ret float 0.000000e+00
}
% llc -mtriple=riscv32 -mattr=+d test.ll
% llc -mtriple=riscv64 -mattr=+d test.ll
error: couldn't allocate output register for constraint '{x10}'

I'm not sure if this is intended to work -mtriple=riscv64, but judging by the newly added test RUN: llc -mtriple=riscv64 ... line it seems like it should?

@achieveartificialintelligence thank you for looking into this, sorry for the late reply!

It looks like the latest version addresses @nikic's IR reproducer with -mtriple=riscv32.

There seems to be an error trying this out with -mtriple=riscv64:

% cat test.ll
define float @test(float %x) {
  %1 = tail call float asm sideeffect alignstack "mv a0, a0", "={x10},{x10}"(float 0.000000e+00)
  ret float 0.000000e+00
}
% llc -mtriple=riscv32 -mattr=+d test.ll
% llc -mtriple=riscv64 -mattr=+d test.ll
error: couldn't allocate output register for constraint '{x10}'

I'm not sure if this is intended to work -mtriple=riscv64, but judging by the newly added test RUN: llc -mtriple=riscv64 ... line it seems like it should?

My patch was only partially correct. I'll fix it

@achieveartificialintelligence thank you for looking into this, sorry for the late reply!

It looks like the latest version addresses @nikic's IR reproducer with -mtriple=riscv32.

There seems to be an error trying this out with -mtriple=riscv64:

% cat test.ll
define float @test(float %x) {
  %1 = tail call float asm sideeffect alignstack "mv a0, a0", "={x10},{x10}"(float 0.000000e+00)
  ret float 0.000000e+00
}
% llc -mtriple=riscv32 -mattr=+d test.ll
% llc -mtriple=riscv64 -mattr=+d test.ll
error: couldn't allocate output register for constraint '{x10}'

I'm not sure if this is intended to work -mtriple=riscv64, but judging by the newly added test RUN: llc -mtriple=riscv64 ... line it seems like it should?

My patch was only partially correct. I'll fix it

I just pushed 6cb42cd6669785f3b611106e1b6b38bbe65733a9 to hopefully fix this.

Does a double with r for RV32 work with that fix? That's supposed to give the low half of the register. You might need to also deal with the register pair class?

Never mind, I see you added a test for that case

I just pushed 6cb42cd6669785f3b611106e1b6b38bbe65733a9 to hopefully fix this.

Thank you Craig! That fixed it.