1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3 ; RUN: | FileCheck -check-prefix=RV32I-FPELIM %s 4 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -disable-fp-elim < %s \ 5 ; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s 6 7 ; As well as calling convention details, we check that ra and fp are 8 ; consistently stored to fp-4 and fp-8. 9 10 ; Check that on RV32, i64 and double are passed in a pair of registers. Unlike 11 ; the convention for varargs, this need not be an aligned pair. 12 13 define i32 @callee_scalars(i32 %a, i64 %b, i32 %c, i32 %d, double %e) nounwind { 14 ; RV32I-FPELIM-LABEL: callee_scalars: 15 ; RV32I-FPELIM: # %bb.0: 16 ; RV32I-FPELIM-NEXT: addi sp, sp, -32 17 ; RV32I-FPELIM-NEXT: sw ra, 28(sp) 18 ; RV32I-FPELIM-NEXT: sw s1, 24(sp) 19 ; RV32I-FPELIM-NEXT: sw s2, 20(sp) 20 ; RV32I-FPELIM-NEXT: sw s3, 16(sp) 21 ; RV32I-FPELIM-NEXT: sw s4, 12(sp) 22 ; RV32I-FPELIM-NEXT: mv s2, a4 23 ; RV32I-FPELIM-NEXT: mv s3, a3 24 ; RV32I-FPELIM-NEXT: mv s4, a1 25 ; RV32I-FPELIM-NEXT: mv s1, a0 26 ; RV32I-FPELIM-NEXT: mv a0, a5 27 ; RV32I-FPELIM-NEXT: mv a1, a6 28 ; RV32I-FPELIM-NEXT: call __fixdfsi 29 ; RV32I-FPELIM-NEXT: add a1, s1, s4 30 ; RV32I-FPELIM-NEXT: add a1, a1, s3 31 ; RV32I-FPELIM-NEXT: add a1, a1, s2 32 ; RV32I-FPELIM-NEXT: add a0, a1, a0 33 ; RV32I-FPELIM-NEXT: lw s4, 12(sp) 34 ; RV32I-FPELIM-NEXT: lw s3, 16(sp) 35 ; RV32I-FPELIM-NEXT: lw s2, 20(sp) 36 ; RV32I-FPELIM-NEXT: lw s1, 24(sp) 37 ; RV32I-FPELIM-NEXT: lw ra, 28(sp) 38 ; RV32I-FPELIM-NEXT: addi sp, sp, 32 39 ; RV32I-FPELIM-NEXT: ret 40 ; 41 ; RV32I-WITHFP-LABEL: callee_scalars: 42 ; RV32I-WITHFP: # %bb.0: 43 ; RV32I-WITHFP-NEXT: addi sp, sp, -32 44 ; RV32I-WITHFP-NEXT: sw ra, 28(sp) 45 ; RV32I-WITHFP-NEXT: sw s0, 24(sp) 46 ; RV32I-WITHFP-NEXT: sw s1, 20(sp) 47 ; RV32I-WITHFP-NEXT: sw s2, 16(sp) 48 ; RV32I-WITHFP-NEXT: sw s3, 12(sp) 49 ; RV32I-WITHFP-NEXT: sw s4, 8(sp) 50 ; RV32I-WITHFP-NEXT: addi s0, sp, 32 51 ; RV32I-WITHFP-NEXT: mv s2, a4 52 ; RV32I-WITHFP-NEXT: mv s3, a3 53 ; RV32I-WITHFP-NEXT: mv s4, a1 54 ; RV32I-WITHFP-NEXT: mv s1, a0 55 ; RV32I-WITHFP-NEXT: mv a0, a5 56 ; RV32I-WITHFP-NEXT: mv a1, a6 57 ; RV32I-WITHFP-NEXT: call __fixdfsi 58 ; RV32I-WITHFP-NEXT: add a1, s1, s4 59 ; RV32I-WITHFP-NEXT: add a1, a1, s3 60 ; RV32I-WITHFP-NEXT: add a1, a1, s2 61 ; RV32I-WITHFP-NEXT: add a0, a1, a0 62 ; RV32I-WITHFP-NEXT: lw s4, 8(sp) 63 ; RV32I-WITHFP-NEXT: lw s3, 12(sp) 64 ; RV32I-WITHFP-NEXT: lw s2, 16(sp) 65 ; RV32I-WITHFP-NEXT: lw s1, 20(sp) 66 ; RV32I-WITHFP-NEXT: lw s0, 24(sp) 67 ; RV32I-WITHFP-NEXT: lw ra, 28(sp) 68 ; RV32I-WITHFP-NEXT: addi sp, sp, 32 69 ; RV32I-WITHFP-NEXT: ret 70 %b_trunc = trunc i64 %b to i32 71 %e_fptosi = fptosi double %e to i32 72 %1 = add i32 %a, %b_trunc 73 %2 = add i32 %1, %c 74 %3 = add i32 %2, %d 75 %4 = add i32 %3, %e_fptosi 76 ret i32 %4 77 } 78 79 define i32 @caller_scalars() nounwind { 80 ; RV32I-FPELIM-LABEL: caller_scalars: 81 ; RV32I-FPELIM: # %bb.0: 82 ; RV32I-FPELIM-NEXT: addi sp, sp, -16 83 ; RV32I-FPELIM-NEXT: sw ra, 12(sp) 84 ; RV32I-FPELIM-NEXT: addi a0, zero, 1 85 ; RV32I-FPELIM-NEXT: addi a1, zero, 2 86 ; RV32I-FPELIM-NEXT: addi a3, zero, 3 87 ; RV32I-FPELIM-NEXT: addi a4, zero, 4 88 ; RV32I-FPELIM-NEXT: lui a6, 262464 89 ; RV32I-FPELIM-NEXT: mv a2, zero 90 ; RV32I-FPELIM-NEXT: mv a5, zero 91 ; RV32I-FPELIM-NEXT: call callee_scalars 92 ; RV32I-FPELIM-NEXT: lw ra, 12(sp) 93 ; RV32I-FPELIM-NEXT: addi sp, sp, 16 94 ; RV32I-FPELIM-NEXT: ret 95 ; 96 ; RV32I-WITHFP-LABEL: caller_scalars: 97 ; RV32I-WITHFP: # %bb.0: 98 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 99 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 100 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 101 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 102 ; RV32I-WITHFP-NEXT: addi a0, zero, 1 103 ; RV32I-WITHFP-NEXT: addi a1, zero, 2 104 ; RV32I-WITHFP-NEXT: addi a3, zero, 3 105 ; RV32I-WITHFP-NEXT: addi a4, zero, 4 106 ; RV32I-WITHFP-NEXT: lui a6, 262464 107 ; RV32I-WITHFP-NEXT: mv a2, zero 108 ; RV32I-WITHFP-NEXT: mv a5, zero 109 ; RV32I-WITHFP-NEXT: call callee_scalars 110 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 111 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 112 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 113 ; RV32I-WITHFP-NEXT: ret 114 %1 = call i32 @callee_scalars(i32 1, i64 2, i32 3, i32 4, double 5.000000e+00) 115 ret i32 %1 116 } 117 118 ; Check that i128 and fp128 are passed indirectly 119 120 define i32 @callee_large_scalars(i128 %a, fp128 %b) nounwind { 121 ; RV32I-FPELIM-LABEL: callee_large_scalars: 122 ; RV32I-FPELIM: # %bb.0: 123 ; RV32I-FPELIM-NEXT: lw a2, 12(a1) 124 ; RV32I-FPELIM-NEXT: lw a3, 12(a0) 125 ; RV32I-FPELIM-NEXT: xor a2, a3, a2 126 ; RV32I-FPELIM-NEXT: lw a3, 4(a1) 127 ; RV32I-FPELIM-NEXT: lw a4, 4(a0) 128 ; RV32I-FPELIM-NEXT: xor a3, a4, a3 129 ; RV32I-FPELIM-NEXT: or a2, a3, a2 130 ; RV32I-FPELIM-NEXT: lw a3, 8(a1) 131 ; RV32I-FPELIM-NEXT: lw a4, 8(a0) 132 ; RV32I-FPELIM-NEXT: xor a3, a4, a3 133 ; RV32I-FPELIM-NEXT: lw a1, 0(a1) 134 ; RV32I-FPELIM-NEXT: lw a0, 0(a0) 135 ; RV32I-FPELIM-NEXT: xor a0, a0, a1 136 ; RV32I-FPELIM-NEXT: or a0, a0, a3 137 ; RV32I-FPELIM-NEXT: or a0, a0, a2 138 ; RV32I-FPELIM-NEXT: xor a0, a0, zero 139 ; RV32I-FPELIM-NEXT: seqz a0, a0 140 ; RV32I-FPELIM-NEXT: ret 141 ; 142 ; RV32I-WITHFP-LABEL: callee_large_scalars: 143 ; RV32I-WITHFP: # %bb.0: 144 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 145 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 146 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 147 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 148 ; RV32I-WITHFP-NEXT: lw a2, 12(a1) 149 ; RV32I-WITHFP-NEXT: lw a3, 12(a0) 150 ; RV32I-WITHFP-NEXT: xor a2, a3, a2 151 ; RV32I-WITHFP-NEXT: lw a3, 4(a1) 152 ; RV32I-WITHFP-NEXT: lw a4, 4(a0) 153 ; RV32I-WITHFP-NEXT: xor a3, a4, a3 154 ; RV32I-WITHFP-NEXT: or a2, a3, a2 155 ; RV32I-WITHFP-NEXT: lw a3, 8(a1) 156 ; RV32I-WITHFP-NEXT: lw a4, 8(a0) 157 ; RV32I-WITHFP-NEXT: xor a3, a4, a3 158 ; RV32I-WITHFP-NEXT: lw a1, 0(a1) 159 ; RV32I-WITHFP-NEXT: lw a0, 0(a0) 160 ; RV32I-WITHFP-NEXT: xor a0, a0, a1 161 ; RV32I-WITHFP-NEXT: or a0, a0, a3 162 ; RV32I-WITHFP-NEXT: or a0, a0, a2 163 ; RV32I-WITHFP-NEXT: xor a0, a0, zero 164 ; RV32I-WITHFP-NEXT: seqz a0, a0 165 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 166 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 167 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 168 ; RV32I-WITHFP-NEXT: ret 169 %b_bitcast = bitcast fp128 %b to i128 170 %1 = icmp eq i128 %a, %b_bitcast 171 %2 = zext i1 %1 to i32 172 ret i32 %2 173 } 174 175 define i32 @caller_large_scalars() nounwind { 176 ; RV32I-FPELIM-LABEL: caller_large_scalars: 177 ; RV32I-FPELIM: # %bb.0: 178 ; RV32I-FPELIM-NEXT: addi sp, sp, -48 179 ; RV32I-FPELIM-NEXT: sw ra, 44(sp) 180 ; RV32I-FPELIM-NEXT: lui a0, 524272 181 ; RV32I-FPELIM-NEXT: sw a0, 12(sp) 182 ; RV32I-FPELIM-NEXT: sw zero, 8(sp) 183 ; RV32I-FPELIM-NEXT: sw zero, 4(sp) 184 ; RV32I-FPELIM-NEXT: sw zero, 0(sp) 185 ; RV32I-FPELIM-NEXT: sw zero, 36(sp) 186 ; RV32I-FPELIM-NEXT: sw zero, 32(sp) 187 ; RV32I-FPELIM-NEXT: sw zero, 28(sp) 188 ; RV32I-FPELIM-NEXT: addi a0, zero, 1 189 ; RV32I-FPELIM-NEXT: sw a0, 24(sp) 190 ; RV32I-FPELIM-NEXT: addi a0, sp, 24 191 ; RV32I-FPELIM-NEXT: mv a1, sp 192 ; RV32I-FPELIM-NEXT: call callee_large_scalars 193 ; RV32I-FPELIM-NEXT: lw ra, 44(sp) 194 ; RV32I-FPELIM-NEXT: addi sp, sp, 48 195 ; RV32I-FPELIM-NEXT: ret 196 ; 197 ; RV32I-WITHFP-LABEL: caller_large_scalars: 198 ; RV32I-WITHFP: # %bb.0: 199 ; RV32I-WITHFP-NEXT: addi sp, sp, -48 200 ; RV32I-WITHFP-NEXT: sw ra, 44(sp) 201 ; RV32I-WITHFP-NEXT: sw s0, 40(sp) 202 ; RV32I-WITHFP-NEXT: addi s0, sp, 48 203 ; RV32I-WITHFP-NEXT: lui a0, 524272 204 ; RV32I-WITHFP-NEXT: sw a0, -36(s0) 205 ; RV32I-WITHFP-NEXT: sw zero, -40(s0) 206 ; RV32I-WITHFP-NEXT: sw zero, -44(s0) 207 ; RV32I-WITHFP-NEXT: sw zero, -48(s0) 208 ; RV32I-WITHFP-NEXT: sw zero, -12(s0) 209 ; RV32I-WITHFP-NEXT: sw zero, -16(s0) 210 ; RV32I-WITHFP-NEXT: sw zero, -20(s0) 211 ; RV32I-WITHFP-NEXT: addi a0, zero, 1 212 ; RV32I-WITHFP-NEXT: sw a0, -24(s0) 213 ; RV32I-WITHFP-NEXT: addi a0, s0, -24 214 ; RV32I-WITHFP-NEXT: addi a1, s0, -48 215 ; RV32I-WITHFP-NEXT: call callee_large_scalars 216 ; RV32I-WITHFP-NEXT: lw s0, 40(sp) 217 ; RV32I-WITHFP-NEXT: lw ra, 44(sp) 218 ; RV32I-WITHFP-NEXT: addi sp, sp, 48 219 ; RV32I-WITHFP-NEXT: ret 220 %1 = call i32 @callee_large_scalars(i128 1, fp128 0xL00000000000000007FFF000000000000) 221 ret i32 %1 222 } 223 224 ; Must keep define on a single line due to an update_llc_test_checks.py limitation 225 define i32 @callee_large_scalars_exhausted_regs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i128 %h, i32 %i, fp128 %j) nounwind { 226 ; Check that arguments larger than 2*xlen are handled correctly when their 227 ; address is passed on the stack rather than in memory 228 ; RV32I-FPELIM-LABEL: callee_large_scalars_exhausted_regs: 229 ; RV32I-FPELIM: # %bb.0: 230 ; RV32I-FPELIM-NEXT: lw a0, 4(sp) 231 ; RV32I-FPELIM-NEXT: lw a1, 12(a0) 232 ; RV32I-FPELIM-NEXT: lw a2, 12(a7) 233 ; RV32I-FPELIM-NEXT: xor a1, a2, a1 234 ; RV32I-FPELIM-NEXT: lw a2, 4(a0) 235 ; RV32I-FPELIM-NEXT: lw a3, 4(a7) 236 ; RV32I-FPELIM-NEXT: xor a2, a3, a2 237 ; RV32I-FPELIM-NEXT: or a1, a2, a1 238 ; RV32I-FPELIM-NEXT: lw a2, 8(a0) 239 ; RV32I-FPELIM-NEXT: lw a3, 8(a7) 240 ; RV32I-FPELIM-NEXT: xor a2, a3, a2 241 ; RV32I-FPELIM-NEXT: lw a0, 0(a0) 242 ; RV32I-FPELIM-NEXT: lw a3, 0(a7) 243 ; RV32I-FPELIM-NEXT: xor a0, a3, a0 244 ; RV32I-FPELIM-NEXT: or a0, a0, a2 245 ; RV32I-FPELIM-NEXT: or a0, a0, a1 246 ; RV32I-FPELIM-NEXT: xor a0, a0, zero 247 ; RV32I-FPELIM-NEXT: seqz a0, a0 248 ; RV32I-FPELIM-NEXT: ret 249 ; 250 ; RV32I-WITHFP-LABEL: callee_large_scalars_exhausted_regs: 251 ; RV32I-WITHFP: # %bb.0: 252 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 253 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 254 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 255 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 256 ; RV32I-WITHFP-NEXT: lw a0, 4(s0) 257 ; RV32I-WITHFP-NEXT: lw a1, 12(a0) 258 ; RV32I-WITHFP-NEXT: lw a2, 12(a7) 259 ; RV32I-WITHFP-NEXT: xor a1, a2, a1 260 ; RV32I-WITHFP-NEXT: lw a2, 4(a0) 261 ; RV32I-WITHFP-NEXT: lw a3, 4(a7) 262 ; RV32I-WITHFP-NEXT: xor a2, a3, a2 263 ; RV32I-WITHFP-NEXT: or a1, a2, a1 264 ; RV32I-WITHFP-NEXT: lw a2, 8(a0) 265 ; RV32I-WITHFP-NEXT: lw a3, 8(a7) 266 ; RV32I-WITHFP-NEXT: xor a2, a3, a2 267 ; RV32I-WITHFP-NEXT: lw a0, 0(a0) 268 ; RV32I-WITHFP-NEXT: lw a3, 0(a7) 269 ; RV32I-WITHFP-NEXT: xor a0, a3, a0 270 ; RV32I-WITHFP-NEXT: or a0, a0, a2 271 ; RV32I-WITHFP-NEXT: or a0, a0, a1 272 ; RV32I-WITHFP-NEXT: xor a0, a0, zero 273 ; RV32I-WITHFP-NEXT: seqz a0, a0 274 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 275 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 276 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 277 ; RV32I-WITHFP-NEXT: ret 278 %j_bitcast = bitcast fp128 %j to i128 279 %1 = icmp eq i128 %h, %j_bitcast 280 %2 = zext i1 %1 to i32 281 ret i32 %2 282 } 283 284 define i32 @caller_large_scalars_exhausted_regs() nounwind { 285 ; RV32I-FPELIM-LABEL: caller_large_scalars_exhausted_regs: 286 ; RV32I-FPELIM: # %bb.0: 287 ; RV32I-FPELIM-NEXT: addi sp, sp, -64 288 ; RV32I-FPELIM-NEXT: sw ra, 60(sp) 289 ; RV32I-FPELIM-NEXT: addi a0, sp, 16 290 ; RV32I-FPELIM-NEXT: sw a0, 4(sp) 291 ; RV32I-FPELIM-NEXT: addi a0, zero, 9 292 ; RV32I-FPELIM-NEXT: sw a0, 0(sp) 293 ; RV32I-FPELIM-NEXT: lui a0, 524272 294 ; RV32I-FPELIM-NEXT: sw a0, 28(sp) 295 ; RV32I-FPELIM-NEXT: sw zero, 24(sp) 296 ; RV32I-FPELIM-NEXT: sw zero, 20(sp) 297 ; RV32I-FPELIM-NEXT: sw zero, 16(sp) 298 ; RV32I-FPELIM-NEXT: sw zero, 52(sp) 299 ; RV32I-FPELIM-NEXT: sw zero, 48(sp) 300 ; RV32I-FPELIM-NEXT: sw zero, 44(sp) 301 ; RV32I-FPELIM-NEXT: addi a0, zero, 8 302 ; RV32I-FPELIM-NEXT: sw a0, 40(sp) 303 ; RV32I-FPELIM-NEXT: addi a0, zero, 1 304 ; RV32I-FPELIM-NEXT: addi a1, zero, 2 305 ; RV32I-FPELIM-NEXT: addi a2, zero, 3 306 ; RV32I-FPELIM-NEXT: addi a3, zero, 4 307 ; RV32I-FPELIM-NEXT: addi a4, zero, 5 308 ; RV32I-FPELIM-NEXT: addi a5, zero, 6 309 ; RV32I-FPELIM-NEXT: addi a6, zero, 7 310 ; RV32I-FPELIM-NEXT: addi a7, sp, 40 311 ; RV32I-FPELIM-NEXT: call callee_large_scalars_exhausted_regs 312 ; RV32I-FPELIM-NEXT: lw ra, 60(sp) 313 ; RV32I-FPELIM-NEXT: addi sp, sp, 64 314 ; RV32I-FPELIM-NEXT: ret 315 ; 316 ; RV32I-WITHFP-LABEL: caller_large_scalars_exhausted_regs: 317 ; RV32I-WITHFP: # %bb.0: 318 ; RV32I-WITHFP-NEXT: addi sp, sp, -64 319 ; RV32I-WITHFP-NEXT: sw ra, 60(sp) 320 ; RV32I-WITHFP-NEXT: sw s0, 56(sp) 321 ; RV32I-WITHFP-NEXT: addi s0, sp, 64 322 ; RV32I-WITHFP-NEXT: addi a0, s0, -48 323 ; RV32I-WITHFP-NEXT: sw a0, 4(sp) 324 ; RV32I-WITHFP-NEXT: addi a0, zero, 9 325 ; RV32I-WITHFP-NEXT: sw a0, 0(sp) 326 ; RV32I-WITHFP-NEXT: lui a0, 524272 327 ; RV32I-WITHFP-NEXT: sw a0, -36(s0) 328 ; RV32I-WITHFP-NEXT: sw zero, -40(s0) 329 ; RV32I-WITHFP-NEXT: sw zero, -44(s0) 330 ; RV32I-WITHFP-NEXT: sw zero, -48(s0) 331 ; RV32I-WITHFP-NEXT: sw zero, -12(s0) 332 ; RV32I-WITHFP-NEXT: sw zero, -16(s0) 333 ; RV32I-WITHFP-NEXT: sw zero, -20(s0) 334 ; RV32I-WITHFP-NEXT: addi a0, zero, 8 335 ; RV32I-WITHFP-NEXT: sw a0, -24(s0) 336 ; RV32I-WITHFP-NEXT: addi a0, zero, 1 337 ; RV32I-WITHFP-NEXT: addi a1, zero, 2 338 ; RV32I-WITHFP-NEXT: addi a2, zero, 3 339 ; RV32I-WITHFP-NEXT: addi a3, zero, 4 340 ; RV32I-WITHFP-NEXT: addi a4, zero, 5 341 ; RV32I-WITHFP-NEXT: addi a5, zero, 6 342 ; RV32I-WITHFP-NEXT: addi a6, zero, 7 343 ; RV32I-WITHFP-NEXT: addi a7, s0, -24 344 ; RV32I-WITHFP-NEXT: call callee_large_scalars_exhausted_regs 345 ; RV32I-WITHFP-NEXT: lw s0, 56(sp) 346 ; RV32I-WITHFP-NEXT: lw ra, 60(sp) 347 ; RV32I-WITHFP-NEXT: addi sp, sp, 64 348 ; RV32I-WITHFP-NEXT: ret 349 %1 = call i32 @callee_large_scalars_exhausted_regs( 350 i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i128 8, i32 9, 351 fp128 0xL00000000000000007FFF000000000000) 352 ret i32 %1 353 } 354 355 ; Ensure that libcalls generated in the middle-end obey the calling convention 356 357 define i32 @caller_mixed_scalar_libcalls(i64 %a) nounwind { 358 ; RV32I-FPELIM-LABEL: caller_mixed_scalar_libcalls: 359 ; RV32I-FPELIM: # %bb.0: 360 ; RV32I-FPELIM-NEXT: addi sp, sp, -32 361 ; RV32I-FPELIM-NEXT: sw ra, 28(sp) 362 ; RV32I-FPELIM-NEXT: mv a2, a1 363 ; RV32I-FPELIM-NEXT: mv a1, a0 364 ; RV32I-FPELIM-NEXT: addi a0, sp, 8 365 ; RV32I-FPELIM-NEXT: call __floatditf 366 ; RV32I-FPELIM-NEXT: lw a0, 8(sp) 367 ; RV32I-FPELIM-NEXT: lw ra, 28(sp) 368 ; RV32I-FPELIM-NEXT: addi sp, sp, 32 369 ; RV32I-FPELIM-NEXT: ret 370 ; 371 ; RV32I-WITHFP-LABEL: caller_mixed_scalar_libcalls: 372 ; RV32I-WITHFP: # %bb.0: 373 ; RV32I-WITHFP-NEXT: addi sp, sp, -32 374 ; RV32I-WITHFP-NEXT: sw ra, 28(sp) 375 ; RV32I-WITHFP-NEXT: sw s0, 24(sp) 376 ; RV32I-WITHFP-NEXT: addi s0, sp, 32 377 ; RV32I-WITHFP-NEXT: mv a2, a1 378 ; RV32I-WITHFP-NEXT: mv a1, a0 379 ; RV32I-WITHFP-NEXT: addi a0, s0, -24 380 ; RV32I-WITHFP-NEXT: call __floatditf 381 ; RV32I-WITHFP-NEXT: lw a0, -24(s0) 382 ; RV32I-WITHFP-NEXT: lw s0, 24(sp) 383 ; RV32I-WITHFP-NEXT: lw ra, 28(sp) 384 ; RV32I-WITHFP-NEXT: addi sp, sp, 32 385 ; RV32I-WITHFP-NEXT: ret 386 %1 = sitofp i64 %a to fp128 387 %2 = bitcast fp128 %1 to i128 388 %3 = trunc i128 %2 to i32 389 ret i32 %3 390 } 391 392 ; Check that the stack is used once the GPRs are exhausted 393 394 define i32 @callee_many_scalars(i8 %a, i16 %b, i32 %c, i64 %d, i32 %e, i32 %f, i64 %g, i32 %h) nounwind { 395 ; RV32I-FPELIM-LABEL: callee_many_scalars: 396 ; RV32I-FPELIM: # %bb.0: 397 ; RV32I-FPELIM-NEXT: lw t0, 0(sp) 398 ; RV32I-FPELIM-NEXT: xor a4, a4, t0 399 ; RV32I-FPELIM-NEXT: xor a3, a3, a7 400 ; RV32I-FPELIM-NEXT: or a3, a3, a4 401 ; RV32I-FPELIM-NEXT: xor a3, a3, zero 402 ; RV32I-FPELIM-NEXT: lui a4, 16 403 ; RV32I-FPELIM-NEXT: addi a4, a4, -1 404 ; RV32I-FPELIM-NEXT: and a1, a1, a4 405 ; RV32I-FPELIM-NEXT: andi a0, a0, 255 406 ; RV32I-FPELIM-NEXT: add a0, a0, a1 407 ; RV32I-FPELIM-NEXT: add a0, a0, a2 408 ; RV32I-FPELIM-NEXT: seqz a1, a3 409 ; RV32I-FPELIM-NEXT: add a0, a1, a0 410 ; RV32I-FPELIM-NEXT: add a0, a0, a5 411 ; RV32I-FPELIM-NEXT: add a0, a0, a6 412 ; RV32I-FPELIM-NEXT: lw a1, 4(sp) 413 ; RV32I-FPELIM-NEXT: add a0, a0, a1 414 ; RV32I-FPELIM-NEXT: ret 415 ; 416 ; RV32I-WITHFP-LABEL: callee_many_scalars: 417 ; RV32I-WITHFP: # %bb.0: 418 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 419 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 420 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 421 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 422 ; RV32I-WITHFP-NEXT: lw t0, 0(s0) 423 ; RV32I-WITHFP-NEXT: xor a4, a4, t0 424 ; RV32I-WITHFP-NEXT: xor a3, a3, a7 425 ; RV32I-WITHFP-NEXT: or a3, a3, a4 426 ; RV32I-WITHFP-NEXT: xor a3, a3, zero 427 ; RV32I-WITHFP-NEXT: lui a4, 16 428 ; RV32I-WITHFP-NEXT: addi a4, a4, -1 429 ; RV32I-WITHFP-NEXT: and a1, a1, a4 430 ; RV32I-WITHFP-NEXT: andi a0, a0, 255 431 ; RV32I-WITHFP-NEXT: add a0, a0, a1 432 ; RV32I-WITHFP-NEXT: add a0, a0, a2 433 ; RV32I-WITHFP-NEXT: seqz a1, a3 434 ; RV32I-WITHFP-NEXT: add a0, a1, a0 435 ; RV32I-WITHFP-NEXT: add a0, a0, a5 436 ; RV32I-WITHFP-NEXT: add a0, a0, a6 437 ; RV32I-WITHFP-NEXT: lw a1, 4(s0) 438 ; RV32I-WITHFP-NEXT: add a0, a0, a1 439 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 440 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 441 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 442 ; RV32I-WITHFP-NEXT: ret 443 %a_ext = zext i8 %a to i32 444 %b_ext = zext i16 %b to i32 445 %1 = add i32 %a_ext, %b_ext 446 %2 = add i32 %1, %c 447 %3 = icmp eq i64 %d, %g 448 %4 = zext i1 %3 to i32 449 %5 = add i32 %4, %2 450 %6 = add i32 %5, %e 451 %7 = add i32 %6, %f 452 %8 = add i32 %7, %h 453 ret i32 %8 454 } 455 456 define i32 @caller_many_scalars() nounwind { 457 ; RV32I-FPELIM-LABEL: caller_many_scalars: 458 ; RV32I-FPELIM: # %bb.0: 459 ; RV32I-FPELIM-NEXT: addi sp, sp, -16 460 ; RV32I-FPELIM-NEXT: sw ra, 12(sp) 461 ; RV32I-FPELIM-NEXT: addi a0, zero, 8 462 ; RV32I-FPELIM-NEXT: sw a0, 4(sp) 463 ; RV32I-FPELIM-NEXT: sw zero, 0(sp) 464 ; RV32I-FPELIM-NEXT: addi a0, zero, 1 465 ; RV32I-FPELIM-NEXT: addi a1, zero, 2 466 ; RV32I-FPELIM-NEXT: addi a2, zero, 3 467 ; RV32I-FPELIM-NEXT: addi a3, zero, 4 468 ; RV32I-FPELIM-NEXT: addi a5, zero, 5 469 ; RV32I-FPELIM-NEXT: addi a6, zero, 6 470 ; RV32I-FPELIM-NEXT: addi a7, zero, 7 471 ; RV32I-FPELIM-NEXT: mv a4, zero 472 ; RV32I-FPELIM-NEXT: call callee_many_scalars 473 ; RV32I-FPELIM-NEXT: lw ra, 12(sp) 474 ; RV32I-FPELIM-NEXT: addi sp, sp, 16 475 ; RV32I-FPELIM-NEXT: ret 476 ; 477 ; RV32I-WITHFP-LABEL: caller_many_scalars: 478 ; RV32I-WITHFP: # %bb.0: 479 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 480 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 481 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 482 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 483 ; RV32I-WITHFP-NEXT: addi a0, zero, 8 484 ; RV32I-WITHFP-NEXT: sw a0, 4(sp) 485 ; RV32I-WITHFP-NEXT: sw zero, 0(sp) 486 ; RV32I-WITHFP-NEXT: addi a0, zero, 1 487 ; RV32I-WITHFP-NEXT: addi a1, zero, 2 488 ; RV32I-WITHFP-NEXT: addi a2, zero, 3 489 ; RV32I-WITHFP-NEXT: addi a3, zero, 4 490 ; RV32I-WITHFP-NEXT: addi a5, zero, 5 491 ; RV32I-WITHFP-NEXT: addi a6, zero, 6 492 ; RV32I-WITHFP-NEXT: addi a7, zero, 7 493 ; RV32I-WITHFP-NEXT: mv a4, zero 494 ; RV32I-WITHFP-NEXT: call callee_many_scalars 495 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 496 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 497 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 498 ; RV32I-WITHFP-NEXT: ret 499 %1 = call i32 @callee_many_scalars(i8 1, i16 2, i32 3, i64 4, i32 5, i32 6, i64 7, i32 8) 500 ret i32 %1 501 } 502 503 ; Check passing of coerced integer arrays 504 505 %struct.small = type { i32, i32* } 506 507 define i32 @callee_small_coerced_struct([2 x i32] %a.coerce) nounwind { 508 ; RV32I-FPELIM-LABEL: callee_small_coerced_struct: 509 ; RV32I-FPELIM: # %bb.0: 510 ; RV32I-FPELIM-NEXT: xor a0, a0, a1 511 ; RV32I-FPELIM-NEXT: seqz a0, a0 512 ; RV32I-FPELIM-NEXT: ret 513 ; 514 ; RV32I-WITHFP-LABEL: callee_small_coerced_struct: 515 ; RV32I-WITHFP: # %bb.0: 516 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 517 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 518 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 519 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 520 ; RV32I-WITHFP-NEXT: xor a0, a0, a1 521 ; RV32I-WITHFP-NEXT: seqz a0, a0 522 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 523 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 524 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 525 ; RV32I-WITHFP-NEXT: ret 526 %1 = extractvalue [2 x i32] %a.coerce, 0 527 %2 = extractvalue [2 x i32] %a.coerce, 1 528 %3 = icmp eq i32 %1, %2 529 %4 = zext i1 %3 to i32 530 ret i32 %4 531 } 532 533 define i32 @caller_small_coerced_struct() nounwind { 534 ; RV32I-FPELIM-LABEL: caller_small_coerced_struct: 535 ; RV32I-FPELIM: # %bb.0: 536 ; RV32I-FPELIM-NEXT: addi sp, sp, -16 537 ; RV32I-FPELIM-NEXT: sw ra, 12(sp) 538 ; RV32I-FPELIM-NEXT: addi a0, zero, 1 539 ; RV32I-FPELIM-NEXT: addi a1, zero, 2 540 ; RV32I-FPELIM-NEXT: call callee_small_coerced_struct 541 ; RV32I-FPELIM-NEXT: lw ra, 12(sp) 542 ; RV32I-FPELIM-NEXT: addi sp, sp, 16 543 ; RV32I-FPELIM-NEXT: ret 544 ; 545 ; RV32I-WITHFP-LABEL: caller_small_coerced_struct: 546 ; RV32I-WITHFP: # %bb.0: 547 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 548 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 549 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 550 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 551 ; RV32I-WITHFP-NEXT: addi a0, zero, 1 552 ; RV32I-WITHFP-NEXT: addi a1, zero, 2 553 ; RV32I-WITHFP-NEXT: call callee_small_coerced_struct 554 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 555 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 556 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 557 ; RV32I-WITHFP-NEXT: ret 558 %1 = call i32 @callee_small_coerced_struct([2 x i32] [i32 1, i32 2]) 559 ret i32 %1 560 } 561 562 ; Check large struct arguments, which are passed byval 563 564 %struct.large = type { i32, i32, i32, i32 } 565 566 define i32 @callee_large_struct(%struct.large* byval align 4 %a) nounwind { 567 ; RV32I-FPELIM-LABEL: callee_large_struct: 568 ; RV32I-FPELIM: # %bb.0: 569 ; RV32I-FPELIM-NEXT: lw a1, 12(a0) 570 ; RV32I-FPELIM-NEXT: lw a0, 0(a0) 571 ; RV32I-FPELIM-NEXT: add a0, a0, a1 572 ; RV32I-FPELIM-NEXT: ret 573 ; 574 ; RV32I-WITHFP-LABEL: callee_large_struct: 575 ; RV32I-WITHFP: # %bb.0: 576 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 577 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 578 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 579 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 580 ; RV32I-WITHFP-NEXT: lw a1, 12(a0) 581 ; RV32I-WITHFP-NEXT: lw a0, 0(a0) 582 ; RV32I-WITHFP-NEXT: add a0, a0, a1 583 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 584 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 585 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 586 ; RV32I-WITHFP-NEXT: ret 587 %1 = getelementptr inbounds %struct.large, %struct.large* %a, i32 0, i32 0 588 %2 = getelementptr inbounds %struct.large, %struct.large* %a, i32 0, i32 3 589 %3 = load i32, i32* %1 590 %4 = load i32, i32* %2 591 %5 = add i32 %3, %4 592 ret i32 %5 593 } 594 595 define i32 @caller_large_struct() nounwind { 596 ; RV32I-FPELIM-LABEL: caller_large_struct: 597 ; RV32I-FPELIM: # %bb.0: 598 ; RV32I-FPELIM-NEXT: addi sp, sp, -48 599 ; RV32I-FPELIM-NEXT: sw ra, 44(sp) 600 ; RV32I-FPELIM-NEXT: addi a0, zero, 1 601 ; RV32I-FPELIM-NEXT: sw a0, 24(sp) 602 ; RV32I-FPELIM-NEXT: sw a0, 8(sp) 603 ; RV32I-FPELIM-NEXT: addi a0, zero, 2 604 ; RV32I-FPELIM-NEXT: sw a0, 28(sp) 605 ; RV32I-FPELIM-NEXT: sw a0, 12(sp) 606 ; RV32I-FPELIM-NEXT: addi a0, zero, 3 607 ; RV32I-FPELIM-NEXT: sw a0, 32(sp) 608 ; RV32I-FPELIM-NEXT: sw a0, 16(sp) 609 ; RV32I-FPELIM-NEXT: addi a0, zero, 4 610 ; RV32I-FPELIM-NEXT: sw a0, 36(sp) 611 ; RV32I-FPELIM-NEXT: sw a0, 20(sp) 612 ; RV32I-FPELIM-NEXT: addi a0, sp, 8 613 ; RV32I-FPELIM-NEXT: call callee_large_struct 614 ; RV32I-FPELIM-NEXT: lw ra, 44(sp) 615 ; RV32I-FPELIM-NEXT: addi sp, sp, 48 616 ; RV32I-FPELIM-NEXT: ret 617 ; 618 ; RV32I-WITHFP-LABEL: caller_large_struct: 619 ; RV32I-WITHFP: # %bb.0: 620 ; RV32I-WITHFP-NEXT: addi sp, sp, -48 621 ; RV32I-WITHFP-NEXT: sw ra, 44(sp) 622 ; RV32I-WITHFP-NEXT: sw s0, 40(sp) 623 ; RV32I-WITHFP-NEXT: addi s0, sp, 48 624 ; RV32I-WITHFP-NEXT: addi a0, zero, 1 625 ; RV32I-WITHFP-NEXT: sw a0, -24(s0) 626 ; RV32I-WITHFP-NEXT: sw a0, -40(s0) 627 ; RV32I-WITHFP-NEXT: addi a0, zero, 2 628 ; RV32I-WITHFP-NEXT: sw a0, -20(s0) 629 ; RV32I-WITHFP-NEXT: sw a0, -36(s0) 630 ; RV32I-WITHFP-NEXT: addi a0, zero, 3 631 ; RV32I-WITHFP-NEXT: sw a0, -16(s0) 632 ; RV32I-WITHFP-NEXT: sw a0, -32(s0) 633 ; RV32I-WITHFP-NEXT: addi a0, zero, 4 634 ; RV32I-WITHFP-NEXT: sw a0, -12(s0) 635 ; RV32I-WITHFP-NEXT: sw a0, -28(s0) 636 ; RV32I-WITHFP-NEXT: addi a0, s0, -40 637 ; RV32I-WITHFP-NEXT: call callee_large_struct 638 ; RV32I-WITHFP-NEXT: lw s0, 40(sp) 639 ; RV32I-WITHFP-NEXT: lw ra, 44(sp) 640 ; RV32I-WITHFP-NEXT: addi sp, sp, 48 641 ; RV32I-WITHFP-NEXT: ret 642 %ls = alloca %struct.large, align 4 643 %1 = bitcast %struct.large* %ls to i8* 644 %a = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 0 645 store i32 1, i32* %a 646 %b = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 1 647 store i32 2, i32* %b 648 %c = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 2 649 store i32 3, i32* %c 650 %d = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 3 651 store i32 4, i32* %d 652 %2 = call i32 @callee_large_struct(%struct.large* byval align 4 %ls) 653 ret i32 %2 654 } 655 656 ; Check 2x*xlen values are aligned appropriately when passed on the stack 657 ; Must keep define on a single line due to an update_llc_test_checks.py limitation 658 define i32 @callee_aligned_stack(i32 %a, i32 %b, fp128 %c, i32 %d, i32 %e, i64 %f, i32 %g, i32 %h, double %i, i32 %j, [2 x i32] %k) nounwind { 659 ; The double should be 8-byte aligned on the stack, but the two-element array 660 ; should only be 4-byte aligned 661 ; RV32I-FPELIM-LABEL: callee_aligned_stack: 662 ; RV32I-FPELIM: # %bb.0: 663 ; RV32I-FPELIM-NEXT: lw a0, 0(a2) 664 ; RV32I-FPELIM-NEXT: add a0, a0, a7 665 ; RV32I-FPELIM-NEXT: lw a1, 0(sp) 666 ; RV32I-FPELIM-NEXT: add a0, a0, a1 667 ; RV32I-FPELIM-NEXT: lw a1, 8(sp) 668 ; RV32I-FPELIM-NEXT: add a0, a0, a1 669 ; RV32I-FPELIM-NEXT: lw a1, 16(sp) 670 ; RV32I-FPELIM-NEXT: add a0, a0, a1 671 ; RV32I-FPELIM-NEXT: lw a1, 20(sp) 672 ; RV32I-FPELIM-NEXT: add a0, a0, a1 673 ; RV32I-FPELIM-NEXT: ret 674 ; 675 ; RV32I-WITHFP-LABEL: callee_aligned_stack: 676 ; RV32I-WITHFP: # %bb.0: 677 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 678 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 679 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 680 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 681 ; RV32I-WITHFP-NEXT: lw a0, 0(a2) 682 ; RV32I-WITHFP-NEXT: add a0, a0, a7 683 ; RV32I-WITHFP-NEXT: lw a1, 0(s0) 684 ; RV32I-WITHFP-NEXT: add a0, a0, a1 685 ; RV32I-WITHFP-NEXT: lw a1, 8(s0) 686 ; RV32I-WITHFP-NEXT: add a0, a0, a1 687 ; RV32I-WITHFP-NEXT: lw a1, 16(s0) 688 ; RV32I-WITHFP-NEXT: add a0, a0, a1 689 ; RV32I-WITHFP-NEXT: lw a1, 20(s0) 690 ; RV32I-WITHFP-NEXT: add a0, a0, a1 691 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 692 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 693 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 694 ; RV32I-WITHFP-NEXT: ret 695 %1 = bitcast fp128 %c to i128 696 %2 = trunc i128 %1 to i32 697 %3 = add i32 %2, %g 698 %4 = add i32 %3, %h 699 %5 = bitcast double %i to i64 700 %6 = trunc i64 %5 to i32 701 %7 = add i32 %4, %6 702 %8 = add i32 %7, %j 703 %9 = extractvalue [2 x i32] %k, 0 704 %10 = add i32 %8, %9 705 ret i32 %10 706 } 707 708 define void @caller_aligned_stack() nounwind { 709 ; The double should be 8-byte aligned on the stack, but the two-element array 710 ; should only be 4-byte aligned 711 ; RV32I-FPELIM-LABEL: caller_aligned_stack: 712 ; RV32I-FPELIM: # %bb.0: 713 ; RV32I-FPELIM-NEXT: addi sp, sp, -64 714 ; RV32I-FPELIM-NEXT: sw ra, 60(sp) 715 ; RV32I-FPELIM-NEXT: addi a0, zero, 18 716 ; RV32I-FPELIM-NEXT: sw a0, 24(sp) 717 ; RV32I-FPELIM-NEXT: addi a0, zero, 17 718 ; RV32I-FPELIM-NEXT: sw a0, 20(sp) 719 ; RV32I-FPELIM-NEXT: addi a0, zero, 16 720 ; RV32I-FPELIM-NEXT: sw a0, 16(sp) 721 ; RV32I-FPELIM-NEXT: lui a0, 262236 722 ; RV32I-FPELIM-NEXT: addi a0, a0, 655 723 ; RV32I-FPELIM-NEXT: sw a0, 12(sp) 724 ; RV32I-FPELIM-NEXT: lui a0, 377487 725 ; RV32I-FPELIM-NEXT: addi a0, a0, 1475 726 ; RV32I-FPELIM-NEXT: sw a0, 8(sp) 727 ; RV32I-FPELIM-NEXT: addi a0, zero, 15 728 ; RV32I-FPELIM-NEXT: sw a0, 0(sp) 729 ; RV32I-FPELIM-NEXT: lui a0, 262153 730 ; RV32I-FPELIM-NEXT: addi a0, a0, 491 731 ; RV32I-FPELIM-NEXT: sw a0, 44(sp) 732 ; RV32I-FPELIM-NEXT: lui a0, 545260 733 ; RV32I-FPELIM-NEXT: addi a0, a0, -1967 734 ; RV32I-FPELIM-NEXT: sw a0, 40(sp) 735 ; RV32I-FPELIM-NEXT: lui a0, 964690 736 ; RV32I-FPELIM-NEXT: addi a0, a0, -328 737 ; RV32I-FPELIM-NEXT: sw a0, 36(sp) 738 ; RV32I-FPELIM-NEXT: lui a0, 335544 739 ; RV32I-FPELIM-NEXT: addi a0, a0, 1311 740 ; RV32I-FPELIM-NEXT: sw a0, 32(sp) 741 ; RV32I-FPELIM-NEXT: lui a0, 688509 742 ; RV32I-FPELIM-NEXT: addi a5, a0, -2048 743 ; RV32I-FPELIM-NEXT: addi a0, zero, 1 744 ; RV32I-FPELIM-NEXT: addi a1, zero, 11 745 ; RV32I-FPELIM-NEXT: addi a2, sp, 32 746 ; RV32I-FPELIM-NEXT: addi a3, zero, 12 747 ; RV32I-FPELIM-NEXT: addi a4, zero, 13 748 ; RV32I-FPELIM-NEXT: addi a6, zero, 4 749 ; RV32I-FPELIM-NEXT: addi a7, zero, 14 750 ; RV32I-FPELIM-NEXT: call callee_aligned_stack 751 ; RV32I-FPELIM-NEXT: lw ra, 60(sp) 752 ; RV32I-FPELIM-NEXT: addi sp, sp, 64 753 ; RV32I-FPELIM-NEXT: ret 754 ; 755 ; RV32I-WITHFP-LABEL: caller_aligned_stack: 756 ; RV32I-WITHFP: # %bb.0: 757 ; RV32I-WITHFP-NEXT: addi sp, sp, -64 758 ; RV32I-WITHFP-NEXT: sw ra, 60(sp) 759 ; RV32I-WITHFP-NEXT: sw s0, 56(sp) 760 ; RV32I-WITHFP-NEXT: addi s0, sp, 64 761 ; RV32I-WITHFP-NEXT: addi a0, zero, 18 762 ; RV32I-WITHFP-NEXT: sw a0, 24(sp) 763 ; RV32I-WITHFP-NEXT: addi a0, zero, 17 764 ; RV32I-WITHFP-NEXT: sw a0, 20(sp) 765 ; RV32I-WITHFP-NEXT: addi a0, zero, 16 766 ; RV32I-WITHFP-NEXT: sw a0, 16(sp) 767 ; RV32I-WITHFP-NEXT: lui a0, 262236 768 ; RV32I-WITHFP-NEXT: addi a0, a0, 655 769 ; RV32I-WITHFP-NEXT: sw a0, 12(sp) 770 ; RV32I-WITHFP-NEXT: lui a0, 377487 771 ; RV32I-WITHFP-NEXT: addi a0, a0, 1475 772 ; RV32I-WITHFP-NEXT: sw a0, 8(sp) 773 ; RV32I-WITHFP-NEXT: addi a0, zero, 15 774 ; RV32I-WITHFP-NEXT: sw a0, 0(sp) 775 ; RV32I-WITHFP-NEXT: lui a0, 262153 776 ; RV32I-WITHFP-NEXT: addi a0, a0, 491 777 ; RV32I-WITHFP-NEXT: sw a0, -20(s0) 778 ; RV32I-WITHFP-NEXT: lui a0, 545260 779 ; RV32I-WITHFP-NEXT: addi a0, a0, -1967 780 ; RV32I-WITHFP-NEXT: sw a0, -24(s0) 781 ; RV32I-WITHFP-NEXT: lui a0, 964690 782 ; RV32I-WITHFP-NEXT: addi a0, a0, -328 783 ; RV32I-WITHFP-NEXT: sw a0, -28(s0) 784 ; RV32I-WITHFP-NEXT: lui a0, 335544 785 ; RV32I-WITHFP-NEXT: addi a0, a0, 1311 786 ; RV32I-WITHFP-NEXT: sw a0, -32(s0) 787 ; RV32I-WITHFP-NEXT: lui a0, 688509 788 ; RV32I-WITHFP-NEXT: addi a5, a0, -2048 789 ; RV32I-WITHFP-NEXT: addi a0, zero, 1 790 ; RV32I-WITHFP-NEXT: addi a1, zero, 11 791 ; RV32I-WITHFP-NEXT: addi a2, s0, -32 792 ; RV32I-WITHFP-NEXT: addi a3, zero, 12 793 ; RV32I-WITHFP-NEXT: addi a4, zero, 13 794 ; RV32I-WITHFP-NEXT: addi a6, zero, 4 795 ; RV32I-WITHFP-NEXT: addi a7, zero, 14 796 ; RV32I-WITHFP-NEXT: call callee_aligned_stack 797 ; RV32I-WITHFP-NEXT: lw s0, 56(sp) 798 ; RV32I-WITHFP-NEXT: lw ra, 60(sp) 799 ; RV32I-WITHFP-NEXT: addi sp, sp, 64 800 ; RV32I-WITHFP-NEXT: ret 801 %1 = call i32 @callee_aligned_stack(i32 1, i32 11, 802 fp128 0xLEB851EB851EB851F400091EB851EB851, i32 12, i32 13, 803 i64 20000000000, i32 14, i32 15, double 2.720000e+00, i32 16, 804 [2 x i32] [i32 17, i32 18]) 805 ret void 806 } 807 808 ; Check return of 2x xlen scalars 809 810 define i64 @callee_small_scalar_ret() nounwind { 811 ; RV32I-FPELIM-LABEL: callee_small_scalar_ret: 812 ; RV32I-FPELIM: # %bb.0: 813 ; RV32I-FPELIM-NEXT: lui a0, 466866 814 ; RV32I-FPELIM-NEXT: addi a0, a0, 1677 815 ; RV32I-FPELIM-NEXT: addi a1, zero, 287 816 ; RV32I-FPELIM-NEXT: ret 817 ; 818 ; RV32I-WITHFP-LABEL: callee_small_scalar_ret: 819 ; RV32I-WITHFP: # %bb.0: 820 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 821 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 822 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 823 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 824 ; RV32I-WITHFP-NEXT: lui a0, 466866 825 ; RV32I-WITHFP-NEXT: addi a0, a0, 1677 826 ; RV32I-WITHFP-NEXT: addi a1, zero, 287 827 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 828 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 829 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 830 ; RV32I-WITHFP-NEXT: ret 831 ret i64 1234567898765 832 } 833 834 define i32 @caller_small_scalar_ret() nounwind { 835 ; RV32I-FPELIM-LABEL: caller_small_scalar_ret: 836 ; RV32I-FPELIM: # %bb.0: 837 ; RV32I-FPELIM-NEXT: addi sp, sp, -16 838 ; RV32I-FPELIM-NEXT: sw ra, 12(sp) 839 ; RV32I-FPELIM-NEXT: sw s1, 8(sp) 840 ; RV32I-FPELIM-NEXT: lui a0, 56 841 ; RV32I-FPELIM-NEXT: addi s1, a0, 580 842 ; RV32I-FPELIM-NEXT: call callee_small_scalar_ret 843 ; RV32I-FPELIM-NEXT: xor a1, a1, s1 844 ; RV32I-FPELIM-NEXT: lui a2, 200614 845 ; RV32I-FPELIM-NEXT: addi a2, a2, 647 846 ; RV32I-FPELIM-NEXT: xor a0, a0, a2 847 ; RV32I-FPELIM-NEXT: or a0, a0, a1 848 ; RV32I-FPELIM-NEXT: xor a0, a0, zero 849 ; RV32I-FPELIM-NEXT: seqz a0, a0 850 ; RV32I-FPELIM-NEXT: lw s1, 8(sp) 851 ; RV32I-FPELIM-NEXT: lw ra, 12(sp) 852 ; RV32I-FPELIM-NEXT: addi sp, sp, 16 853 ; RV32I-FPELIM-NEXT: ret 854 ; 855 ; RV32I-WITHFP-LABEL: caller_small_scalar_ret: 856 ; RV32I-WITHFP: # %bb.0: 857 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 858 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 859 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 860 ; RV32I-WITHFP-NEXT: sw s1, 4(sp) 861 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 862 ; RV32I-WITHFP-NEXT: lui a0, 56 863 ; RV32I-WITHFP-NEXT: addi s1, a0, 580 864 ; RV32I-WITHFP-NEXT: call callee_small_scalar_ret 865 ; RV32I-WITHFP-NEXT: xor a1, a1, s1 866 ; RV32I-WITHFP-NEXT: lui a2, 200614 867 ; RV32I-WITHFP-NEXT: addi a2, a2, 647 868 ; RV32I-WITHFP-NEXT: xor a0, a0, a2 869 ; RV32I-WITHFP-NEXT: or a0, a0, a1 870 ; RV32I-WITHFP-NEXT: xor a0, a0, zero 871 ; RV32I-WITHFP-NEXT: seqz a0, a0 872 ; RV32I-WITHFP-NEXT: lw s1, 4(sp) 873 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 874 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 875 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 876 ; RV32I-WITHFP-NEXT: ret 877 %1 = call i64 @callee_small_scalar_ret() 878 %2 = icmp eq i64 987654321234567, %1 879 %3 = zext i1 %2 to i32 880 ret i32 %3 881 } 882 883 ; Check return of 2x xlen structs 884 885 define %struct.small @callee_small_struct_ret() nounwind { 886 ; RV32I-FPELIM-LABEL: callee_small_struct_ret: 887 ; RV32I-FPELIM: # %bb.0: 888 ; RV32I-FPELIM-NEXT: addi a0, zero, 1 889 ; RV32I-FPELIM-NEXT: mv a1, zero 890 ; RV32I-FPELIM-NEXT: ret 891 ; 892 ; RV32I-WITHFP-LABEL: callee_small_struct_ret: 893 ; RV32I-WITHFP: # %bb.0: 894 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 895 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 896 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 897 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 898 ; RV32I-WITHFP-NEXT: addi a0, zero, 1 899 ; RV32I-WITHFP-NEXT: mv a1, zero 900 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 901 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 902 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 903 ; RV32I-WITHFP-NEXT: ret 904 ret %struct.small { i32 1, i32* null } 905 } 906 907 define i32 @caller_small_struct_ret() nounwind { 908 ; RV32I-FPELIM-LABEL: caller_small_struct_ret: 909 ; RV32I-FPELIM: # %bb.0: 910 ; RV32I-FPELIM-NEXT: addi sp, sp, -16 911 ; RV32I-FPELIM-NEXT: sw ra, 12(sp) 912 ; RV32I-FPELIM-NEXT: call callee_small_struct_ret 913 ; RV32I-FPELIM-NEXT: add a0, a0, a1 914 ; RV32I-FPELIM-NEXT: lw ra, 12(sp) 915 ; RV32I-FPELIM-NEXT: addi sp, sp, 16 916 ; RV32I-FPELIM-NEXT: ret 917 ; 918 ; RV32I-WITHFP-LABEL: caller_small_struct_ret: 919 ; RV32I-WITHFP: # %bb.0: 920 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 921 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 922 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 923 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 924 ; RV32I-WITHFP-NEXT: call callee_small_struct_ret 925 ; RV32I-WITHFP-NEXT: add a0, a0, a1 926 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 927 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 928 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 929 ; RV32I-WITHFP-NEXT: ret 930 %1 = call %struct.small @callee_small_struct_ret() 931 %2 = extractvalue %struct.small %1, 0 932 %3 = extractvalue %struct.small %1, 1 933 %4 = ptrtoint i32* %3 to i32 934 %5 = add i32 %2, %4 935 ret i32 %5 936 } 937 938 ; Check return of >2x xlen scalars 939 940 define fp128 @callee_large_scalar_ret() nounwind { 941 ; RV32I-FPELIM-LABEL: callee_large_scalar_ret: 942 ; RV32I-FPELIM: # %bb.0: 943 ; RV32I-FPELIM-NEXT: lui a1, 524272 944 ; RV32I-FPELIM-NEXT: sw a1, 12(a0) 945 ; RV32I-FPELIM-NEXT: sw zero, 8(a0) 946 ; RV32I-FPELIM-NEXT: sw zero, 4(a0) 947 ; RV32I-FPELIM-NEXT: sw zero, 0(a0) 948 ; RV32I-FPELIM-NEXT: ret 949 ; 950 ; RV32I-WITHFP-LABEL: callee_large_scalar_ret: 951 ; RV32I-WITHFP: # %bb.0: 952 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 953 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 954 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 955 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 956 ; RV32I-WITHFP-NEXT: lui a1, 524272 957 ; RV32I-WITHFP-NEXT: sw a1, 12(a0) 958 ; RV32I-WITHFP-NEXT: sw zero, 8(a0) 959 ; RV32I-WITHFP-NEXT: sw zero, 4(a0) 960 ; RV32I-WITHFP-NEXT: sw zero, 0(a0) 961 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 962 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 963 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 964 ; RV32I-WITHFP-NEXT: ret 965 ret fp128 0xL00000000000000007FFF000000000000 966 } 967 968 define void @caller_large_scalar_ret() nounwind { 969 ; RV32I-FPELIM-LABEL: caller_large_scalar_ret: 970 ; RV32I-FPELIM: # %bb.0: 971 ; RV32I-FPELIM-NEXT: addi sp, sp, -32 972 ; RV32I-FPELIM-NEXT: sw ra, 28(sp) 973 ; RV32I-FPELIM-NEXT: mv a0, sp 974 ; RV32I-FPELIM-NEXT: call callee_large_scalar_ret 975 ; RV32I-FPELIM-NEXT: lw ra, 28(sp) 976 ; RV32I-FPELIM-NEXT: addi sp, sp, 32 977 ; RV32I-FPELIM-NEXT: ret 978 ; 979 ; RV32I-WITHFP-LABEL: caller_large_scalar_ret: 980 ; RV32I-WITHFP: # %bb.0: 981 ; RV32I-WITHFP-NEXT: addi sp, sp, -32 982 ; RV32I-WITHFP-NEXT: sw ra, 28(sp) 983 ; RV32I-WITHFP-NEXT: sw s0, 24(sp) 984 ; RV32I-WITHFP-NEXT: addi s0, sp, 32 985 ; RV32I-WITHFP-NEXT: addi a0, s0, -32 986 ; RV32I-WITHFP-NEXT: call callee_large_scalar_ret 987 ; RV32I-WITHFP-NEXT: lw s0, 24(sp) 988 ; RV32I-WITHFP-NEXT: lw ra, 28(sp) 989 ; RV32I-WITHFP-NEXT: addi sp, sp, 32 990 ; RV32I-WITHFP-NEXT: ret 991 %1 = call fp128 @callee_large_scalar_ret() 992 ret void 993 } 994 995 ; Check return of >2x xlen structs 996 997 define void @callee_large_struct_ret(%struct.large* noalias sret %agg.result) nounwind { 998 ; RV32I-FPELIM-LABEL: callee_large_struct_ret: 999 ; RV32I-FPELIM: # %bb.0: 1000 ; RV32I-FPELIM-NEXT: addi a1, zero, 2 1001 ; RV32I-FPELIM-NEXT: sw a1, 4(a0) 1002 ; RV32I-FPELIM-NEXT: addi a1, zero, 1 1003 ; RV32I-FPELIM-NEXT: sw a1, 0(a0) 1004 ; RV32I-FPELIM-NEXT: addi a1, zero, 3 1005 ; RV32I-FPELIM-NEXT: sw a1, 8(a0) 1006 ; RV32I-FPELIM-NEXT: addi a1, zero, 4 1007 ; RV32I-FPELIM-NEXT: sw a1, 12(a0) 1008 ; RV32I-FPELIM-NEXT: ret 1009 ; 1010 ; RV32I-WITHFP-LABEL: callee_large_struct_ret: 1011 ; RV32I-WITHFP: # %bb.0: 1012 ; RV32I-WITHFP-NEXT: addi sp, sp, -16 1013 ; RV32I-WITHFP-NEXT: sw ra, 12(sp) 1014 ; RV32I-WITHFP-NEXT: sw s0, 8(sp) 1015 ; RV32I-WITHFP-NEXT: addi s0, sp, 16 1016 ; RV32I-WITHFP-NEXT: addi a1, zero, 2 1017 ; RV32I-WITHFP-NEXT: sw a1, 4(a0) 1018 ; RV32I-WITHFP-NEXT: addi a1, zero, 1 1019 ; RV32I-WITHFP-NEXT: sw a1, 0(a0) 1020 ; RV32I-WITHFP-NEXT: addi a1, zero, 3 1021 ; RV32I-WITHFP-NEXT: sw a1, 8(a0) 1022 ; RV32I-WITHFP-NEXT: addi a1, zero, 4 1023 ; RV32I-WITHFP-NEXT: sw a1, 12(a0) 1024 ; RV32I-WITHFP-NEXT: lw s0, 8(sp) 1025 ; RV32I-WITHFP-NEXT: lw ra, 12(sp) 1026 ; RV32I-WITHFP-NEXT: addi sp, sp, 16 1027 ; RV32I-WITHFP-NEXT: ret 1028 %a = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 0 1029 store i32 1, i32* %a, align 4 1030 %b = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 1 1031 store i32 2, i32* %b, align 4 1032 %c = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 2 1033 store i32 3, i32* %c, align 4 1034 %d = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 3 1035 store i32 4, i32* %d, align 4 1036 ret void 1037 } 1038 1039 define i32 @caller_large_struct_ret() nounwind { 1040 ; RV32I-FPELIM-LABEL: caller_large_struct_ret: 1041 ; RV32I-FPELIM: # %bb.0: 1042 ; RV32I-FPELIM-NEXT: addi sp, sp, -32 1043 ; RV32I-FPELIM-NEXT: sw ra, 28(sp) 1044 ; RV32I-FPELIM-NEXT: addi a0, sp, 8 1045 ; RV32I-FPELIM-NEXT: call callee_large_struct_ret 1046 ; RV32I-FPELIM-NEXT: lw a0, 20(sp) 1047 ; RV32I-FPELIM-NEXT: lw a1, 8(sp) 1048 ; RV32I-FPELIM-NEXT: add a0, a1, a0 1049 ; RV32I-FPELIM-NEXT: lw ra, 28(sp) 1050 ; RV32I-FPELIM-NEXT: addi sp, sp, 32 1051 ; RV32I-FPELIM-NEXT: ret 1052 ; 1053 ; RV32I-WITHFP-LABEL: caller_large_struct_ret: 1054 ; RV32I-WITHFP: # %bb.0: 1055 ; RV32I-WITHFP-NEXT: addi sp, sp, -32 1056 ; RV32I-WITHFP-NEXT: sw ra, 28(sp) 1057 ; RV32I-WITHFP-NEXT: sw s0, 24(sp) 1058 ; RV32I-WITHFP-NEXT: addi s0, sp, 32 1059 ; RV32I-WITHFP-NEXT: addi a0, s0, -24 1060 ; RV32I-WITHFP-NEXT: call callee_large_struct_ret 1061 ; RV32I-WITHFP-NEXT: lw a0, -12(s0) 1062 ; RV32I-WITHFP-NEXT: lw a1, -24(s0) 1063 ; RV32I-WITHFP-NEXT: add a0, a1, a0 1064 ; RV32I-WITHFP-NEXT: lw s0, 24(sp) 1065 ; RV32I-WITHFP-NEXT: lw ra, 28(sp) 1066 ; RV32I-WITHFP-NEXT: addi sp, sp, 32 1067 ; RV32I-WITHFP-NEXT: ret 1068 %1 = alloca %struct.large 1069 call void @callee_large_struct_ret(%struct.large* sret %1) 1070 %2 = getelementptr inbounds %struct.large, %struct.large* %1, i32 0, i32 0 1071 %3 = load i32, i32* %2 1072 %4 = getelementptr inbounds %struct.large, %struct.large* %1, i32 0, i32 3 1073 %5 = load i32, i32* %4 1074 %6 = add i32 %3, %5 1075 ret i32 %6 1076 } 1077