-
Notifications
You must be signed in to change notification settings - Fork 16.7k
[RISCV] Handle codegen for Big Endian #172668
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
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,6 +97,9 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { | |
| RISCVProcFamilyEnum RISCVProcFamily = Others; | ||
| RISCVVRGatherCostModelEnum RISCVVRGatherCostModel = Quadratic; | ||
|
|
||
| Triple TargetTriple; | ||
|
||
| bool IsLittleEndian = true; | ||
|
|
||
| #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ | ||
| bool ATTRIBUTE = DEFAULT; | ||
| #include "RISCVGenSubtargetInfo.inc" | ||
|
|
@@ -220,6 +223,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { | |
| } | ||
|
|
||
| bool is64Bit() const { return IsRV64; } | ||
| bool isLittleEndian() const { return IsLittleEndian; } | ||
| MVT getXLenVT() const { | ||
| return is64Bit() ? MVT::i64 : MVT::i32; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | ||
| ; RUN: llc -mtriple=riscv32 -target-abi=ilp32 -mattr=+d -verify-machineinstrs < %s | FileCheck -check-prefix=RV32IFD-LE %s | ||
| ; RUN: llc -mtriple=riscv32be -target-abi=ilp32 -mattr=+d -verify-machineinstrs < %s | FileCheck -check-prefix=RV32IFD-BE %s | ||
|
|
||
| ; Test operations that involve SplitF64/BuildPairF64 on RV32 with D extension | ||
| ; but soft-float ABI. This configuration triggers the special handling for | ||
| ; big-endian. | ||
|
|
||
| define double @fneg(double %a) nounwind { | ||
| ; RV32IFD-LE-LABEL: fneg: | ||
| ; RV32IFD-LE: # %bb.0: | ||
| ; RV32IFD-LE-NEXT: lui a2, 524288 | ||
| ; RV32IFD-LE-NEXT: xor a1, a1, a2 | ||
| ; RV32IFD-LE-NEXT: ret | ||
| ; | ||
| ; RV32IFD-BE-LABEL: fneg: | ||
| ; RV32IFD-BE: # %bb.0: | ||
| ; RV32IFD-BE-NEXT: lui a2, 524288 | ||
| ; RV32IFD-BE-NEXT: xor a0, a0, a2 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The PSABI doc riscv-non-isa/riscv-elf-psabi-doc#470 says Yet this code seems to be toggling the sign bit in a0. If the psabi doc is correct, isn't the sign bit in a1?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The thing is that riscv-non-isa/riscv-elf-psabi-doc#470 is not ready yet -- or at least not merged/accepted officially yet. Therefore, once psabi is ready, we can change both GCC and LLVM. Until then, we will emit a warning for |
||
| ; RV32IFD-BE-NEXT: ret | ||
| %1 = fneg double %a | ||
| ret double %1 | ||
| } | ||
|
|
||
| define double @fabs(double %a) nounwind { | ||
| ; RV32IFD-LE-LABEL: fabs: | ||
| ; RV32IFD-LE: # %bb.0: | ||
| ; RV32IFD-LE-NEXT: slli a1, a1, 1 | ||
| ; RV32IFD-LE-NEXT: srli a1, a1, 1 | ||
| ; RV32IFD-LE-NEXT: ret | ||
| ; | ||
| ; RV32IFD-BE-LABEL: fabs: | ||
| ; RV32IFD-BE: # %bb.0: | ||
| ; RV32IFD-BE-NEXT: slli a0, a0, 1 | ||
| ; RV32IFD-BE-NEXT: srli a0, a0, 1 | ||
| ; RV32IFD-BE-NEXT: ret | ||
| %1 = call double @llvm.fabs.f64(double %a) | ||
| ret double %1 | ||
| } | ||
|
|
||
| define double @fcopysign(double %a, double %b) nounwind { | ||
| ; RV32IFD-LE-LABEL: fcopysign: | ||
| ; RV32IFD-LE: # %bb.0: | ||
| ; RV32IFD-LE-NEXT: addi sp, sp, -16 | ||
| ; RV32IFD-LE-NEXT: sw a2, 8(sp) | ||
| ; RV32IFD-LE-NEXT: sw a3, 12(sp) | ||
| ; RV32IFD-LE-NEXT: fld fa5, 8(sp) | ||
| ; RV32IFD-LE-NEXT: sw a0, 8(sp) | ||
| ; RV32IFD-LE-NEXT: sw a1, 12(sp) | ||
| ; RV32IFD-LE-NEXT: fld fa4, 8(sp) | ||
| ; RV32IFD-LE-NEXT: fsgnj.d fa5, fa4, fa5 | ||
| ; RV32IFD-LE-NEXT: fsd fa5, 8(sp) | ||
| ; RV32IFD-LE-NEXT: lw a0, 8(sp) | ||
| ; RV32IFD-LE-NEXT: lw a1, 12(sp) | ||
| ; RV32IFD-LE-NEXT: addi sp, sp, 16 | ||
| ; RV32IFD-LE-NEXT: ret | ||
| ; | ||
| ; RV32IFD-BE-LABEL: fcopysign: | ||
| ; RV32IFD-BE: # %bb.0: | ||
| ; RV32IFD-BE-NEXT: addi sp, sp, -16 | ||
| ; RV32IFD-BE-NEXT: sw a2, 8(sp) | ||
| ; RV32IFD-BE-NEXT: sw a3, 12(sp) | ||
| ; RV32IFD-BE-NEXT: fld fa5, 8(sp) | ||
| ; RV32IFD-BE-NEXT: sw a0, 8(sp) | ||
| ; RV32IFD-BE-NEXT: sw a1, 12(sp) | ||
| ; RV32IFD-BE-NEXT: fld fa4, 8(sp) | ||
| ; RV32IFD-BE-NEXT: fsgnj.d fa5, fa4, fa5 | ||
| ; RV32IFD-BE-NEXT: fsd fa5, 8(sp) | ||
| ; RV32IFD-BE-NEXT: lw a0, 8(sp) | ||
| ; RV32IFD-BE-NEXT: lw a1, 12(sp) | ||
| ; RV32IFD-BE-NEXT: addi sp, sp, 16 | ||
| ; RV32IFD-BE-NEXT: ret | ||
| %1 = call double @llvm.copysign.f64(double %a, double %b) | ||
| ret double %1 | ||
| } | ||
|
|
||
| declare double @llvm.fabs.f64(double) | ||
| declare double @llvm.copysign.f64(double, double) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | ||
| ; RUN: llc -mtriple=riscv32 -target-abi=ilp32 -mattr=+d -verify-machineinstrs < %s | FileCheck -check-prefix=RV32LE %s | ||
| ; RUN: llc -mtriple=riscv32be -target-abi=ilp32 -mattr=+d -verify-machineinstrs < %s | FileCheck -check-prefix=RV32BE %s | ||
|
|
||
| ; Test f64 function calls with D extension and soft-float ABI | ||
| ; This specifically tests the LowerCall path that needs to swap Lo/Hi for BE | ||
|
|
||
| declare double @external_func(double, double) | ||
|
|
||
| define double @test_f64_call(double %a, double %b) { | ||
| ; RV32LE-LABEL: test_f64_call: | ||
| ; RV32LE: # %bb.0: | ||
| ; RV32LE-NEXT: addi sp, sp, -16 | ||
| ; RV32LE-NEXT: .cfi_def_cfa_offset 16 | ||
| ; RV32LE-NEXT: sw ra, 12(sp) # 4-byte Folded Spill | ||
| ; RV32LE-NEXT: .cfi_offset ra, -4 | ||
| ; RV32LE-NEXT: call external_func | ||
| ; RV32LE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload | ||
| ; RV32LE-NEXT: .cfi_restore ra | ||
| ; RV32LE-NEXT: addi sp, sp, 16 | ||
| ; RV32LE-NEXT: .cfi_def_cfa_offset 0 | ||
| ; RV32LE-NEXT: ret | ||
| ; | ||
| ; RV32BE-LABEL: test_f64_call: | ||
| ; RV32BE: # %bb.0: | ||
| ; RV32BE-NEXT: addi sp, sp, -16 | ||
| ; RV32BE-NEXT: .cfi_def_cfa_offset 16 | ||
| ; RV32BE-NEXT: sw ra, 12(sp) # 4-byte Folded Spill | ||
| ; RV32BE-NEXT: .cfi_offset ra, -4 | ||
| ; RV32BE-NEXT: call external_func | ||
| ; RV32BE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload | ||
| ; RV32BE-NEXT: .cfi_restore ra | ||
| ; RV32BE-NEXT: addi sp, sp, 16 | ||
| ; RV32BE-NEXT: .cfi_def_cfa_offset 0 | ||
| ; RV32BE-NEXT: ret | ||
| %result = call double @external_func(double %a, double %b) | ||
| ret double %result | ||
| } | ||
|
|
||
| ; Test with a computation before the call to force SplitF64 | ||
| define double @test_f64_call_with_fadd(double %a, double %b) { | ||
| ; RV32LE-LABEL: test_f64_call_with_fadd: | ||
| ; RV32LE: # %bb.0: | ||
| ; RV32LE-NEXT: addi sp, sp, -16 | ||
| ; RV32LE-NEXT: .cfi_def_cfa_offset 16 | ||
| ; RV32LE-NEXT: sw ra, 12(sp) # 4-byte Folded Spill | ||
| ; RV32LE-NEXT: .cfi_offset ra, -4 | ||
| ; RV32LE-NEXT: sw a2, 0(sp) | ||
| ; RV32LE-NEXT: sw a3, 4(sp) | ||
| ; RV32LE-NEXT: fld fa5, 0(sp) | ||
| ; RV32LE-NEXT: sw a0, 0(sp) | ||
| ; RV32LE-NEXT: sw a1, 4(sp) | ||
| ; RV32LE-NEXT: fld fa4, 0(sp) | ||
| ; RV32LE-NEXT: fadd.d fa5, fa4, fa5 | ||
| ; RV32LE-NEXT: fsd fa5, 0(sp) | ||
| ; RV32LE-NEXT: lw a0, 0(sp) | ||
| ; RV32LE-NEXT: lw a1, 4(sp) | ||
| ; RV32LE-NEXT: mv a2, a0 | ||
| ; RV32LE-NEXT: mv a3, a1 | ||
| ; RV32LE-NEXT: call external_func | ||
| ; RV32LE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload | ||
| ; RV32LE-NEXT: .cfi_restore ra | ||
| ; RV32LE-NEXT: addi sp, sp, 16 | ||
| ; RV32LE-NEXT: .cfi_def_cfa_offset 0 | ||
| ; RV32LE-NEXT: ret | ||
| ; | ||
| ; RV32BE-LABEL: test_f64_call_with_fadd: | ||
| ; RV32BE: # %bb.0: | ||
| ; RV32BE-NEXT: addi sp, sp, -16 | ||
| ; RV32BE-NEXT: .cfi_def_cfa_offset 16 | ||
| ; RV32BE-NEXT: sw ra, 12(sp) # 4-byte Folded Spill | ||
| ; RV32BE-NEXT: .cfi_offset ra, -4 | ||
| ; RV32BE-NEXT: sw a2, 0(sp) | ||
| ; RV32BE-NEXT: sw a3, 4(sp) | ||
| ; RV32BE-NEXT: fld fa5, 0(sp) | ||
| ; RV32BE-NEXT: sw a0, 0(sp) | ||
| ; RV32BE-NEXT: sw a1, 4(sp) | ||
| ; RV32BE-NEXT: fld fa4, 0(sp) | ||
| ; RV32BE-NEXT: fadd.d fa5, fa4, fa5 | ||
| ; RV32BE-NEXT: fsd fa5, 0(sp) | ||
| ; RV32BE-NEXT: lw a0, 0(sp) | ||
| ; RV32BE-NEXT: lw a1, 4(sp) | ||
| ; RV32BE-NEXT: mv a2, a0 | ||
| ; RV32BE-NEXT: mv a3, a1 | ||
| ; RV32BE-NEXT: call external_func | ||
| ; RV32BE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload | ||
| ; RV32BE-NEXT: .cfi_restore ra | ||
| ; RV32BE-NEXT: addi sp, sp, 16 | ||
| ; RV32BE-NEXT: .cfi_def_cfa_offset 0 | ||
| ; RV32BE-NEXT: ret | ||
| %sum = fadd double %a, %b | ||
| %result = call double @external_func(double %sum, double %sum) | ||
| ret double %result | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot of code duplication here. Can we use more variables to reduce it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks for the suggestion.