diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td b/llvm/lib/Target/PowerPC/PPCCallingConv.td --- a/llvm/lib/Target/PowerPC/PPCCallingConv.td +++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td @@ -291,6 +291,8 @@ F27, F28, F29, F30, F31, CR2, CR3, CR4 )>; +def CSR_AIX32_Altivec : CalleeSavedRegs<(add CSR_AIX32, CSR_Altivec)>; + // Common CalleeSavedRegs for SVR4 and AIX. def CSR_PPC64 : CalleeSavedRegs<(add X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -223,13 +223,13 @@ CALLEE_SAVED_GPRS32, // Add AIX's extra CSR. {PPC::R13, -76}, - // TODO: Update when we add vector support for AIX. + CALLEE_SAVED_VRS }; static const SpillSlot AIXOffsets64[] = { CALLEE_SAVED_FPRS, CALLEE_SAVED_GPRS64, - // TODO: Update when we add vector support for AIX. + CALLEE_SAVED_VRS }; if (Subtarget.is64BitELFABI()) { diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -188,7 +188,8 @@ } // 32-bit targets. if (Subtarget.isAIXABI()) - return CSR_AIX32_SaveList; + return (Subtarget.hasAltivec()) ? CSR_AIX32_Altivec_SaveList + : CSR_AIX32_SaveList; if (Subtarget.hasAltivec()) return CSR_SVR432_Altivec_SaveList; else if (Subtarget.hasSPE()) @@ -209,8 +210,11 @@ } if (Subtarget.isAIXABI()) { - assert(!Subtarget.hasAltivec() && "Altivec is not implemented on AIX yet."); - return TM.isPPC64() ? CSR_PPC64_RegMask : CSR_AIX32_RegMask; + return TM.isPPC64() + ? (Subtarget.hasAltivec() ? CSR_64_AllRegs_Altivec_RegMask + : CSR_PPC64_RegMask) + : (Subtarget.hasAltivec() ? CSR_AIX32_Altivec_RegMask + : CSR_AIX32_RegMask); } if (CC == CallingConv::Cold) { diff --git a/llvm/test/CodeGen/PowerPC/aix-csr-vector.ll b/llvm/test/CodeGen/PowerPC/aix-csr-vector.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-csr-vector.ll @@ -0,0 +1,253 @@ +; RUN: llc -mtriple=powerpc-unknown-aix-xcoff -verify-machineinstrs -mcpu=pwr7 \ +; RUN: -mattr=+altivec -stop-after=prologepilog < %s | \ +; RUN: FileCheck --check-prefix=MIR32 %s + +; RUN: llc -mtriple=powerpc-unknown-aix-xcoff -verify-machineinstrs \ +; RUN: -mcpu=pwr7 -mattr=+altivec < %s | \ +; RUN: FileCheck --check-prefix=ASM32 %s + +; RUN: llc -mtriple=powerpc64-unknown-aix-xcoff -verify-machineinstrs \ +; RUN: -mcpu=pwr7 -mattr=+altivec -stop-after=prologepilog < %s | \ +; RUN: FileCheck --check-prefix=MIR64 %s + +; RUN: llc -mtriple=powerpc64-unknown-aix-xcoff -verify-machineinstrs \ +; RUN: -mcpu=pwr7 -mattr=+altivec < %s | \ +; RUN: FileCheck --check-prefix=ASM64 %s + + +define dso_local void @vec_regs() { +entry: + call void asm sideeffect "", "~{v13},~{v20},~{v26},~{v31}"() + ret void +} + +; MIR32: name: vec_regs + +; MIR32-LABEL: fixedStack: +; MIR32-NEXT: - { id: 0, type: spill-slot, offset: -16, size: 16, alignment: 16, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$v31', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: - { id: 1, type: spill-slot, offset: -96, size: 16, alignment: 16, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$v26', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: - { id: 2, type: spill-slot, offset: -192, size: 16, alignment: 16, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$v20', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: stack: + +; MIR32: liveins: $v20, $v26, $v31 + +; MIR32-DAG: STXVD2X killed $v20, $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (store 16 into %fixed-stack.2) +; MIR32-DAG: STXVD2X killed $v26, $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (store 16 into %fixed-stack.1) +; MIR32-DAG: STXVD2X killed $v31, $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (store 16 into %fixed-stack.0) + +; MIR32: INLINEASM + +; MIR32-DAG: $v20 = LXVD2X $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (load 16 from %fixed-stack.2) +; MIR32-DAG: $v26 = LXVD2X $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (load 16 from %fixed-stack.1) +; MIR32-DAG: $v31 = LXVD2X $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (load 16 from %fixed-stack.0) +; MIR32: BLR implicit $lr, implicit $rm + +; MIR64: name: vec_regs + +; MIR64-LABEL: fixedStack: +; MIR64-NEXT: - { id: 0, type: spill-slot, offset: -16, size: 16, alignment: 16, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$v31', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: - { id: 1, type: spill-slot, offset: -96, size: 16, alignment: 16, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$v26', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: - { id: 2, type: spill-slot, offset: -192, size: 16, alignment: 16, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$v20', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: stack: + +; MIR64: liveins: $v20, $v26, $v31 + +; MIR64-DAG: STXVD2X killed $v20, $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (store 16 into %fixed-stack.2) +; MIR64-DAG: STXVD2X killed $v26, $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (store 16 into %fixed-stack.1) +; MIR64-DAG: STXVD2X killed $v31, $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (store 16 into %fixed-stack.0) + +; MIR64: INLINEASM + +; MIR64-DAG: $v20 = LXVD2X $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (load 16 from %fixed-stack.2) +; MIR64-DAG: $v26 = LXVD2X $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (load 16 from %fixed-stack.1) +; MIR64-DAG: $v31 = LXVD2X $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (load 16 from %fixed-stack.0) +; MIR64: BLR8 implicit $lr8, implicit $rm + + +; ASM32-LABEL: .vec_regs: + +; ASM32: li {{[0-9]+}}, -192 +; ASM32-DAG: stxvd2x 52, 1, {{[0-9]+}} # 16-byte Folded Spill +; ASM32-DAG: li {{[0-9]+}}, -96 +; ASM32-DAG: stxvd2x 58, 1, {{[0-9]+}} # 16-byte Folded Spill +; ASM32-DAG: li {{[0-9]+}}, -16 +; ASM32-DAG: stxvd2x 63, 1, {{[0-9]+}} # 16-byte Folded Spill +; ASM32: #APP +; ASM32-DAG: #NO_APP +; ASM32-DAG: lxvd2x 63, {{[0-9]+}}, {{[0-9]+}} # 16-byte Folded Reload +; ASM32-DAG: li {{[0-9]+}}, -96 +; ASM32-DAG: lxvd2x 58, {{[0-9]+}}, {{[0-9]+}} # 16-byte Folded Reload +; ASM32-DAG: li {{[0-9]+}}, -192 +; ASM32-DAG: lxvd2x 52, {{[0-9]+}}, {{[0-9]+}} # 16-byte Folded Reload +; ASM32: blr + +; ASM64-LABEL: .vec_regs: + +; ASM64-DAG: li {{[0-9]+}}, -192 +; ASM64-DAG: stxvd2x 52, 1, {{[0-9]+}} # 16-byte Folded Spill +; ASM64-DAG: li {{[0-9]+}}, -96 +; ASM64-DAG: stxvd2x 58, 1, {{[0-9]+}} # 16-byte Folded Spill +; ASM64-DAG: li {{[0-9]+}}, -16 +; ASM64-DAG: stxvd2x 6{{[0-9]+}}, 1, {{[0-9]+}} # 16-byte Folded Spill +; ASM64-DAG: #APP +; ASM64-DAG: #NO_APP +; ASM64-DAG: lxvd2x 6{{[0-9]+}}, 1, {{[0-9]+}} # 16-byte Folded Reload +; ASM64-DAG: li {{[0-9]+}}, -96 +; ASM64-DAG: lxvd2x 58, 1, {{[0-9]+}} # 16-byte Folded Reload +; ASM64-DAG: li {{[0-9]+}}, -192 +; ASM64-DAG: lxvd2x 52, 1, {{[0-9]+}} # 16-byte Folded Reload +; ASM64-DAG: blr + +define dso_local void @fprs_gprs_vecregs() { + call void asm sideeffect "", "~{r25},~{r31},~{f21},~{f31},~{v21},~{v31}"() + ret void +} + +; MIR32: name: fprs_gprs_vecregs +; MIR32-LABEL: fixedStack: +; MIR32-NEXT: - { id: 0, type: spill-slot, offset: -144, size: 16, alignment: 16, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$v31', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: - { id: 1, type: spill-slot, offset: -304, size: 16, alignment: 16, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$v21', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: - { id: 2, type: spill-slot, offset: -8, size: 8, alignment: 8, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$f31', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: - { id: 3, type: spill-slot, offset: -88, size: 8, alignment: 8, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$f21', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: - { id: 4, type: spill-slot, offset: -92, size: 4, alignment: 4, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$r31', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: - { id: 5, type: spill-slot, offset: -116, size: 4, alignment: 4, stack-id: default, +; MIR32-NEXT: callee-saved-register: '$r25', callee-saved-restored: true, debug-info-variable: '', +; MIR32-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR32-NEXT: stack: + +; MIR32: liveins: $r25, $r31, $f21, $f31, $v21, $v31 + +; MIR32-DAG: STFD killed $f31, 328, $r{{[0-9]+}} :: (store 8 into %fixed-stack.2) +; MIR32-DAG: $r{{[0-9]+}} = LI 32 +; MIR32-DAG: STXVD2X killed $v21, $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (store 16 into %fixed-stack.1) +; MIR32-DAG: $r{{[0-9]+}} = LI 192 +; MIR32-DAG: STXVD2X killed $v31, $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (store 16 into %fixed-stack.0) + +; MIR32: INLINEASM + +; MIR32-DAG: $r{{[0-9]+}} = LI 192 +; MIR32-DAG: $v31 = LXVD2X $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (load 16 from %fixed-stack.0) +; MIR32-DAG: $r{{[0-9]+}} = LI 32 +; MIR32-DAG: $v21 = LXVD2X $r{{[0-9]+}}, killed $r{{[0-9]+}} :: (load 16 from %fixed-stack.1) +; MIR32-DAG: $f31 = LFD 328, $r{{[0-9]+}} :: (load 8 from %fixed-stack.2) +; MIR32-DAG: $f21 = LFD 248, $r{{[0-9]+}} :: (load 8 from %fixed-stack.3) +; MIR32-DAG: $r{{[0-9]+}}1 = LWZ 244, $r{{[0-9]+}} :: (load 4 from %fixed-stack.4) +; MIR32-DAG: $r25 = LWZ 220, $r{{[0-9]+}} :: (load 4 from %fixed-stack.5) +; MIR32-DAG: $r1 = ADDI $r1, 336 +; MIR32-DAG: BLR implicit $lr, implicit $rm + +; MIR64: name: fprs_gprs_vecregs + +; MIR64-LABEL: fixedStack: +; MIR64-NEXT: - { id: 0, type: spill-slot, offset: -160, size: 16, alignment: 16, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$v31', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: - { id: 1, type: spill-slot, offset: -320, size: 16, alignment: 16, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$v21', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: - { id: 2, type: spill-slot, offset: -8, size: 8, alignment: 8, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$f31', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: - { id: 3, type: spill-slot, offset: -88, size: 8, alignment: 8, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$f21', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: - { id: 4, type: spill-slot, offset: -96, size: 8, alignment: 8, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$x31', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: - { id: 5, type: spill-slot, offset: -144, size: 8, alignment: 8, stack-id: default, +; MIR64-NEXT: callee-saved-register: '$x25', callee-saved-restored: true, debug-info-variable: '', +; MIR64-NEXT: debug-info-expression: '', debug-info-location: '' } +; MIR64-NEXT: stack: + +; MIR64: liveins: $x25, $x31, $f21, $f31, $v21, $v31 + +; MIR64-DAG: $x1 = STDU $x1, -384, $x1 +; MIR64-DAG: STD killed $x25, 240, $x{{[0-9]+}} :: (store 8 into %fixed-stack.5) +; MIR64-DAG: STD killed $x31, 288, $x{{[0-9]+}} :: (store 8 into %fixed-stack.4) +; MIR64-DAG: STFD killed $f21, 296, $x{{[0-9]+}} :: (store 8 into %fixed-stack.3) +; MIR64-DAG: STFD killed $f31, 376, $x{{[0-9]+}} :: (store 8 into %fixed-stack.2) +; MIR64-DAG: $x{{[0-9]+}} = LI8 64 +; MIR64-DAG: STXVD2X killed $v21, $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (store 16 into %fixed-stack.1) +; MIR64-DAG: $x{{[0-9]+}} = LI8 224 +; MIR64-DAG: STXVD2X killed $v31, $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (store 16 into %fixed-stack.0) + +; MIR64: INLINEASM + +; MIR64-DAG: $x3 = LI8 224 +; MIR64-DAG: $v31 = LXVD2X $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (load 16 from %fixed-stack.0) +; MIR64-DAG: $x{{[0-9]+}} = LI8 64 +; MIR64-DAG: $v21 = LXVD2X $x{{[0-9]+}}, killed $x{{[0-9]+}} :: (load 16 from %fixed-stack.1) +; MIR64-DAG: $f31 = LFD 376, $x{{[0-9]+}} :: (load 8 from %fixed-stack.2) +; MIR64-DAG: $f21 = LFD 296, $x{{[0-9]+}} :: (load 8 from %fixed-stack.3) +; MIR64-DAG: $x31 = LD 288, $x{{[0-9]+}} :: (load 8 from %fixed-stack.4) +; MIR64-DAG: $x25 = LD 240, $x{{[0-9]+}} :: (load 8 from %fixed-stack.5) +; MIR64-DAG: $x1 = ADDI8 $x1, 384 +; MIR64-DAG: BLR8 implicit $lr8, implicit $rm + +; ASM32-LABEL: .fprs_gprs_vecregs: + +; ASM32-DAG: stwu 1, -336(1) +; ASM32-DAG: li {{[0-9]+}}, 32 +; ASM32-DAG: stw 25, 220(1) # 4-byte Folded Spill +; ASM32-DAG: stfd 21, 248(1) # 8-byte Folded Spill +; ASM32-DAG: stxvd2x 53, {{[0-9]+}}, {{[0-9]+}} # 16-byte Folded Spill +; ASM32-DAG: li {{[0-9]+}}, 192 +; ASM32-DAG: stw 31, 244(1) # 4-byte Folded Spill +; ASM32-DAG: stfd 31, 328(1) # 8-byte Folded Spill +; ASM32-DAG: stxvd2x 63, {{[0-9]+}}, {{[0-9]+}} # 16-byte Folded Spill +; ASM32-DAG: #APP +; ASM32-DAG: #NO_APP +; ASM32-DAG: lxvd2x 63, {{[0-9]+}}, {{[0-9]+}} # 16-byte Folded Reload +; ASM32-DAG: li {{[0-9]+}}, 32 +; ASM32-DAG: lfd 31, 328(1) # 8-byte Folded Reload +; ASM32-DAG: lxvd2x 53, {{[0-9]+}}, {{[0-9]+}} # 16-byte Folded Reload +; ASM32-DAG: lfd 21, 248(1) # 8-byte Folded Reload +; ASM32-DAG: lwz 31, 244(1) # 4-byte Folded Reload +; ASM32-DAG: lwz 25, 220(1) # 4-byte Folded Reload +; ASM32-DAG: addi 1, 1, 336 +; ASM32-DAG: blr + +; ASM64-LABEL: .fprs_gprs_vecregs: + +; ASM64-DAG: stdu 1, -384(1) +; ASM64-DAG: li {{[0-9]+}}, 64 +; ASM64-DAG: std 25, 240(1) # 8-byte Folded Spill +; ASM64-DAG: stfd 21, 296(1) # 8-byte Folded Spill +; ASM64-DAG: stxvd2x 53, 1, {{[0-9]+}} # 16-byte Folded Spill +; ASM64-DAG: li {{[0-9]+}}, 224 +; ASM64-DAG: std 31, 288(1) # 8-byte Folded Spill +; ASM64-DAG: stfd 31, 376(1) # 8-byte Folded Spill +; ASM64-DAG: stxvd2x 63, 1, {{[0-9]+}} # 16-byte Folded Spill +; ASM64-DAG: #APP +; ASM64-DAG: #NO_APP +; ASM64-DAG: lxvd2x 63, 1, {{[0-9]+}} # 16-byte Folded Reload +; ASM64-DAG: li {{[0-9]+}}, 64 +; ASM64-DAG: lfd 31, {{[0-9]+}}76(1) # 8-byte Folded Reload +; ASM64-DAG: lxvd2x 53, 1, {{[0-9]+}} # 16-byte Folded Reload +; ASM64-DAG: lfd 21, 296(1) # 8-byte Folded Reload +; ASM64-DAG: ld 31, 288(1) # 8-byte Folded Reload +; ASM64-DAG: ld 25, 240(1) # 8-byte Folded Reload +; ASM64-DAG: addi 1, 1, 384 +; ASM64-DAG: blr