diff options
author | bvlgah <octopus.busts_0w@icloud.com> | 2024-03-28 18:09:18 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-28 13:09:18 +0300 |
commit | e640d9e725ef06b9787ab0ab884598f4f5532e48 (patch) | |
tree | af831d72b50801cf0a59721a1cb250c6c08603ef /llvm/test/CodeGen/RISCV | |
parent | 856e815ca1c416de263438e90e8120947e33a03c (diff) | |
download | llvm-e640d9e725ef06b9787ab0ab884598f4f5532e48.zip llvm-e640d9e725ef06b9787ab0ab884598f4f5532e48.tar.gz llvm-e640d9e725ef06b9787ab0ab884598f4f5532e48.tar.bz2 |
[RISCV][GlobalISel] Fix legalizing ‘llvm.va_copy’ intrinsic (#86863)
Hi, I spotted a problem when running benchmarking programs on a RISCV64
device.
## Issue
Segmentation faults only occurred while running the programs compiled
with `GlobalISel` enabled.
Here is a small but complete example (it is adopted from [Google's
benchmark
framework](https://github.com/llvm/llvm-test-suite/blob/95a9f0d0b45056274f0bb4b0e0dd019023e414dc/MicroBenchmarks/libs/benchmark/src/colorprint.cc#L85-L119)
to reproduce the issue,
```cpp
#include <cstdarg>
#include <cstdio>
#include <iostream>
#include <memory>
#include <string>
std::string FormatString(const char* msg, va_list args) {
// we might need a second shot at this, so pre-emptivly make a copy
va_list args_cp;
va_copy(args_cp, args);
std::size_t size = 256;
char local_buff[256];
auto ret = vsnprintf(local_buff, size, msg, args_cp);
va_end(args_cp);
// currently there is no error handling for failure, so this is hack.
// BM_CHECK(ret >= 0);
if (ret == 0) // handle empty expansion
return {};
else if (static_cast<size_t>(ret) < size)
return local_buff;
else {
// we did not provide a long enough buffer on our first attempt.
size = static_cast<size_t>(ret) + 1; // + 1 for the null byte
std::unique_ptr<char[]> buff(new char[size]);
ret = vsnprintf(buff.get(), size, msg, args);
// BM_CHECK(ret > 0 && (static_cast<size_t>(ret)) < size);
return buff.get();
}
}
std::string FormatString(const char* msg, ...) {
va_list args;
va_start(args, msg);
auto tmp = FormatString(msg, args);
va_end(args);
return tmp;
}
int main() {
std::string Str =
FormatString("%-*s %13s %15s %12s", static_cast<int>(20),
"Benchmark", "Time", "CPU", "Iterations");
std::cout << Str << std::endl;
}
```
Use `clang++ -fglobal-isel -o main main.cpp` to compile it.
## Cause
I have examined MIR, it shows that these segmentation faults resulted
from a small mistake about legalizing the intrinsic function
`llvm.va_copy`.
https://github.com/llvm/llvm-project/blob/36e74cfdbde208e384c72bcb52ea638303fb7d67/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp#L451-L453
`DstLst` and `Tmp` are placed in the wrong order.
## Changes
I have tweaked the test case `CodeGen/RISCV/GlobalISel/vararg.ll` so
that `s0` is used as the frame pointer (not in all checks) which points
to the starting address of the save area. I believe that it helps reason
about how `llvm.va_copy` is handled.
Diffstat (limited to 'llvm/test/CodeGen/RISCV')
-rw-r--r-- | llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir | 2 | ||||
-rw-r--r-- | llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll | 936 |
2 files changed, 932 insertions, 6 deletions
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir index f9eda12..16542f58 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir @@ -14,7 +14,7 @@ body: | ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11 ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[COPY1]](p0) :: (load (p0)) - ; CHECK-NEXT: G_STORE [[COPY]](p0), [[LOAD]](p0) :: (store (p0)) + ; CHECK-NEXT: G_STORE [[LOAD]](p0), [[COPY]](p0) :: (store (p0)) ; CHECK-NEXT: PseudoRET %0:_(p0) = COPY $x10 %1:_(p0) = COPY $x11 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll b/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll index 7b110e5..d55adf3 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll @@ -17,6 +17,12 @@ ; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -global-isel -mattr=+d -target-abi lp64d \ ; RUN: -verify-machineinstrs \ ; RUN: | FileCheck -check-prefixes=RV64,LP64D %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv32 -global-isel \ +; RUN: -frame-pointer=all -target-abi ilp32 -verify-machineinstrs \ +; RUN: | FileCheck -check-prefixes=RV32-WITHFP %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -global-isel \ +; RUN: -frame-pointer=all -target-abi lp64 -verify-machineinstrs \ +; RUN: | FileCheck -check-prefixes=RV64-WITHFP %s ; The same vararg calling convention is used for ilp32/ilp32f/ilp32d and for ; lp64/lp64f/lp64d. Different CHECK lines are required due to slight @@ -79,6 +85,67 @@ define i32 @va1(ptr %fmt, ...) { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: lw a0, -20(s0) +; RV64-WITHFP-NEXT: lwu a1, -24(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: or a0, a0, a1 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: srli a2, a1, 32 +; RV64-WITHFP-NEXT: sw a1, -24(s0) +; RV64-WITHFP-NEXT: sw a2, -20(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va, align 4 @@ -131,6 +198,58 @@ define i32 @va1_va_arg(ptr %fmt, ...) nounwind { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -212,6 +331,78 @@ define i32 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { ; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 96 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_va_arg_alloca: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw s1, 0(a0) +; RV32-WITHFP-NEXT: addi a0, s1, 15 +; RV32-WITHFP-NEXT: andi a0, a0, -16 +; RV32-WITHFP-NEXT: sub a0, sp, a0 +; RV32-WITHFP-NEXT: mv sp, a0 +; RV32-WITHFP-NEXT: call notdead +; RV32-WITHFP-NEXT: mv a0, s1 +; RV32-WITHFP-NEXT: addi sp, s0, -16 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_va_arg_alloca: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: lw s1, 0(a0) +; RV64-WITHFP-NEXT: slli a0, s1, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: andi a0, a0, -16 +; RV64-WITHFP-NEXT: sub a0, sp, a0 +; RV64-WITHFP-NEXT: mv sp, a0 +; RV64-WITHFP-NEXT: call notdead +; RV64-WITHFP-NEXT: mv a0, s1 +; RV64-WITHFP-NEXT: addi sp, s0, -32 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -273,6 +464,36 @@ define void @va1_caller() nounwind { ; LP64D-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; LP64D-NEXT: addi sp, sp, 16 ; LP64D-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: lui a3, 261888 +; RV32-WITHFP-NEXT: li a4, 2 +; RV32-WITHFP-NEXT: li a2, 0 +; RV32-WITHFP-NEXT: call va1 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: lui a0, %hi(.LCPI3_0) +; RV64-WITHFP-NEXT: ld a1, %lo(.LCPI3_0)(a0) +; RV64-WITHFP-NEXT: li a2, 2 +; RV64-WITHFP-NEXT: call va1 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i32 (ptr, ...) @va1(ptr undef, double 1.0, i32 2) ret void } @@ -395,6 +616,59 @@ define i64 @va2(ptr %fmt, ...) nounwind { ; RV64-NEXT: ld a0, 0(a1) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 7 +; RV32-WITHFP-NEXT: andi a1, a0, -8 +; RV32-WITHFP-NEXT: addi a0, a0, 8 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a1) +; RV32-WITHFP-NEXT: lw a1, 4(a1) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a1, a0, 7 +; RV64-WITHFP-NEXT: andi a1, a1, -8 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, 0(a1) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va @@ -459,6 +733,61 @@ define i64 @va2_va_arg(ptr %fmt, ...) nounwind { ; RV64-NEXT: srli a0, a0, 32 ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: li a1, 0 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -487,6 +816,32 @@ define void @va2_caller() nounwind { ; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 16 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: li a1, 1 +; RV32-WITHFP-NEXT: call va2 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: li a1, 1 +; RV64-WITHFP-NEXT: call va2 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i64 (ptr, ...) @va2(ptr undef, i32 1) ret void } @@ -617,6 +972,61 @@ define i64 @va3(i32 %a, i64 %b, ...) nounwind { ; RV64-NEXT: add a0, a1, a0 ; RV64-NEXT: addi sp, sp, 64 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 16(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 24 +; RV32-WITHFP-NEXT: sw a3, 4(s0) +; RV32-WITHFP-NEXT: sw a4, 8(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 12(s0) +; RV32-WITHFP-NEXT: sw a6, 16(s0) +; RV32-WITHFP-NEXT: sw a7, 20(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 7 +; RV32-WITHFP-NEXT: andi a3, a0, -8 +; RV32-WITHFP-NEXT: addi a0, a0, 8 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a4, 0(a3) +; RV32-WITHFP-NEXT: lw a3, 4(a3) +; RV32-WITHFP-NEXT: add a0, a1, a4 +; RV32-WITHFP-NEXT: sltu a1, a0, a4 +; RV32-WITHFP-NEXT: add a2, a2, a3 +; RV32-WITHFP-NEXT: add a1, a2, a1 +; RV32-WITHFP-NEXT: lw ra, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 16(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -80 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a2, 0(s0) +; RV64-WITHFP-NEXT: sd a3, 8(s0) +; RV64-WITHFP-NEXT: sd a4, 16(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 24(s0) +; RV64-WITHFP-NEXT: sd a6, 32(s0) +; RV64-WITHFP-NEXT: sd a7, 40(s0) +; RV64-WITHFP-NEXT: addi a2, a0, 7 +; RV64-WITHFP-NEXT: andi a2, a2, -8 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, 0(a2) +; RV64-WITHFP-NEXT: add a0, a1, a0 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 80 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va @@ -682,6 +1092,61 @@ define i64 @va3_va_arg(i32 %a, i64 %b, ...) nounwind { ; RV64-NEXT: add a0, a1, a0 ; RV64-NEXT: addi sp, sp, 64 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 16(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 24 +; RV32-WITHFP-NEXT: sw a3, 4(s0) +; RV32-WITHFP-NEXT: sw a4, 8(s0) +; RV32-WITHFP-NEXT: sw a5, 12(s0) +; RV32-WITHFP-NEXT: sw a6, 16(s0) +; RV32-WITHFP-NEXT: sw a7, 20(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a3, a0, 4 +; RV32-WITHFP-NEXT: sw a3, -12(s0) +; RV32-WITHFP-NEXT: lw a3, 0(a0) +; RV32-WITHFP-NEXT: add a0, a1, a3 +; RV32-WITHFP-NEXT: sltu a1, a0, a3 +; RV32-WITHFP-NEXT: add a1, a2, a1 +; RV32-WITHFP-NEXT: lw ra, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 16(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -80 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a2, 0(s0) +; RV64-WITHFP-NEXT: sd a3, 8(s0) +; RV64-WITHFP-NEXT: sd a4, 16(s0) +; RV64-WITHFP-NEXT: sd a5, 24(s0) +; RV64-WITHFP-NEXT: sd a6, 32(s0) +; RV64-WITHFP-NEXT: sd a7, 40(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a2, a0, 4 +; RV64-WITHFP-NEXT: sd a2, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: add a0, a1, a0 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 80 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -718,6 +1183,39 @@ define void @va3_caller() nounwind { ; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 16 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: lui a0, 5 +; RV32-WITHFP-NEXT: addi a3, a0, -480 +; RV32-WITHFP-NEXT: li a0, 2 +; RV32-WITHFP-NEXT: li a1, 1111 +; RV32-WITHFP-NEXT: li a2, 0 +; RV32-WITHFP-NEXT: call va3 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: lui a0, 5 +; RV64-WITHFP-NEXT: addiw a2, a0, -480 +; RV64-WITHFP-NEXT: li a0, 2 +; RV64-WITHFP-NEXT: li a1, 1111 +; RV64-WITHFP-NEXT: call va3 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i64 (i32, i64, ...) @va3(i32 2, i64 1111, i32 20000) ret void } @@ -745,9 +1243,8 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV32-NEXT: addi a1, a0, 4 ; RV32-NEXT: sw a1, 4(sp) ; RV32-NEXT: lw a1, 4(sp) -; RV32-NEXT: mv a2, sp ; RV32-NEXT: lw s0, 0(a0) -; RV32-NEXT: sw a2, 0(a1) +; RV32-NEXT: sw a1, 0(sp) ; RV32-NEXT: lw a0, 0(sp) ; RV32-NEXT: call notdead ; RV32-NEXT: lw a0, 4(sp) @@ -796,9 +1293,8 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV64-NEXT: addi a1, a0, 4 ; RV64-NEXT: sd a1, 8(sp) ; RV64-NEXT: ld a1, 8(sp) -; RV64-NEXT: mv a2, sp ; RV64-NEXT: lw s0, 0(a0) -; RV64-NEXT: sd a2, 0(a1) +; RV64-NEXT: sd a1, 0(sp) ; RV64-NEXT: lw a0, 4(sp) ; RV64-NEXT: lwu a1, 0(sp) ; RV64-NEXT: slli a0, a0, 32 @@ -829,6 +1325,115 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 96 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va4_va_copy: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -64 +; RV32-WITHFP-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 24(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s1, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a1, -16(s0) +; RV32-WITHFP-NEXT: lw s1, 0(a0) +; RV32-WITHFP-NEXT: sw a1, -20(s0) +; RV32-WITHFP-NEXT: lw a0, -20(s0) +; RV32-WITHFP-NEXT: call notdead +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: addi a1, a1, 3 +; RV32-WITHFP-NEXT: andi a1, a1, -4 +; RV32-WITHFP-NEXT: addi a2, a1, 4 +; RV32-WITHFP-NEXT: sw a2, -16(s0) +; RV32-WITHFP-NEXT: lw a2, -16(s0) +; RV32-WITHFP-NEXT: lw a1, 0(a1) +; RV32-WITHFP-NEXT: addi a2, a2, 3 +; RV32-WITHFP-NEXT: andi a2, a2, -4 +; RV32-WITHFP-NEXT: addi a3, a2, 4 +; RV32-WITHFP-NEXT: sw a3, -16(s0) +; RV32-WITHFP-NEXT: lw a2, 0(a2) +; RV32-WITHFP-NEXT: add a0, a0, s1 +; RV32-WITHFP-NEXT: add a1, a1, a2 +; RV32-WITHFP-NEXT: add a0, a0, a1 +; RV32-WITHFP-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 24(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s1, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 64 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va4_va_copy: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -112 +; RV64-WITHFP-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s1, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 48 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: ld a1, -32(s0) +; RV64-WITHFP-NEXT: lw s1, 0(a0) +; RV64-WITHFP-NEXT: sd a1, -40(s0) +; RV64-WITHFP-NEXT: lw a0, -36(s0) +; RV64-WITHFP-NEXT: lwu a1, -40(s0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: or a0, a0, a1 +; RV64-WITHFP-NEXT: call notdead +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: ld a1, -32(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: addi a1, a1, 3 +; RV64-WITHFP-NEXT: andi a1, a1, -4 +; RV64-WITHFP-NEXT: addi a2, a1, 4 +; RV64-WITHFP-NEXT: sd a2, -32(s0) +; RV64-WITHFP-NEXT: ld a2, -32(s0) +; RV64-WITHFP-NEXT: lw a1, 0(a1) +; RV64-WITHFP-NEXT: addi a2, a2, 3 +; RV64-WITHFP-NEXT: andi a2, a2, -4 +; RV64-WITHFP-NEXT: addi a3, a2, 4 +; RV64-WITHFP-NEXT: sd a3, -32(s0) +; RV64-WITHFP-NEXT: lw a2, 0(a2) +; RV64-WITHFP-NEXT: add a0, a0, s1 +; RV64-WITHFP-NEXT: add a1, a1, a2 +; RV64-WITHFP-NEXT: addw a0, a0, a1 +; RV64-WITHFP-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s1, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 112 +; RV64-WITHFP-NEXT: ret %vargs = alloca ptr %wargs = alloca ptr call void @llvm.va_start(ptr %vargs) @@ -899,6 +1504,60 @@ define i32 @va6_no_fixed_args(...) nounwind { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va6_no_fixed_args: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a0, 0(s0) +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: mv a0, s0 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va6_no_fixed_args: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a0, 0(s0) +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -993,6 +1652,85 @@ define i32 @va_large_stack(ptr %fmt, ...) { ; RV64-NEXT: addiw a1, a1, 336 ; RV64-NEXT: add sp, sp, a1 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_large_stack: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -2032 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 2032 +; RV32-WITHFP-NEXT: sw ra, 1996(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 1992(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 2000 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: lui a0, 24414 +; RV32-WITHFP-NEXT: addi a0, a0, -1728 +; RV32-WITHFP-NEXT: sub sp, sp, a0 +; RV32-WITHFP-NEXT: lui a0, 24414 +; RV32-WITHFP-NEXT: addi a0, a0, 272 +; RV32-WITHFP-NEXT: sub a0, s0, a0 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a1, s0, 4 +; RV32-WITHFP-NEXT: sw a1, 0(a0) +; RV32-WITHFP-NEXT: lw a1, 0(a0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a2, a1, 4 +; RV32-WITHFP-NEXT: sw a2, 0(a0) +; RV32-WITHFP-NEXT: lw a0, 0(a1) +; RV32-WITHFP-NEXT: lui a1, 24414 +; RV32-WITHFP-NEXT: addi a1, a1, -1728 +; RV32-WITHFP-NEXT: add sp, sp, a1 +; RV32-WITHFP-NEXT: lw ra, 1996(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 1992(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 2032 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_large_stack: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -2032 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 2032 +; RV64-WITHFP-NEXT: sd ra, 1960(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 1952(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 1968 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: lui a0, 24414 +; RV64-WITHFP-NEXT: addiw a0, a0, -1680 +; RV64-WITHFP-NEXT: sub sp, sp, a0 +; RV64-WITHFP-NEXT: lui a0, 24414 +; RV64-WITHFP-NEXT: addiw a0, a0, 288 +; RV64-WITHFP-NEXT: sub a0, s0, a0 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: addi a1, s0, 8 +; RV64-WITHFP-NEXT: sd a1, 0(a0) +; RV64-WITHFP-NEXT: lw a1, 4(a0) +; RV64-WITHFP-NEXT: lwu a2, 0(a0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: slli a1, a1, 32 +; RV64-WITHFP-NEXT: or a1, a1, a2 +; RV64-WITHFP-NEXT: addi a2, a1, 4 +; RV64-WITHFP-NEXT: srli a3, a2, 32 +; RV64-WITHFP-NEXT: sw a2, 0(a0) +; RV64-WITHFP-NEXT: sw a3, 4(a0) +; RV64-WITHFP-NEXT: lw a0, 0(a1) +; RV64-WITHFP-NEXT: lui a1, 24414 +; RV64-WITHFP-NEXT: addiw a1, a1, -1680 +; RV64-WITHFP-NEXT: add sp, sp, a1 +; RV64-WITHFP-NEXT: ld ra, 1960(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 1952(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 2032 +; RV64-WITHFP-NEXT: ret %large = alloca [ 100000000 x i8 ] %va = alloca ptr call void @llvm.va_start(ptr %va) @@ -1004,5 +1742,193 @@ define i32 @va_large_stack(ptr %fmt, ...) { ret i32 %1 } +define i32 @va_vprintf(ptr %fmt, ptr %arg_start) { +; RV32-LABEL: va_vprintf: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw a1, 12(sp) +; RV32-NEXT: lw a0, 12(sp) +; RV32-NEXT: sw a0, 8(sp) +; RV32-NEXT: lw a0, 8(sp) +; RV32-NEXT: addi a0, a0, 3 +; RV32-NEXT: andi a0, a0, -4 +; RV32-NEXT: addi a1, a0, 4 +; RV32-NEXT: sw a1, 8(sp) +; RV32-NEXT: lw a0, 0(a0) +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: ret +; +; RV64-LABEL: va_vprintf: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd a1, 8(sp) +; RV64-NEXT: ld a0, 8(sp) +; RV64-NEXT: sd a0, 0(sp) +; RV64-NEXT: ld a0, 0(sp) +; RV64-NEXT: addi a0, a0, 3 +; RV64-NEXT: andi a0, a0, -4 +; RV64-NEXT: addi a1, a0, 4 +; RV64-NEXT: sd a1, 0(sp) +; RV64-NEXT: lw a0, 0(a0) +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_vprintf: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -4 +; RV32-WITHFP-NEXT: .cfi_offset s0, -8 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 0 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_vprintf: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -32 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 32 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -8 +; RV64-WITHFP-NEXT: .cfi_offset s0, -16 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 0 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 32 +; RV64-WITHFP-NEXT: ret + %args = alloca ptr + %args_cp = alloca ptr + store ptr %arg_start, ptr %args + call void @llvm.va_copy(ptr %args_cp, ptr %args) + %width = va_arg ptr %args_cp, i32 + call void @llvm.va_end(ptr %args_cp) + ret i32 %width +} - +define i32 @va_printf(ptr %fmt, ...) { +; RV32-LABEL: va_printf: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -48 +; RV32-NEXT: .cfi_def_cfa_offset 48 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -36 +; RV32-NEXT: sw a1, 20(sp) +; RV32-NEXT: sw a2, 24(sp) +; RV32-NEXT: sw a3, 28(sp) +; RV32-NEXT: sw a4, 32(sp) +; RV32-NEXT: addi a1, sp, 20 +; RV32-NEXT: sw a1, 8(sp) +; RV32-NEXT: lw a1, 8(sp) +; RV32-NEXT: sw a5, 36(sp) +; RV32-NEXT: sw a6, 40(sp) +; RV32-NEXT: sw a7, 44(sp) +; RV32-NEXT: call va_vprintf +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 48 +; RV32-NEXT: ret +; +; RV64-LABEL: va_printf: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -80 +; RV64-NEXT: .cfi_def_cfa_offset 80 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -72 +; RV64-NEXT: sd a1, 24(sp) +; RV64-NEXT: sd a2, 32(sp) +; RV64-NEXT: sd a3, 40(sp) +; RV64-NEXT: sd a4, 48(sp) +; RV64-NEXT: addi a1, sp, 24 +; RV64-NEXT: sd a1, 0(sp) +; RV64-NEXT: ld a1, 0(sp) +; RV64-NEXT: sd a5, 56(sp) +; RV64-NEXT: sd a6, 64(sp) +; RV64-NEXT: sd a7, 72(sp) +; RV64-NEXT: call va_vprintf +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 80 +; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_printf: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a1, s0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a1, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: call va_vprintf +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_printf: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: addi a1, s0, 8 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: ld a1, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: call va_vprintf +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret + %args = alloca ptr + call void @llvm.va_start(ptr %args) + %arg_start = load ptr, ptr %args + %ret_val = call i32 @va_vprintf(ptr %fmt, ptr %arg_start) + call void @llvm.va_end(ptr %args) + ret i32 %ret_val +} |