1; RUN: llc -O0 -mtriple arm-unknown -mattr=+vfp2,+v4t -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=ARM -check-prefix=LITTLE 2; RUN: llc -O0 -mtriple armeb-unknown -mattr=+vfp2,+v4t -global-isel -global-isel-abort=0 -enable-arm-gisel-bigendian -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=ARM -check-prefix=BIG 3; RUN: llc -O0 -mtriple thumb-unknown -mattr=+vfp2,+v6t2 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LITTLE -check-prefix=THUMB 4 5declare arm_aapcscc ptr @simple_reg_params_target(i32, ptr) 6 7define arm_aapcscc ptr @test_call_simple_reg_params(ptr %a, i32 %b) { 8; CHECK-LABEL: name: test_call_simple_reg_params 9; CHECK-DAG: [[AVREG:%[0-9]+]]:_(p0) = COPY $r0 10; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $r1 11; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 12; CHECK-DAG: $r0 = COPY [[BVREG]] 13; CHECK-DAG: $r1 = COPY [[AVREG]] 14; ARM: BL @simple_reg_params_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0 15; THUMB: tBL 14 /* CC::al */, $noreg, @simple_reg_params_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0 16; CHECK: [[RVREG:%[0-9]+]]:_(p0) = COPY $r0 17; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 18; CHECK: $r0 = COPY [[RVREG]] 19; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0 20; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0 21entry: 22 %r = notail call arm_aapcscc ptr @simple_reg_params_target(i32 %b, ptr %a) 23 ret ptr %r 24} 25 26declare arm_aapcscc ptr @simple_stack_params_target(i32, ptr, i32, ptr, i32, ptr) 27 28define arm_aapcscc ptr @test_call_simple_stack_params(ptr %a, i32 %b) { 29; CHECK-LABEL: name: test_call_simple_stack_params 30; CHECK-DAG: [[AVREG:%[0-9]+]]:_(p0) = COPY $r0 31; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $r1 32; CHECK: ADJCALLSTACKDOWN 8, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 33; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp 34; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 35; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP1]], [[OFF1]](s32) 36; CHECK: G_STORE [[BVREG]](s32), [[FI1]](p0){{.*}}store (s32) 37; CHECK: [[SP2:%[0-9]+]]:_(p0) = COPY $sp 38; CHECK: [[OFF2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 39; CHECK: [[FI2:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP2]], [[OFF2]](s32) 40; CHECK: G_STORE [[AVREG]](p0), [[FI2]](p0){{.*}}store (p0) 41; CHECK-DAG: $r0 = COPY [[BVREG]] 42; CHECK-DAG: $r1 = COPY [[AVREG]] 43; CHECK-DAG: $r2 = COPY [[BVREG]] 44; CHECK-DAG: $r3 = COPY [[AVREG]] 45; ARM: BL @simple_stack_params_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0 46; THUMB: tBL 14 /* CC::al */, $noreg, @simple_stack_params_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0 47; CHECK: [[RVREG:%[0-9]+]]:_(p0) = COPY $r0 48; CHECK: ADJCALLSTACKUP 8, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 49; CHECK: $r0 = COPY [[RVREG]] 50; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0 51; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0 52entry: 53 %r = notail call arm_aapcscc ptr @simple_stack_params_target(i32 %b, ptr %a, i32 %b, ptr %a, i32 %b, ptr %a) 54 ret ptr %r 55} 56 57declare arm_aapcscc signext i16 @ext_target(i8 signext, i8 zeroext, i16 signext, i16 zeroext, i8 signext, i8 zeroext, i16 signext, i16 zeroext, i1 zeroext) 58 59define arm_aapcscc signext i16 @test_call_ext_params(i8 %a, i16 %b, i1 %c) { 60; CHECK-LABEL: name: test_call_ext_params 61; CHECK-DAG: [[R0VREG:%[0-9]+]]:_(s32) = COPY $r0 62; CHECK-DAG: [[AVREG:%[0-9]+]]:_(s8) = G_TRUNC [[R0VREG]] 63; CHECK-DAG: [[R1VREG:%[0-9]+]]:_(s32) = COPY $r1 64; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s16) = G_TRUNC [[R1VREG]] 65; CHECK-DAG: [[R2VREG:%[0-9]+]]:_(s32) = COPY $r2 66; CHECK-DAG: [[CVREG:%[0-9]+]]:_(s1) = G_TRUNC [[R2VREG]] 67; CHECK: ADJCALLSTACKDOWN 20, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 68; CHECK: [[SEXTA:%[0-9]+]]:_(s32) = G_SEXT [[AVREG]](s8) 69; CHECK: [[ZEXTA:%[0-9]+]]:_(s32) = G_ZEXT [[AVREG]](s8) 70; CHECK: [[SEXTB:%[0-9]+]]:_(s32) = G_SEXT [[BVREG]](s16) 71; CHECK: [[ZEXTB:%[0-9]+]]:_(s32) = G_ZEXT [[BVREG]](s16) 72; CHECK: [[SEXTA2:%[0-9]+]]:_(s32) = G_SEXT [[AVREG]] 73; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp 74; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 75; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP1]], [[OFF1]](s32) 76; CHECK: G_STORE [[SEXTA2]](s32), [[FI1]](p0){{.*}}store (s32) 77; CHECK: [[ZEXTA2:%[0-9]+]]:_(s32) = G_ZEXT [[AVREG]] 78; CHECK: [[SP2:%[0-9]+]]:_(p0) = COPY $sp 79; CHECK: [[OFF2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 80; CHECK: [[FI2:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP2]], [[OFF2]](s32) 81; CHECK: G_STORE [[ZEXTA2]](s32), [[FI2]](p0){{.*}}store (s32) 82; CHECK: [[SEXTB2:%[0-9]+]]:_(s32) = G_SEXT [[BVREG]] 83; CHECK: [[SP3:%[0-9]+]]:_(p0) = COPY $sp 84; CHECK: [[OFF3:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 85; CHECK: [[FI3:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP3]], [[OFF3]](s32) 86; CHECK: G_STORE [[SEXTB2]](s32), [[FI3]](p0){{.*}}store (s32) 87; CHECK: [[ZEXTB2:%[0-9]+]]:_(s32) = G_ZEXT [[BVREG]] 88; CHECK: [[SP4:%[0-9]+]]:_(p0) = COPY $sp 89; CHECK: [[OFF4:%[0-9]+]]:_(s32) = G_CONSTANT i32 12 90; CHECK: [[FI4:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP4]], [[OFF4]](s32) 91; CHECK: G_STORE [[ZEXTB2]](s32), [[FI4]](p0){{.*}}store (s32) 92; CHECK: [[ZEXTC:%[0-9]+]]:_(s32) = G_ZEXT [[CVREG]] 93; CHECK: [[SP5:%[0-9]+]]:_(p0) = COPY $sp 94; CHECK: [[OFF5:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 95; CHECK: [[FI5:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP5]], [[OFF5]](s32) 96; CHECK: G_STORE [[ZEXTC]](s32), [[FI5]](p0){{.*}}store (s32) 97; CHECK: $r0 = COPY [[SEXTA]] 98; CHECK: $r1 = COPY [[ZEXTA]] 99; CHECK: $r2 = COPY [[SEXTB]] 100; CHECK: $r3 = COPY [[ZEXTB]] 101; ARM: BL @ext_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0 102; THUMB: tBL 14 /* CC::al */, $noreg, @ext_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0 103; CHECK: [[R0VREG:%[0-9]+]]:_(s32) = COPY $r0 104; CHECK: [[R0VREG_ASSERT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[R0VREG]], 16 105; CHECK: [[RVREG:%[0-9]+]]:_(s16) = G_TRUNC [[R0VREG_ASSERT]] 106; CHECK: ADJCALLSTACKUP 20, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 107; CHECK: [[RExtVREG:%[0-9]+]]:_(s32) = G_SEXT [[RVREG]] 108; CHECK: $r0 = COPY [[RExtVREG]] 109; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0 110; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0 111entry: 112 %r = notail call arm_aapcscc signext i16 @ext_target(i8 signext %a, i8 zeroext %a, i16 signext %b, i16 zeroext %b, i8 signext %a, i8 zeroext %a, i16 signext %b, i16 zeroext %b, i1 zeroext %c) 113 ret i16 %r 114} 115 116declare arm_aapcs_vfpcc double @vfpcc_fp_target(float, double) 117 118define arm_aapcs_vfpcc double @test_call_vfpcc_fp_params(double %a, float %b) { 119; CHECK-LABEL: name: test_call_vfpcc_fp_params 120; CHECK-DAG: [[AVREG:%[0-9]+]]:_(s64) = COPY $d0 121; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $s2 122; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 123; CHECK-DAG: $s0 = COPY [[BVREG]] 124; CHECK-DAG: $d1 = COPY [[AVREG]] 125; ARM: BL @vfpcc_fp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $s0, implicit $d1, implicit-def $d0 126; THUMB: tBL 14 /* CC::al */, $noreg, @vfpcc_fp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $s0, implicit $d1, implicit-def $d0 127; CHECK: [[RVREG:%[0-9]+]]:_(s64) = COPY $d0 128; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 129; CHECK: $d0 = COPY [[RVREG]] 130; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $d0 131; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $d0 132entry: 133 %r = notail call arm_aapcs_vfpcc double @vfpcc_fp_target(float %b, double %a) 134 ret double %r 135} 136 137declare arm_aapcscc double @aapcscc_fp_target(float, double, float, double) 138 139define arm_aapcscc double @test_call_aapcs_fp_params(double %a, float %b) { 140; CHECK-LABEL: name: test_call_aapcs_fp_params 141; CHECK-DAG: [[A1:%[0-9]+]]:_(s32) = COPY $r0 142; CHECK-DAG: [[A2:%[0-9]+]]:_(s32) = COPY $r1 143; LITTLE-DAG: [[AVREG:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[A1]](s32), [[A2]](s32) 144; BIG-DAG: [[AVREG:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[A2]](s32), [[A1]](s32) 145; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $r2 146; CHECK: ADJCALLSTACKDOWN 16, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 147; CHECK-DAG: [[A1:%[0-9]+]]:_(s32), [[A2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[AVREG]](s64) 148; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp 149; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 150; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP1]], [[OFF1]](s32) 151; CHECK: G_STORE [[BVREG]](s32), [[FI1]](p0){{.*}}store (s32) 152; CHECK: [[SP2:%[0-9]+]]:_(p0) = COPY $sp 153; CHECK: [[OFF2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 154; CHECK: [[FI2:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP2]], [[OFF2]](s32) 155; CHECK: G_STORE [[AVREG]](s64), [[FI2]](p0){{.*}}store (s64) 156; CHECK-DAG: $r0 = COPY [[BVREG]] 157; LITTLE-DAG: $r2 = COPY [[A1]] 158; LITTLE-DAG: $r3 = COPY [[A2]] 159; BIG-DAG: $r2 = COPY [[A2]] 160; BIG-DAG: $r3 = COPY [[A1]] 161; ARM: BL @aapcscc_fp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 162; THUMB: tBL 14 /* CC::al */, $noreg, @aapcscc_fp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 163; CHECK-DAG: [[R1:%[0-9]+]]:_(s32) = COPY $r0 164; CHECK-DAG: [[R2:%[0-9]+]]:_(s32) = COPY $r1 165; LITTLE: [[RVREG:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[R1]](s32), [[R2]](s32) 166; BIG: [[RVREG:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[R2]](s32), [[R1]](s32) 167; CHECK: ADJCALLSTACKUP 16, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 168; CHECK: [[R1:%[0-9]+]]:_(s32), [[R2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[RVREG]](s64) 169; LITTLE-DAG: $r0 = COPY [[R1]] 170; LITTLE-DAG: $r1 = COPY [[R2]] 171; BIG-DAG: $r0 = COPY [[R2]] 172; BIG-DAG: $r1 = COPY [[R1]] 173; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1 174; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1 175entry: 176 %r = notail call arm_aapcscc double @aapcscc_fp_target(float %b, double %a, float %b, double %a) 177 ret double %r 178} 179 180declare arm_aapcscc float @different_call_conv_target(float) 181 182define arm_aapcs_vfpcc float @test_call_different_call_conv(float %x) { 183; CHECK-LABEL: name: test_call_different_call_conv 184; CHECK: [[X:%[0-9]+]]:_(s32) = COPY $s0 185; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 186; CHECK: $r0 = COPY [[X]] 187; ARM: BL @different_call_conv_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit-def $r0 188; THUMB: tBL 14 /* CC::al */, $noreg, @different_call_conv_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit-def $r0 189; CHECK: [[R:%[0-9]+]]:_(s32) = COPY $r0 190; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 191; CHECK: $s0 = COPY [[R]] 192; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $s0 193; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $s0 194entry: 195 %r = notail call arm_aapcscc float @different_call_conv_target(float %x) 196 ret float %r 197} 198 199declare arm_aapcscc [3 x i32] @tiny_int_arrays_target([2 x i32]) 200 201define arm_aapcscc [3 x i32] @test_tiny_int_arrays([2 x i32] %arr) { 202; CHECK-LABEL: name: test_tiny_int_arrays 203; CHECK: liveins: $r0, $r1 204; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 205; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 206; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 207; CHECK: $r0 = COPY [[R0]] 208; CHECK: $r1 = COPY [[R1]] 209; ARM: BL @tiny_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1 210; THUMB: tBL 14 /* CC::al */, $noreg, @tiny_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1 211; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 212; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 213; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $r2 214; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 215; FIXME: This doesn't seem correct with regard to the AAPCS docs (which say 216; that composite types larger than 4 bytes should be passed through memory), 217; but it's what DAGISel does. We should fix it in the common code for both. 218; CHECK: $r0 = COPY [[R0]] 219; CHECK: $r1 = COPY [[R1]] 220; CHECK: $r2 = COPY [[R2]] 221; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1, implicit $r2 222; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1, implicit $r2 223entry: 224 %r = notail call arm_aapcscc [3 x i32] @tiny_int_arrays_target([2 x i32] %arr) 225 ret [3 x i32] %r 226} 227 228declare arm_aapcscc void @multiple_int_arrays_target([2 x i32], [2 x i32]) 229 230define arm_aapcscc void @test_multiple_int_arrays([2 x i32] %arr0, [2 x i32] %arr1) { 231; CHECK-LABEL: name: test_multiple_int_arrays 232; CHECK: liveins: $r0, $r1 233; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 234; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 235; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $r2 236; CHECK: [[R3:%[0-9]+]]:_(s32) = COPY $r3 237; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 238; CHECK: $r0 = COPY [[R0]] 239; CHECK: $r1 = COPY [[R1]] 240; CHECK: $r2 = COPY [[R2]] 241; CHECK: $r3 = COPY [[R3]] 242; ARM: BL @multiple_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3 243; THUMB: tBL 14 /* CC::al */, $noreg, @multiple_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3 244; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 245; ARM: BX_RET 14 /* CC::al */, $noreg 246; THUMB: tBX_RET 14 /* CC::al */, $noreg 247entry: 248 notail call arm_aapcscc void @multiple_int_arrays_target([2 x i32] %arr0, [2 x i32] %arr1) 249 ret void 250} 251 252declare arm_aapcscc void @large_int_arrays_target([20 x i32]) 253 254define arm_aapcscc void @test_large_int_arrays([20 x i32] %arr) { 255; CHECK-LABEL: name: test_large_int_arrays 256; CHECK: fixedStack: 257; The parameters live in separate stack locations, one for each element that 258; doesn't fit in the registers. 259; CHECK-DAG: id: [[FIRST_STACK_ID:[0-9]+]], type: default, offset: 0, size: 4, 260; CHECK-DAG: id: [[LAST_STACK_ID:[-0]+]], type: default, offset: 60, size: 4 261; CHECK: liveins: $r0, $r1, $r2, $r3 262; CHECK-DAG: [[R0:%[0-9]+]]:_(s32) = COPY $r0 263; CHECK-DAG: [[R1:%[0-9]+]]:_(s32) = COPY $r1 264; CHECK-DAG: [[R2:%[0-9]+]]:_(s32) = COPY $r2 265; CHECK-DAG: [[R3:%[0-9]+]]:_(s32) = COPY $r3 266; CHECK: [[FIRST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[FIRST_STACK_ID]] 267; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load (s32) from %fixed-stack.[[FIRST_STACK_ID]] 268; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]] 269; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load (s32) from %fixed-stack.[[LAST_STACK_ID]] 270; CHECK: ADJCALLSTACKDOWN 64, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 271; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 272; CHECK: [[OFF_FIRST_ELEMENT:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 273; CHECK: [[FIRST_STACK_ARG_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFF_FIRST_ELEMENT]](s32) 274; CHECK: G_STORE [[FIRST_STACK_ELEMENT]](s32), [[FIRST_STACK_ARG_ADDR]]{{.*}}store (s32) 275; Match the second-to-last offset, so we can get the correct SP for the last element 276; CHECK: G_CONSTANT i32 56 277; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 278; CHECK: [[OFF_LAST_ELEMENT:%[0-9]+]]:_(s32) = G_CONSTANT i32 60 279; CHECK: [[LAST_STACK_ARG_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFF_LAST_ELEMENT]](s32) 280; CHECK: G_STORE [[LAST_STACK_ELEMENT]](s32), [[LAST_STACK_ARG_ADDR]]{{.*}}store (s32) 281; CHECK: $r0 = COPY [[R0]] 282; CHECK: $r1 = COPY [[R1]] 283; CHECK: $r2 = COPY [[R2]] 284; CHECK: $r3 = COPY [[R3]] 285; ARM: BL @large_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3 286; THUMB: tBL 14 /* CC::al */, $noreg, @large_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3 287; CHECK: ADJCALLSTACKUP 64, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 288; ARM: BX_RET 14 /* CC::al */, $noreg 289; THUMB: tBX_RET 14 /* CC::al */, $noreg 290entry: 291 notail call arm_aapcscc void @large_int_arrays_target([20 x i32] %arr) 292 ret void 293} 294 295declare arm_aapcscc [2 x float] @fp_arrays_aapcs_target([3 x double]) 296 297define arm_aapcscc [2 x float] @test_fp_arrays_aapcs([3 x double] %arr) { 298; CHECK-LABEL: name: test_fp_arrays_aapcs 299; CHECK: fixedStack: 300; CHECK: id: [[ARR2_ID:[0-9]+]], type: default, offset: 0, size: 8, 301; CHECK: liveins: $r0, $r1, $r2, $r3 302; CHECK: [[ARR0_0:%[0-9]+]]:_(s32) = COPY $r0 303; CHECK: [[ARR0_1:%[0-9]+]]:_(s32) = COPY $r1 304; LITTLE: [[ARR0:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR0_0]](s32), [[ARR0_1]](s32) 305; BIG: [[ARR0:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR0_1]](s32), [[ARR0_0]](s32) 306; CHECK: [[ARR1_0:%[0-9]+]]:_(s32) = COPY $r2 307; CHECK: [[ARR1_1:%[0-9]+]]:_(s32) = COPY $r3 308; LITTLE: [[ARR1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR1_0]](s32), [[ARR1_1]](s32) 309; BIG: [[ARR1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR1_1]](s32), [[ARR1_0]](s32) 310; CHECK: [[ARR2_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[ARR2_ID]] 311; CHECK: [[ARR2:%[0-9]+]]:_(s64) = G_LOAD [[ARR2_FI]]{{.*}}load (s64) from %fixed-stack.[[ARR2_ID]] 312; CHECK: ADJCALLSTACKDOWN 8, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 313; CHECK: [[ARR0_0:%[0-9]+]]:_(s32), [[ARR0_1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ARR0]](s64) 314; CHECK: [[ARR1_0:%[0-9]+]]:_(s32), [[ARR1_1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ARR1]](s64) 315; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 316; CHECK: [[ARR2_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 317; CHECK: [[ARR2_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[ARR2_OFFSET]](s32) 318; CHECK: G_STORE [[ARR2]](s64), [[ARR2_ADDR]](p0){{.*}}store (s64) 319; LITTLE: $r0 = COPY [[ARR0_0]](s32) 320; LITTLE: $r1 = COPY [[ARR0_1]](s32) 321; BIG: $r0 = COPY [[ARR0_1]](s32) 322; BIG: $r1 = COPY [[ARR0_0]](s32) 323; LITTLE: $r2 = COPY [[ARR1_0]](s32) 324; LITTLE: $r3 = COPY [[ARR1_1]](s32) 325; BIG: $r2 = COPY [[ARR1_1]](s32) 326; BIG: $r3 = COPY [[ARR1_0]](s32) 327; ARM: BL @fp_arrays_aapcs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 328; THUMB: tBL 14 /* CC::al */, $noreg, @fp_arrays_aapcs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 329; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 330; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 331; CHECK: ADJCALLSTACKUP 8, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 332; CHECK: $r0 = COPY [[R0]] 333; CHECK: $r1 = COPY [[R1]] 334; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1 335; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1 336entry: 337 %r = notail call arm_aapcscc [2 x float] @fp_arrays_aapcs_target([3 x double] %arr) 338 ret [2 x float] %r 339} 340 341declare arm_aapcs_vfpcc [4 x float] @fp_arrays_aapcs_vfp_target([3 x double], [3 x float], [4 x double]) 342 343define arm_aapcs_vfpcc [4 x float] @test_fp_arrays_aapcs_vfp([3 x double] %x, [3 x float] %y, [4 x double] %z) { 344; CHECK-LABEL: name: test_fp_arrays_aapcs_vfp 345; CHECK: fixedStack: 346; CHECK-DAG: id: [[Z0_ID:[0-9]+]], type: default, offset: 0, size: 8, 347; CHECK-DAG: id: [[Z1_ID:[0-9]+]], type: default, offset: 8, size: 8, 348; CHECK-DAG: id: [[Z2_ID:[0-9]+]], type: default, offset: 16, size: 8, 349; CHECK-DAG: id: [[Z3_ID:[0-9]+]], type: default, offset: 24, size: 8, 350; CHECK: liveins: $d0, $d1, $d2, $s6, $s7, $s8 351; CHECK: [[X0:%[0-9]+]]:_(s64) = COPY $d0 352; CHECK: [[X1:%[0-9]+]]:_(s64) = COPY $d1 353; CHECK: [[X2:%[0-9]+]]:_(s64) = COPY $d2 354; CHECK: [[Y0:%[0-9]+]]:_(s32) = COPY $s6 355; CHECK: [[Y1:%[0-9]+]]:_(s32) = COPY $s7 356; CHECK: [[Y2:%[0-9]+]]:_(s32) = COPY $s8 357; CHECK: [[Z0_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z0_ID]] 358; CHECK: [[Z0:%[0-9]+]]:_(s64) = G_LOAD [[Z0_FI]]{{.*}}load (s64) 359; CHECK: [[Z1_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z1_ID]] 360; CHECK: [[Z1:%[0-9]+]]:_(s64) = G_LOAD [[Z1_FI]]{{.*}}load (s64) 361; CHECK: [[Z2_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z2_ID]] 362; CHECK: [[Z2:%[0-9]+]]:_(s64) = G_LOAD [[Z2_FI]]{{.*}}load (s64) 363; CHECK: [[Z3_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z3_ID]] 364; CHECK: [[Z3:%[0-9]+]]:_(s64) = G_LOAD [[Z3_FI]]{{.*}}load (s64) 365; CHECK: ADJCALLSTACKDOWN 32, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 366; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 367; CHECK: [[Z0_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 368; CHECK: [[Z0_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[Z0_OFFSET]](s32) 369; CHECK: G_STORE [[Z0]](s64), [[Z0_ADDR]](p0){{.*}}store (s64) 370; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 371; CHECK: [[Z1_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 372; CHECK: [[Z1_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[Z1_OFFSET]](s32) 373; CHECK: G_STORE [[Z1]](s64), [[Z1_ADDR]](p0){{.*}}store (s64) 374; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 375; CHECK: [[Z2_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 376; CHECK: [[Z2_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[Z2_OFFSET]](s32) 377; CHECK: G_STORE [[Z2]](s64), [[Z2_ADDR]](p0){{.*}}store (s64) 378; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 379; CHECK: [[Z3_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 380; CHECK: [[Z3_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[Z3_OFFSET]](s32) 381; CHECK: G_STORE [[Z3]](s64), [[Z3_ADDR]](p0){{.*}}store (s64) 382; CHECK: $d0 = COPY [[X0]](s64) 383; CHECK: $d1 = COPY [[X1]](s64) 384; CHECK: $d2 = COPY [[X2]](s64) 385; CHECK: $s6 = COPY [[Y0]](s32) 386; CHECK: $s7 = COPY [[Y1]](s32) 387; CHECK: $s8 = COPY [[Y2]](s32) 388; ARM: BL @fp_arrays_aapcs_vfp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $d0, implicit $d1, implicit $d2, implicit $s6, implicit $s7, implicit $s8, implicit-def $s0, implicit-def $s1, implicit-def $s2, implicit-def $s3 389; THUMB: tBL 14 /* CC::al */, $noreg, @fp_arrays_aapcs_vfp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $d0, implicit $d1, implicit $d2, implicit $s6, implicit $s7, implicit $s8, implicit-def $s0, implicit-def $s1, implicit-def $s2, implicit-def $s3 390; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $s0 391; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $s1 392; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $s2 393; CHECK: [[R3:%[0-9]+]]:_(s32) = COPY $s3 394; CHECK: ADJCALLSTACKUP 32, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 395; CHECK: $s0 = COPY [[R0]] 396; CHECK: $s1 = COPY [[R1]] 397; CHECK: $s2 = COPY [[R2]] 398; CHECK: $s3 = COPY [[R3]] 399; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $s0, implicit $s1, implicit $s2, implicit $s3 400; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $s0, implicit $s1, implicit $s2, implicit $s3 401entry: 402 %r = notail call arm_aapcs_vfpcc [4 x float] @fp_arrays_aapcs_vfp_target([3 x double] %x, [3 x float] %y, [4 x double] %z) 403 ret [4 x float] %r 404} 405 406declare arm_aapcscc [2 x ptr] @tough_arrays_target([6 x [4 x i32]] %arr) 407 408define arm_aapcscc [2 x ptr] @test_tough_arrays([6 x [4 x i32]] %arr) { 409; CHECK-LABEL: name: test_tough_arrays 410; CHECK: fixedStack: 411; The parameters live in separate stack locations, one for each element that 412; doesn't fit in the registers. 413; CHECK-DAG: id: [[FIRST_STACK_ID:[0-9]+]], type: default, offset: 0, size: 4, 414; CHECK-DAG: id: [[LAST_STACK_ID:[-0]+]], type: default, offset: 76, size: 4 415; CHECK: liveins: $r0, $r1, $r2, $r3 416; CHECK-DAG: [[R0:%[0-9]+]]:_(s32) = COPY $r0 417; CHECK-DAG: [[R1:%[0-9]+]]:_(s32) = COPY $r1 418; CHECK-DAG: [[R2:%[0-9]+]]:_(s32) = COPY $r2 419; CHECK-DAG: [[R3:%[0-9]+]]:_(s32) = COPY $r3 420; CHECK: [[FIRST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[FIRST_STACK_ID]] 421; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load (s32) from %fixed-stack.[[FIRST_STACK_ID]] 422; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]] 423; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load (s32) from %fixed-stack.[[LAST_STACK_ID]] 424; CHECK: ADJCALLSTACKDOWN 80, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 425; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 426; CHECK: [[OFF_FIRST_ELEMENT:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 427; CHECK: [[FIRST_STACK_ARG_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFF_FIRST_ELEMENT]](s32) 428; CHECK: G_STORE [[FIRST_STACK_ELEMENT]](s32), [[FIRST_STACK_ARG_ADDR]]{{.*}}store (s32) 429; Match the second-to-last offset, so we can get the correct SP for the last element 430; CHECK: G_CONSTANT i32 72 431; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp 432; CHECK: [[OFF_LAST_ELEMENT:%[0-9]+]]:_(s32) = G_CONSTANT i32 76 433; CHECK: [[LAST_STACK_ARG_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFF_LAST_ELEMENT]](s32) 434; CHECK: G_STORE [[LAST_STACK_ELEMENT]](s32), [[LAST_STACK_ARG_ADDR]]{{.*}}store (s32) 435; CHECK: $r0 = COPY [[R0]] 436; CHECK: $r1 = COPY [[R1]] 437; CHECK: $r2 = COPY [[R2]] 438; CHECK: $r3 = COPY [[R3]] 439; ARM: BL @tough_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 440; THUMB: tBL 14 /* CC::al */, $noreg, @tough_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1 441; CHECK: [[R0:%[0-9]+]]:_(p0) = COPY $r0 442; CHECK: [[R1:%[0-9]+]]:_(p0) = COPY $r1 443; CHECK: ADJCALLSTACKUP 80, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 444; CHECK: $r0 = COPY [[R0]] 445; CHECK: $r1 = COPY [[R1]] 446; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1 447; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1 448entry: 449 %r = notail call arm_aapcscc [2 x ptr] @tough_arrays_target([6 x [4 x i32]] %arr) 450 ret [2 x ptr] %r 451} 452 453declare arm_aapcscc {i32, i32} @structs_target({i32, i32}) 454 455define arm_aapcscc {i32, i32} @test_structs({i32, i32} %x) { 456; CHECK-LABEL: test_structs 457; CHECK: liveins: $r0, $r1 458; CHECK-DAG: [[X0:%[0-9]+]]:_(s32) = COPY $r0 459; CHECK-DAG: [[X1:%[0-9]+]]:_(s32) = COPY $r1 460; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 461; CHECK-DAG: $r0 = COPY [[X0]](s32) 462; CHECK-DAG: $r1 = COPY [[X1]](s32) 463; ARM: BL @structs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1 464; THUMB: tBL 14 /* CC::al */, $noreg, @structs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1 465; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0 466; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1 467; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp 468; CHECK: $r0 = COPY [[R0]](s32) 469; CHECK: $r1 = COPY [[R1]](s32) 470; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1 471; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1 472 %r = notail call arm_aapcscc {i32, i32} @structs_target({i32, i32} %x) 473 ret {i32, i32} %r 474} 475