1 ; RUN: llc -mtriple=mips-linux -relocation-model=static < %s | FileCheck -allow-deprecated-dag-overlap --check-prefixes=ALL,O32,O32-BE %s 2 ; RUN: llc -mtriple=mipsel-linux -relocation-model=static < %s | FileCheck -allow-deprecated-dag-overlap --check-prefixes=ALL,O32,O32-LE %s 3 4 ; RUN-TODO: llc -march=mips64 -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s 5 ; RUN-TODO: llc -march=mips64el -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s 6 7 ; RUN: llc -mtriple=mips64-linux -relocation-model=static -target-abi n32 < %s | FileCheck -allow-deprecated-dag-overlap --check-prefixes=ALL,NEW,N32,NEW-BE %s 8 ; RUN: llc -mtriple=mips64el-linux -relocation-model=static -target-abi n32 < %s | FileCheck -allow-deprecated-dag-overlap --check-prefixes=ALL,NEW,N32,NEW-LE %s 9 10 ; RUN: llc -march=mips64 -relocation-model=static -target-abi n64 < %s | FileCheck -allow-deprecated-dag-overlap --check-prefixes=ALL,NEW,N64,NEW-BE %s 11 ; RUN: llc -march=mips64el -relocation-model=static -target-abi n64 < %s | FileCheck -allow-deprecated-dag-overlap --check-prefixes=ALL,NEW,N64,NEW-LE %s 12 13 @hwords = global [3 x i16] zeroinitializer, align 1 14 @words = global [3 x i32] zeroinitializer, align 1 15 @dwords = global [3 x i64] zeroinitializer, align 1 16 17 define void @fn_i16_dotdotdot_i16(i16 %a, ...) { 18 entry: 19 ; ALL-LABEL: fn_i16_dotdotdot_i16: 20 21 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 22 ; the argument save area (56 bytes). 23 ; O32: addiu [[SP:\$sp]], $sp, -8 24 ; N32: addiu [[SP:\$sp]], $sp, -64 25 ; N64: daddiu [[SP:\$sp]], $sp, -64 26 27 ; Save variable argument portion on the stack 28 ; O32-DAG: sw $7, 20([[SP]]) 29 ; O32-DAG: sw $6, 16([[SP]]) 30 ; O32-DAG: sw $5, 12([[SP]]) 31 32 ; NEW-DAG: sd $11, 56([[SP]]) 33 ; NEW-DAG: sd $10, 48([[SP]]) 34 ; NEW-DAG: sd $9, 40([[SP]]) 35 ; NEW-DAG: sd $8, 32([[SP]]) 36 ; NEW-DAG: sd $7, 24([[SP]]) 37 ; NEW-DAG: sd $6, 16([[SP]]) 38 ; NEW-DAG: sd $5, 8([[SP]]) 39 40 ; Initialize variable argument pointer. 41 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 42 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 43 ; fixed argument. 44 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 45 ; space. 46 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 47 ; O32-DAG: sw [[VA]], 0([[SP]]) 48 49 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 50 ; N32-DAG: sw [[VA]], 0([[SP]]) 51 52 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 53 ; N64-DAG: sd [[VA]], 0([[SP]]) 54 55 ; Store [[VA]] 56 ; O32-DAG: sw [[VA]], 0([[SP]]) 57 58 ; ALL: teqi $zero, 1 59 60 ; Increment [[VA]] 61 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 62 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 63 ; O32-DAG: sw [[VA2]], 0([[SP]]) 64 65 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 66 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 67 ; N32-DAG: sw [[VA2]], 0([[SP]]) 68 69 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 70 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 71 ; N64-DAG: sd [[VA2]], 0([[SP]]) 72 73 ; Load the first argument from the variable portion. 74 ; This has used the stack pointer directly rather than the [[VA]] we just set 75 ; up. 76 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 77 ; order. 78 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 79 80 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 81 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 82 83 ; Copy the arg to the global 84 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 85 86 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 87 88 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 89 90 ; ALL-DAG: sh [[ARG1]], 2([[GV]]) 91 92 ; ALL: teqi $zero, 2 93 94 ; Increment [[VA]] again. 95 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 96 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 97 ; O32-DAG: sw [[VA2]], 0([[SP]]) 98 99 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 100 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 101 ; N32-DAG: sw [[VA3]], 0([[SP]]) 102 103 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 104 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 105 ; N64-DAG: sd [[VA3]], 0([[SP]]) 106 107 ; Load the second argument from the variable portion. 108 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 109 110 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 111 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 112 113 ; Copy the arg to the global 114 ; ALL-DAG: sh [[ARG2]], 4([[GV]]) 115 116 %ap = alloca i8*, align 8 117 %ap2 = bitcast i8** %ap to i8* 118 call void @llvm.va_start(i8* %ap2) 119 120 call void asm sideeffect "teqi $$zero, 1", ""() 121 %arg1 = va_arg i8** %ap, i16 122 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 123 store volatile i16 %arg1, i16* %e1, align 2 124 125 call void asm sideeffect "teqi $$zero, 2", ""() 126 %arg2 = va_arg i8** %ap, i16 127 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 128 store volatile i16 %arg2, i16* %e2, align 2 129 130 call void @llvm.va_end(i8* %ap2) 131 132 ret void 133 } 134 135 define void @fn_i16_dotdotdot_i32(i16 %a, ...) { 136 entry: 137 ; ALL-LABEL: fn_i16_dotdotdot_i32: 138 139 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 140 ; the argument save area (56 bytes). 141 ; O32: addiu [[SP:\$sp]], $sp, -8 142 ; N32: addiu [[SP:\$sp]], $sp, -64 143 ; N64: daddiu [[SP:\$sp]], $sp, -64 144 145 ; Save variable argument portion on the stack 146 ; O32-DAG: sw $7, 20([[SP]]) 147 ; O32-DAG: sw $6, 16([[SP]]) 148 ; O32-DAG: sw $5, 12([[SP]]) 149 150 ; NEW-DAG: sd $11, 56([[SP]]) 151 ; NEW-DAG: sd $10, 48([[SP]]) 152 ; NEW-DAG: sd $9, 40([[SP]]) 153 ; NEW-DAG: sd $8, 32([[SP]]) 154 ; NEW-DAG: sd $7, 24([[SP]]) 155 ; NEW-DAG: sd $6, 16([[SP]]) 156 ; NEW-DAG: sd $5, 8([[SP]]) 157 158 ; Initialize variable argument pointer. 159 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 160 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 161 ; fixed argument. 162 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 163 ; space. 164 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 165 ; O32-DAG: sw [[VA]], 0([[SP]]) 166 167 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 168 ; N32-DAG: sw [[VA]], 0([[SP]]) 169 170 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 171 ; N64-DAG: sd [[VA]], 0([[SP]]) 172 173 ; Store [[VA]] 174 ; O32-DAG: sw [[VA]], 0([[SP]]) 175 176 ; ALL: teqi $zero, 1 177 178 ; Increment [[VA]] 179 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 180 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 181 ; O32-DAG: sw [[VA2]], 0([[SP]]) 182 183 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 184 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 185 ; N32-DAG: sw [[VA2]], 0([[SP]]) 186 187 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 188 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 189 ; N64-DAG: sd [[VA2]], 0([[SP]]) 190 191 ; Load the first argument from the variable portion. 192 ; This has used the stack pointer directly rather than the [[VA]] we just set 193 ; up. 194 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 195 ; order. 196 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 197 198 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 199 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 200 201 ; Copy the arg to the global 202 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 203 204 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 205 206 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 207 208 ; ALL-DAG: sw [[ARG1]], 4([[GV]]) 209 210 ; ALL: teqi $zero, 2 211 212 ; Increment [[VA]] again. 213 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 214 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 215 ; O32-DAG: sw [[VA2]], 0([[SP]]) 216 217 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 218 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 219 ; N32-DAG: sw [[VA3]], 0([[SP]]) 220 221 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 222 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 223 ; N64-DAG: sd [[VA3]], 0([[SP]]) 224 225 ; Load the second argument from the variable portion. 226 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 227 228 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 229 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 230 231 ; Copy the arg to the global 232 ; ALL-DAG: sw [[ARG2]], 8([[GV]]) 233 234 %ap = alloca i8*, align 8 235 %ap2 = bitcast i8** %ap to i8* 236 call void @llvm.va_start(i8* %ap2) 237 238 call void asm sideeffect "teqi $$zero, 1", ""() 239 %arg1 = va_arg i8** %ap, i32 240 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 241 store volatile i32 %arg1, i32* %e1, align 4 242 243 call void asm sideeffect "teqi $$zero, 2", ""() 244 %arg2 = va_arg i8** %ap, i32 245 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 246 store volatile i32 %arg2, i32* %e2, align 4 247 248 call void @llvm.va_end(i8* %ap2) 249 250 ret void 251 } 252 253 define void @fn_i16_dotdotdot_i64(i16 %a, ...) { 254 entry: 255 ; ALL-LABEL: fn_i16_dotdotdot_i64: 256 257 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 258 ; the argument save area (56 bytes). 259 ; O32: addiu [[SP:\$sp]], $sp, -8 260 ; N32: addiu [[SP:\$sp]], $sp, -64 261 ; N64: daddiu [[SP:\$sp]], $sp, -64 262 263 ; Save variable argument portion on the stack 264 ; O32-DAG: sw $7, 20([[SP]]) 265 ; O32-DAG: sw $6, 16([[SP]]) 266 ; O32-DAG: sw $5, 12([[SP]]) 267 268 ; NEW-DAG: sd $11, 56([[SP]]) 269 ; NEW-DAG: sd $10, 48([[SP]]) 270 ; NEW-DAG: sd $9, 40([[SP]]) 271 ; NEW-DAG: sd $8, 32([[SP]]) 272 ; NEW-DAG: sd $7, 24([[SP]]) 273 ; NEW-DAG: sd $6, 16([[SP]]) 274 ; NEW-DAG: sd $5, 8([[SP]]) 275 276 ; Initialize variable argument pointer. 277 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 278 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 279 ; fixed argument. 280 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 281 ; space. 282 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 283 ; O32-DAG: sw [[VA]], 0([[SP]]) 284 285 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 286 ; N32-DAG: sw [[VA]], 0([[SP]]) 287 288 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 289 ; N64-DAG: sd [[VA]], 0([[SP]]) 290 291 ; Store [[VA]] 292 ; O32-DAG: sw [[VA]], 0([[SP]]) 293 294 ; ALL: teqi $zero, 1 295 296 ; Increment [[VA]] (and realign pointer for O32) 297 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 298 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 299 ; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 300 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 301 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 302 ; O32-DAG: sw [[VA2]], 0([[SP]]) 303 304 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 305 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 306 ; N32-DAG: sw [[VA2]], 0([[SP]]) 307 308 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 309 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 310 ; N64-DAG: sd [[VA2]], 0([[SP]]) 311 312 ; Load the first argument from the variable portion and copy it to the global. 313 ; This has used the stack pointer directly rather than the [[VA]] we just set 314 ; up. 315 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 316 ; order. 317 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 318 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA_TMP2]]) 319 ; O32-DAG: sw [[ARG1]], 8([[GV]]) 320 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 4 321 ; O32-DAG: sw [[VA3]], 0([[SP]]) 322 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]]) 323 ; O32-DAG: sw [[ARG1]], 12([[GV]]) 324 325 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 326 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 327 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 328 ; NEW-DAG: sd [[ARG1]], 8([[GV]]) 329 330 ; ALL: teqi $zero, 2 331 332 ; Increment [[VA]] again. 333 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 334 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 335 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 336 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 337 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 338 ; O32-DAG: sw [[VA2]], 0([[SP]]) 339 340 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 341 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 342 ; N32-DAG: sw [[VA3]], 0([[SP]]) 343 344 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 345 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 346 ; N64-DAG: sd [[VA3]], 0([[SP]]) 347 348 ; Load the second argument from the variable portion and copy it to the global. 349 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 350 ; O32-DAG: sw [[ARG2]], 16([[GV]]) 351 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 4 352 ; O32-DAG: sw [[VA3]], 0([[SP]]) 353 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA_TMP2]]) 354 ; O32-DAG: sw [[ARG2]], 20([[GV]]) 355 356 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 357 ; NEW-DAG: sd [[ARG2]], 16([[GV]]) 358 359 %ap = alloca i8*, align 8 360 %ap2 = bitcast i8** %ap to i8* 361 call void @llvm.va_start(i8* %ap2) 362 363 call void asm sideeffect "teqi $$zero, 1", ""() 364 %arg1 = va_arg i8** %ap, i64 365 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 366 store volatile i64 %arg1, i64* %e1, align 8 367 368 call void asm sideeffect "teqi $$zero, 2", ""() 369 %arg2 = va_arg i8** %ap, i64 370 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 371 store volatile i64 %arg2, i64* %e2, align 8 372 373 call void @llvm.va_end(i8* %ap2) 374 375 ret void 376 } 377 378 define void @fn_i32_dotdotdot_i16(i32 %a, ...) { 379 entry: 380 ; ALL-LABEL: fn_i32_dotdotdot_i16: 381 382 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 383 ; the argument save area (56 bytes). 384 ; O32: addiu [[SP:\$sp]], $sp, -8 385 ; N32: addiu [[SP:\$sp]], $sp, -64 386 ; N64: daddiu [[SP:\$sp]], $sp, -64 387 388 ; Save variable argument portion on the stack 389 ; O32-DAG: sw $7, 20([[SP]]) 390 ; O32-DAG: sw $6, 16([[SP]]) 391 ; O32-DAG: sw $5, 12([[SP]]) 392 393 ; NEW-DAG: sd $11, 56([[SP]]) 394 ; NEW-DAG: sd $10, 48([[SP]]) 395 ; NEW-DAG: sd $9, 40([[SP]]) 396 ; NEW-DAG: sd $8, 32([[SP]]) 397 ; NEW-DAG: sd $7, 24([[SP]]) 398 ; NEW-DAG: sd $6, 16([[SP]]) 399 ; NEW-DAG: sd $5, 8([[SP]]) 400 401 ; Initialize variable argument pointer. 402 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 403 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 404 ; fixed argument. 405 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 406 ; space. 407 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 408 ; O32-DAG: sw [[VA]], 0([[SP]]) 409 410 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 411 ; N32-DAG: sw [[VA]], 0([[SP]]) 412 413 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 414 ; N64-DAG: sd [[VA]], 0([[SP]]) 415 416 ; Store [[VA]] 417 ; O32-DAG: sw [[VA]], 0([[SP]]) 418 419 ; ALL: teqi $zero, 1 420 421 ; Increment [[VA]] 422 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 423 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 424 ; O32-DAG: sw [[VA2]], 0([[SP]]) 425 426 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 427 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 428 ; N32-DAG: sw [[VA2]], 0([[SP]]) 429 430 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 431 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 432 ; N64-DAG: sd [[VA2]], 0([[SP]]) 433 434 ; Load the first argument from the variable portion. 435 ; This has used the stack pointer directly rather than the [[VA]] we just set 436 ; up. 437 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 438 ; order. 439 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 440 441 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 442 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 443 444 ; Copy the arg to the global 445 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 446 447 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 448 449 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 450 451 ; ALL-DAG: sh [[ARG1]], 2([[GV]]) 452 453 ; ALL: teqi $zero, 2 454 455 ; Increment [[VA]] again. 456 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 457 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 458 ; O32-DAG: sw [[VA2]], 0([[SP]]) 459 460 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 461 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 462 ; N32-DAG: sw [[VA3]], 0([[SP]]) 463 464 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 465 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 466 ; N64-DAG: sd [[VA3]], 0([[SP]]) 467 468 ; Load the second argument from the variable portion. 469 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 470 471 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 472 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 473 474 ; Copy the arg to the global 475 ; ALL-DAG: sh [[ARG2]], 4([[GV]]) 476 477 %ap = alloca i8*, align 8 478 %ap2 = bitcast i8** %ap to i8* 479 call void @llvm.va_start(i8* %ap2) 480 481 call void asm sideeffect "teqi $$zero, 1", ""() 482 %arg1 = va_arg i8** %ap, i16 483 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 484 store volatile i16 %arg1, i16* %e1, align 2 485 486 call void asm sideeffect "teqi $$zero, 2", ""() 487 %arg2 = va_arg i8** %ap, i16 488 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 489 store volatile i16 %arg2, i16* %e2, align 2 490 491 call void @llvm.va_end(i8* %ap2) 492 493 ret void 494 } 495 496 define void @fn_i32_dotdotdot_i32(i32 %a, ...) { 497 entry: 498 ; ALL-LABEL: fn_i32_dotdotdot_i32: 499 500 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 501 ; the argument save area (56 bytes). 502 ; O32: addiu [[SP:\$sp]], $sp, -8 503 ; N32: addiu [[SP:\$sp]], $sp, -64 504 ; N64: daddiu [[SP:\$sp]], $sp, -64 505 506 ; Save variable argument portion on the stack 507 ; O32-DAG: sw $7, 20([[SP]]) 508 ; O32-DAG: sw $6, 16([[SP]]) 509 ; O32-DAG: sw $5, 12([[SP]]) 510 511 ; NEW-DAG: sd $11, 56([[SP]]) 512 ; NEW-DAG: sd $10, 48([[SP]]) 513 ; NEW-DAG: sd $9, 40([[SP]]) 514 ; NEW-DAG: sd $8, 32([[SP]]) 515 ; NEW-DAG: sd $7, 24([[SP]]) 516 ; NEW-DAG: sd $6, 16([[SP]]) 517 ; NEW-DAG: sd $5, 8([[SP]]) 518 519 ; Initialize variable argument pointer. 520 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 521 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 522 ; fixed argument. 523 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 524 ; space. 525 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 526 ; O32-DAG: sw [[VA]], 0([[SP]]) 527 528 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 529 ; N32-DAG: sw [[VA]], 0([[SP]]) 530 531 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 532 ; N64-DAG: sd [[VA]], 0([[SP]]) 533 534 ; Store [[VA]] 535 ; O32-DAG: sw [[VA]], 0([[SP]]) 536 537 ; ALL: teqi $zero, 1 538 539 ; Increment [[VA]] 540 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 541 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 542 ; O32-DAG: sw [[VA2]], 0([[SP]]) 543 544 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 545 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 546 ; N32-DAG: sw [[VA2]], 0([[SP]]) 547 548 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 549 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 550 ; N64-DAG: sd [[VA2]], 0([[SP]]) 551 552 ; Load the first argument from the variable portion. 553 ; This has used the stack pointer directly rather than the [[VA]] we just set 554 ; up. 555 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 556 ; order. 557 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 558 559 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 560 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 561 562 ; Copy the arg to the global 563 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 564 565 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 566 567 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 568 569 ; ALL-DAG: sw [[ARG1]], 4([[GV]]) 570 571 ; ALL: teqi $zero, 2 572 573 ; Increment [[VA]] again. 574 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 575 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 576 ; O32-DAG: sw [[VA2]], 0([[SP]]) 577 578 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 579 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 580 ; N32-DAG: sw [[VA3]], 0([[SP]]) 581 582 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 583 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 584 ; N64-DAG: sd [[VA3]], 0([[SP]]) 585 586 ; Load the second argument from the variable portion. 587 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 588 589 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 590 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 591 592 ; Copy the arg to the global 593 ; ALL-DAG: sw [[ARG2]], 8([[GV]]) 594 595 %ap = alloca i8*, align 8 596 %ap2 = bitcast i8** %ap to i8* 597 call void @llvm.va_start(i8* %ap2) 598 599 call void asm sideeffect "teqi $$zero, 1", ""() 600 %arg1 = va_arg i8** %ap, i32 601 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 602 store volatile i32 %arg1, i32* %e1, align 4 603 604 call void asm sideeffect "teqi $$zero, 2", ""() 605 %arg2 = va_arg i8** %ap, i32 606 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 607 store volatile i32 %arg2, i32* %e2, align 4 608 609 call void @llvm.va_end(i8* %ap2) 610 611 ret void 612 } 613 614 define void @fn_i32_dotdotdot_i64(i32 %a, ...) { 615 entry: 616 ; ALL-LABEL: fn_i32_dotdotdot_i64: 617 618 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 619 ; the argument save area (56 bytes). 620 ; O32: addiu [[SP:\$sp]], $sp, -8 621 ; N32: addiu [[SP:\$sp]], $sp, -64 622 ; N64: daddiu [[SP:\$sp]], $sp, -64 623 624 ; Save variable argument portion on the stack 625 ; O32-DAG: sw $7, 20([[SP]]) 626 ; O32-DAG: sw $6, 16([[SP]]) 627 ; O32-DAG: sw $5, 12([[SP]]) 628 629 ; NEW-DAG: sd $11, 56([[SP]]) 630 ; NEW-DAG: sd $10, 48([[SP]]) 631 ; NEW-DAG: sd $9, 40([[SP]]) 632 ; NEW-DAG: sd $8, 32([[SP]]) 633 ; NEW-DAG: sd $7, 24([[SP]]) 634 ; NEW-DAG: sd $6, 16([[SP]]) 635 ; NEW-DAG: sd $5, 8([[SP]]) 636 637 ; Initialize variable argument pointer. 638 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 639 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 640 ; fixed argument. 641 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 642 ; space. 643 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 644 ; O32-DAG: sw [[VA]], 0([[SP]]) 645 646 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 647 ; N32-DAG: sw [[VA]], 0([[SP]]) 648 649 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 650 ; N64-DAG: sd [[VA]], 0([[SP]]) 651 652 ; Store [[VA]] 653 ; O32-DAG: sw [[VA]], 0([[SP]]) 654 655 ; ALL: teqi $zero, 1 656 657 ; Increment [[VA]] (and realign pointer for O32) 658 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 659 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 660 ; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 661 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 662 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 663 ; O32-DAG: sw [[VA2]], 0([[SP]]) 664 665 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 666 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 667 ; N32-DAG: sw [[VA2]], 0([[SP]]) 668 669 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 670 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 671 ; N64-DAG: sd [[VA2]], 0([[SP]]) 672 673 ; Load the first argument from the variable portion and copy it to the global. 674 ; This has used the stack pointer directly rather than the [[VA]] we just set 675 ; up. 676 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 677 ; order. 678 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 679 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA_TMP2]]) 680 ; O32-DAG: sw [[ARG1]], 8([[GV]]) 681 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 4 682 ; O32-DAG: sw [[VA3]], 0([[SP]]) 683 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]]) 684 ; O32-DAG: sw [[ARG1]], 12([[GV]]) 685 686 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 687 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 688 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 689 ; NEW-DAG: sd [[ARG1]], 8([[GV]]) 690 691 ; ALL: teqi $zero, 2 692 693 ; Increment [[VA]] again. 694 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 695 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 696 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 697 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 698 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 699 ; O32-DAG: sw [[VA2]], 0([[SP]]) 700 701 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 702 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 703 ; N32-DAG: sw [[VA3]], 0([[SP]]) 704 705 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 706 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 707 ; N64-DAG: sd [[VA3]], 0([[SP]]) 708 709 ; Load the second argument from the variable portion and copy it to the global. 710 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 711 ; O32-DAG: sw [[ARG2]], 16([[GV]]) 712 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 4 713 ; O32-DAG: sw [[VA2]], 0([[SP]]) 714 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA_TMP2]]) 715 ; O32-DAG: sw [[ARG2]], 20([[GV]]) 716 717 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 718 ; NEW-DAG: sd [[ARG2]], 16([[GV]]) 719 720 %ap = alloca i8*, align 8 721 %ap2 = bitcast i8** %ap to i8* 722 call void @llvm.va_start(i8* %ap2) 723 724 call void asm sideeffect "teqi $$zero, 1", ""() 725 %arg1 = va_arg i8** %ap, i64 726 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 727 store volatile i64 %arg1, i64* %e1, align 8 728 729 call void asm sideeffect "teqi $$zero, 2", ""() 730 %arg2 = va_arg i8** %ap, i64 731 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 732 store volatile i64 %arg2, i64* %e2, align 8 733 734 call void @llvm.va_end(i8* %ap2) 735 736 ret void 737 } 738 739 define void @fn_i64_dotdotdot_i16(i64 %a, ...) { 740 entry: 741 ; ALL-LABEL: fn_i64_dotdotdot_i16: 742 743 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 744 ; the argument save area (56 bytes). 745 ; O32: addiu [[SP:\$sp]], $sp, -8 746 ; N32: addiu [[SP:\$sp]], $sp, -64 747 ; N64: daddiu [[SP:\$sp]], $sp, -64 748 749 ; Save variable argument portion on the stack 750 ; O32-DAG: sw $7, 20([[SP]]) 751 ; O32-DAG: sw $6, 16([[SP]]) 752 753 ; NEW-DAG: sd $11, 56([[SP]]) 754 ; NEW-DAG: sd $10, 48([[SP]]) 755 ; NEW-DAG: sd $9, 40([[SP]]) 756 ; NEW-DAG: sd $8, 32([[SP]]) 757 ; NEW-DAG: sd $7, 24([[SP]]) 758 ; NEW-DAG: sd $6, 16([[SP]]) 759 ; NEW-DAG: sd $5, 8([[SP]]) 760 761 ; Initialize variable argument pointer. 762 ; For O32, the offset is 16 due to the 4 bytes used to store local variables, 763 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 764 ; first fixed argument. 765 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 766 ; space. 767 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 768 ; O32-DAG: sw [[VA]], 0([[SP]]) 769 770 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 771 ; N32-DAG: sw [[VA]], 0([[SP]]) 772 773 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 774 ; N64-DAG: sd [[VA]], 0([[SP]]) 775 776 ; Store [[VA]] 777 ; O32-DAG: sw [[VA]], 0([[SP]]) 778 779 ; ALL: teqi $zero, 1 780 781 ; Increment [[VA]] 782 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 783 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 784 ; O32-DAG: sw [[VA2]], 0([[SP]]) 785 786 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 787 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 788 ; N32-DAG: sw [[VA2]], 0([[SP]]) 789 790 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 791 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 792 ; N64-DAG: sd [[VA2]], 0([[SP]]) 793 794 ; Load the first argument from the variable portion. 795 ; This has used the stack pointer directly rather than the [[VA]] we just set 796 ; up. 797 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 798 ; order. 799 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 800 801 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 802 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 803 804 ; Copy the arg to the global 805 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 806 807 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 808 809 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 810 811 ; ALL-DAG: sh [[ARG1]], 2([[GV]]) 812 813 ; ALL: teqi $zero, 2 814 815 ; Increment [[VA]] again. 816 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 817 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 818 ; O32-DAG: sw [[VA2]], 0([[SP]]) 819 820 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 821 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 822 ; N32-DAG: sw [[VA3]], 0([[SP]]) 823 824 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 825 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 826 ; N64-DAG: sd [[VA3]], 0([[SP]]) 827 828 ; Load the second argument from the variable portion. 829 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 830 831 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 832 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 833 834 ; Copy the arg to the global 835 ; ALL-DAG: sh [[ARG2]], 4([[GV]]) 836 837 %ap = alloca i8*, align 8 838 %ap2 = bitcast i8** %ap to i8* 839 call void @llvm.va_start(i8* %ap2) 840 841 call void asm sideeffect "teqi $$zero, 1", ""() 842 %arg1 = va_arg i8** %ap, i16 843 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 844 store volatile i16 %arg1, i16* %e1, align 2 845 846 call void asm sideeffect "teqi $$zero, 2", ""() 847 %arg2 = va_arg i8** %ap, i16 848 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 849 store volatile i16 %arg2, i16* %e2, align 2 850 851 call void @llvm.va_end(i8* %ap2) 852 853 ret void 854 } 855 856 define void @fn_i64_dotdotdot_i32(i64 %a, ...) { 857 entry: 858 ; ALL-LABEL: fn_i64_dotdotdot_i32: 859 860 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 861 ; the argument save area (56 bytes). 862 ; O32: addiu [[SP:\$sp]], $sp, -8 863 ; N32: addiu [[SP:\$sp]], $sp, -64 864 ; N64: daddiu [[SP:\$sp]], $sp, -64 865 866 ; Save variable argument portion on the stack 867 ; O32-DAG: sw $7, 20([[SP]]) 868 ; O32-DAG: sw $6, 16([[SP]]) 869 870 ; NEW-DAG: sd $11, 56([[SP]]) 871 ; NEW-DAG: sd $10, 48([[SP]]) 872 ; NEW-DAG: sd $9, 40([[SP]]) 873 ; NEW-DAG: sd $8, 32([[SP]]) 874 ; NEW-DAG: sd $7, 24([[SP]]) 875 ; NEW-DAG: sd $6, 16([[SP]]) 876 ; NEW-DAG: sd $5, 8([[SP]]) 877 878 ; Initialize variable argument pointer. 879 ; For O32, the offset is 16 due to the 4 bytes used to store local variables, 880 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 881 ; first fixed argument. 882 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 883 ; space. 884 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 885 ; O32-DAG: sw [[VA]], 0([[SP]]) 886 887 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 888 ; N32-DAG: sw [[VA]], 0([[SP]]) 889 890 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 891 ; N64-DAG: sd [[VA]], 0([[SP]]) 892 893 ; Store [[VA]] 894 ; O32-DAG: sw [[VA]], 0([[SP]]) 895 896 ; ALL: teqi $zero, 1 897 898 ; Increment [[VA]] 899 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 900 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 901 ; O32-DAG: sw [[VA2]], 0([[SP]]) 902 903 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 904 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 905 ; N32-DAG: sw [[VA2]], 0([[SP]]) 906 907 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 908 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 909 ; N64-DAG: sd [[VA2]], 0([[SP]]) 910 911 ; Load the first argument from the variable portion. 912 ; This has used the stack pointer directly rather than the [[VA]] we just set 913 ; up. 914 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 915 ; order. 916 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 917 918 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 919 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 920 921 ; Copy the arg to the global 922 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 923 924 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 925 926 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 927 928 ; ALL-DAG: sw [[ARG1]], 4([[GV]]) 929 930 ; ALL: teqi $zero, 2 931 932 ; Increment [[VA]] again. 933 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 934 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 935 ; O32-DAG: sw [[VA2]], 0([[SP]]) 936 937 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 938 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 939 ; N32-DAG: sw [[VA3]], 0([[SP]]) 940 941 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 942 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 943 ; N64-DAG: sd [[VA3]], 0([[SP]]) 944 945 ; Load the second argument from the variable portion. 946 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 947 948 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 949 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 950 951 ; Copy the arg to the global 952 ; ALL-DAG: sw [[ARG2]], 8([[GV]]) 953 954 %ap = alloca i8*, align 8 955 %ap2 = bitcast i8** %ap to i8* 956 call void @llvm.va_start(i8* %ap2) 957 958 call void asm sideeffect "teqi $$zero, 1", ""() 959 %arg1 = va_arg i8** %ap, i32 960 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 961 store volatile i32 %arg1, i32* %e1, align 4 962 963 call void asm sideeffect "teqi $$zero, 2", ""() 964 %arg2 = va_arg i8** %ap, i32 965 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 966 store volatile i32 %arg2, i32* %e2, align 4 967 968 call void @llvm.va_end(i8* %ap2) 969 970 ret void 971 } 972 973 define void @fn_i64_dotdotdot_i64(i64 %a, ...) { 974 entry: 975 ; ALL-LABEL: fn_i64_dotdotdot_i64: 976 977 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 978 ; the argument save area (56 bytes). 979 ; O32: addiu [[SP:\$sp]], $sp, -8 980 ; N32: addiu [[SP:\$sp]], $sp, -64 981 ; N64: daddiu [[SP:\$sp]], $sp, -64 982 983 ; Save variable argument portion on the stack 984 ; O32-DAG: sw $7, 20([[SP]]) 985 ; O32-DAG: sw $6, 16([[SP]]) 986 987 ; NEW-DAG: sd $11, 56([[SP]]) 988 ; NEW-DAG: sd $10, 48([[SP]]) 989 ; NEW-DAG: sd $9, 40([[SP]]) 990 ; NEW-DAG: sd $8, 32([[SP]]) 991 ; NEW-DAG: sd $7, 24([[SP]]) 992 ; NEW-DAG: sd $6, 16([[SP]]) 993 ; NEW-DAG: sd $5, 8([[SP]]) 994 995 ; Initialize variable argument pointer. 996 ; For O32, the offset is 16 due to the 4 bytes used to store local variables, 997 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 998 ; first fixed argument. 999 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 1000 ; space. 1001 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 1002 ; O32-DAG: sw [[VA]], 0([[SP]]) 1003 1004 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 1005 ; N32-DAG: sw [[VA]], 0([[SP]]) 1006 1007 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 1008 ; N64-DAG: sd [[VA]], 0([[SP]]) 1009 1010 ; Store [[VA]] 1011 ; O32-DAG: sw [[VA]], 0([[SP]]) 1012 1013 ; ALL: teqi $zero, 1 1014 1015 ; Increment [[VA]] (and realign pointer for O32) 1016 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 1017 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 1018 ; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 1019 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 1020 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 1021 ; O32-DAG: sw [[VA2]], 0([[SP]]) 1022 1023 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 1024 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 1025 ; N32-DAG: sw [[VA2]], 0([[SP]]) 1026 1027 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 1028 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 1029 ; N64-DAG: sd [[VA2]], 0([[SP]]) 1030 1031 ; Load the first argument from the variable portion and copy it to the global. 1032 ; This has used the stack pointer directly rather than the [[VA]] we just set 1033 ; up. 1034 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 1035 ; order. 1036 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1037 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 1038 ; O32-DAG: sw [[ARG1]], 8([[GV]]) 1039 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 4 1040 ; O32-DAG: sw [[VA3]], 0([[SP]]) 1041 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]]) 1042 ; O32-DAG: sw [[ARG1]], 12([[GV]]) 1043 1044 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1045 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1046 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 1047 ; NEW-DAG: sd [[ARG1]], 8([[GV]]) 1048 1049 ; ALL: teqi $zero, 2 1050 1051 ; Increment [[VA]] again. 1052 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 1053 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 1054 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 1055 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 1056 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 1057 ; O32-DAG: sw [[VA2]], 0([[SP]]) 1058 1059 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 1060 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 1061 ; N32-DAG: sw [[VA3]], 0([[SP]]) 1062 1063 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 1064 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 1065 ; N64-DAG: sd [[VA3]], 0([[SP]]) 1066 1067 ; Load the second argument from the variable portion and copy it to the global. 1068 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 1069 ; O32-DAG: sw [[ARG2]], 16([[GV]]) 1070 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 4 1071 ; O32-DAG: sw [[VA3]], 0([[SP]]) 1072 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA_TMP2]]) 1073 ; O32-DAG: sw [[ARG2]], 20([[GV]]) 1074 1075 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 1076 ; NEW-DAG: sd [[ARG2]], 16([[GV]]) 1077 1078 %ap = alloca i8*, align 8 1079 %ap2 = bitcast i8** %ap to i8* 1080 call void @llvm.va_start(i8* %ap2) 1081 1082 call void asm sideeffect "teqi $$zero, 1", ""() 1083 %arg1 = va_arg i8** %ap, i64 1084 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 1085 store volatile i64 %arg1, i64* %e1, align 8 1086 1087 call void asm sideeffect "teqi $$zero, 2", ""() 1088 %arg2 = va_arg i8** %ap, i64 1089 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 1090 store volatile i64 %arg2, i64* %e2, align 8 1091 1092 call void @llvm.va_end(i8* %ap2) 1093 1094 ret void 1095 } 1096 1097 declare void @llvm.va_start(i8*) 1098 declare void @llvm.va_end(i8*) 1099