summaryrefslogtreecommitdiffstats
path: root/llvm/test/CodeGen/RISCV/double-calling-conv.ll
blob: 5e9382fdf696ce4f8bc6901dba21c331a8605d04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
; 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(.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:    call callee_double_inreg
; 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(.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:    call callee_double_split_reg_stack
; 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:    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:    call callee_double_stack
; 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
}
OpenPOWER on IntegriCloud