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 7define 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 15define 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 25define 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 34define 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 43define 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 52define 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 60define 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 72define 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 87define 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 100define 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 113define 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 126define 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 137attributes #0 = { nounwind "target-features"="-d32,+vfp2,+vfp3" "use-soft-float"="true" } 138 139 140; Check support for returning a float in GPR with hard float ABI 141define 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 150define 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 161define 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 172define 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 183define 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 194define 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 204define %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 219define %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 237define %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 255define %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 273define %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 291define %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 307attributes #1 = { nounwind "target-features"="-d32,+vfp2,+vfp3" "use-soft-float"="false" } 308