Thomas Preud'homme | 4107b31 | 2018-08-08 09:35:26 +0000 | [diff] [blame] | 1 | ; RUN: llc -mtriple armv7-arm-linux-gnueabihf -O2 -mcpu=cortex-a7 < %s | FileCheck %s |
| 2 | |
| 3 | %struct.twofloat = type { float, float } |
| 4 | %struct.twodouble = type { double, double } |
| 5 | |
| 6 | ; Check support for returning a float in GPR with soft float ABI |
| 7 | define arm_aapcscc float @zerobits_float_soft() #0 { |
| 8 | ; CHECK-LABEL: zerobits_float_soft |
| 9 | ; CHECK: mov r0, #0 |
| 10 | %1 = tail call float asm "mov ${0}, #0", "=&r"() |
| 11 | ret float %1 |
| 12 | } |
| 13 | |
| 14 | ; Check support for returning a double in GPR with soft float ABI |
| 15 | define arm_aapcscc double @zerobits_double_soft() #0 { |
| 16 | ; CHECK-LABEL: zerobits_double_soft |
| 17 | ; CHECK: mov r0, #0 |
| 18 | ; CHECK-NEXT: mov r1, #0 |
| 19 | %1 = tail call double asm "mov ${0:Q}, #0\0Amov ${0:R}, #0", "=&r"() |
| 20 | ret double %1 |
| 21 | } |
| 22 | |
| 23 | ; Check support for returning a float in GPR with matching float input with |
| 24 | ; soft float ABI |
| 25 | define arm_aapcscc float @flt_gpr_matching_in_op_soft(float %f) #0 { |
| 26 | ; CHECK-LABEL: flt_gpr_matching_in_op_soft |
| 27 | ; CHECK: mov r0, r0 |
| 28 | %1 = call float asm "mov $0, $1", "=&r,0"(float %f) |
| 29 | ret float %1 |
| 30 | } |
| 31 | |
| 32 | ; Check support for returning a double in GPR with matching double input with |
| 33 | ; soft float ABI |
| 34 | define arm_aapcscc double @dbl_gpr_matching_in_op_soft(double %d) #0 { |
| 35 | ; CHECK-LABEL: dbl_gpr_matching_in_op_soft |
| 36 | ; CHECK: mov r1, r0 |
| 37 | %1 = call double asm "mov ${0:R}, ${1:Q}", "=&r,0"(double %d) |
| 38 | ret double %1 |
| 39 | } |
| 40 | |
| 41 | ; Check support for returning a float in specific GPR with matching float input |
| 42 | ; with soft float ABI |
| 43 | define arm_aapcscc float @flt_gpr_matching_spec_reg_in_op_soft(float %f) #0 { |
| 44 | ; CHECK-LABEL: flt_gpr_matching_spec_reg_in_op_soft |
| 45 | ; CHECK: mov r3, r3 |
| 46 | %1 = call float asm "mov $0, $1", "=&{r3},0"(float %f) |
| 47 | ret float %1 |
| 48 | } |
| 49 | |
| 50 | ; Check support for returning a double in specific GPR with matching double |
| 51 | ; input with soft float ABI |
| 52 | define arm_aapcscc double @dbl_gpr_matching_spec_reg_in_op_soft(double %d) #0 { |
| 53 | ; CHECK-LABEL: dbl_gpr_matching_spec_reg_in_op_soft |
| 54 | ; CHECK: mov r3, r2 |
| 55 | %1 = call double asm "mov ${0:R}, ${1:Q}", "=&{r2},0"(double %d) |
| 56 | ret double %1 |
| 57 | } |
| 58 | |
| 59 | ; Check support for returning several float in GPR |
| 60 | define arm_aapcscc float @zerobits_float_convoluted_soft() #0 { |
| 61 | ; CHECK-LABEL: zerobits_float_convoluted_soft |
| 62 | ; CHECK: mov r0, #0 |
| 63 | ; CHECK-NEXT: mov r1, #0 |
| 64 | %1 = call { float, float } asm "mov $0, #0; mov $1, #0", "=r,=r"() |
| 65 | %asmresult = extractvalue { float, float } %1, 0 |
| 66 | %asmresult1 = extractvalue { float, float } %1, 1 |
| 67 | %add = fadd float %asmresult, %asmresult1 |
| 68 | ret float %add |
| 69 | } |
| 70 | |
| 71 | ; Check support for returning several double in GPR |
| 72 | define double @zerobits_double_convoluted_soft() #0 { |
| 73 | ; CHECK-LABEL: zerobits_double_convoluted_soft |
| 74 | ; CHECK: mov r0, #0 |
| 75 | ; CHECK-NEXT: mov r1, #0 |
| 76 | ; CHECK-NEXT: mov r2, #0 |
| 77 | ; CHECK-NEXT: mov r3, #0 |
| 78 | %1 = call { double, double } asm "mov ${0:Q}, #0; mov ${0:R}, #0; mov ${1:Q}, #0; mov ${1:R}, #0", "=r,=r"() |
| 79 | %asmresult = extractvalue { double, double } %1, 0 |
| 80 | %asmresult1 = extractvalue { double, double } %1, 1 |
| 81 | %add = fadd double %asmresult, %asmresult1 |
| 82 | ret double %add |
| 83 | } |
| 84 | |
| 85 | ; Check support for returning several floats in GPRs with matching float inputs |
| 86 | ; with soft float ABI |
| 87 | define arm_aapcscc float @flt_gprs_matching_in_op_soft(float %f1, float %f2) #0 { |
| 88 | ; CHECK-LABEL: flt_gprs_matching_in_op_soft |
| 89 | ; CHECK: mov r0, r0 |
| 90 | ; CHECK-NEXT: mov r1, r1 |
| 91 | %1 = call { float, float } asm "mov $0, $2; mov $1, $3", "=&r,=&r,0,1"(float %f1, float %f2) |
| 92 | %asmresult1 = extractvalue { float, float } %1, 0 |
| 93 | %asmresult2 = extractvalue { float, float } %1, 1 |
| 94 | %add = fadd float %asmresult1, %asmresult2 |
| 95 | ret float %add |
| 96 | } |
| 97 | |
| 98 | ; Check support for returning several double in GPRs with matching double input |
| 99 | ; with soft float ABI |
| 100 | define arm_aapcscc double @dbl_gprs_matching_in_op_soft(double %d1, double %d2) #0 { |
| 101 | ; CHECK-LABEL: dbl_gprs_matching_in_op_soft |
| 102 | ; CHECK: mov r1, r0 |
| 103 | ; CHECK-NEXT: mov r3, r2 |
| 104 | %1 = call { double, double } asm "mov ${0:R}, ${2:Q}; mov ${1:R}, ${3:Q}", "=&r,=&r,0,1"(double %d1, double %d2) |
| 105 | %asmresult1 = extractvalue { double, double } %1, 0 |
| 106 | %asmresult2 = extractvalue { double, double } %1, 1 |
| 107 | %add = fadd double %asmresult1, %asmresult2 |
| 108 | ret double %add |
| 109 | } |
| 110 | |
| 111 | ; Check support for returning several float in specific GPRs with matching |
| 112 | ; float input with soft float ABI |
| 113 | define arm_aapcscc float @flt_gprs_matching_spec_reg_in_op_soft(float %f1, float %f2) #0 { |
| 114 | ; CHECK-LABEL: flt_gprs_matching_spec_reg_in_op_soft |
| 115 | ; CHECK: mov r3, r3 |
| 116 | ; CHECK-NEXT: mov r4, r4 |
| 117 | %1 = call { float, float } asm "mov $0, $2; mov $1, $3", "=&{r3},=&{r4},0,1"(float %f1, float %f2) |
| 118 | %asmresult1 = extractvalue { float, float } %1, 0 |
| 119 | %asmresult2 = extractvalue { float, float } %1, 1 |
| 120 | %add = fadd float %asmresult1, %asmresult2 |
| 121 | ret float %add |
| 122 | } |
| 123 | |
| 124 | ; Check support for returning several double in specific GPRs with matching |
| 125 | ; double input with soft float ABI |
| 126 | define arm_aapcscc double @dbl_gprs_matching_spec_reg_in_op_soft(double %d1, double %d2) #0 { |
| 127 | ; CHECK-LABEL: dbl_gprs_matching_spec_reg_in_op_soft |
| 128 | ; CHECK: mov r3, r2 |
| 129 | ; CHECK-NEXT: mov r5, r4 |
| 130 | %1 = call { double, double } asm "mov ${0:R}, ${2:Q}; mov ${1:R}, ${3:Q}", "=&{r2},=&{r4},0,1"(double %d1, double %d2) |
| 131 | %asmresult1 = extractvalue { double, double } %1, 0 |
| 132 | %asmresult2 = extractvalue { double, double } %1, 1 |
| 133 | %add = fadd double %asmresult1, %asmresult2 |
| 134 | ret double %add |
| 135 | } |
| 136 | |
Simon Tatham | 760df47 | 2019-05-28 16:13:20 +0000 | [diff] [blame] | 137 | attributes #0 = { nounwind "target-features"="-d32,+vfp2,+vfp3" "use-soft-float"="true" } |
Thomas Preud'homme | 4107b31 | 2018-08-08 09:35:26 +0000 | [diff] [blame] | 138 | |
| 139 | |
| 140 | ; Check support for returning a float in GPR with hard float ABI |
| 141 | define float @zerobits_float_hard() #1 { |
| 142 | ; CHECK-LABEL: zerobits_float_hard |
| 143 | ; CHECK: mov r0, #0 |
| 144 | ; CHECK: vmov s0, r0 |
| 145 | %1 = tail call float asm "mov ${0}, #0", "=&r"() |
| 146 | ret float %1 |
| 147 | } |
| 148 | |
| 149 | ; Check support for returning a double in GPR with hard float ABI |
| 150 | define double @zerobits_double_hard() #1 { |
| 151 | ; CHECK-LABEL: zerobits_double_hard |
| 152 | ; CHECK: mov r0, #0 |
| 153 | ; CHECK-NEXT: mov r1, #0 |
| 154 | ; CHECK: vmov d0, r0, r1 |
| 155 | %1 = tail call double asm "mov ${0:Q}, #0\0Amov ${0:R}, #0", "=&r"() |
| 156 | ret double %1 |
| 157 | } |
| 158 | |
| 159 | ; Check support for returning a float in GPR with matching float input with |
| 160 | ; hard float ABI |
| 161 | define float @flt_gpr_matching_in_op_hard(float %f) #1 { |
| 162 | ; CHECK-LABEL: flt_gpr_matching_in_op_hard |
| 163 | ; CHECK: vmov r0, s0 |
| 164 | ; CHECK: mov r0, r0 |
| 165 | ; CHECK: vmov s0, r0 |
| 166 | %1 = call float asm "mov $0, $1", "=&r,0"(float %f) |
| 167 | ret float %1 |
| 168 | } |
| 169 | |
| 170 | ; Check support for returning a double in GPR with matching double input with |
| 171 | ; hard float ABI |
| 172 | define double @dbl_gpr_matching_in_op_hard(double %d) #1 { |
| 173 | ; CHECK-LABEL: dbl_gpr_matching_in_op_hard |
| 174 | ; CHECK: vmov r0, r1, d0 |
| 175 | ; CHECK: mov r1, r0 |
| 176 | ; CHECK: vmov d0, r0, r1 |
| 177 | %1 = call double asm "mov ${0:R}, ${1:Q}", "=&r,0"(double %d) |
| 178 | ret double %1 |
| 179 | } |
| 180 | |
| 181 | ; Check support for returning a float in specific GPR with matching float |
| 182 | ; input with hard float ABI |
| 183 | define float @flt_gpr_matching_spec_reg_in_op_hard(float %f) #1 { |
| 184 | ; CHECK-LABEL: flt_gpr_matching_spec_reg_in_op_hard |
| 185 | ; CHECK: vmov r3, s0 |
| 186 | ; CHECK: mov r3, r3 |
| 187 | ; CHECK: vmov s0, r3 |
| 188 | %1 = call float asm "mov $0, $1", "=&{r3},0"(float %f) |
| 189 | ret float %1 |
| 190 | } |
| 191 | |
| 192 | ; Check support for returning a double in specific GPR with matching double |
| 193 | ; input with hard float ABI |
| 194 | define double @dbl_gpr_matching_spec_reg_in_op_hard(double %d) #1 { |
| 195 | ; CHECK-LABEL: dbl_gpr_matching_spec_reg_in_op_hard |
| 196 | ; CHECK: vmov r2, r3, d0 |
| 197 | ; CHECK: mov r3, r2 |
| 198 | ; CHECK: vmov d0, r2, r3 |
| 199 | %1 = call double asm "mov ${0:R}, ${1:Q}", "=&{r2},0"(double %d) |
| 200 | ret double %1 |
| 201 | } |
| 202 | |
| 203 | ; Check support for returning several float in GPR |
| 204 | define %struct.twofloat @zerobits_float_convoluted_hard() #1 { |
| 205 | ; CHECK-LABEL: zerobits_float_convoluted_hard |
| 206 | ; CHECK: mov r0, #0 |
| 207 | ; CHECK-NEXT: mov r1, #0 |
| 208 | ; CHECK: vmov s0, r0 |
| 209 | ; CHECK-NEXT: vmov s1, r1 |
| 210 | %1 = call { float, float } asm "mov $0, #0; mov $1, #0", "=r,=r"() |
| 211 | %asmresult1 = extractvalue { float, float } %1, 0 |
| 212 | %asmresult2 = extractvalue { float, float } %1, 1 |
| 213 | %partialres = insertvalue %struct.twofloat undef, float %asmresult1, 0 |
| 214 | %res = insertvalue %struct.twofloat %partialres, float %asmresult2, 1 |
| 215 | ret %struct.twofloat %res |
| 216 | } |
| 217 | |
| 218 | ; Check support for returning several double in GPR |
| 219 | define %struct.twodouble @zerobits_double_convoluted_hard() #1 { |
| 220 | ; CHECK-LABEL: zerobits_double_convoluted_hard |
| 221 | ; CHECK: mov r0, #0 |
| 222 | ; CHECK-NEXT: mov r1, #0 |
| 223 | ; CHECK-NEXT: mov r2, #0 |
| 224 | ; CHECK-NEXT: mov r3, #0 |
| 225 | ; CHECK: vmov d0, r0, r1 |
| 226 | ; CHECK-NEXT: vmov d1, r2, r3 |
| 227 | %1 = call { double, double } asm "mov ${0:Q}, #0; mov ${0:R}, #0; mov ${1:Q}, #0; mov ${1:R}, #0", "=r,=r"() |
| 228 | %asmresult1 = extractvalue { double, double } %1, 0 |
| 229 | %asmresult2 = extractvalue { double, double } %1, 1 |
| 230 | %partialres = insertvalue %struct.twodouble undef, double %asmresult1, 0 |
| 231 | %res = insertvalue %struct.twodouble %partialres, double %asmresult2, 1 |
| 232 | ret %struct.twodouble %res |
| 233 | } |
| 234 | |
| 235 | ; Check support for returning several floats in GPRs with matching float inputs |
| 236 | ; with hard float ABI |
| 237 | define %struct.twofloat @flt_gprs_matching_in_op_hard(float %f1, float %f2) #1 { |
| 238 | ; CHECK-LABEL: flt_gprs_matching_in_op_hard |
| 239 | ; CHECK: vmov r0, s0 |
| 240 | ; CHECK-NEXT: vmov r1, s1 |
| 241 | ; CHECK: mov r0, r0 |
| 242 | ; CHECK-NEXT: mov r1, r1 |
| 243 | ; CHECK: vmov s0, r0 |
| 244 | ; CHECK-NEXT: vmov s1, r1 |
| 245 | %1 = call { float, float } asm "mov $0, $2; mov $1, $3", "=&r,=&r,0,1"(float %f1, float %f2) |
| 246 | %asmresult1 = extractvalue { float, float } %1, 0 |
| 247 | %asmresult2 = extractvalue { float, float } %1, 1 |
| 248 | %partialres = insertvalue %struct.twofloat undef, float %asmresult1, 0 |
| 249 | %res = insertvalue %struct.twofloat %partialres, float %asmresult2, 1 |
| 250 | ret %struct.twofloat %res |
| 251 | } |
| 252 | |
| 253 | ; Check support for returning several double in GPRs with matching double input |
| 254 | ; with hard float ABI |
| 255 | define %struct.twodouble @dbl_gprs_matching_in_op_hard(double %d1, double %d2) #1 { |
| 256 | ; CHECK-LABEL: dbl_gprs_matching_in_op_hard |
| 257 | ; CHECK: vmov r0, r1, d0 |
| 258 | ; CHECK-NEXT: vmov r2, r3, d1 |
| 259 | ; CHECK: mov r1, r0 |
| 260 | ; CHECK-NEXT: mov r3, r2 |
| 261 | ; CHECK: vmov d0, r0, r1 |
| 262 | ; CHECK-NEXT: vmov d1, r2, r3 |
| 263 | %1 = call { double, double } asm "mov ${0:R}, ${2:Q}; mov ${1:R}, ${3:Q}", "=&r,=&r,0,1"(double %d1, double %d2) |
| 264 | %asmresult1 = extractvalue { double, double } %1, 0 |
| 265 | %asmresult2 = extractvalue { double, double } %1, 1 |
| 266 | %partialres = insertvalue %struct.twodouble undef, double %asmresult1, 0 |
| 267 | %res = insertvalue %struct.twodouble %partialres, double %asmresult2, 1 |
| 268 | ret %struct.twodouble %res |
| 269 | } |
| 270 | |
| 271 | ; Check support for returning several float in specific GPRs with matching |
| 272 | ; float input with hard float ABI |
| 273 | define %struct.twofloat @flt_gprs_matching_spec_reg_in_op_hard(float %f1, float %f2) #1 { |
| 274 | ; CHECK-LABEL: flt_gprs_matching_spec_reg_in_op_hard |
| 275 | ; CHECK: vmov r3, s0 |
| 276 | ; CHECK-NEXT: vmov r4, s1 |
| 277 | ; CHECK: mov r3, r3 |
| 278 | ; CHECK-NEXT: mov r4, r4 |
| 279 | ; CHECK: vmov s0, r3 |
| 280 | ; CHECK-NEXT: vmov s1, r4 |
| 281 | %1 = call { float, float } asm "mov $0, $2; mov $1, $3", "=&{r3},=&{r4},0,1"(float %f1, float %f2) |
| 282 | %asmresult1 = extractvalue { float, float } %1, 0 |
| 283 | %asmresult2 = extractvalue { float, float } %1, 1 |
| 284 | %partialres = insertvalue %struct.twofloat undef, float %asmresult1, 0 |
| 285 | %res = insertvalue %struct.twofloat %partialres, float %asmresult2, 1 |
| 286 | ret %struct.twofloat %res |
| 287 | } |
| 288 | |
| 289 | ; Check support for returning several double in specific GPRs with matching |
| 290 | ; double input with hard float ABI |
| 291 | define %struct.twodouble @dbl_gprs_matching_spec_reg_in_op_hard(double %d1, double %d2) #1 { |
| 292 | ; CHECK-LABEL: dbl_gprs_matching_spec_reg_in_op_hard |
| 293 | ; CHECK: vmov r2, r3, d0 |
| 294 | ; CHECK-NEXT: vmov r4, r5, d1 |
| 295 | ; CHECK: mov r3, r2 |
| 296 | ; CHECK-NEXT: mov r5, r4 |
| 297 | ; CHECK: vmov d0, r2, r3 |
| 298 | ; CHECK-NEXT: vmov d1, r4, r5 |
| 299 | %1 = call { double, double } asm "mov ${0:R}, ${2:Q}; mov ${1:R}, ${3:Q}", "=&{r2},=&{r4},0,1"(double %d1, double %d2) |
| 300 | %asmresult1 = extractvalue { double, double } %1, 0 |
| 301 | %asmresult2 = extractvalue { double, double } %1, 1 |
| 302 | %partialres = insertvalue %struct.twodouble undef, double %asmresult1, 0 |
| 303 | %res = insertvalue %struct.twodouble %partialres, double %asmresult2, 1 |
| 304 | ret %struct.twodouble %res |
| 305 | } |
| 306 | |
Simon Tatham | 760df47 | 2019-05-28 16:13:20 +0000 | [diff] [blame] | 307 | attributes #1 = { nounwind "target-features"="-d32,+vfp2,+vfp3" "use-soft-float"="false" } |