1 ; RUN: llc -mtriple=mips-linux -relocation-model=static < %s | FileCheck --check-prefixes=ALL,O32,O32-BE %s 2 ; RUN: llc -mtriple=mipsel-linux -relocation-model=static < %s | FileCheck --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 --check-prefixes=ALL,NEW,N32,NEW-BE %s 8 ; RUN: llc -mtriple=mips64el-linux -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,NEW,N32,NEW-LE %s 9 10 ; RUN: llc -march=mips64 -relocation-model=static -target-abi n64 < %s | FileCheck --check-prefixes=ALL,NEW,N64,NEW-BE %s 11 ; RUN: llc -march=mips64el -relocation-model=static -target-abi n64 < %s | FileCheck --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: ld [[GV:\$[0-9]+]], %got_disp(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: ld [[GV:\$[0-9]+]], %got_disp(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]]) 319 ; O32-DAG: sw [[ARG1]], 8([[GV]]) 320 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 321 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 322 ; O32-DAG: sw [[VA2]], 0([[SP]]) 323 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 324 ; O32-DAG: sw [[ARG1]], 12([[GV]]) 325 326 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 327 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( 328 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 329 ; NEW-DAG: sd [[ARG1]], 8([[GV]]) 330 331 ; ALL: teqi $zero, 2 332 333 ; Increment [[VA]] again. 334 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 335 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 336 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 337 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 338 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 339 ; O32-DAG: sw [[VA2]], 0([[SP]]) 340 341 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 342 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 343 ; N32-DAG: sw [[VA3]], 0([[SP]]) 344 345 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 346 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 347 ; N64-DAG: sd [[VA3]], 0([[SP]]) 348 349 ; Load the second argument from the variable portion and copy it to the global. 350 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 351 ; O32-DAG: sw [[ARG2]], 16([[GV]]) 352 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 353 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 354 ; O32-DAG: sw [[VA2]], 0([[SP]]) 355 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 356 ; O32-DAG: sw [[ARG2]], 20([[GV]]) 357 358 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 359 ; NEW-DAG: sd [[ARG2]], 16([[GV]]) 360 361 %ap = alloca i8*, align 8 362 %ap2 = bitcast i8** %ap to i8* 363 call void @llvm.va_start(i8* %ap2) 364 365 call void asm sideeffect "teqi $$zero, 1", ""() 366 %arg1 = va_arg i8** %ap, i64 367 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 368 store volatile i64 %arg1, i64* %e1, align 8 369 370 call void asm sideeffect "teqi $$zero, 2", ""() 371 %arg2 = va_arg i8** %ap, i64 372 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 373 store volatile i64 %arg2, i64* %e2, align 8 374 375 call void @llvm.va_end(i8* %ap2) 376 377 ret void 378 } 379 380 define void @fn_i32_dotdotdot_i16(i32 %a, ...) { 381 entry: 382 ; ALL-LABEL: fn_i32_dotdotdot_i16: 383 384 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 385 ; the argument save area (56 bytes). 386 ; O32: addiu [[SP:\$sp]], $sp, -8 387 ; N32: addiu [[SP:\$sp]], $sp, -64 388 ; N64: daddiu [[SP:\$sp]], $sp, -64 389 390 ; Save variable argument portion on the stack 391 ; O32-DAG: sw $7, 20([[SP]]) 392 ; O32-DAG: sw $6, 16([[SP]]) 393 ; O32-DAG: sw $5, 12([[SP]]) 394 395 ; NEW-DAG: sd $11, 56([[SP]]) 396 ; NEW-DAG: sd $10, 48([[SP]]) 397 ; NEW-DAG: sd $9, 40([[SP]]) 398 ; NEW-DAG: sd $8, 32([[SP]]) 399 ; NEW-DAG: sd $7, 24([[SP]]) 400 ; NEW-DAG: sd $6, 16([[SP]]) 401 ; NEW-DAG: sd $5, 8([[SP]]) 402 403 ; Initialize variable argument pointer. 404 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 405 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 406 ; fixed argument. 407 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 408 ; space. 409 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 410 ; O32-DAG: sw [[VA]], 0([[SP]]) 411 412 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 413 ; N32-DAG: sw [[VA]], 0([[SP]]) 414 415 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 416 ; N64-DAG: sd [[VA]], 0([[SP]]) 417 418 ; Store [[VA]] 419 ; O32-DAG: sw [[VA]], 0([[SP]]) 420 421 ; ALL: teqi $zero, 1 422 423 ; Increment [[VA]] 424 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 425 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 426 ; O32-DAG: sw [[VA2]], 0([[SP]]) 427 428 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 429 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 430 ; N32-DAG: sw [[VA2]], 0([[SP]]) 431 432 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 433 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 434 ; N64-DAG: sd [[VA2]], 0([[SP]]) 435 436 ; Load the first argument from the variable portion. 437 ; This has used the stack pointer directly rather than the [[VA]] we just set 438 ; up. 439 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 440 ; order. 441 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 442 443 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 444 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 445 446 ; Copy the arg to the global 447 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 448 449 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 450 451 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)( 452 453 ; ALL-DAG: sh [[ARG1]], 2([[GV]]) 454 455 ; ALL: teqi $zero, 2 456 457 ; Increment [[VA]] again. 458 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 459 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 460 ; O32-DAG: sw [[VA2]], 0([[SP]]) 461 462 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 463 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 464 ; N32-DAG: sw [[VA3]], 0([[SP]]) 465 466 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 467 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 468 ; N64-DAG: sd [[VA3]], 0([[SP]]) 469 470 ; Load the second argument from the variable portion. 471 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 472 473 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 474 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 475 476 ; Copy the arg to the global 477 ; ALL-DAG: sh [[ARG2]], 4([[GV]]) 478 479 %ap = alloca i8*, align 8 480 %ap2 = bitcast i8** %ap to i8* 481 call void @llvm.va_start(i8* %ap2) 482 483 call void asm sideeffect "teqi $$zero, 1", ""() 484 %arg1 = va_arg i8** %ap, i16 485 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 486 store volatile i16 %arg1, i16* %e1, align 2 487 488 call void asm sideeffect "teqi $$zero, 2", ""() 489 %arg2 = va_arg i8** %ap, i16 490 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 491 store volatile i16 %arg2, i16* %e2, align 2 492 493 call void @llvm.va_end(i8* %ap2) 494 495 ret void 496 } 497 498 define void @fn_i32_dotdotdot_i32(i32 %a, ...) { 499 entry: 500 ; ALL-LABEL: fn_i32_dotdotdot_i32: 501 502 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 503 ; the argument save area (56 bytes). 504 ; O32: addiu [[SP:\$sp]], $sp, -8 505 ; N32: addiu [[SP:\$sp]], $sp, -64 506 ; N64: daddiu [[SP:\$sp]], $sp, -64 507 508 ; Save variable argument portion on the stack 509 ; O32-DAG: sw $7, 20([[SP]]) 510 ; O32-DAG: sw $6, 16([[SP]]) 511 ; O32-DAG: sw $5, 12([[SP]]) 512 513 ; NEW-DAG: sd $11, 56([[SP]]) 514 ; NEW-DAG: sd $10, 48([[SP]]) 515 ; NEW-DAG: sd $9, 40([[SP]]) 516 ; NEW-DAG: sd $8, 32([[SP]]) 517 ; NEW-DAG: sd $7, 24([[SP]]) 518 ; NEW-DAG: sd $6, 16([[SP]]) 519 ; NEW-DAG: sd $5, 8([[SP]]) 520 521 ; Initialize variable argument pointer. 522 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 523 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 524 ; fixed argument. 525 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 526 ; space. 527 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 528 ; O32-DAG: sw [[VA]], 0([[SP]]) 529 530 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 531 ; N32-DAG: sw [[VA]], 0([[SP]]) 532 533 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 534 ; N64-DAG: sd [[VA]], 0([[SP]]) 535 536 ; Store [[VA]] 537 ; O32-DAG: sw [[VA]], 0([[SP]]) 538 539 ; ALL: teqi $zero, 1 540 541 ; Increment [[VA]] 542 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 543 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 544 ; O32-DAG: sw [[VA2]], 0([[SP]]) 545 546 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 547 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 548 ; N32-DAG: sw [[VA2]], 0([[SP]]) 549 550 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 551 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 552 ; N64-DAG: sd [[VA2]], 0([[SP]]) 553 554 ; Load the first argument from the variable portion. 555 ; This has used the stack pointer directly rather than the [[VA]] we just set 556 ; up. 557 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 558 ; order. 559 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 560 561 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 562 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 563 564 ; Copy the arg to the global 565 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 566 567 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 568 569 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)( 570 571 ; ALL-DAG: sw [[ARG1]], 4([[GV]]) 572 573 ; ALL: teqi $zero, 2 574 575 ; Increment [[VA]] again. 576 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 577 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 578 ; O32-DAG: sw [[VA2]], 0([[SP]]) 579 580 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 581 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 582 ; N32-DAG: sw [[VA3]], 0([[SP]]) 583 584 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 585 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 586 ; N64-DAG: sd [[VA3]], 0([[SP]]) 587 588 ; Load the second argument from the variable portion. 589 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 590 591 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 592 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 593 594 ; Copy the arg to the global 595 ; ALL-DAG: sw [[ARG2]], 8([[GV]]) 596 597 %ap = alloca i8*, align 8 598 %ap2 = bitcast i8** %ap to i8* 599 call void @llvm.va_start(i8* %ap2) 600 601 call void asm sideeffect "teqi $$zero, 1", ""() 602 %arg1 = va_arg i8** %ap, i32 603 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 604 store volatile i32 %arg1, i32* %e1, align 4 605 606 call void asm sideeffect "teqi $$zero, 2", ""() 607 %arg2 = va_arg i8** %ap, i32 608 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 609 store volatile i32 %arg2, i32* %e2, align 4 610 611 call void @llvm.va_end(i8* %ap2) 612 613 ret void 614 } 615 616 define void @fn_i32_dotdotdot_i64(i32 %a, ...) { 617 entry: 618 ; ALL-LABEL: fn_i32_dotdotdot_i64: 619 620 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 621 ; the argument save area (56 bytes). 622 ; O32: addiu [[SP:\$sp]], $sp, -8 623 ; N32: addiu [[SP:\$sp]], $sp, -64 624 ; N64: daddiu [[SP:\$sp]], $sp, -64 625 626 ; Save variable argument portion on the stack 627 ; O32-DAG: sw $7, 20([[SP]]) 628 ; O32-DAG: sw $6, 16([[SP]]) 629 ; O32-DAG: sw $5, 12([[SP]]) 630 631 ; NEW-DAG: sd $11, 56([[SP]]) 632 ; NEW-DAG: sd $10, 48([[SP]]) 633 ; NEW-DAG: sd $9, 40([[SP]]) 634 ; NEW-DAG: sd $8, 32([[SP]]) 635 ; NEW-DAG: sd $7, 24([[SP]]) 636 ; NEW-DAG: sd $6, 16([[SP]]) 637 ; NEW-DAG: sd $5, 8([[SP]]) 638 639 ; Initialize variable argument pointer. 640 ; For O32, the offset is 12 due to the 4 bytes used to store local variables, 641 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 642 ; fixed argument. 643 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 644 ; space. 645 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 646 ; O32-DAG: sw [[VA]], 0([[SP]]) 647 648 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 649 ; N32-DAG: sw [[VA]], 0([[SP]]) 650 651 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 652 ; N64-DAG: sd [[VA]], 0([[SP]]) 653 654 ; Store [[VA]] 655 ; O32-DAG: sw [[VA]], 0([[SP]]) 656 657 ; ALL: teqi $zero, 1 658 659 ; Increment [[VA]] (and realign pointer for O32) 660 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 661 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 662 ; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 663 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 664 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 665 ; O32-DAG: sw [[VA2]], 0([[SP]]) 666 667 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 668 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 669 ; N32-DAG: sw [[VA2]], 0([[SP]]) 670 671 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 672 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 673 ; N64-DAG: sd [[VA2]], 0([[SP]]) 674 675 ; Load the first argument from the variable portion and copy it to the global. 676 ; This has used the stack pointer directly rather than the [[VA]] we just set 677 ; up. 678 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 679 ; order. 680 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 681 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 682 ; O32-DAG: sw [[ARG1]], 8([[GV]]) 683 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 684 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 685 ; O32-DAG: sw [[VA2]], 0([[SP]]) 686 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 687 ; O32-DAG: sw [[ARG1]], 12([[GV]]) 688 689 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 690 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( 691 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 692 ; NEW-DAG: sd [[ARG1]], 8([[GV]]) 693 694 ; ALL: teqi $zero, 2 695 696 ; Increment [[VA]] again. 697 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 698 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 699 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 700 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 701 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 702 ; O32-DAG: sw [[VA2]], 0([[SP]]) 703 704 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 705 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 706 ; N32-DAG: sw [[VA3]], 0([[SP]]) 707 708 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 709 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 710 ; N64-DAG: sd [[VA3]], 0([[SP]]) 711 712 ; Load the second argument from the variable portion and copy it to the global. 713 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 714 ; O32-DAG: sw [[ARG2]], 16([[GV]]) 715 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 716 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 717 ; O32-DAG: sw [[VA2]], 0([[SP]]) 718 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 719 ; O32-DAG: sw [[ARG2]], 20([[GV]]) 720 721 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 722 ; NEW-DAG: sd [[ARG2]], 16([[GV]]) 723 724 %ap = alloca i8*, align 8 725 %ap2 = bitcast i8** %ap to i8* 726 call void @llvm.va_start(i8* %ap2) 727 728 call void asm sideeffect "teqi $$zero, 1", ""() 729 %arg1 = va_arg i8** %ap, i64 730 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 731 store volatile i64 %arg1, i64* %e1, align 8 732 733 call void asm sideeffect "teqi $$zero, 2", ""() 734 %arg2 = va_arg i8** %ap, i64 735 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 736 store volatile i64 %arg2, i64* %e2, align 8 737 738 call void @llvm.va_end(i8* %ap2) 739 740 ret void 741 } 742 743 define void @fn_i64_dotdotdot_i16(i64 %a, ...) { 744 entry: 745 ; ALL-LABEL: fn_i64_dotdotdot_i16: 746 747 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 748 ; the argument save area (56 bytes). 749 ; O32: addiu [[SP:\$sp]], $sp, -8 750 ; N32: addiu [[SP:\$sp]], $sp, -64 751 ; N64: daddiu [[SP:\$sp]], $sp, -64 752 753 ; Save variable argument portion on the stack 754 ; O32-DAG: sw $7, 20([[SP]]) 755 ; O32-DAG: sw $6, 16([[SP]]) 756 757 ; NEW-DAG: sd $11, 56([[SP]]) 758 ; NEW-DAG: sd $10, 48([[SP]]) 759 ; NEW-DAG: sd $9, 40([[SP]]) 760 ; NEW-DAG: sd $8, 32([[SP]]) 761 ; NEW-DAG: sd $7, 24([[SP]]) 762 ; NEW-DAG: sd $6, 16([[SP]]) 763 ; NEW-DAG: sd $5, 8([[SP]]) 764 765 ; Initialize variable argument pointer. 766 ; For O32, the offset is 16 due to the 4 bytes used to store local variables, 767 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 768 ; first fixed argument. 769 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 770 ; space. 771 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 772 ; O32-DAG: sw [[VA]], 0([[SP]]) 773 774 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 775 ; N32-DAG: sw [[VA]], 0([[SP]]) 776 777 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 778 ; N64-DAG: sd [[VA]], 0([[SP]]) 779 780 ; Store [[VA]] 781 ; O32-DAG: sw [[VA]], 0([[SP]]) 782 783 ; ALL: teqi $zero, 1 784 785 ; Increment [[VA]] 786 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 787 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 788 ; O32-DAG: sw [[VA2]], 0([[SP]]) 789 790 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 791 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 792 ; N32-DAG: sw [[VA2]], 0([[SP]]) 793 794 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 795 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 796 ; N64-DAG: sd [[VA2]], 0([[SP]]) 797 798 ; Load the first argument from the variable portion. 799 ; This has used the stack pointer directly rather than the [[VA]] we just set 800 ; up. 801 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 802 ; order. 803 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 804 805 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 806 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 807 808 ; Copy the arg to the global 809 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 810 811 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 812 813 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)( 814 815 ; ALL-DAG: sh [[ARG1]], 2([[GV]]) 816 817 ; ALL: teqi $zero, 2 818 819 ; Increment [[VA]] again. 820 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 821 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 822 ; O32-DAG: sw [[VA2]], 0([[SP]]) 823 824 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 825 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 826 ; N32-DAG: sw [[VA3]], 0([[SP]]) 827 828 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 829 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 830 ; N64-DAG: sd [[VA3]], 0([[SP]]) 831 832 ; Load the second argument from the variable portion. 833 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 834 835 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 836 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 837 838 ; Copy the arg to the global 839 ; ALL-DAG: sh [[ARG2]], 4([[GV]]) 840 841 %ap = alloca i8*, align 8 842 %ap2 = bitcast i8** %ap to i8* 843 call void @llvm.va_start(i8* %ap2) 844 845 call void asm sideeffect "teqi $$zero, 1", ""() 846 %arg1 = va_arg i8** %ap, i16 847 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 848 store volatile i16 %arg1, i16* %e1, align 2 849 850 call void asm sideeffect "teqi $$zero, 2", ""() 851 %arg2 = va_arg i8** %ap, i16 852 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 853 store volatile i16 %arg2, i16* %e2, align 2 854 855 call void @llvm.va_end(i8* %ap2) 856 857 ret void 858 } 859 860 define void @fn_i64_dotdotdot_i32(i64 %a, ...) { 861 entry: 862 ; ALL-LABEL: fn_i64_dotdotdot_i32: 863 864 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 865 ; the argument save area (56 bytes). 866 ; O32: addiu [[SP:\$sp]], $sp, -8 867 ; N32: addiu [[SP:\$sp]], $sp, -64 868 ; N64: daddiu [[SP:\$sp]], $sp, -64 869 870 ; Save variable argument portion on the stack 871 ; O32-DAG: sw $7, 20([[SP]]) 872 ; O32-DAG: sw $6, 16([[SP]]) 873 874 ; NEW-DAG: sd $11, 56([[SP]]) 875 ; NEW-DAG: sd $10, 48([[SP]]) 876 ; NEW-DAG: sd $9, 40([[SP]]) 877 ; NEW-DAG: sd $8, 32([[SP]]) 878 ; NEW-DAG: sd $7, 24([[SP]]) 879 ; NEW-DAG: sd $6, 16([[SP]]) 880 ; NEW-DAG: sd $5, 8([[SP]]) 881 882 ; Initialize variable argument pointer. 883 ; For O32, the offset is 16 due to the 4 bytes used to store local variables, 884 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 885 ; first fixed argument. 886 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 887 ; space. 888 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 889 ; O32-DAG: sw [[VA]], 0([[SP]]) 890 891 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 892 ; N32-DAG: sw [[VA]], 0([[SP]]) 893 894 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 895 ; N64-DAG: sd [[VA]], 0([[SP]]) 896 897 ; Store [[VA]] 898 ; O32-DAG: sw [[VA]], 0([[SP]]) 899 900 ; ALL: teqi $zero, 1 901 902 ; Increment [[VA]] 903 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 904 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 905 ; O32-DAG: sw [[VA2]], 0([[SP]]) 906 907 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 908 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 909 ; N32-DAG: sw [[VA2]], 0([[SP]]) 910 911 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 912 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 913 ; N64-DAG: sd [[VA2]], 0([[SP]]) 914 915 ; Load the first argument from the variable portion. 916 ; This has used the stack pointer directly rather than the [[VA]] we just set 917 ; up. 918 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 919 ; order. 920 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 921 922 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 923 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 924 925 ; Copy the arg to the global 926 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 927 928 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 929 930 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)( 931 932 ; ALL-DAG: sw [[ARG1]], 4([[GV]]) 933 934 ; ALL: teqi $zero, 2 935 936 ; Increment [[VA]] again. 937 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 938 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 939 ; O32-DAG: sw [[VA2]], 0([[SP]]) 940 941 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 942 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 943 ; N32-DAG: sw [[VA3]], 0([[SP]]) 944 945 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 946 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 947 ; N64-DAG: sd [[VA3]], 0([[SP]]) 948 949 ; Load the second argument from the variable portion. 950 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 951 952 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 953 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 954 955 ; Copy the arg to the global 956 ; ALL-DAG: sw [[ARG2]], 8([[GV]]) 957 958 %ap = alloca i8*, align 8 959 %ap2 = bitcast i8** %ap to i8* 960 call void @llvm.va_start(i8* %ap2) 961 962 call void asm sideeffect "teqi $$zero, 1", ""() 963 %arg1 = va_arg i8** %ap, i32 964 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 965 store volatile i32 %arg1, i32* %e1, align 4 966 967 call void asm sideeffect "teqi $$zero, 2", ""() 968 %arg2 = va_arg i8** %ap, i32 969 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 970 store volatile i32 %arg2, i32* %e2, align 4 971 972 call void @llvm.va_end(i8* %ap2) 973 974 ret void 975 } 976 977 define void @fn_i64_dotdotdot_i64(i64 %a, ...) { 978 entry: 979 ; ALL-LABEL: fn_i64_dotdotdot_i64: 980 981 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for 982 ; the argument save area (56 bytes). 983 ; O32: addiu [[SP:\$sp]], $sp, -8 984 ; N32: addiu [[SP:\$sp]], $sp, -64 985 ; N64: daddiu [[SP:\$sp]], $sp, -64 986 987 ; Save variable argument portion on the stack 988 ; O32-DAG: sw $7, 20([[SP]]) 989 ; O32-DAG: sw $6, 16([[SP]]) 990 991 ; NEW-DAG: sd $11, 56([[SP]]) 992 ; NEW-DAG: sd $10, 48([[SP]]) 993 ; NEW-DAG: sd $9, 40([[SP]]) 994 ; NEW-DAG: sd $8, 32([[SP]]) 995 ; NEW-DAG: sd $7, 24([[SP]]) 996 ; NEW-DAG: sd $6, 16([[SP]]) 997 ; NEW-DAG: sd $5, 8([[SP]]) 998 999 ; Initialize variable argument pointer. 1000 ; For O32, the offset is 16 due to the 4 bytes used to store local variables, 1001 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 1002 ; first fixed argument. 1003 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 1004 ; space. 1005 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 1006 ; O32-DAG: sw [[VA]], 0([[SP]]) 1007 1008 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 1009 ; N32-DAG: sw [[VA]], 0([[SP]]) 1010 1011 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 1012 ; N64-DAG: sd [[VA]], 0([[SP]]) 1013 1014 ; Store [[VA]] 1015 ; O32-DAG: sw [[VA]], 0([[SP]]) 1016 1017 ; ALL: teqi $zero, 1 1018 1019 ; Increment [[VA]] (and realign pointer for O32) 1020 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 1021 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 1022 ; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 1023 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 1024 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 1025 ; O32-DAG: sw [[VA2]], 0([[SP]]) 1026 1027 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 1028 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 1029 ; N32-DAG: sw [[VA2]], 0([[SP]]) 1030 1031 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 1032 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 1033 ; N64-DAG: sd [[VA2]], 0([[SP]]) 1034 1035 ; Load the first argument from the variable portion and copy it to the global. 1036 ; This has used the stack pointer directly rather than the [[VA]] we just set 1037 ; up. 1038 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 1039 ; order. 1040 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1041 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 1042 ; O32-DAG: sw [[ARG1]], 8([[GV]]) 1043 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 1044 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 1045 ; O32-DAG: sw [[VA2]], 0([[SP]]) 1046 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 1047 ; O32-DAG: sw [[ARG1]], 12([[GV]]) 1048 1049 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1050 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( 1051 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 1052 ; NEW-DAG: sd [[ARG1]], 8([[GV]]) 1053 1054 ; ALL: teqi $zero, 2 1055 1056 ; Increment [[VA]] again. 1057 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 1058 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 1059 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 1060 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 1061 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 1062 ; O32-DAG: sw [[VA2]], 0([[SP]]) 1063 1064 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 1065 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 1066 ; N32-DAG: sw [[VA3]], 0([[SP]]) 1067 1068 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 1069 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 1070 ; N64-DAG: sd [[VA3]], 0([[SP]]) 1071 1072 ; Load the second argument from the variable portion and copy it to the global. 1073 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 1074 ; O32-DAG: sw [[ARG2]], 16([[GV]]) 1075 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 1076 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 1077 ; O32-DAG: sw [[VA2]], 0([[SP]]) 1078 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 1079 ; O32-DAG: sw [[ARG2]], 20([[GV]]) 1080 1081 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 1082 ; NEW-DAG: sd [[ARG2]], 16([[GV]]) 1083 1084 %ap = alloca i8*, align 8 1085 %ap2 = bitcast i8** %ap to i8* 1086 call void @llvm.va_start(i8* %ap2) 1087 1088 call void asm sideeffect "teqi $$zero, 1", ""() 1089 %arg1 = va_arg i8** %ap, i64 1090 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 1091 store volatile i64 %arg1, i64* %e1, align 8 1092 1093 call void asm sideeffect "teqi $$zero, 2", ""() 1094 %arg2 = va_arg i8** %ap, i64 1095 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 1096 store volatile i64 %arg2, i64* %e2, align 8 1097 1098 call void @llvm.va_end(i8* %ap2) 1099 1100 ret void 1101 } 1102 1103 declare void @llvm.va_start(i8*) 1104 declare void @llvm.va_end(i8*) 1105