1; RUN: llc -verify-machineinstrs < %s -mcpu=pwr8 \ 2; RUN: -mattr=+altivec -mattr=-vsx | FileCheck %s 3; RUN: llc -verify-machineinstrs < %s -mattr=+altivec \ 4; RUN: -mattr=-vsx | FileCheck %s 5; RUN: llc -verify-machineinstrs < %s -mcpu=pwr9 \ 6; RUN: -mattr=-direct-move -mattr=+altivec | FileCheck %s 7 8; Currently VSX support is disabled for this test because we generate lxsdx 9; instead of lfd, and stxsdx instead of stfd. That is a poor choice when we 10; have reg+imm addressing, and is on the list of things to be fixed. 11; The second run step is to ensure that -march=ppc64le is adequate to select 12; the same feature set as with -mcpu=pwr8 since that is the baseline for ppc64le. 13 14target datalayout = "e-m:e-i64:64-n32:64" 15target triple = "powerpc64le-unknown-linux-gnu" 16 17; 18; Verify use of registers for float/vector aggregate return. 19; 20 21define [8 x float] @return_float([8 x float] %x) { 22entry: 23 ret [8 x float] %x 24} 25; CHECK-LABEL: @return_float 26; CHECK: %entry 27; CHECK-NEXT: blr 28 29define [8 x double] @return_double([8 x double] %x) { 30entry: 31 ret [8 x double] %x 32} 33; CHECK-LABEL: @return_double 34; CHECK: %entry 35; CHECK-NEXT: blr 36 37define [4 x ppc_fp128] @return_ppcf128([4 x ppc_fp128] %x) { 38entry: 39 ret [4 x ppc_fp128] %x 40} 41; CHECK-LABEL: @return_ppcf128 42; CHECK: %entry 43; CHECK-NEXT: blr 44 45define [8 x <4 x i32>] @return_v4i32([8 x <4 x i32>] %x) { 46entry: 47 ret [8 x <4 x i32>] %x 48} 49; CHECK-LABEL: @return_v4i32 50; CHECK: %entry 51; CHECK-NEXT: blr 52 53 54; 55; Verify amount of space taken up by aggregates in the parameter save area. 56; 57 58define i64 @callee_float([7 x float] %a, [7 x float] %b, i64 %c) { 59entry: 60 ret i64 %c 61} 62; CHECK-LABEL: @callee_float 63; CHECK: ld 3, 96(1) 64; CHECK: blr 65 66define void @caller_float(i64 %x, [7 x float] %y) { 67entry: 68 tail call void @test_float([7 x float] %y, [7 x float] %y, i64 %x) 69 ret void 70} 71; CHECK-LABEL: @caller_float 72; CHECK: std 3, 96(1) 73; CHECK: bl test_float 74 75declare void @test_float([7 x float], [7 x float], i64) 76 77define i64 @callee_double(i64 %a, [7 x double] %b, i64 %c) { 78entry: 79 ret i64 %c 80} 81; CHECK-LABEL: @callee_double 82; CHECK: ld 3, 96(1) 83; CHECK: blr 84 85define void @caller_double(i64 %x, [7 x double] %y) { 86entry: 87 tail call void @test_double(i64 %x, [7 x double] %y, i64 %x) 88 ret void 89} 90; CHECK-LABEL: @caller_double 91; CHECK: std 3, 96(1) 92; CHECK: bl test_double 93 94declare void @test_double(i64, [7 x double], i64) 95 96define i64 @callee_ppcf128(i64 %a, [4 x ppc_fp128] %b, i64 %c) { 97entry: 98 ret i64 %c 99} 100; CHECK-LABEL: @callee_ppcf128 101; CHECK: ld 3, 104(1) 102; CHECK: blr 103 104define void @caller_ppcf128(i64 %x, [4 x ppc_fp128] %y) { 105entry: 106 tail call void @test_ppcf128(i64 %x, [4 x ppc_fp128] %y, i64 %x) 107 ret void 108} 109; CHECK-LABEL: @caller_ppcf128 110; CHECK: std 3, 104(1) 111; CHECK: bl test_ppcf128 112 113declare void @test_ppcf128(i64, [4 x ppc_fp128], i64) 114 115define i64 @callee_i64(i64 %a, [7 x i64] %b, i64 %c) { 116entry: 117 ret i64 %c 118} 119; CHECK-LABEL: @callee_i64 120; CHECK: ld 3, 96(1) 121; CHECK: blr 122 123define void @caller_i64(i64 %x, [7 x i64] %y) { 124entry: 125 tail call void @test_i64(i64 %x, [7 x i64] %y, i64 %x) 126 ret void 127} 128; CHECK-LABEL: @caller_i64 129; CHECK: std 3, 96(1) 130; CHECK: bl test_i64 131 132declare void @test_i64(i64, [7 x i64], i64) 133 134define i64 @callee_i128(i64 %a, [4 x i128] %b, i64 %c) { 135entry: 136 ret i64 %c 137} 138; CHECK-LABEL: @callee_i128 139; CHECK: ld 3, 112(1) 140; CHECK: blr 141 142define void @caller_i128(i64 %x, [4 x i128] %y) { 143entry: 144 tail call void @test_i128(i64 %x, [4 x i128] %y, i64 %x) 145 ret void 146} 147; CHECK-LABEL: @caller_i128 148; CHECK: std 3, 112(1) 149; CHECK: bl test_i128 150 151declare void @test_i128(i64, [4 x i128], i64) 152 153define i64 @callee_v4i32(i64 %a, [4 x <4 x i32>] %b, i64 %c) { 154entry: 155 ret i64 %c 156} 157; CHECK-LABEL: @callee_v4i32 158; CHECK: ld 3, 112(1) 159; CHECK: blr 160 161define void @caller_v4i32(i64 %x, [4 x <4 x i32>] %y) { 162entry: 163 tail call void @test_v4i32(i64 %x, [4 x <4 x i32>] %y, i64 %x) 164 ret void 165} 166; CHECK-LABEL: @caller_v4i32 167; CHECK: std 3, 112(1) 168; CHECK: bl test_v4i32 169 170declare void @test_v4i32(i64, [4 x <4 x i32>], i64) 171 172 173; 174; Verify handling of floating point arguments in GPRs 175; 176 177%struct.float8 = type { [8 x float] } 178%struct.float5 = type { [5 x float] } 179%struct.float2 = type { [2 x float] } 180 181@g8 = common global %struct.float8 zeroinitializer, align 4 182@g5 = common global %struct.float5 zeroinitializer, align 4 183@g2 = common global %struct.float2 zeroinitializer, align 4 184 185define float @callee0([7 x float] %a, [7 x float] %b) { 186entry: 187 %b.extract = extractvalue [7 x float] %b, 6 188 ret float %b.extract 189} 190; CHECK-LABEL: @callee0 191; CHECK: stw 10, [[OFF:.*]](1) 192; CHECK: lfs 1, [[OFF]](1) 193; CHECK: blr 194 195define void @caller0([7 x float] %a) { 196entry: 197 tail call void @test0([7 x float] %a, [7 x float] %a) 198 ret void 199} 200; CHECK-LABEL: @caller0 201; CHECK-DAG: fmr 8, 1 202; CHECK-DAG: fmr 9, 2 203; CHECK-DAG: fmr 10, 3 204; CHECK-DAG: fmr 11, 4 205; CHECK-DAG: fmr 12, 5 206; CHECK-DAG: fmr 13, 6 207; CHECK-DAG: stfs 7, [[OFF:[0-9]+]](1) 208; CHECK-DAG: lwz 10, [[OFF]](1) 209; CHECK: bl test0 210 211declare void @test0([7 x float], [7 x float]) 212 213define float @callee1([8 x float] %a, [8 x float] %b) { 214entry: 215 %b.extract = extractvalue [8 x float] %b, 7 216 ret float %b.extract 217} 218; CHECK-LABEL: @callee1 219; CHECK: rldicl [[REG:[0-9]+]], 10, 32, 32 220; CHECK: stw [[REG]], [[OFF:.*]](1) 221; CHECK: lfs 1, [[OFF]](1) 222; CHECK: blr 223 224define void @caller1([8 x float] %a) { 225entry: 226 tail call void @test1([8 x float] %a, [8 x float] %a) 227 ret void 228} 229; CHECK-LABEL: @caller1 230; CHECK-DAG: fmr 9, 1 231; CHECK-DAG: fmr 10, 2 232; CHECK-DAG: fmr 11, 3 233; CHECK-DAG: fmr 12, 4 234; CHECK-DAG: fmr 13, 5 235; CHECK-DAG: stfs 5, [[OFF0:[0-9]+]](1) 236; CHECK-DAG: stfs 6, [[OFF1:[0-9]+]](1) 237; CHECK-DAG: stfs 7, [[OFF2:[0-9]+]](1) 238; CHECK-DAG: stfs 8, [[OFF3:[0-9]+]](1) 239; CHECK-DAG: lwz [[REG0:[0-9]+]], [[OFF0]](1) 240; CHECK-DAG: lwz [[REG1:[0-9]+]], [[OFF1]](1) 241; CHECK-DAG: lwz [[REG2:[0-9]+]], [[OFF2]](1) 242; CHECK-DAG: lwz [[REG3:[0-9]+]], [[OFF3]](1) 243; CHECK-DAG: sldi [[REG1]], [[REG1]], 32 244; CHECK-DAG: sldi [[REG3]], [[REG3]], 32 245; CHECK-DAG: or 9, [[REG0]], [[REG1]] 246; CHECK-DAG: or 10, [[REG2]], [[REG3]] 247; CHECK: bl test1 248 249declare void @test1([8 x float], [8 x float]) 250 251define float @callee2([8 x float] %a, [5 x float] %b, [2 x float] %c) { 252entry: 253 %c.extract = extractvalue [2 x float] %c, 1 254 ret float %c.extract 255} 256; CHECK-LABEL: @callee2 257; CHECK: rldicl [[REG:[0-9]+]], 10, 32, 32 258; CHECK: stw [[REG]], [[OFF:.*]](1) 259; CHECK: lfs 1, [[OFF]](1) 260; CHECK: blr 261 262define void @caller2() { 263entry: 264 %0 = load [8 x float], [8 x float]* getelementptr inbounds (%struct.float8, %struct.float8* @g8, i64 0, i32 0), align 4 265 %1 = load [5 x float], [5 x float]* getelementptr inbounds (%struct.float5, %struct.float5* @g5, i64 0, i32 0), align 4 266 %2 = load [2 x float], [2 x float]* getelementptr inbounds (%struct.float2, %struct.float2* @g2, i64 0, i32 0), align 4 267 tail call void @test2([8 x float] %0, [5 x float] %1, [2 x float] %2) 268 ret void 269} 270; CHECK-LABEL: @caller2 271; CHECK: ld {{[0-9]+}}, .LC 272; CHECK-DAG: lfs 1, 0({{[0-9]+}}) 273; CHECK-DAG: lfs 2, 4({{[0-9]+}}) 274; CHECK-DAG: lfs 3, 8({{[0-9]+}}) 275; CHECK-DAG: lfs 4, 12({{[0-9]+}}) 276; CHECK-DAG: lfs 5, 16({{[0-9]+}}) 277; CHECK-DAG: lfs 6, 20({{[0-9]+}}) 278; CHECK-DAG: lfs 7, 24({{[0-9]+}}) 279; CHECK-DAG: lfs 8, 28({{[0-9]+}}) 280 281; CHECK-DAG: lfs 9, 0({{[0-9]+}}) 282; CHECK-DAG: lfs 10, 4({{[0-9]+}}) 283; CHECK-DAG: lfs 11, 8({{[0-9]+}}) 284; CHECK-DAG: lfs 12, 12({{[0-9]+}}) 285; CHECK-DAG: lfs 13, 16({{[0-9]+}}) 286 287; CHECK-DAG: ld 10, 0({{[0-9]+}}) 288; CHECK: bl test2 289 290declare void @test2([8 x float], [5 x float], [2 x float]) 291 292define double @callee3([8 x float] %a, [5 x float] %b, double %c) { 293entry: 294 ret double %c 295} 296; CHECK-LABEL: @callee3 297; CHECK: std 10, [[OFF:.*]](1) 298; CHECK: lfd 1, [[OFF]](1) 299; CHECK: blr 300 301define void @caller3(double %d) { 302entry: 303 %0 = load [8 x float], [8 x float]* getelementptr inbounds (%struct.float8, %struct.float8* @g8, i64 0, i32 0), align 4 304 %1 = load [5 x float], [5 x float]* getelementptr inbounds (%struct.float5, %struct.float5* @g5, i64 0, i32 0), align 4 305 tail call void @test3([8 x float] %0, [5 x float] %1, double %d) 306 ret void 307} 308; CHECK-LABEL: @caller3 309; CHECK: stfd 1, [[OFF:.*]](1) 310; CHECK: ld 10, [[OFF]](1) 311; CHECK: bl test3 312 313declare void @test3([8 x float], [5 x float], double) 314 315define float @callee4([8 x float] %a, [5 x float] %b, float %c) { 316entry: 317 ret float %c 318} 319; CHECK-LABEL: @callee4 320; CHECK: stw 10, [[OFF:.*]](1) 321; CHECK: lfs 1, [[OFF]](1) 322; CHECK: blr 323 324define void @caller4(float %f) { 325entry: 326 %0 = load [8 x float], [8 x float]* getelementptr inbounds (%struct.float8, %struct.float8* @g8, i64 0, i32 0), align 4 327 %1 = load [5 x float], [5 x float]* getelementptr inbounds (%struct.float5, %struct.float5* @g5, i64 0, i32 0), align 4 328 tail call void @test4([8 x float] %0, [5 x float] %1, float %f) 329 ret void 330} 331; CHECK-LABEL: @caller4 332; CHECK: stfs 1, [[OFF:.*]](1) 333; CHECK: lwz 10, [[OFF]](1) 334; CHECK: bl test4 335 336declare void @test4([8 x float], [5 x float], float) 337 338