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