ZarkoCA updated this revision to Diff 250749.
ZarkoCA added a comment.
- Removed 64BIT support varargs.
- Added a fatal error for 64bit varargs on AIX.
- Removed 64bit testcases
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D76130/new/
https://reviews.llvm.org/D76130
Files:
clang/lib/Basic/Targets/PPC.h
clang/lib/CodeGen/TargetInfo.cpp
clang/test/CodeGen/aix-vararg.c
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/test/CodeGen/PowerPC/aix-cc-abi-va_args-32.ll
llvm/test/CodeGen/PowerPC/aix-cc-abi.ll
Index: llvm/test/CodeGen/PowerPC/aix-cc-abi.ll
===================================================================
--- llvm/test/CodeGen/PowerPC/aix-cc-abi.ll
+++ llvm/test/CodeGen/PowerPC/aix-cc-abi.ll
@@ -1745,6 +1745,335 @@
; ASM64PWR-DAG: li [[REGB]], 1
; ASM64PWR-DAG: bl .test_i1
+; ASM32PWR4: add 3, 3, 4
+; ASM32PWR4-DAG: lwz [[REG1:[0-9]+]], 60(1)
+; ASM32PWR4-DAG: add 3, 3, 5
+; ASM32PWR4-DAG: add 3, 3, 6
+; ASM32PWR4-DAG: add 3, 3, 7
+; ASM32PWR4-DAG: lwz [[REG2:[0-9]+]], 64(1)
+; ASM32PWR4-DAG: add 3, 3, 8
+; ASM32PWR4-DAG: add 3, 3, 9
+; ASM32PWR4-DAG: lwz [[REG3:[0-9]+]], 68(1)
+; ASM32PWR4-DAG: add 3, 3, 10
+; ASM32PWR4-DAG: add 3, 3, [[REG1]]
+; ASM32PWR4-DAG: add 3, 3, [[REG2]]
+; ASM32PWR4-DAG: lwz [[REG4:[0-9]+]], 72(1)
+; ASM32PWR4-DAG: add 3, 3, [[REG3]]
+; ASM32PWR4-DAG: lwz [[REG5:[0-9]+]], 76(1)
+; ASM32PWR4-DAG: add 3, 3, [[REG4]]
+; ASM32PWR4-DAG: lwz [[REG6:[0-9]+]], 84(1)
+; ASM32PWR4-DAG: add 3, 3, [[REG5]]
+; ASM32PWR4-DAG: lwz [[REG7:[0-9]+]], 88(1)
+; ASM32PWR4-DAG: add 3, 3, [[REG6]]
+; ASM32PWR4-DAG: lwz [[REG8:[0-9]+]], 92(1)
+; ASM32PWR4-DAG: add 3, 3, [[REG7]]
+; ASM32PWR4-DAG: add 3, 3, [[REG8]]
+
+; ASM64PWR4-DAG: ld [[REG1:[0-9]+]], 112(1)
+; ASM64PWR4-DAG: lwz [[REG2:[0-9]+]], 124(1)
+; ASM64PWR4-DAG: lwz [[REG3:[0-9]+]], 132(1)
+; ASM64PWR4-DAG: lwz [[REG4:[0-9]+]], 140(1)
+; ASM64PWR4-DAG: lwa [[REG5:[0-9]+]], 148(1)
+; ASM64PWR4-DAG: ld [[REG6:[0-9]+]], 152(1)
+; ASM64PWR4-DAG: lwz [[REG7:[0-9]+]], 164(1)
+; ASM64PWR4-DAG: lwa [[REG8:[0-9]+]], 172(1)
+
+@ll1 = common global i64 0, align 8
+@si1 = common global i16 0, align 2
+@ch = common global i8 0, align 1
+@ui = common global i32 0, align 4
+@sint = common global i32 0, align 4
+@ll2 = common global i64 0, align 8
+@uc1 = common global i8 0, align 1
+@i1 = common global i32 0, align 4
+
+define void @caller_ints_stack() {
+entry:
+ %0 = load i64, i64* @ll1, align 8
+ %1 = load i16, i16* @si1, align 2
+ %2 = load i8, i8* @ch, align 1
+ %3 = load i32, i32* @ui, align 4
+ %4 = load i32, i32* @sint, align 4
+ %5 = load i64, i64* @ll2, align 8
+ %6 = load i8, i8* @uc1, align 1
+ %7 = load i32, i32* @i1, align 4
+ %call = call i64 @test_ints_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i64 %0, i16 signext %1, i8 zeroext %2, i32 %3, i32 %4, i64 %5, i8 zeroext %6, i32 %7)
+ ret void
+}
+
+; CHECK-LABEL: name: caller_ints_stack
+
+; 32BIT-DAG: $r3 = LI 1
+; 32BIT-DAG: $r4 = LI 2
+; 32BIT-DAG: $r5 = LI 3
+; 32BIT-DAG: $r6 = LI 4
+; 32BIT-DAG: $r7 = LI 5
+; 32BIT-DAG: $r8 = LI 6
+; 32BIT-DAG: $r9 = LI 7
+; 32BIT-DAG: $r10 = LI 8
+; 32BIT-DAG: renamable $r[[REGLL1ADDR:[0-9]+]] = LWZtoc @ll1, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $r[[REGLL1A:[0-9]+]] = LWZ 0, renamable $r[[REGLL1ADDR]] :: (dereferenceable load 4 from @ll1, align 8)
+; 32BIT-DAG: renamable $r[[REGLL1B:[0-9]+]] = LWZ 4, killed renamable $r[[REGLL1ADDR]] :: (dereferenceable load 4 from @ll1 + 4)
+; 32BIT-DAG: STW killed renamable $r[[REGLL1A]], 56, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REGLL1B]], 60, $r1 :: (store 4)
+; 32BIT-DAG: renamable $r[[REGSIADDR:[0-9]+]] = LWZtoc @si1, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $r[[REGSI:[0-9]+]] = LHA 0, killed renamable $r[[REGSIADDR]] :: (dereferenceable load 2 from @si1)
+; 32BIT-DAG: STW killed renamable $r[[REGSI]], 64, $r1 :: (store 4)
+; 32BIT-DAG: renamable $r[[REGCHADDR:[0-9]+]] = LWZtoc @ch, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $r[[REGCH:[0-9]+]] = LBZ 0, killed renamable $r[[REGCHADDR]] :: (dereferenceable load 1 from @ch)
+; 32BIT-DAG: STW killed renamable $r[[REGCH]], 68, $r1 :: (store 4)
+; 32BIT-DAG: renamable $r[[REGUIADDR:[0-9]+]] = LWZtoc @ui, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $r[[REGUI:[0-9]+]] = LWZ 0, killed renamable $r[[REGUIADDR]] :: (dereferenceable load 4 from @ui)
+; 32BIT-DAG: STW killed renamable $r[[REGUI]], 72, $r1 :: (store 4)
+; 32BIT-DAG: renamable $r[[REGSIADDR:[0-9]+]] = LWZtoc @sint, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $r[[REGSI:[0-9]+]] = LWZ 0, killed renamable $r[[REGSIADDR]] :: (dereferenceable load 4 from @sint)
+; 32BIT-DAG: STW killed renamable $r[[REGSI]], 76, $r1 :: (store 4)
+; 32BIT-DAG: renamable $r[[REGLL2ADDR:[0-9]+]] = LWZtoc @ll2, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $r[[REGLL2A:[0-9]+]] = LWZ 0, renamable $r[[REGLL2ADDR]] :: (dereferenceable load 4 from @ll2, align 8)
+; 32BIT-DAG: renamable $r[[REGLL2B:[0-9]+]] = LWZ 4, killed renamable $r[[REGLL2ADDR]] :: (dereferenceable load 4 from @ll2 + 4)
+; 32BIT-DAG: STW killed renamable $r[[REGLL2A]], 80, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REGLL2B]], 84, $r1 :: (store 4)
+; 32BIT-DAG: renamable $r[[REGUCADDR:[0-9]+]] = LWZtoc @uc1, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $r[[REGUC:[0-9]+]] = LBZ 0, killed renamable $r[[REGUCADDR]] :: (dereferenceable load 1 from @uc1)
+; 32BIT-DAG: STW killed renamable $r[[REGUC]], 88, $r1 :: (store 4)
+; 32BIT-DAG: renamable $r[[REGIADDR:[0-9]+]] = LWZtoc @i1, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $r[[REGI:[0-9]+]] = LWZ 0, killed renamable $r[[REGIADDR]] :: (dereferenceable load 4 from @i1)
+; 32BIT-DAG: STW killed renamable $r[[REGI]], 92, $r1 :: (store 4)
+; 32BIT-DAG: ADJCALLSTACKDOWN 96, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-NEXT: BL_NOP <mcsymbol .test_ints_stack>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $r4, implicit $r5, implicit $r6, implicit $r7, implicit $r8, implicit $r9, implicit $r10, implicit $r2, implicit-def $r1, implicit-def dead $r3
+; 32BIT-NEXT: ADJCALLSTACKUP 96, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT-DAG: $x3 = LI8 1
+; 64BIT-DAG: $x4 = LI8 2
+; 64BIT-DAG: $x5 = LI8 3
+; 64BIT-DAG: $x6 = LI8 4
+; 64BIT-DAG: $x7 = LI8 5
+; 64BIT-DAG: $x8 = LI8 6
+; 64BIT-DAG: $x9 = LI8 7
+; 64BIT-DAG: $x10 = LI8 8
+; 64BIT-DAG: renamable $x[[REGLL1ADDR:[0-9]+]] = LDtoc @ll1, $x2 :: (load 8 from got)
+; 64BIT-DAG: renamable $x[[REGLL1:[0-9]+]] = LD 0, killed renamable $x[[REGLL1ADDR]] :: (dereferenceable load 8 from @ll1)
+; 64BIT-DAG: STD killed renamable $x[[REGLL1]], 112, $x1 :: (store 8)
+; 64BIT-DAG: renamable $x[[REGSIADDR:[0-9]+]] = LDtoc @si1, $x2 :: (load 8 from got)
+; 64BIT-DAG: renamable $r[[REGSI:[0-9]+]] = LHA 0, killed renamable $x[[REGSIADDR]] :: (dereferenceable load 2 from @si1)
+; 64BIT-DAG: STW killed renamable $r[[REGSI]], 120, $x1 :: (store 4)
+; 64BIT-DAG: renamable $x[[REGCHADDR:[0-9]+]] = LDtoc @ch, $x2 :: (load 8 from got)
+; 64BIT-DAG: renamable $r[[REGCH:[0-9]+]] = LBZ 0, killed renamable $x[[REGCHADDR]] :: (dereferenceable load 1 from @ch)
+; 64BIT-DAG: STW killed renamable $r[[REGCH]], 128, $x1 :: (store 4)
+; 64BIT-DAG: renamable $x[[REGUIADDR:[0-9]+]] = LDtoc @ui, $x2 :: (load 8 from got)
+; 64BIT-DAG: renamable $r[[REGUI:[0-9]+]] = LWZ 0, killed renamable $x[[REGUIADDR]] :: (dereferenceable load 4 from @ui)
+; 64BIT-DAG: STW killed renamable $r[[REGUI]], 136, $x1 :: (store 4)
+; 64BIT-DAG: renamable $x[[REGSIADDR:[0-9]+]] = LDtoc @sint, $x2 :: (load 8 from got)
+; 64BIT-DAG: renamable $r[[REGSI:[0-9]+]] = LWZ 0, killed renamable $x[[REGSIADDR]] :: (dereferenceable load 4 from @sint)
+; 64BIT-DAG: STW killed renamable $r[[REGSI]], 144, $x1 :: (store 4)
+; 64BIT-DAG: renamable $x[[REGLL2ADDR:[0-9]+]] = LDtoc @ll2, $x2 :: (load 8 from got)
+; 64BIT-DAG: renamable $x[[REGLL2:[0-9]+]] = LD 0, killed renamable $x[[REGLL2ADDR]] :: (dereferenceable load 8 from @ll2)
+; 64BIT-DAG: STD killed renamable $x[[REGLL2]], 152, $x1 :: (store 8)
+; 64BIT-DAG: renamable $x[[REGUCADDR:[0-9]+]] = LDtoc @uc1, $x2 :: (load 8 from got)
+; 64BIT-DAG: renamable $r[[REGUC:[0-9]+]] = LBZ 0, killed renamable $x[[REGUCADDR]] :: (dereferenceable load 1 from @uc1)
+; 64BIT-DAG: STW killed renamable $r[[REGUC]], 160, $x1 :: (store 4)
+; 64BIT-DAG: renamable $x[[REGIADDR:[0-9]+]] = LDtoc @i1, $x2 :: (load 8 from got)
+; 64BIT-DAG: renamable $r[[REGI:[0-9]+]] = LWZ 0, killed renamable $x[[REGIADDR]] :: (dereferenceable load 4 from @i1)
+; 64BIT-DAG: STW killed renamable $r[[REGI]], 168, $x1 :: (store 4)
+; 64BIT-DAG: ADJCALLSTACKDOWN 176, 0, implicit-def dead $r1, implicit $r1
+; 64BIT-NEXT: BL8_NOP <mcsymbol .test_ints_stack>, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit $x3, implicit $x4, implicit $x5, implicit $x6, implicit $x7, implicit $x8, implicit $x9, implicit $x10, implicit $x2, implicit-def $r1, implicit-def dead $x3
+; 64BIT-NEXT: ADJCALLSTACKUP 176, 0, implicit-def dead $r1, implicit $r1
+; 64BIT-NEXT: BLR8 implicit $lr8, implicit $rm
+
+; CHECKASM-LABEL: .caller_ints_stack:
+
+; ASM32PWR4: mflr 0
+; ASM32PWR4-DAG: stw 0, 8(1)
+; ASM32PWR4-DAG: stwu 1, -96(1)
+; ASM32PWR4-DAG: li 3, 1
+; ASM32PWR4-DAG: li 4, 2
+; ASM32PWR4-DAG: li 5, 3
+; ASM32PWR4-DAG: li 6, 4
+; ASM32PWR4-DAG: li 7, 5
+; ASM32PWR4-DAG: li 9, 7
+; ASM32PWR4-DAG: li 8, 6
+; ASM32PWR4-DAG: li 10, 8
+; ASM32PWR4-DAG: lwz [[REG1:[0-9]+]], LC10(2)
+; ASM32PWR4-DAG: lwz [[REG2:[0-9]+]], LC11(2)
+; ASM32PWR4-DAG: lwz [[REG3:[0-9]+]], LC12(2)
+; ASM32PWR4-DAG: lwz [[REG4:[0-9]+]], LC13(2)
+; ASM32PWR4-DAG: lwz [[REG5:[0-9]+]], LC14(2)
+; ASM32PWR4-DAG: lwz [[REG6:[0-9]+]], LC15(2)
+; ASM32PWR4-DAG: lwz [[REG7:[0-9]+]], LC16(2)
+; ASM32PWR4-DAG: lwz [[REG8:[0-9]+]], LC17(2)
+; ASM32PWR4-DAG: lha 5, 0([[REG1]])
+; ASM32PWR4-DAG: lwz 11, 0([[REG7]])
+; ASM32PWR4-DAG: lwz 7, 4([[REG7]])
+; ASM32PWR4-DAG: lbz 4, 0([[REG2]])
+; ASM32PWR4-DAG: lwz 3, 0([[REG8]])
+; ASM32PWR4-DAG: lwz 6, 0([[REG3]])
+; ASM32PWR4-DAG: lwz 9, 0([[REG4]])
+; ASM32PWR4-DAG: lwz 8, 4([[REG4]])
+; ASM32PWR4-DAG: lbz 10, 0([[REG5]])
+; ASM32PWR4-DAG: lwz 12, 0([[REG6]])
+; ASM32PWR4-DAG: stw 11, 56(1)
+; ASM32PWR4-DAG: stw 7, 60(1)
+; ASM32PWR4-DAG: stw 5, 64(1)
+; ASM32PWR4-DAG: stw 4, 68(1)
+; ASM32PWR4-DAG: stw 3, 72(1)
+; ASM32PWR4-DAG: stw 6, 76(1)
+; ASM32PWR4-DAG: stw 9, 80(1)
+; ASM32PWR4-DAG: stw 8, 84(1)
+; ASM32PWR4-DAG: stw 10, 88(1)
+; ASM32PWR4-DAG: stw 12, 92(1)
+; ASM32PWR4-DAG: bl .test_ints_stack
+; ASM32PWR4-DAG: nop
+; ASM32PWR4-DAG: addi 1, 1, 96
+; ASM32PWR4-DAG: lwz 0, 8(1)
+; ASM32PWR4-NEXT: mtlr 0
+; ASM32PWR4-NEXT: blr
+
+; ASM64PWR4: mflr 0
+; ASM64PWR4-DAG: std 0, 16(1)
+; ASM64PWR4-DAG: stdu 1, -176(1)
+; ASM64PWR4-DAG: li 3, 1
+; ASM64PWR4-DAG: li 4, 2
+; ASM64PWR4-DAG: li 5, 3
+; ASM64PWR4-DAG: li 6, 4
+; ASM64PWR4-DAG: li 7, 5
+; ASM64PWR4-DAG: li 8, 6
+; ASM64PWR4-DAG: li 9, 7
+; ASM64PWR4-DAG: li 10, 8
+; ASM64PWR4-DAG: ld [[REG1:[0-9]+]], LC9(2)
+; ASM64PWR4-DAG: ld [[REG2:[0-9]+]], LC10(2)
+; ASM64PWR4-DAG: ld [[REG3:[0-9]+]], LC11(2)
+; ASM64PWR4-DAG: ld [[REG4:[0-9]+]], LC12(2)
+; ASM64PWR4-DAG: ld [[REG5:[0-9]+]], LC13(2)
+; ASM64PWR4-DAG: ld [[REG6:[0-9]+]], LC14(2)
+; ASM64PWR4-DAG: ld [[REG7:[0-9]+]], LC15(2)
+; ASM64PWR4-DAG: ld [[REG8:[0-9]+]], LC16(2)
+; ASM64PWR4-DAG: lha 7, 0([[REG1]])
+; ASM64PWR4-DAG: lbz 5, 0([[REG2]])
+; ASM64PWR4-DAG: ld 6, 0([[REG3]])
+; ASM64PWR4-DAG: lbz 8, 0([[REG4]])
+; ASM64PWR4-DAG: lwz 9, 0([[REG5]])
+; ASM64PWR4-DAG: ld 11, 0([[REG6]])
+; ASM64PWR4-DAG: lwz 3, 0([[REG7]])
+; ASM64PWR4-DAG: lwz 4, 0([[REG8]])
+; ASM64PWR4-DAG: std 11, 112(1)
+; ASM64PWR4-DAG: stw 7, 120(1)
+; ASM64PWR4-DAG: stw 5, 128(1)
+; ASM64PWR4-DAG: stw 3, 136(1)
+; ASM64PWR4-DAG: stw 4, 144(1)
+; ASM64PWR4-DAG: std 6, 152(1)
+; ASM64PWR4-DAG: stw 8, 160(1)
+; ASM64PWR4-DAG: stw 9, 168(1)
+; ASM64PWR4-NEXT: bl .test_ints_stack
+; ASM64PWR4-NEXT: nop
+; ASM64PWR4-NEXT: addi 1, 1, 176
+; ASM64PWR4-NEXT: ld 0, 16(1)
+; ASM64PWR4-NEXT: mtlr 0
+; ASM64PWR4-NEXT: blr
+
+@globali1 = global i8 0, align 1
+
+define void @test_i1_stack(i32 %a, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i1 zeroext %b) {
+ entry:
+ %frombool = zext i1 %b to i8
+ store i8 %frombool, i8* @globali1, align 1
+ ret void
+}
+
+; CHECK-LABEL: name: test_i1_stack
+
+; 32BIT-LABEL: fixedStack:
+; 32BIT-DAG: - { id: 0, type: default, offset: 59, size: 1
+; 32BIT-DAG: body: |
+; 32BIT-DAG: bb.0.entry:
+; 32BIT-DAG: renamable $r[[REGB:[0-9]+]] = LBZ 0, %fixed-stack.0 :: (load 1 from %fixed-stack.0)
+; 32BIT-DAG: renamable $r[[REGBTOC:[0-9]+]] = LWZtoc @globali1, $r2 :: (load 4 from got)
+; 32BIT-DAG: STB killed renamable $r[[REGB]], 0, killed renamable $r[[REGBTOC]] :: (store 1 into @globali1)
+
+; 64BIT-LABEL: fixedStack:
+; 64BIT-DAG: - { id: 0, type: default, offset: 119, size: 1
+; 64BIT-DAG: body: |
+; 64BIT-DAG: bb.0.entry:
+; 64BIT-DAG: renamable $r[[REGB:[0-9]+]] = LBZ 0, %fixed-stack.0 :: (load 1 from %fixed-stack.0)
+; 64BIT-DAG: renamable $x[[REGBTOC:[0-9]+]] = LDtoc @globali1, $x2 :: (load 8 from got)
+; 64BIT-DAG: STB killed renamable $r[[SCRATCHREG:[0-9]+]], 0, killed renamable $x[[REGBTOC]] :: (store 1 into @globali1)
+; 64BIT-DAG: BLR8 implicit $lr8, implicit $rm
+
+; CHECKASM-LABEL: test_i1_stack:
+
+; ASM32PWR4-DAG: lbz [[REGB:[0-9]+]], 59(1)
+; ASM32PWR4-DAG: lwz [[REGBTOC:[0-9]+]], LC18(2)
+; ASM32PWR4-DAG: stb [[SCRATCHREG:[0-9]+]], 0([[REGBTOC]])
+; ASM32PWR4-DAG: blr
+
+; ASM64PWR4-DAG: lbz [[REGB:[0-9]+]], 119(1)
+; ASM64PWR4-DAG: ld [[REGBTOC:[0-9]+]], LC17(2)
+; ASM64PWR4-DAG: stb [[SCRATCHREG:[0-9]+]], 0([[REGBTOC]])
+; ASM64PWR4-DAG: blr
+
+define void @call_test_i1_stack() {
+ entry:
+ call void @test_i1_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i1 true)
+ ret void
+}
+
+; CHECK-LABEL: name: call_test_i1_stack
+
+; 32BIT-DAG: ADJCALLSTACKDOWN 60, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-DAG: $r3 = LI 1
+; 32BIT-DAG: $r4 = LI 2
+; 32BIT-DAG: $r5 = LI 3
+; 32BIT-DAG: $r6 = LI 4
+; 32BIT-DAG: $r7 = LI 5
+; 32BIT-DAG: $r8 = LI 6
+; 32BIT-DAG: $r9 = LI 7
+; 32BIT-DAG: $r10 = LI 8
+; 32BIT-DAG: renamable $r[[REGBOOLADDR:[0-9]+]] = LI 1
+; 32BIT-DAG: STB killed renamable $r[[REGBOOLADDR]], 56, $r1 :: (store 1)
+; 32BIT-DAG: BL_NOP <mcsymbol .test_i1_stack>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $r3, implicit $r4, implicit $r5, implicit $r6, implicit $r7, implicit $r8, implicit $r9, implicit $r10, implicit $r2, implicit-def $r1
+; 32BIT-DAG: ADJCALLSTACKUP 60, 0, implicit-def dead $r1, implicit $r1
+
+; 64BIT-DAG: ADJCALLSTACKDOWN 120, 0, implicit-def dead $r1, implicit $r1
+; 64BIT-DAG: $x3 = LI8 1
+; 64BIT-DAG: $x4 = LI8 2
+; 64BIT-DAG: $x5 = LI8 3
+; 64BIT-DAG: $x6 = LI8 4
+; 64BIT-DAG: $x7 = LI8 5
+; 64BIT-DAG: $x8 = LI8 6
+; 64BIT-DAG: $x9 = LI8 7
+; 64BIT-DAG: $x10 = LI8 8
+; 64BIT-DAG: renamable $x[[REGBOOLADDR:[0-9]+]] = LI8 1
+; 64BIT-DAG: STB8 killed renamable $x[[REGBOOLADDR]], 112, $x1 :: (store 1)
+; 64BIT-DAG: BL8_NOP <mcsymbol .test_i1_stack>, csr_aix64, implicit-def dead $lr8, implicit $rm, implicit $x3, implicit $x4, implicit $x5, implicit $x6, implicit $x7, implicit $x8, implicit $x9, implicit $x10, implicit $x2, implicit-def $r1
+; 64BIT-DAG: ADJCALLSTACKUP 120, 0, implicit-def dead $r1, implicit $r1
+
+; CHECKASM-LABEL: .call_test_i1_stack:
+
+; ASM32PWR4-DAG: mflr 0
+; ASM32PWR4-DAG: li 3, 1
+; ASM32PWR4-DAG: li 4, 2
+; ASM32PWR4-DAG: li 5, 3
+; ASM32PWR4-DAG: li 6, 4
+; ASM32PWR4-DAG: li 7, 5
+; ASM32PWR4-DAG: li 8, 6
+; ASM32PWR4-DAG: li 9, 7
+; ASM32PWR4-DAG: li 10, 8
+; ASM32PWR4-DAG: stb [[REGB:[0-9]+]], 56(1)
+; ASM32PWR4-DAG: li [[REGB]], 1
+; ASM32PWR4-DAG: bl .test_i1
+
+; ASM64PWR-DAG: mflr 0
+; ASM64PWR-DAG: li 3, 1
+; ASM64PWR-DAG: li 4, 2
+; ASM64PWR-DAG: li 5, 3
+; ASM64PWR-DAG: li 6, 4
+; ASM64PWR-DAG: li 7, 5
+; ASM64PWR-DAG: li 8, 6
+; ASM64PWR-DAG: li 9, 7
+; ASM64PWR-DAG: li 10, 8
+; ASM64PWR-DAG: stb [[REGB:[0-9]+]], 112(1)
+; ASM64PWR-DAG: li [[REGB]], 1
+; ASM64PWR-DAG: bl .test_i1
+
define double @test_fpr_stack(double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %s10, double %l11, double %d12, double %d13, float %f14, double %d15, float %f16) {
entry:
%add = fadd double %d1, %d2
@@ -2085,6 +2414,40 @@
; 32BIT-DAG: ADJCALLSTACKUP 84, 0, implicit-def dead $r1, implicit $r1
; 32BIT-NEXT: BLR implicit $lr, implicit $rm
+; 32BIT-DAG: ADJCALLSTACKDOWN 84, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-DAG: STW killed renamable $r[[REG1ADDR:[0-9]+]], 56, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG2ADDR:[0-9]+]], 60, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG3ADDR:[0-9]+]], 64, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG4ADDR:[0-9]+]], 68, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG5ADDR:[0-9]+]], 72, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG6ADDR:[0-9]+]], 76, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG7ADDR:[0-9]+]], 80, $r1 :: (store 4)
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LWZtoc %const.0, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $f1 = LFD 0, killed renamable $r[[SCRATCHREG:[0-9]+]] :: (load 8 from constant-pool)
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LWZtoc %const.1, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $f2 = LFD 0, killed renamable $r[[SCRATCHREG:[0-9]+]] :: (load 8 from constant-pool)
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LWZtoc %const.2, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $f3 = LFD 0, killed renamable $r[[SCRATCHREG:[0-9]+]] :: (load 8 from constant-pool)
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LWZtoc %const.3, $r2 :: (load 4 from got)
+; 32BIT-DAG: renamable $f4 = LFD 0, killed renamable $r[[SCRATCHREG:[0-9]+]] :: (load 8 from constant-pool)
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LI 1
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LI 2
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LIS 457
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LI 0
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LI 40
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LI 50
+; 32BIT-DAG: renamable $r[[SCRATCHREG:[0-9]+]] = LI 60
+; 32BIT-DAG: STW killed renamable $r[[REG1:[0-9]+]], 56, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG2:[0-9]+]], 60, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG3:[0-9]+]], 64, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG4:[0-9]+]], 68, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG5:[0-9]+]], 72, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG6:[0-9]+]], 76, $r1 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r[[REG7:[0-9]+]], 80, $r1 :: (store 4)
+; 32BIT-DAG: BL_NOP <mcsymbol .mix_callee>, csr_aix32, implicit-def dead $lr, implicit $rm, implicit $f1, implicit $f2, implicit $f3, implicit $f4, implicit $r2, implicit-def $r1, implicit-def dead $r3
+; 32BIT-DAG: ADJCALLSTACKUP 84, 0, implicit-def dead $r1, implicit $r1
+; 32BIT-NEXT: BLR implicit $lr, implicit $rm
+
; 64BIT-DAG: ADJCALLSTACKDOWN 128, 0, implicit-def dead $r1, implicit $r1
; 64BIT-DAG: renamable $x[[SCRATCHREG:[0-9]+]] = LDtocCPT %const.0, $x2 :: (load 8 from got)
; 64BIT-DAG: renamable $x[[SCRATCHREG:[0-9]+]] = LDtocCPT %const.1, $x2 :: (load 8 from got)
Index: llvm/test/CodeGen/PowerPC/aix-cc-abi-va_args-32.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/PowerPC/aix-cc-abi-va_args-32.ll
@@ -0,0 +1,277 @@
+; RUN: llc -O2 -mtriple powerpc-ibm-aix-xcoff -stop-after=machine-cp -mattr=-altivec -verify-machineinstrs < %s | \
+; RUN: FileCheck --check-prefixes=CHECK,32BIT %s
+
+; RUN: llc -O2 -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec \
+; RUN: -mtriple powerpc-ibm-aix-xcoff < %s | \
+; RUN: FileCheck --check-prefixes=CHECKASM,ASM32PWR4 %s
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind
+declare void @llvm.va_start(i8*) #2
+
+; Function Attrs: nounwind
+declare void @llvm.va_end(i8*) #2
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+@a = local_unnamed_addr global i32 1, align 4
+@b = local_unnamed_addr global i32 2, align 4
+@c = local_unnamed_addr global i32 3, align 4
+@d = local_unnamed_addr global i32 4, align 4
+@e = local_unnamed_addr global i32 5, align 4
+@f = local_unnamed_addr global i32 6, align 4
+@g = local_unnamed_addr global i32 7, align 4
+@h = local_unnamed_addr global i32 8, align 4
+@i = local_unnamed_addr global i32 9, align 4
+@j = local_unnamed_addr global i32 10, align 4
+
+; Function Attrs: nounwind
+define i32 @va_arg1(i32 %a, ...) local_unnamed_addr #0 {
+entry:
+ %arg = alloca i8*, align 4
+ %0 = bitcast i8** %arg to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #2
+ call void @llvm.va_start(i8* nonnull %0)
+ %cmp7 = icmp sgt i32 %a, 0
+ br i1 %cmp7, label %for.body.preheader, label %for.end
+
+for.body.preheader: ; preds = %entry
+ %argp.cur.pre = load i8*, i8** %arg, align 4
+ %min.iters.check = icmp eq i32 %a, 1
+ br i1 %min.iters.check, label %for.body.preheader15, label %vector.memcheck
+
+vector.memcheck: ; preds = %for.body.preheader
+ %uglygep = getelementptr inbounds i8, i8* %0, i32 1
+ %1 = shl i32 %a, 2
+ %scevgep = getelementptr i8, i8* %argp.cur.pre, i32 %1
+ %bound0 = icmp ugt i8* %scevgep, %0
+ %bound1 = icmp ult i8* %argp.cur.pre, %uglygep
+ %found.conflict = and i1 %bound0, %bound1
+ br i1 %found.conflict, label %for.body.preheader15, label %vector.ph
+
+vector.ph: ; preds = %vector.memcheck
+ %n.vec = and i32 %a, -2
+ %2 = shl i32 %n.vec, 2
+ %ind.end = getelementptr i8, i8* %argp.cur.pre, i32 %2
+ br label %vector.body
+
+vector.body: ; preds = %vector.body, %vector.ph
+ %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
+ %vec.phi = phi i32 [ undef, %vector.ph ], [ %11, %vector.body ]
+ %vec.phi13 = phi i32 [ 0, %vector.ph ], [ %12, %vector.body ]
+ %3 = shl i32 %index, 2
+ %next.gep = getelementptr i8, i8* %argp.cur.pre, i32 %3
+ %4 = shl i32 %index, 2
+ %5 = or i32 %4, 4
+ %next.gep12 = getelementptr i8, i8* %argp.cur.pre, i32 %5
+ %6 = getelementptr inbounds i8, i8* %next.gep12, i32 4
+ %7 = bitcast i8* %next.gep to i32*
+ %8 = bitcast i8* %next.gep12 to i32*
+ %9 = load i32, i32* %7, align 4
+ %10 = load i32, i32* %8, align 4
+ %11 = add i32 %9, %vec.phi
+ %12 = add i32 %10, %vec.phi13
+ %index.next = add i32 %index, 2
+ %13 = icmp eq i32 %index.next, %n.vec
+ br i1 %13, label %middle.block, label %vector.body
+
+middle.block: ; preds = %vector.body
+ store i8* %6, i8** %arg, align 4
+ %bin.rdx = add i32 %12, %11
+ %cmp.n = icmp eq i32 %n.vec, %a
+ br i1 %cmp.n, label %for.end, label %for.body.preheader15
+
+for.body.preheader15: ; preds = %middle.block, %vector.memcheck, %for.body.preheader
+ %argp.cur.ph = phi i8* [ %argp.cur.pre, %vector.memcheck ], [ %argp.cur.pre, %for.body.preheader ], [ %ind.end, %middle.block ]
+ %total.09.ph = phi i32 [ undef, %vector.memcheck ], [ undef, %for.body.preheader ], [ %bin.rdx, %middle.block ]
+ %i.08.ph = phi i32 [ 0, %vector.memcheck ], [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
+ br label %for.body
+
+for.body: ; preds = %for.body.preheader15, %for.body
+ %argp.cur = phi i8* [ %argp.next, %for.body ], [ %argp.cur.ph, %for.body.preheader15 ]
+ %total.09 = phi i32 [ %add, %for.body ], [ %total.09.ph, %for.body.preheader15 ]
+ %i.08 = phi i32 [ %inc, %for.body ], [ %i.08.ph, %for.body.preheader15 ]
+ %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
+ store i8* %argp.next, i8** %arg, align 4
+ %14 = bitcast i8* %argp.cur to i32*
+ %15 = load i32, i32* %14, align 4
+ %add = add nsw i32 %15, %total.09
+ %inc = add nuw nsw i32 %i.08, 1
+ %exitcond = icmp eq i32 %inc, %a
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body, %middle.block, %entry
+ %total.0.lcssa = phi i32 [ undef, %entry ], [ %bin.rdx, %middle.block ], [ %add, %for.body ]
+ call void @llvm.va_end(i8* nonnull %0)
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #2
+ ret i32 %total.0.lcssa
+}
+
+
+; 32BIT-LABEL: name: va_arg1
+; 32BIT-LABEL: liveins:
+; 32BIT-DAG: - { reg: '$r3', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r4', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r5', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r6', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r7', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r8', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r9', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r10', virtual-reg: '' }
+; 32BIT-LABEL: fixedStack:
+; 32BIT-DAG: - { id: 0, type: default, offset: 28, size: 4
+; 32BIT-LABEL: body: |
+; 32BIT-LABEL: bb.0.entry:
+; 32BIT-DAG: liveins: $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10
+; 32BIT-DAG: renamable $cr0 = CMPWI renamable $r3, 1
+; 32BIT-DAG: STW killed renamable $r4, 0, %fixed-stack.0 :: (store 4 into %fixed-stack.0)
+; 32BIT-DAG: STW killed renamable $r5, 4, %fixed-stack.0 :: (store 4 into %fixed-stack.0 + 4)
+; 32BIT-DAG: STW killed renamable $r6, 8, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r7, 12, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r8, 16, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r9, 20, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG: STW killed renamable $r10, 24, %fixed-stack.0 :: (store 4)
+; 32BIT-DAG: renamable $r[[SCRATHREG:[0-9]+]] = ADDI %fixed-stack.0, 0
+; 32BIT-DAG: STW killed renamable $r[[SCRATHREG:[0-9]+]], 0, %stack.0.arg :: (store 4 into %ir.0)
+
+; ASM32PWR4-LABEL: .va_arg1:
+; ASM32PWR4-DAG: cmpwi 3, 1
+; ASM32PWR4-DAG: stw 4, 28(1)
+; ASM32PWR4-DAG: stw 5, 32(1)
+; ASM32PWR4-DAG: stw 6, 36(1)
+; ASM32PWR4-DAG: stw 7, 40(1)
+; ASM32PWR4-DAG: stw 8, 44(1)
+; ASM32PWR4-DAG: stw 9, 48(1)
+; ASM32PWR4-DAG: stw 10, 52(1)
+; ASM32PWR4-DAG: stw [[SCRATCHREG:[0-9]+]], -4(1)
+; ASM32PWR4-DAG: addi [[SCRATCHREG:[0-9]+]], 1, 28
+; ASM32PWR4-DAG: blt 0, LBB0_8
+
+
+define i32 @va_arg2(i32 %one, i32 %two, i32 %three, i32 %four, i32 %five, i32 %six, i32 %seven, i32 %eight, ...) local_unnamed_addr #0 {
+entry:
+ %arg = alloca i8*, align 4
+ %0 = bitcast i8** %arg to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #2
+ call void @llvm.va_start(i8* nonnull %0)
+ %add = add nsw i32 %two, %one
+ %add2 = add nsw i32 %add, %three
+ %add3 = add nsw i32 %add2, %four
+ %add4 = add nsw i32 %add3, %five
+ %add5 = add nsw i32 %add4, %six
+ %add6 = add nsw i32 %add5, %seven
+ %add7 = add nsw i32 %add6, %eight
+ %cmp15 = icmp sgt i32 %eight, 0
+ br i1 %cmp15, label %for.body.preheader, label %for.end
+
+for.body.preheader: ; preds = %entry
+ %argp.cur.pre = load i8*, i8** %arg, align 4
+ %min.iters.check = icmp eq i32 %eight, 1
+ br i1 %min.iters.check, label %for.body.preheader23, label %vector.memcheck
+
+vector.memcheck: ; preds = %for.body.preheader
+ %uglygep = getelementptr inbounds i8, i8* %0, i32 1
+ %1 = shl i32 %eight, 2
+ %scevgep = getelementptr i8, i8* %argp.cur.pre, i32 %1
+ %bound0 = icmp ugt i8* %scevgep, %0
+ %bound1 = icmp ult i8* %argp.cur.pre, %uglygep
+ %found.conflict = and i1 %bound0, %bound1
+ br i1 %found.conflict, label %for.body.preheader23, label %vector.ph
+
+vector.ph: ; preds = %vector.memcheck
+ %n.vec = and i32 %eight, -2
+ %2 = shl i32 %n.vec, 2
+ %ind.end = getelementptr i8, i8* %argp.cur.pre, i32 %2
+ br label %vector.body
+
+vector.body: ; preds = %vector.body, %vector.ph
+ %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
+ %vec.phi = phi i32 [ %add7, %vector.ph ], [ %11, %vector.body ]
+ %vec.phi21 = phi i32 [ 0, %vector.ph ], [ %12, %vector.body ]
+ %3 = shl i32 %index, 2
+ %next.gep = getelementptr i8, i8* %argp.cur.pre, i32 %3
+ %4 = shl i32 %index, 2
+ %5 = or i32 %4, 4
+ %next.gep20 = getelementptr i8, i8* %argp.cur.pre, i32 %5
+ %6 = getelementptr inbounds i8, i8* %next.gep20, i32 4
+ %7 = bitcast i8* %next.gep to i32*
+ %8 = bitcast i8* %next.gep20 to i32*
+ %9 = load i32, i32* %7, align 4
+ %10 = load i32, i32* %8, align 4
+ %11 = add i32 %9, %vec.phi
+ %12 = add i32 %10, %vec.phi21
+ %index.next = add i32 %index, 2
+ %13 = icmp eq i32 %index.next, %n.vec
+ br i1 %13, label %middle.block, label %vector.body
+
+middle.block: ; preds = %vector.body
+ store i8* %6, i8** %arg, align 4
+ %bin.rdx = add i32 %12, %11
+ %cmp.n = icmp eq i32 %n.vec, %eight
+ br i1 %cmp.n, label %for.end, label %for.body.preheader23
+
+for.body.preheader23: ; preds = %middle.block, %vector.memcheck, %for.body.preheader
+ %argp.cur.ph = phi i8* [ %argp.cur.pre, %vector.memcheck ], [ %argp.cur.pre, %for.body.preheader ], [ %ind.end, %middle.block ]
+ %total.017.ph = phi i32 [ %add7, %vector.memcheck ], [ %add7, %for.body.preheader ], [ %bin.rdx, %middle.block ]
+ %i.016.ph = phi i32 [ 0, %vector.memcheck ], [ 0, %for.body.preheader ], [ %n.vec, %middle.block ]
+ br label %for.body
+
+for.body: ; preds = %for.body.preheader23, %for.body
+ %argp.cur = phi i8* [ %argp.next, %for.body ], [ %argp.cur.ph, %for.body.preheader23 ]
+ %total.017 = phi i32 [ %add8, %for.body ], [ %total.017.ph, %for.body.preheader23 ]
+ %i.016 = phi i32 [ %inc, %for.body ], [ %i.016.ph, %for.body.preheader23 ]
+ %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
+ store i8* %argp.next, i8** %arg, align 4
+ %14 = bitcast i8* %argp.cur to i32*
+ %15 = load i32, i32* %14, align 4
+ %add8 = add nsw i32 %15, %total.017
+ %inc = add nuw nsw i32 %i.016, 1
+ %exitcond = icmp eq i32 %inc, %eight
+ br i1 %exitcond, label %for.end, label %for.body
+
+for.end: ; preds = %for.body, %middle.block, %entry
+ %total.0.lcssa = phi i32 [ %add7, %entry ], [ %bin.rdx, %middle.block ], [ %add8, %for.body ]
+ call void @llvm.va_end(i8* nonnull %0)
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #2
+ ret i32 %total.0.lcssa
+}
+
+; 32BIT-LABEL: name: va_arg2
+; 32BIT-LABEL: liveins:
+; 32BIT-DAG: - { reg: '$r3', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r4', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r5', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r6', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r7', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r8', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r9', virtual-reg: '' }
+; 32BIT-DAG: - { reg: '$r10', virtual-reg: '' }
+; 32BIT-LABEL: fixedStack:
+; 32BIT-DAG: - { id: 0, type: default, offset: 56, size: 4
+; 32BIT-LABEL: body: |
+; 32BIT-LABEL: bb.0.entry:
+; 32BIT-DAG: liveins: $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10
+; 32BIT-DAG: STW killed renamable $r11, 0, %stack.0.arg :: (store 4 into %ir.0)
+; 32BIT-DAG: renamable $r3 = nsw ADD4 killed renamable $r4, killed renamable $r3
+; 32BIT-DAG: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r5
+; 32BIT-DAG: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r6
+; 32BIT-DAG: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r7
+; 32BIT-DAG: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r8
+; 32BIT-DAG: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r9
+; 32BIT-DAG: renamable $cr0 = CMPWI renamable $r10, 1
+; 32BIT-DAG: renamable $r3 = nsw ADD4 killed renamable $r3, renamable $r10
+; 32BIT-DAG: renamable $r11 = ADDI %fixed-stack.0, 0
+
+; ASM32PWR4-LABEL: .va_arg2:
+; ASM32PWR4-DAG: add 3, 4, 3
+; ASM32PWR4-DAG: add 3, 3, 5
+; ASM32PWR4-DAG: add 3, 3, 6
+; ASM32PWR4-DAG: add 3, 3, 7
+; ASM32PWR4-DAG: add 3, 3, 8
+; ASM32PWR4-DAG: add 3, 3, 9
+; ASM32PWR4-DAG: add 3, 3, 10
+; ASM32PWR4-DAG: cmpwi 10, 1
+; ASM32PWR4-DAG: addi [[SCRATCHREG:[0-9]+]], 1, 56
+; ASM32PWR4-DAG: stw [[SCRATCHREG:[0-9]+]], -4(1)
+
Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
===================================================================
--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -3238,7 +3238,7 @@
SDLoc dl(Op);
- if (Subtarget.isPPC64()) {
+ if (Subtarget.isPPC64() || Subtarget.isAIXABI()) {
// vastart just stores the address of the VarArgsFrameIndex slot into the
// memory location argument.
SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
@@ -6967,9 +6967,6 @@
CallConv == CallingConv::Fast) &&
"Unexpected calling convention!");
- if (isVarArg)
- report_fatal_error("This call type is unimplemented on AIX.");
-
if (getTargetMachine().Options.GuaranteedTailCallOpt)
report_fatal_error("Tail call support is unimplemented on AIX.");
@@ -6982,11 +6979,15 @@
report_fatal_error("QPX support is not supported on AIX.");
const bool IsPPC64 = Subtarget.isPPC64();
+ if (IsPPC64 && isVarArg)
+ report_fatal_error("This call type is unimplemented on 63-bit AIX.");
+
const unsigned PtrByteSize = IsPPC64 ? 8 : 4;
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext());
const EVT PtrVT = getPointerTy(MF.getDataLayout());
@@ -7013,7 +7014,7 @@
if (VA.isMemLoc() && VA.needsCustom())
continue;
- if (VA.isRegLoc()) {
+ if (VA.isRegLoc() && !VA.needsCustom()) {
MVT::SimpleValueType SVT = ValVT.getSimpleVT().SimpleTy;
unsigned VReg =
MF.addLiveIn(VA.getLocReg(), getRegClassForSVT(SVT, IsPPC64));
@@ -7025,42 +7026,87 @@
}
InVals.push_back(ArgValue);
continue;
+ } else if (VA.isMemLoc()) {
+ const unsigned LocSize = LocVT.getStoreSize();
+ const unsigned ValSize = ValVT.getStoreSize();
+ assert((ValSize <= LocSize) &&
+ "Object size is larger than size of MemLoc");
+ int CurArgOffset = VA.getLocMemOffset();
+ // Objects are right-justified because AIX is big-endian.
+ if (LocSize > ValSize)
+ CurArgOffset += LocSize - ValSize;
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ // Potential tail calls could cause overwriting of argument stack slots.
+ const bool IsImmutable =
+ !(getTargetMachine().Options.GuaranteedTailCallOpt &&
+ (CallConv == CallingConv::Fast));
+ int FI = MFI.CreateFixedObject(ValSize, CurArgOffset, IsImmutable);
+ SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
+ SDValue ArgValue =
+ DAG.getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo());
+ InVals.push_back(ArgValue);
+ }
+ }
+ // On AIX a minimum of 8 words is saved to the parameter save area.
+ const unsigned MinParameterSaveArea = 8 * PtrByteSize;
+ // Area that is at least reserved in the caller of this function.
+ unsigned CallerReservedArea = std::max(CCInfo.getNextStackOffset(),
+ LinkageSize + MinParameterSaveArea);
+
+ // Set the size that is at least reserved in caller of this function. Tail
+ // call optimized function's reserved stack space needs to be aligned so
+ // that taking the difference between two stack areas will result in an
+ // aligned stack.
+ CallerReservedArea =
+ EnsureStackAlignment(Subtarget.getFrameLowering(), CallerReservedArea);
+ PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
+ FuncInfo->setMinReservedArea(CallerReservedArea);
+
+ SmallVector<SDValue, 8> MemOps;
+
+ if (isVarArg) {
+
+ const static MCPhysReg GPR_32[] = {PPC::R3, PPC::R4, PPC::R5, PPC::R6,
+ PPC::R7, PPC::R8, PPC::R9, PPC::R10};
+
+ const static MCPhysReg GPR_64[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6,
+ PPC::X7, PPC::X8, PPC::X9, PPC::X10};
+
+ const unsigned NumGPArgRegs = array_lengthof(IsPPC64 ? GPR_64 : GPR_32);
+
+ FuncInfo->setVarArgsNumGPR(
+ CCInfo.getFirstUnallocated(IsPPC64 ? GPR_64 : GPR_32));
+ FuncInfo->setVarArgsFrameIndex(MFI.CreateFixedObject(
+ PtrByteSize, CCInfo.getNextStackOffset(), true));
+ SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
+ // The fixed integer arguments of a variadic function are stored to the
+ // VarArgsFrameIndex on the stack so that they may be loaded by
+ // dereferencing the result of va_next.
+ for (unsigned GPRIndex =
+ (CCInfo.getNextStackOffset() - LinkageSize) / PtrByteSize;
+ GPRIndex < NumGPArgRegs; ++GPRIndex) {
+ unsigned VReg = MF.getRegInfo().getLiveInVirtReg(
+ IsPPC64 ? GPR_64[GPRIndex] : GPR_32[GPRIndex]);
+ if (!VReg) {
+ if (IsPPC64)
+ VReg = MF.addLiveIn(GPR_64[GPRIndex], &PPC::G8RCRegClass);
+ else
+ VReg = MF.addLiveIn(GPR_32[GPRIndex], &PPC::GPRCRegClass);
+ }
+ SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
+ SDValue Store =
+ DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo());
+ MemOps.push_back(Store);
+ // Increment the address for the next argument to store.
+ SDValue PtrOff = DAG.getConstant(PtrByteSize, dl, PtrVT);
+ FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff);
+ }
}
- const unsigned LocSize = LocVT.getStoreSize();
- const unsigned ValSize = ValVT.getStoreSize();
- assert((ValSize <= LocSize) && "Object size is larger than size of MemLoc");
- int CurArgOffset = VA.getLocMemOffset();
- // Objects are right-justified because AIX is big-endian.
- if (LocSize > ValSize)
- CurArgOffset += LocSize - ValSize;
- MachineFrameInfo &MFI = MF.getFrameInfo();
- // Potential tail calls could cause overwriting of argument stack slots.
- const bool IsImmutable =
- !(getTargetMachine().Options.GuaranteedTailCallOpt &&
- (CallConv == CallingConv::Fast));
- int FI = MFI.CreateFixedObject(ValSize, CurArgOffset, IsImmutable);
- SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
- SDValue ArgValue = DAG.getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo());
- InVals.push_back(ArgValue);
- }
-
- // On AIX a minimum of 8 words is saved to the parameter save area.
- const unsigned MinParameterSaveArea = 8 * PtrByteSize;
- // Area that is at least reserved in the caller of this function.
- unsigned CallerReservedArea =
- std::max(CCInfo.getNextStackOffset(), LinkageSize + MinParameterSaveArea);
-
- // Set the size that is at least reserved in caller of this function. Tail
- // call optimized function's reserved stack space needs to be aligned so
- // that taking the difference between two stack areas will result in an
- // aligned stack.
- CallerReservedArea =
- EnsureStackAlignment(Subtarget.getFrameLowering(), CallerReservedArea);
- PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
- FuncInfo->setMinReservedArea(CallerReservedArea);
+ if (!MemOps.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
- return Chain;
+ return Chain;
}
SDValue PPCTargetLowering::LowerCall_AIX(
Index: clang/test/CodeGen/aix-vararg.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aix-vararg.c
@@ -0,0 +1,30 @@
+// REQUIRES: powerpc-registered-target
+// REQUIRES: asserts
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -emit-llvm -o - %s | FileCheck %s --check-prefix=32BIT
+#include <stdarg.h>
+
+void aix_varg(int a, ...) {
+ va_list arg;
+ va_start(arg, a);
+ va_arg(arg, int);
+ va_end(arg);
+}
+
+// 32BIT: define void @aix_varg(i32 %a, ...) #0 {
+// 32BIT: entry:
+// 32BIT-NEXT: %a.addr = alloca i32, align 4
+// 32BIT-NEXT: %arg = alloca i8*, align 4
+// 32BIT-NEXT: store i32 %a, i32* %a.addr, align 4
+// 32BIT-NEXT: %arg1 = bitcast i8** %arg to i8*
+// 32BIT-NEXT: call void @llvm.va_start(i8* %arg1)
+// 32BIT-NEXT: %argp.cur = load i8*, i8** %arg, align 4
+// 32BIT-NEXT: %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4
+// 32BIT-NEXT: store i8* %argp.next, i8** %arg, align 4
+// 32BIT-NEXT: %0 = bitcast i8* %argp.cur to i32*
+// 32BIT-NEXT: %1 = load i32, i32* %0, align 4
+// 32BIT-NEXT: %arg2 = bitcast i8** %arg to i8*
+// 32BIT-NEXT: call void @llvm.va_end(i8* %arg2)
+// 32BIT-NEXT: ret void
+// 32BIT-NEXT: }
+// 32BIT: declare void @llvm.va_start(i8*)
+// 32BIT: declare void @llvm.va_end(i8*)
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -4229,7 +4229,10 @@
// DefaultABIInfo::EmitVAArg.
Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList,
QualType Ty) const {
- if (getTarget().getTriple().isOSDarwin()) {
+ // TODO: Add AIX ABI Info. Currently we are relying on PPC32_SVR4_ABIInfo to
+ // emit correct VAArg.
+ if (getTarget().getTriple().isOSDarwin() ||
+ getTarget().getTriple().isOSAIX()) {
auto TI = getContext().getTypeInfoInChars(Ty);
TI.second = getParamTypeAlignment(Ty);
Index: clang/lib/Basic/Targets/PPC.h
===================================================================
--- clang/lib/Basic/Targets/PPC.h
+++ clang/lib/Basic/Targets/PPC.h
@@ -369,7 +369,8 @@
}
BuiltinVaListKind getBuiltinVaListKind() const override {
- // This is the ELF definition, and is overridden by the Darwin sub-target
+ // This is the ELF definition, and is overridden by the Darwin and AIX
+ // sub-target
return TargetInfo::PowerABIBuiltinVaList;
}
};
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits