forked from OSchip/llvm-project
parent
0b4175f160
commit
8f296478eb
|
@ -0,0 +1,23 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefix=RV32IFD %s
|
||||
|
||||
define double @fadd_d(double %a, double %b) nounwind {
|
||||
; RV32IFD-LABEL: fadd_d:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a2, 8(sp)
|
||||
; RV32IFD-NEXT: sw a3, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = fadd double %a, %b
|
||||
ret double %1
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefix=RV32IFD %s
|
||||
|
||||
; Sanity checks for calling convention lowering for RV32D. This can be
|
||||
; somewhat error-prone for soft-float RV32D due to the fact that f64 is legal
|
||||
; but i64 is not, and there is no instruction to move values directly between
|
||||
; the GPRs and 64-bit FPRs.
|
||||
|
||||
define double @callee_double_inreg(double %a, double %b) nounwind {
|
||||
; RV32IFD-LABEL: callee_double_inreg:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a2, 8(sp)
|
||||
; RV32IFD-NEXT: sw a3, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = fadd double %a, %b
|
||||
ret double %1
|
||||
}
|
||||
|
||||
; TODO: code quality for loading and then passing f64 constants is poor.
|
||||
|
||||
define double @caller_double_inreg() nounwind {
|
||||
; RV32IFD-LABEL: caller_double_inreg:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw ra, 12(sp)
|
||||
; RV32IFD-NEXT: lui a0, %hi(callee_double_inreg)
|
||||
; RV32IFD-NEXT: addi a4, a0, %lo(callee_double_inreg)
|
||||
; RV32IFD-NEXT: lui a0, %hi(.LCPI1_0)
|
||||
; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI1_0)
|
||||
; RV32IFD-NEXT: fld ft0, 0(a0)
|
||||
; RV32IFD-NEXT: lui a0, %hi(.LCPI1_1)
|
||||
; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI1_1)
|
||||
; RV32IFD-NEXT: fld ft1, 0(a0)
|
||||
; RV32IFD-NEXT: fsd ft1, 0(sp)
|
||||
; RV32IFD-NEXT: lw a0, 0(sp)
|
||||
; RV32IFD-NEXT: lw a1, 4(sp)
|
||||
; RV32IFD-NEXT: fsd ft0, 0(sp)
|
||||
; RV32IFD-NEXT: lw a2, 0(sp)
|
||||
; RV32IFD-NEXT: lw a3, 4(sp)
|
||||
; RV32IFD-NEXT: jalr a4
|
||||
; RV32IFD-NEXT: lw ra, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = call double @callee_double_inreg(double 2.720000e+00, double 3.720000e+00)
|
||||
ret double %1
|
||||
}
|
||||
|
||||
define double @callee_double_split_reg_stack(i32 %a, i64 %b, i64 %c, double %d, double %e) nounwind {
|
||||
; RV32IFD-LABEL: callee_double_split_reg_stack:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: lw a0, 16(sp)
|
||||
; RV32IFD-NEXT: sw a7, 8(sp)
|
||||
; RV32IFD-NEXT: sw a0, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a5, 8(sp)
|
||||
; RV32IFD-NEXT: sw a6, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = fadd double %d, %e
|
||||
ret double %1
|
||||
}
|
||||
|
||||
define double @caller_double_split_reg_stack() nounwind {
|
||||
; RV32IFD-LABEL: caller_double_split_reg_stack:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -32
|
||||
; RV32IFD-NEXT: sw ra, 28(sp)
|
||||
; RV32IFD-NEXT: lui a0, %hi(.LCPI3_0)
|
||||
; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI3_0)
|
||||
; RV32IFD-NEXT: fld ft0, 0(a0)
|
||||
; RV32IFD-NEXT: fsd ft0, 16(sp)
|
||||
; RV32IFD-NEXT: lw a7, 16(sp)
|
||||
; RV32IFD-NEXT: lw a0, 20(sp)
|
||||
; RV32IFD-NEXT: sw a0, 0(sp)
|
||||
; RV32IFD-NEXT: lui a0, %hi(callee_double_split_reg_stack)
|
||||
; RV32IFD-NEXT: addi t0, a0, %lo(callee_double_split_reg_stack)
|
||||
; RV32IFD-NEXT: lui a0, %hi(.LCPI3_1)
|
||||
; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI3_1)
|
||||
; RV32IFD-NEXT: fld ft0, 0(a0)
|
||||
; RV32IFD-NEXT: fsd ft0, 16(sp)
|
||||
; RV32IFD-NEXT: lw a5, 16(sp)
|
||||
; RV32IFD-NEXT: lw a6, 20(sp)
|
||||
; RV32IFD-NEXT: addi a0, zero, 1
|
||||
; RV32IFD-NEXT: addi a1, zero, 2
|
||||
; RV32IFD-NEXT: addi a3, zero, 3
|
||||
; RV32IFD-NEXT: mv a2, zero
|
||||
; RV32IFD-NEXT: mv a4, zero
|
||||
; RV32IFD-NEXT: jalr t0
|
||||
; RV32IFD-NEXT: lw ra, 28(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 32
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = call double @callee_double_split_reg_stack(i32 1, i64 2, i64 3, double 4.72, double 5.72)
|
||||
ret double %1
|
||||
}
|
||||
|
||||
define double @callee_double_stack(i64 %a, i64 %b, i64 %c, i64 %d, double %e, double %f) nounwind {
|
||||
; RV32IFD-LABEL: callee_double_stack:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: fld ft0, 24(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 16(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = fadd double %e, %f
|
||||
ret double %1
|
||||
}
|
||||
|
||||
define double @caller_double_stack() nounwind {
|
||||
; RV32IFD-LABEL: caller_double_stack:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -32
|
||||
; RV32IFD-NEXT: sw ra, 28(sp)
|
||||
; RV32IFD-NEXT: lui a0, 262510
|
||||
; RV32IFD-NEXT: addi a0, a0, 327
|
||||
; RV32IFD-NEXT: sw a0, 4(sp)
|
||||
; RV32IFD-NEXT: lui a0, 262574
|
||||
; RV32IFD-NEXT: addi a0, a0, 327
|
||||
; RV32IFD-NEXT: sw a0, 12(sp)
|
||||
; RV32IFD-NEXT: lui a0, 713032
|
||||
; RV32IFD-NEXT: addi a0, a0, -1311
|
||||
; RV32IFD-NEXT: sw a0, 0(sp)
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lui a0, %hi(callee_double_stack)
|
||||
; RV32IFD-NEXT: addi t0, a0, %lo(callee_double_stack)
|
||||
; RV32IFD-NEXT: addi a0, zero, 1
|
||||
; RV32IFD-NEXT: addi a2, zero, 2
|
||||
; RV32IFD-NEXT: addi a4, zero, 3
|
||||
; RV32IFD-NEXT: addi a6, zero, 4
|
||||
; RV32IFD-NEXT: mv a1, zero
|
||||
; RV32IFD-NEXT: mv a3, zero
|
||||
; RV32IFD-NEXT: mv a5, zero
|
||||
; RV32IFD-NEXT: mv a7, zero
|
||||
; RV32IFD-NEXT: jalr t0
|
||||
; RV32IFD-NEXT: lw ra, 28(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 32
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = call double @callee_double_stack(i64 1, i64 2, i64 3, i64 4, double 5.72, double 6.72)
|
||||
ret double %1
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefix=RV32IFD %s
|
||||
|
||||
define double @double_imm() nounwind {
|
||||
; RV32IFD-LABEL: double_imm:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: lui a0, %hi(.LCPI0_0)
|
||||
; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI0_0)
|
||||
; RV32IFD-NEXT: fld ft0, 0(a0)
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
ret double 3.1415926535897931159979634685441851615905761718750
|
||||
}
|
||||
|
||||
define double @double_imm_op(double %a) nounwind {
|
||||
; RV32IFD-LABEL: double_imm_op:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lui a0, %hi(.LCPI1_0)
|
||||
; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI1_0)
|
||||
; RV32IFD-NEXT: fld ft1, 0(a0)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft0, ft1
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = fadd double %a, 1.0
|
||||
ret double %1
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefix=RV32IFD %s
|
||||
|
||||
declare double @llvm.floor.f64(double)
|
||||
|
||||
; The call to ffloor is introduced very late, meaning this test case covers
|
||||
; aspects of passing f64 on RV32D soft-float that double-calling-conv.ll
|
||||
; doesn't.
|
||||
|
||||
define double @foo(double %a) nounwind {
|
||||
; RV32IFD-LABEL: foo:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw ra, 12(sp)
|
||||
; RV32IFD-NEXT: lui a2, %hi(floor)
|
||||
; RV32IFD-NEXT: addi a2, a2, %lo(floor)
|
||||
; RV32IFD-NEXT: jalr a2
|
||||
; RV32IFD-NEXT: lw ra, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = call double @llvm.floor.f64(double %a)
|
||||
ret double %1
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefix=RV32IFD %s
|
||||
|
||||
define double @fld(double *%a) nounwind {
|
||||
; RV32IFD-LABEL: fld:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: fld ft0, 24(a0)
|
||||
; RV32IFD-NEXT: fld ft1, 0(a0)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = load double, double* %a
|
||||
%2 = getelementptr double, double* %a, i32 3
|
||||
%3 = load double, double* %2
|
||||
; Use both loaded values in an FP op to ensure an fld is used, even for the
|
||||
; soft float ABI
|
||||
%4 = fadd double %1, %3
|
||||
ret double %4
|
||||
}
|
||||
|
||||
define void @fsd(double *%a, double %b, double %c) nounwind {
|
||||
; RV32IFD-LABEL: fsd:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a3, 8(sp)
|
||||
; RV32IFD-NEXT: sw a4, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 8(sp)
|
||||
; RV32IFD-NEXT: sw a2, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 64(a0)
|
||||
; RV32IFD-NEXT: fsd ft0, 0(a0)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
; Use %b and %c in an FP op to ensure floating point registers are used, even
|
||||
; for the soft float ABI
|
||||
%1 = fadd double %b, %c
|
||||
store double %1, double* %a
|
||||
%2 = getelementptr double, double* %a, i32 8
|
||||
store double %1, double* %2
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check load and store to a global
|
||||
@G = global double 0.0
|
||||
|
||||
define double @fld_fsd_global(double %a, double %b) nounwind {
|
||||
; RV32IFD-LABEL: fld_fsd_global:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a2, 8(sp)
|
||||
; RV32IFD-NEXT: sw a3, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: lui a0, %hi(G)
|
||||
; RV32IFD-NEXT: fld ft1, %lo(G)(a0)
|
||||
; RV32IFD-NEXT: fsd ft0, %lo(G)(a0)
|
||||
; RV32IFD-NEXT: lui a0, %hi(G+72)
|
||||
; RV32IFD-NEXT: fld ft1, %lo(G+72)(a0)
|
||||
; RV32IFD-NEXT: fsd ft0, %lo(G+72)(a0)
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
; Use %a and %b in an FP op to ensure floating point registers are used, even
|
||||
; for the soft float ABI
|
||||
%1 = fadd double %a, %b
|
||||
%2 = load volatile double, double* @G
|
||||
store double %1, double* @G
|
||||
%3 = getelementptr double, double* @G, i32 9
|
||||
%4 = load volatile double, double* %3
|
||||
store double %1, double* %3
|
||||
ret double %1
|
||||
}
|
||||
|
||||
; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1
|
||||
define double @fld_fsd_constant(double %a) nounwind {
|
||||
; RV32IFD-LABEL: fld_fsd_constant:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lui a0, 912092
|
||||
; RV32IFD-NEXT: fld ft1, -273(a0)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft0, ft1
|
||||
; RV32IFD-NEXT: fsd ft0, -273(a0)
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = inttoptr i32 3735928559 to double*
|
||||
%2 = load volatile double, double* %1
|
||||
%3 = fadd double %a, %2
|
||||
store double %3, double* %1
|
||||
ret double %3
|
||||
}
|
||||
|
||||
declare void @notdead(i8*)
|
||||
|
||||
define double @fld_stack(double %a) nounwind {
|
||||
; RV32IFD-LABEL: fld_stack:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -32
|
||||
; RV32IFD-NEXT: sw ra, 28(sp)
|
||||
; RV32IFD-NEXT: sw s1, 24(sp)
|
||||
; RV32IFD-NEXT: sw s2, 20(sp)
|
||||
; RV32IFD-NEXT: mv s1, a1
|
||||
; RV32IFD-NEXT: mv s2, a0
|
||||
; RV32IFD-NEXT: lui a0, %hi(notdead)
|
||||
; RV32IFD-NEXT: addi a1, a0, %lo(notdead)
|
||||
; RV32IFD-NEXT: addi a0, sp, 8
|
||||
; RV32IFD-NEXT: jalr a1
|
||||
; RV32IFD-NEXT: sw s2, 0(sp)
|
||||
; RV32IFD-NEXT: sw s1, 4(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 0(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 0(sp)
|
||||
; RV32IFD-NEXT: lw a0, 0(sp)
|
||||
; RV32IFD-NEXT: lw a1, 4(sp)
|
||||
; RV32IFD-NEXT: lw s2, 20(sp)
|
||||
; RV32IFD-NEXT: lw s1, 24(sp)
|
||||
; RV32IFD-NEXT: lw ra, 28(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 32
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = alloca double, align 8
|
||||
%2 = bitcast double* %1 to i8*
|
||||
call void @notdead(i8* %2)
|
||||
%3 = load double, double* %1
|
||||
%4 = fadd double %3, %a ; force load in to FPR64
|
||||
ret double %4
|
||||
}
|
||||
|
||||
define void @fsd_stack(double %a, double %b) nounwind {
|
||||
; RV32IFD-LABEL: fsd_stack:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -32
|
||||
; RV32IFD-NEXT: sw ra, 28(sp)
|
||||
; RV32IFD-NEXT: sw a2, 8(sp)
|
||||
; RV32IFD-NEXT: sw a3, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 16(sp)
|
||||
; RV32IFD-NEXT: lui a0, %hi(notdead)
|
||||
; RV32IFD-NEXT: addi a1, a0, %lo(notdead)
|
||||
; RV32IFD-NEXT: addi a0, sp, 16
|
||||
; RV32IFD-NEXT: jalr a1
|
||||
; RV32IFD-NEXT: lw ra, 28(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 32
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = fadd double %a, %b ; force store from FPR64
|
||||
%2 = alloca double, align 8
|
||||
store double %1, double* %2
|
||||
%3 = bitcast double* %2 to i8*
|
||||
call void @notdead(i8* %3)
|
||||
ret void
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
|
||||
; RUN: | FileCheck -check-prefix=RV32IFD %s
|
||||
|
||||
define double @func(double %d, i32 %n) nounwind {
|
||||
; RV32IFD-LABEL: func:
|
||||
; RV32IFD: # %bb.0: # %entry
|
||||
; RV32IFD-NEXT: addi sp, sp, -32
|
||||
; RV32IFD-NEXT: sw ra, 28(sp)
|
||||
; RV32IFD-NEXT: sw a0, 16(sp)
|
||||
; RV32IFD-NEXT: sw a1, 20(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 16(sp)
|
||||
; RV32IFD-NEXT: beqz a2, .LBB0_2
|
||||
; RV32IFD-NEXT: # %bb.1: # %if.else
|
||||
; RV32IFD-NEXT: addi a2, a2, -1
|
||||
; RV32IFD-NEXT: lui a0, %hi(func)
|
||||
; RV32IFD-NEXT: addi a3, a0, %lo(func)
|
||||
; RV32IFD-NEXT: fsd ft0, 16(sp)
|
||||
; RV32IFD-NEXT: lw a0, 16(sp)
|
||||
; RV32IFD-NEXT: lw a1, 20(sp)
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: jalr a3
|
||||
; RV32IFD-NEXT: sw a0, 16(sp)
|
||||
; RV32IFD-NEXT: sw a1, 20(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 16(sp)
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft0, ft1
|
||||
; RV32IFD-NEXT: .LBB0_2: # %return
|
||||
; RV32IFD-NEXT: fsd ft0, 16(sp)
|
||||
; RV32IFD-NEXT: lw a0, 16(sp)
|
||||
; RV32IFD-NEXT: lw a1, 20(sp)
|
||||
; RV32IFD-NEXT: lw ra, 28(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 32
|
||||
; RV32IFD-NEXT: ret
|
||||
entry:
|
||||
%cmp = icmp eq i32 %n, 0
|
||||
br i1 %cmp, label %return, label %if.else
|
||||
|
||||
if.else:
|
||||
%sub = add i32 %n, -1
|
||||
%call = tail call double @func(double %d, i32 %sub)
|
||||
%add = fadd double %call, %d
|
||||
ret double %add
|
||||
|
||||
return:
|
||||
ret double %d
|
||||
}
|
Loading…
Reference in New Issue