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 17define void @fn_i16_dotdotdot_i16(i16 %a, ...) { 18entry: 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 135define void @fn_i16_dotdotdot_i32(i16 %a, ...) { 136entry: 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 253define void @fn_i16_dotdotdot_i64(i16 %a, ...) { 254entry: 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 378define void @fn_i32_dotdotdot_i16(i32 %a, ...) { 379entry: 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 496define void @fn_i32_dotdotdot_i32(i32 %a, ...) { 497entry: 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 614define void @fn_i32_dotdotdot_i64(i32 %a, ...) { 615entry: 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 739define void @fn_i64_dotdotdot_i16(i64 %a, ...) { 740entry: 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 856define void @fn_i64_dotdotdot_i32(i64 %a, ...) { 857entry: 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 973define void @fn_i64_dotdotdot_i64(i64 %a, ...) { 974entry: 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 1097declare void @llvm.va_start(i8*) 1098declare void @llvm.va_end(i8*) 1099