1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc --mtriple=loongarch64 --mattr=+d --target-abi=lp64d < %s \ 3; RUN: | FileCheck --check-prefix=LA64-FPELIM %s 4; RUN: llc --mtriple=loongarch64 --mattr=+d --target-abi=lp64d < %s \ 5; RUN: --frame-pointer=all < %s \ 6; RUN: | FileCheck --check-prefix=LA64-WITHFP %s 7 8declare void @llvm.va_start(ptr) 9declare void @llvm.va_end(ptr) 10 11declare void @notdead(ptr) 12 13define i64 @va1(ptr %fmt, ...) { 14; LA64-FPELIM-LABEL: va1: 15; LA64-FPELIM: # %bb.0: 16; LA64-FPELIM-NEXT: addi.d $sp, $sp, -80 17; LA64-FPELIM-NEXT: .cfi_def_cfa_offset 80 18; LA64-FPELIM-NEXT: move $a0, $a1 19; LA64-FPELIM-NEXT: st.d $a7, $sp, 72 20; LA64-FPELIM-NEXT: st.d $a6, $sp, 64 21; LA64-FPELIM-NEXT: st.d $a5, $sp, 56 22; LA64-FPELIM-NEXT: st.d $a4, $sp, 48 23; LA64-FPELIM-NEXT: st.d $a3, $sp, 40 24; LA64-FPELIM-NEXT: st.d $a2, $sp, 32 25; LA64-FPELIM-NEXT: st.d $a1, $sp, 24 26; LA64-FPELIM-NEXT: addi.d $a1, $sp, 32 27; LA64-FPELIM-NEXT: st.d $a1, $sp, 8 28; LA64-FPELIM-NEXT: addi.d $sp, $sp, 80 29; LA64-FPELIM-NEXT: ret 30; 31; LA64-WITHFP-LABEL: va1: 32; LA64-WITHFP: # %bb.0: 33; LA64-WITHFP-NEXT: addi.d $sp, $sp, -96 34; LA64-WITHFP-NEXT: .cfi_def_cfa_offset 96 35; LA64-WITHFP-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill 36; LA64-WITHFP-NEXT: st.d $fp, $sp, 16 # 8-byte Folded Spill 37; LA64-WITHFP-NEXT: .cfi_offset 1, -72 38; LA64-WITHFP-NEXT: .cfi_offset 22, -80 39; LA64-WITHFP-NEXT: addi.d $fp, $sp, 32 40; LA64-WITHFP-NEXT: .cfi_def_cfa 22, 64 41; LA64-WITHFP-NEXT: move $a0, $a1 42; LA64-WITHFP-NEXT: st.d $a7, $fp, 56 43; LA64-WITHFP-NEXT: st.d $a6, $fp, 48 44; LA64-WITHFP-NEXT: st.d $a5, $fp, 40 45; LA64-WITHFP-NEXT: st.d $a4, $fp, 32 46; LA64-WITHFP-NEXT: st.d $a3, $fp, 24 47; LA64-WITHFP-NEXT: st.d $a2, $fp, 16 48; LA64-WITHFP-NEXT: st.d $a1, $fp, 8 49; LA64-WITHFP-NEXT: addi.d $a1, $fp, 16 50; LA64-WITHFP-NEXT: st.d $a1, $fp, -24 51; LA64-WITHFP-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload 52; LA64-WITHFP-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload 53; LA64-WITHFP-NEXT: addi.d $sp, $sp, 96 54; LA64-WITHFP-NEXT: ret 55 %va = alloca ptr, align 8 56 call void @llvm.va_start(ptr %va) 57 %argp.cur = load ptr, ptr %va, align 8 58 %argp.next = getelementptr inbounds i64, ptr %argp.cur, i32 1 59 store ptr %argp.next, ptr %va, align 8 60 %1 = load i64, ptr %argp.cur, align 8 61 call void @llvm.va_end(ptr %va) 62 ret i64 %1 63} 64 65define i64 @va1_va_arg(ptr %fmt, ...) nounwind { 66; LA64-FPELIM-LABEL: va1_va_arg: 67; LA64-FPELIM: # %bb.0: 68; LA64-FPELIM-NEXT: addi.d $sp, $sp, -80 69; LA64-FPELIM-NEXT: move $a0, $a1 70; LA64-FPELIM-NEXT: st.d $a7, $sp, 72 71; LA64-FPELIM-NEXT: st.d $a6, $sp, 64 72; LA64-FPELIM-NEXT: st.d $a5, $sp, 56 73; LA64-FPELIM-NEXT: st.d $a4, $sp, 48 74; LA64-FPELIM-NEXT: st.d $a3, $sp, 40 75; LA64-FPELIM-NEXT: st.d $a2, $sp, 32 76; LA64-FPELIM-NEXT: st.d $a1, $sp, 24 77; LA64-FPELIM-NEXT: addi.d $a1, $sp, 32 78; LA64-FPELIM-NEXT: st.d $a1, $sp, 8 79; LA64-FPELIM-NEXT: addi.d $sp, $sp, 80 80; LA64-FPELIM-NEXT: ret 81; 82; LA64-WITHFP-LABEL: va1_va_arg: 83; LA64-WITHFP: # %bb.0: 84; LA64-WITHFP-NEXT: addi.d $sp, $sp, -96 85; LA64-WITHFP-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill 86; LA64-WITHFP-NEXT: st.d $fp, $sp, 16 # 8-byte Folded Spill 87; LA64-WITHFP-NEXT: addi.d $fp, $sp, 32 88; LA64-WITHFP-NEXT: move $a0, $a1 89; LA64-WITHFP-NEXT: st.d $a7, $fp, 56 90; LA64-WITHFP-NEXT: st.d $a6, $fp, 48 91; LA64-WITHFP-NEXT: st.d $a5, $fp, 40 92; LA64-WITHFP-NEXT: st.d $a4, $fp, 32 93; LA64-WITHFP-NEXT: st.d $a3, $fp, 24 94; LA64-WITHFP-NEXT: st.d $a2, $fp, 16 95; LA64-WITHFP-NEXT: st.d $a1, $fp, 8 96; LA64-WITHFP-NEXT: addi.d $a1, $fp, 16 97; LA64-WITHFP-NEXT: st.d $a1, $fp, -24 98; LA64-WITHFP-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload 99; LA64-WITHFP-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload 100; LA64-WITHFP-NEXT: addi.d $sp, $sp, 96 101; LA64-WITHFP-NEXT: ret 102 %va = alloca ptr, align 8 103 call void @llvm.va_start(ptr %va) 104 %1 = va_arg ptr %va, i64 105 call void @llvm.va_end(ptr %va) 106 ret i64 %1 107} 108 109;; Ensure the adjustment when restoring the stack pointer using the frame 110;; pointer is correct 111 112define i64 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { 113; LA64-FPELIM-LABEL: va1_va_arg_alloca: 114; LA64-FPELIM: # %bb.0: 115; LA64-FPELIM-NEXT: addi.d $sp, $sp, -96 116; LA64-FPELIM-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill 117; LA64-FPELIM-NEXT: st.d $fp, $sp, 16 # 8-byte Folded Spill 118; LA64-FPELIM-NEXT: st.d $s0, $sp, 8 # 8-byte Folded Spill 119; LA64-FPELIM-NEXT: addi.d $fp, $sp, 32 120; LA64-FPELIM-NEXT: move $s0, $a1 121; LA64-FPELIM-NEXT: st.d $a7, $fp, 56 122; LA64-FPELIM-NEXT: st.d $a6, $fp, 48 123; LA64-FPELIM-NEXT: st.d $a5, $fp, 40 124; LA64-FPELIM-NEXT: st.d $a4, $fp, 32 125; LA64-FPELIM-NEXT: st.d $a3, $fp, 24 126; LA64-FPELIM-NEXT: st.d $a2, $fp, 16 127; LA64-FPELIM-NEXT: st.d $a1, $fp, 8 128; LA64-FPELIM-NEXT: addi.d $a0, $fp, 16 129; LA64-FPELIM-NEXT: st.d $a0, $fp, -32 130; LA64-FPELIM-NEXT: addi.d $a0, $a1, 15 131; LA64-FPELIM-NEXT: bstrins.d $a0, $zero, 3, 0 132; LA64-FPELIM-NEXT: sub.d $a0, $sp, $a0 133; LA64-FPELIM-NEXT: move $sp, $a0 134; LA64-FPELIM-NEXT: bl %plt(notdead) 135; LA64-FPELIM-NEXT: move $a0, $s0 136; LA64-FPELIM-NEXT: addi.d $sp, $fp, -32 137; LA64-FPELIM-NEXT: ld.d $s0, $sp, 8 # 8-byte Folded Reload 138; LA64-FPELIM-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload 139; LA64-FPELIM-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload 140; LA64-FPELIM-NEXT: addi.d $sp, $sp, 96 141; LA64-FPELIM-NEXT: ret 142; 143; LA64-WITHFP-LABEL: va1_va_arg_alloca: 144; LA64-WITHFP: # %bb.0: 145; LA64-WITHFP-NEXT: addi.d $sp, $sp, -96 146; LA64-WITHFP-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill 147; LA64-WITHFP-NEXT: st.d $fp, $sp, 16 # 8-byte Folded Spill 148; LA64-WITHFP-NEXT: st.d $s0, $sp, 8 # 8-byte Folded Spill 149; LA64-WITHFP-NEXT: addi.d $fp, $sp, 32 150; LA64-WITHFP-NEXT: move $s0, $a1 151; LA64-WITHFP-NEXT: st.d $a7, $fp, 56 152; LA64-WITHFP-NEXT: st.d $a6, $fp, 48 153; LA64-WITHFP-NEXT: st.d $a5, $fp, 40 154; LA64-WITHFP-NEXT: st.d $a4, $fp, 32 155; LA64-WITHFP-NEXT: st.d $a3, $fp, 24 156; LA64-WITHFP-NEXT: st.d $a2, $fp, 16 157; LA64-WITHFP-NEXT: st.d $a1, $fp, 8 158; LA64-WITHFP-NEXT: addi.d $a0, $fp, 16 159; LA64-WITHFP-NEXT: st.d $a0, $fp, -32 160; LA64-WITHFP-NEXT: addi.d $a0, $a1, 15 161; LA64-WITHFP-NEXT: bstrins.d $a0, $zero, 3, 0 162; LA64-WITHFP-NEXT: sub.d $a0, $sp, $a0 163; LA64-WITHFP-NEXT: move $sp, $a0 164; LA64-WITHFP-NEXT: bl %plt(notdead) 165; LA64-WITHFP-NEXT: move $a0, $s0 166; LA64-WITHFP-NEXT: addi.d $sp, $fp, -32 167; LA64-WITHFP-NEXT: ld.d $s0, $sp, 8 # 8-byte Folded Reload 168; LA64-WITHFP-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload 169; LA64-WITHFP-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload 170; LA64-WITHFP-NEXT: addi.d $sp, $sp, 96 171; LA64-WITHFP-NEXT: ret 172 %va = alloca ptr, align 8 173 call void @llvm.va_start(ptr %va) 174 %1 = va_arg ptr %va, i64 175 %2 = alloca i8, i64 %1 176 call void @notdead(ptr %2) 177 call void @llvm.va_end(ptr %va) 178 ret i64 %1 179} 180 181define void @va1_caller() nounwind { 182; LA64-FPELIM-LABEL: va1_caller: 183; LA64-FPELIM: # %bb.0: 184; LA64-FPELIM-NEXT: addi.d $sp, $sp, -16 185; LA64-FPELIM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill 186; LA64-FPELIM-NEXT: lu52i.d $a1, $zero, 1023 187; LA64-FPELIM-NEXT: ori $a2, $zero, 2 188; LA64-FPELIM-NEXT: bl %plt(va1) 189; LA64-FPELIM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload 190; LA64-FPELIM-NEXT: addi.d $sp, $sp, 16 191; LA64-FPELIM-NEXT: ret 192; 193; LA64-WITHFP-LABEL: va1_caller: 194; LA64-WITHFP: # %bb.0: 195; LA64-WITHFP-NEXT: addi.d $sp, $sp, -16 196; LA64-WITHFP-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill 197; LA64-WITHFP-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill 198; LA64-WITHFP-NEXT: addi.d $fp, $sp, 16 199; LA64-WITHFP-NEXT: lu52i.d $a1, $zero, 1023 200; LA64-WITHFP-NEXT: ori $a2, $zero, 2 201; LA64-WITHFP-NEXT: bl %plt(va1) 202; LA64-WITHFP-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload 203; LA64-WITHFP-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload 204; LA64-WITHFP-NEXT: addi.d $sp, $sp, 16 205; LA64-WITHFP-NEXT: ret 206 %1 = call i64 (ptr, ...) @va1(ptr undef, double 1.0, i64 2) 207 ret void 208} 209 210;; Ensure a named 2*GRLen argument is passed in a1 and a2, while the 211;; vararg long double is passed in a4 and a5 (rather than a3 and a4) 212 213declare i64 @va_aligned_register(i64 %a, i128 %b, ...) 214 215define void @va_aligned_register_caller() nounwind { 216; LA64-FPELIM-LABEL: va_aligned_register_caller: 217; LA64-FPELIM: # %bb.0: 218; LA64-FPELIM-NEXT: addi.d $sp, $sp, -16 219; LA64-FPELIM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill 220; LA64-FPELIM-NEXT: lu12i.w $a0, 335544 221; LA64-FPELIM-NEXT: ori $a0, $a0, 1311 222; LA64-FPELIM-NEXT: lu32i.d $a0, 335544 223; LA64-FPELIM-NEXT: lu52i.d $a4, $a0, -328 224; LA64-FPELIM-NEXT: lu12i.w $a0, -503317 225; LA64-FPELIM-NEXT: ori $a0, $a0, 2129 226; LA64-FPELIM-NEXT: lu32i.d $a0, 37355 227; LA64-FPELIM-NEXT: lu52i.d $a5, $a0, 1024 228; LA64-FPELIM-NEXT: ori $a0, $zero, 2 229; LA64-FPELIM-NEXT: ori $a1, $zero, 1111 230; LA64-FPELIM-NEXT: move $a2, $zero 231; LA64-FPELIM-NEXT: bl %plt(va_aligned_register) 232; LA64-FPELIM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload 233; LA64-FPELIM-NEXT: addi.d $sp, $sp, 16 234; LA64-FPELIM-NEXT: ret 235; 236; LA64-WITHFP-LABEL: va_aligned_register_caller: 237; LA64-WITHFP: # %bb.0: 238; LA64-WITHFP-NEXT: addi.d $sp, $sp, -16 239; LA64-WITHFP-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill 240; LA64-WITHFP-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill 241; LA64-WITHFP-NEXT: addi.d $fp, $sp, 16 242; LA64-WITHFP-NEXT: lu12i.w $a0, 335544 243; LA64-WITHFP-NEXT: ori $a0, $a0, 1311 244; LA64-WITHFP-NEXT: lu32i.d $a0, 335544 245; LA64-WITHFP-NEXT: lu52i.d $a4, $a0, -328 246; LA64-WITHFP-NEXT: lu12i.w $a0, -503317 247; LA64-WITHFP-NEXT: ori $a0, $a0, 2129 248; LA64-WITHFP-NEXT: lu32i.d $a0, 37355 249; LA64-WITHFP-NEXT: lu52i.d $a5, $a0, 1024 250; LA64-WITHFP-NEXT: ori $a0, $zero, 2 251; LA64-WITHFP-NEXT: ori $a1, $zero, 1111 252; LA64-WITHFP-NEXT: move $a2, $zero 253; LA64-WITHFP-NEXT: bl %plt(va_aligned_register) 254; LA64-WITHFP-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload 255; LA64-WITHFP-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload 256; LA64-WITHFP-NEXT: addi.d $sp, $sp, 16 257; LA64-WITHFP-NEXT: ret 258 %1 = call i64 (i64, i128, ...) @va_aligned_register(i64 2, i128 1111, 259 fp128 0xLEB851EB851EB851F400091EB851EB851) 260 ret void 261} 262 263;; Check 2*GRLen values are aligned appropriately when passed on the stack 264;; in a vararg call 265 266declare i32 @va_aligned_stack_callee(i32, ...) 267 268define void @va_aligned_stack_caller() nounwind { 269; LA64-FPELIM-LABEL: va_aligned_stack_caller: 270; LA64-FPELIM: # %bb.0: 271; LA64-FPELIM-NEXT: addi.d $sp, $sp, -112 272; LA64-FPELIM-NEXT: st.d $ra, $sp, 104 # 8-byte Folded Spill 273; LA64-FPELIM-NEXT: ori $a0, $zero, 17 274; LA64-FPELIM-NEXT: st.d $a0, $sp, 48 275; LA64-FPELIM-NEXT: ori $a0, $zero, 16 276; LA64-FPELIM-NEXT: st.d $a0, $sp, 40 277; LA64-FPELIM-NEXT: ori $a0, $zero, 15 278; LA64-FPELIM-NEXT: st.d $a0, $sp, 32 279; LA64-FPELIM-NEXT: ori $a0, $zero, 14 280; LA64-FPELIM-NEXT: st.d $a0, $sp, 0 281; LA64-FPELIM-NEXT: lu12i.w $a0, -503317 282; LA64-FPELIM-NEXT: ori $a0, $a0, 2129 283; LA64-FPELIM-NEXT: lu32i.d $a0, 37355 284; LA64-FPELIM-NEXT: lu52i.d $a0, $a0, 1024 285; LA64-FPELIM-NEXT: st.d $a0, $sp, 24 286; LA64-FPELIM-NEXT: lu12i.w $a0, 335544 287; LA64-FPELIM-NEXT: ori $a0, $a0, 1311 288; LA64-FPELIM-NEXT: lu32i.d $a0, 335544 289; LA64-FPELIM-NEXT: lu52i.d $a0, $a0, -328 290; LA64-FPELIM-NEXT: st.d $a0, $sp, 16 291; LA64-FPELIM-NEXT: st.d $zero, $sp, 88 292; LA64-FPELIM-NEXT: vrepli.b $vr0, 0 293; LA64-FPELIM-NEXT: vst $vr0, $sp, 72 294; LA64-FPELIM-NEXT: ori $a5, $zero, 1000 295; LA64-FPELIM-NEXT: ori $a0, $zero, 1 296; LA64-FPELIM-NEXT: ori $a1, $zero, 11 297; LA64-FPELIM-NEXT: addi.d $a2, $sp, 64 298; LA64-FPELIM-NEXT: ori $a3, $zero, 12 299; LA64-FPELIM-NEXT: ori $a4, $zero, 13 300; LA64-FPELIM-NEXT: ori $a7, $zero, 1 301; LA64-FPELIM-NEXT: st.d $a5, $sp, 64 302; LA64-FPELIM-NEXT: move $a6, $zero 303; LA64-FPELIM-NEXT: bl %plt(va_aligned_stack_callee) 304; LA64-FPELIM-NEXT: ld.d $ra, $sp, 104 # 8-byte Folded Reload 305; LA64-FPELIM-NEXT: addi.d $sp, $sp, 112 306; LA64-FPELIM-NEXT: ret 307; 308; LA64-WITHFP-LABEL: va_aligned_stack_caller: 309; LA64-WITHFP: # %bb.0: 310; LA64-WITHFP-NEXT: addi.d $sp, $sp, -112 311; LA64-WITHFP-NEXT: st.d $ra, $sp, 104 # 8-byte Folded Spill 312; LA64-WITHFP-NEXT: st.d $fp, $sp, 96 # 8-byte Folded Spill 313; LA64-WITHFP-NEXT: addi.d $fp, $sp, 112 314; LA64-WITHFP-NEXT: ori $a0, $zero, 17 315; LA64-WITHFP-NEXT: st.d $a0, $sp, 48 316; LA64-WITHFP-NEXT: ori $a0, $zero, 16 317; LA64-WITHFP-NEXT: st.d $a0, $sp, 40 318; LA64-WITHFP-NEXT: ori $a0, $zero, 15 319; LA64-WITHFP-NEXT: st.d $a0, $sp, 32 320; LA64-WITHFP-NEXT: ori $a0, $zero, 14 321; LA64-WITHFP-NEXT: st.d $a0, $sp, 0 322; LA64-WITHFP-NEXT: lu12i.w $a0, -503317 323; LA64-WITHFP-NEXT: ori $a0, $a0, 2129 324; LA64-WITHFP-NEXT: lu32i.d $a0, 37355 325; LA64-WITHFP-NEXT: lu52i.d $a0, $a0, 1024 326; LA64-WITHFP-NEXT: st.d $a0, $sp, 24 327; LA64-WITHFP-NEXT: lu12i.w $a0, 335544 328; LA64-WITHFP-NEXT: ori $a0, $a0, 1311 329; LA64-WITHFP-NEXT: lu32i.d $a0, 335544 330; LA64-WITHFP-NEXT: lu52i.d $a0, $a0, -328 331; LA64-WITHFP-NEXT: st.d $a0, $sp, 16 332; LA64-WITHFP-NEXT: st.d $zero, $fp, -24 333; LA64-WITHFP-NEXT: vrepli.b $vr0, 0 334; LA64-WITHFP-NEXT: vst $vr0, $fp, -40 335; LA64-WITHFP-NEXT: ori $a5, $zero, 1000 336; LA64-WITHFP-NEXT: ori $a0, $zero, 1 337; LA64-WITHFP-NEXT: ori $a1, $zero, 11 338; LA64-WITHFP-NEXT: addi.d $a2, $fp, -48 339; LA64-WITHFP-NEXT: ori $a3, $zero, 12 340; LA64-WITHFP-NEXT: ori $a4, $zero, 13 341; LA64-WITHFP-NEXT: ori $a7, $zero, 1 342; LA64-WITHFP-NEXT: st.d $a5, $fp, -48 343; LA64-WITHFP-NEXT: move $a6, $zero 344; LA64-WITHFP-NEXT: bl %plt(va_aligned_stack_callee) 345; LA64-WITHFP-NEXT: ld.d $fp, $sp, 96 # 8-byte Folded Reload 346; LA64-WITHFP-NEXT: ld.d $ra, $sp, 104 # 8-byte Folded Reload 347; LA64-WITHFP-NEXT: addi.d $sp, $sp, 112 348; LA64-WITHFP-NEXT: ret 349 %1 = call i32 (i32, ...) @va_aligned_stack_callee(i32 1, i32 11, 350 i256 1000, i32 12, i32 13, i128 18446744073709551616, i32 14, 351 fp128 0xLEB851EB851EB851F400091EB851EB851, i64 15, 352 [2 x i64] [i64 16, i64 17]) 353 ret void 354} 355