From 2b50ce152417286e0091a1683482457473d4d7a8 Mon Sep 17 00:00:00 2001 From: Zarko Todorovski Date: Fri, 5 Mar 2021 12:36:45 -0500 Subject: [PATCH] [PowerPC][AIX] Enable the default AltiVec ABI on AIX This patch adds support for the default AltiVec ABI for AIX. Vector registers 20 through 31 are marked as reserved and cannot be used in the default ABI. This patch adds handling for this case and also remove the default AltiVec ABI errors. Reviewed By: sfertile Differential Revision: https://reviews.llvm.org/D96351 --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 14 +- llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 54 ++++-- llvm/test/CodeGen/PowerPC/aix-csr-vector.ll | 201 +++++++++++++++++++++ .../aix-inlineasm-reserved-reg-dflt-warn.ll | 14 ++ llvm/test/CodeGen/PowerPC/aix-vec-abi.ll | 8 - 5 files changed, 264 insertions(+), 27 deletions(-) create mode 100644 llvm/test/CodeGen/PowerPC/aix-csr-vector.ll create mode 100644 llvm/test/CodeGen/PowerPC/aix-inlineasm-reserved-reg-dflt-warn.ll delete mode 100644 llvm/test/CodeGen/PowerPC/aix-vec-abi.ll diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 460ddd2..9ecf61d 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -6307,11 +6307,6 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT, const Align PtrAlign = IsPPC64 ? Align(8) : Align(4); const MVT RegVT = IsPPC64 ? MVT::i64 : MVT::i32; - if (ValVT.isVector() && !State.getMachineFunction() - .getTarget() - .Options.EnableAIXExtendedAltivecABI) - report_fatal_error("the default Altivec AIX ABI is not yet supported"); - if (ValVT == MVT::f128) report_fatal_error("f128 is unimplemented on AIX."); @@ -15327,6 +15322,15 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, R.first = PPC::CR0; R.second = &PPC::CRRCRegClass; } + // FIXME: This warning should ideally be emitted in the front end. + const auto &TM = getTargetMachine(); + if (Subtarget.isAIXABI() && !TM.getAIXExtendedAltivecABI()) { + if (((R.first >= PPC::V20 && R.first <= PPC::V31) || + (R.first >= PPC::VF20 && R.first <= PPC::VF31)) && + (R.second == &PPC::VSRCRegClass || R.second == &PPC::VSFRCRegClass)) + errs() << "warning: vector registers 20 to 32 are reserved in the " + "default AIX AltiVec ABI and cannot be used\n"; + } return R; } diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp index 76b1cfe..171bb77 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -156,10 +156,6 @@ PPCRegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) const MCPhysReg* PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { const PPCSubtarget &Subtarget = MF->getSubtarget(); - if (Subtarget.isAIXABI() && - (Subtarget.hasAltivec() && !TM.getAIXExtendedAltivecABI())) - report_fatal_error("the default AIX Altivec ABI is not yet " - "supported."); if (MF->getFunction().getCallingConv() == CallingConv::AnyReg) { if (!TM.isPPC64() && Subtarget.isAIXABI()) report_fatal_error("AnyReg unimplemented on 32-bit AIX."); @@ -200,15 +196,18 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { } // Standard calling convention CSRs. if (TM.isPPC64()) { - if (Subtarget.hasAltivec()) + if (Subtarget.hasAltivec() && + (!Subtarget.isAIXABI() || TM.getAIXExtendedAltivecABI())) { return SaveR2 ? CSR_PPC64_R2_Altivec_SaveList : CSR_PPC64_Altivec_SaveList; + } return SaveR2 ? CSR_PPC64_R2_SaveList : CSR_PPC64_SaveList; } // 32-bit targets. if (Subtarget.isAIXABI()) { if (Subtarget.hasAltivec()) - return CSR_AIX32_Altivec_SaveList; + return TM.getAIXExtendedAltivecABI() ? CSR_AIX32_Altivec_SaveList + : CSR_AIX32_SaveList; return CSR_AIX32_SaveList; } if (Subtarget.hasAltivec()) @@ -231,10 +230,13 @@ PPCRegisterInfo::getCallPreservedMask(const MachineFunction &MF, } if (Subtarget.isAIXABI()) { - return TM.isPPC64() ? (Subtarget.hasAltivec() ? CSR_PPC64_Altivec_RegMask - : CSR_PPC64_RegMask) - : (Subtarget.hasAltivec() ? CSR_AIX32_Altivec_RegMask - : CSR_AIX32_RegMask); + return TM.isPPC64() + ? ((Subtarget.hasAltivec() && TM.getAIXExtendedAltivecABI()) + ? CSR_PPC64_Altivec_RegMask + : CSR_PPC64_RegMask) + : ((Subtarget.hasAltivec() && TM.getAIXExtendedAltivecABI()) + ? CSR_AIX32_Altivec_RegMask + : CSR_AIX32_RegMask); } if (CC == CallingConv::Cold) { @@ -335,6 +337,17 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const { IE = PPC::VRRCRegClass.end(); I != IE; ++I) markSuperRegs(Reserved, *I); + if (Subtarget.isAIXABI() && Subtarget.hasAltivec() && + !TM.getAIXExtendedAltivecABI()) { + // In the AIX default Altivec ABI, vector registers VR20-VR31 are reserved + // and cannot be used. + for (auto Reg : CSR_Altivec_SaveList) { + if (Reg == 0) + break; + markSuperRegs(Reserved, Reg); + } + } + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } @@ -426,15 +439,28 @@ unsigned PPCRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, unsigned FP = TFI->hasFP(MF) ? 1 : 0; return 32 - FP - DefaultSafety; } - case PPC::F8RCRegClassID: case PPC::F4RCRegClassID: - case PPC::VRRCRegClassID: - case PPC::VFRCRegClassID: + case PPC::F8RCRegClassID: case PPC::VSLRCRegClassID: return 32 - DefaultSafety; - case PPC::VSRCRegClassID: + case PPC::VFRCRegClassID: + case PPC::VRRCRegClassID: { + const PPCSubtarget &Subtarget = MF.getSubtarget(); + // Vector registers VR20-VR31 are reserved and cannot be used in the default + // Altivec ABI on AIX. + if (!TM.getAIXExtendedAltivecABI() && Subtarget.isAIXABI()) + return 20 - DefaultSafety; + } + return 32 - DefaultSafety; case PPC::VSFRCRegClassID: case PPC::VSSRCRegClassID: + case PPC::VSRCRegClassID: { + const PPCSubtarget &Subtarget = MF.getSubtarget(); + if (!TM.getAIXExtendedAltivecABI() && Subtarget.isAIXABI()) + // Vector registers VR20-VR31 are reserved and cannot be used in the + // default Altivec ABI on AIX. + return 52 - DefaultSafety; + } return 64 - DefaultSafety; case PPC::CRRCRegClassID: return 8 - DefaultSafety; diff --git a/llvm/test/CodeGen/PowerPC/aix-csr-vector.ll b/llvm/test/CodeGen/PowerPC/aix-csr-vector.ll new file mode 100644 index 0000000..05b8d31 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-csr-vector.ll @@ -0,0 +1,201 @@ +; 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-LABEL: name: vec_regs + +; MIR32: fixedStack: [] +; MIR32-NOT: STXVD2X killed $v20 +; MIR32-NOT: STXVD2X killed $v26 +; MIR32-NOT: STXVD2X killed $v31 +; MIR32-LABEL: INLINEASM +; MIR32-NOT: $v20 = LXVD2X +; MIR32-NOT: $v26 = LXVD2X +; MIR32-NOT: $v31 = LXVD2X +; MIR32: BLR implicit $lr, implicit $rm + +; MIR64-LABEL: name: vec_regs + +; MIR64: fixedStack: [] +; MIR64-NOT: STXVD2X killed $v20 +; MIR64-NOT: STXVD2X killed $v26 +; MIR64-NOT: STXVD2X killed $v31 +; MIR64-LABEL: INLINEASM +; MIR64-NOT: $v20 = LXVD2X +; MIR64-NOT: $v26 = LXVD2X +; MIR64-NOT: $v31 = LXVD2X +; MIR64: BLR8 implicit $lr8, implicit $rm + +; ASM32-LABEL: .vec_regs: + +; ASM32-NOT: 20 +; ASM32-NOT: 26 +; ASM32-NOT: 31 +; ASM32-DAG: #APP +; ASM32-DAG: #NO_APP +; ASM32: blr + +; ASM64-LABEL: .vec_regs: + +; ASM64-NOT: 20 +; ASM64-NOT: 26 +; ASM64-NOT: 31 +; ASM64-DAG: #APP +; ASM64-DAG: #NO_APP +; ASM64: blr + +define dso_local void @fprs_gprs_vecregs() { + call void asm sideeffect "", "~{r14},~{r25},~{r31},~{f14},~{f21},~{f31},~{v20},~{v26},~{v31}"() + ret void +} + +; MIR32-LABEL: name: fprs_gprs_vecregs + +; MIR32: fixedStack: + +; MIR32: liveins: $r14, $r25, $r31, $f14, $f21, $f31 + +; MIR32-NOT: STXVD2X killed $v20 +; MIR32-NOT: STXVD2X killed $v26 +; MIR32-NOT: STXVD2X killed $v31 +; MIR32-DAG: STW killed $r14, -216, $r1 :: (store 4 into %fixed-stack.5, align 8) +; MIR32-DAG: STW killed $r25, -172, $r1 :: (store 4 into %fixed-stack.4) +; MIR32-DAG: STW killed $r31, -148, $r1 :: (store 4 into %fixed-stack.3) +; MIR32-DAG: STFD killed $f14, -144, $r1 :: (store 8 into %fixed-stack.2, align 16) +; MIR32-DAG: STFD killed $f21, -88, $r1 :: (store 8 into %fixed-stack.1) +; MIR32-DAG: STFD killed $f31, -8, $r1 :: (store 8 into %fixed-stack.0) + +; MIR32-LABEL: INLINEASM + +; MIR32-NOT: $v20 = LXVD2X +; MIR32-NOT: $v26 = LXVD2X +; MIR32-NOT: $v31 = LXVD2X +; MIR32-DAG: $r14 = LWZ -216, $r1 :: (load 4 from %fixed-stack.5, align 8) +; MIR32-DAG: $r25 = LWZ -172, $r1 :: (load 4 from %fixed-stack.4) +; MIR32-DAG: $r31 = LWZ -148, $r1 :: (load 4 from %fixed-stack.3) +; MIR32-DAG: $f14 = LFD -144, $r1 :: (load 8 from %fixed-stack.2, align 16) +; MIR32-DAG: $f21 = LFD -88, $r1 :: (load 8 from %fixed-stack.1) +; MIR32-DAG: $f31 = LFD -8, $r1 :: (load 8 from %fixed-stack.0) +; MIR32-DAG: BLR implicit $lr, implicit $rm + +; MIR64-LABEL: name: fprs_gprs_vecregs + +; MIR64: fixedStack: + +; MIR64: liveins: $x14, $x25, $x31, $f14, $f21, $f31 + +; MIR64-NOT: STXVD2X killed $v20 +; MIR64-NOT: STXVD2X killed $v26 +; MIR64-NOT: STXVD2X killed $v31 +; MIR64-DAG: STD killed $x14, -288, $x1 :: (store 8 into %fixed-stack.5, align 16) +; MIR64-DAG: STD killed $x25, -200, $x1 :: (store 8 into %fixed-stack.4) +; MIR64-DAG: STD killed $x31, -152, $x1 :: (store 8 into %fixed-stack.3) +; MIR64-DAG: STFD killed $f14, -144, $x1 :: (store 8 into %fixed-stack.2, align 16) +; MIR64-DAG: STFD killed $f21, -88, $x1 :: (store 8 into %fixed-stack.1) +; MIR64-DAG: STFD killed $f31, -8, $x1 :: (store 8 into %fixed-stack.0) + +; MIR64-LABEL: INLINEASM + +; MIR64-NOT: $v20 = LXVD2X +; MIR64-NOT: $v26 = LXVD2X +; MIR64-NOT: $v31 = LXVD2X +; MIR64-DAG: $x14 = LD -288, $x1 :: (load 8 from %fixed-stack.5, align 16) +; MIR64-DAG: $x25 = LD -200, $x1 :: (load 8 from %fixed-stack.4) +; MIR64-DAG: $x31 = LD -152, $x1 :: (load 8 from %fixed-stack.3) +; MIR64-DAG: $f14 = LFD -144, $x1 :: (load 8 from %fixed-stack.2, align 16) +; MIR64-DAG: $f21 = LFD -88, $x1 :: (load 8 from %fixed-stack.1) +; MIR64-DAG: $f31 = LFD -8, $x1 :: (load 8 from %fixed-stack.0) +; MIR64: BLR8 implicit $lr8, implicit $rm + +;; We don't have -ppc-full-reg-names on AIX so can't reliably check-not for +;; only vector registers numbers in this case. + +; ASM32-LABEL: .fprs_gprs_vecregs: + +; ASM32-DAG: stw 14, -216(1) # 4-byte Folded Spill +; ASM32-DAG: stw 25, -172(1) # 4-byte Folded Spill +; ASM32-DAG: stw 31, -148(1) # 4-byte Folded Spill +; ASM32-DAG: stfd 14, -144(1) # 8-byte Folded Spill +; ASM32-DAG: stfd 21, -88(1) # 8-byte Folded Spill +; ASM32-DAG: stfd 31, -8(1) # 8-byte Folded Spill +; ASM32-DAG: #APP +; ASM32-DAG: #NO_APP +; ASM32-DAG: lfd 31, -8(1) # 8-byte Folded Reload +; ASM32-DAG: lfd 21, -88(1) # 8-byte Folded Reload +; ASM32-DAG: lfd 14, -144(1) # 8-byte Folded Reload +; ASM32-DAG: lwz 31, -148(1) # 4-byte Folded Reload +; ASM32-DAG: lwz 25, -172(1) # 4-byte Folded Reload +; ASM32-DAG: lwz 14, -216(1) # 4-byte Folded Reload +; ASM32: blr + +; ASM64-LABEL .fprs_gprs_vecregs: + +; ASM64-DAG: std 14, -288(1) # 8-byte Folded Spill +; ASM64-DAG: std 25, -200(1) # 8-byte Folded Spill +; ASM64-DAG: std 31, -152(1) # 8-byte Folded Spill +; ASM64-DAG: stfd 14, -144(1) # 8-byte Folded Spill +; ASM64-DAG: stfd 21, -88(1) # 8-byte Folded Spill +; ASM64-DAG: stfd 31, -8(1) # 8-byte Folded Spill +; ASM64-DAG: #APP +; ASM64-DAG: #NO_APP +; ASM64-DAG: lfd 31, -8(1) # 8-byte Folded Reload +; ASM64-DAG: lfd 21, -88(1) # 8-byte Folded Reload +; ASM64-DAG: lfd 14, -144(1) # 8-byte Folded Reload +; ASM64-DAG: ld 31, -152(1) # 8-byte Folded Reload +; ASM64-DAG: ld 25, -200(1) # 8-byte Folded Reload +; ASM64-DAG: ld 14, -288(1) # 8-byte Folded Reload +; ASM64: blr + +define dso_local void @all_fprs_and_vecregs() { + call void asm sideeffect "", "~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f18},~{f19},~{f20},~{f21},~{f22},~{f23},~{f24},~{f25},~{f26},~{f27},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6}~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19}"() + ret void +} + +;; Check that reserved vectors are not used. +; MIR32-LABEL: all_fprs_and_vecregs + +; MIR32-NOT: $v20 +; MIR32-NOT: $v21 +; MIR32-NOT: $v22 +; MIR32-NOT: $v23 +; MIR32-NOT: $v24 +; MIR32-NOT: $v25 +; MIR32-NOT: $v26 +; MIR32-NOT: $v27 +; MIR32-NOT: $v28 +; MIR32-NOT: $v29 +; MIR32-NOT: $v30 +; MIR32-NOT: $v31 + +; MIR64-LABEL: all_fprs_and_vecregs + +; MIR64-NOT: $v20 +; MIR64-NOT: $v21 +; MIR64-NOT: $v22 +; MIR64-NOT: $v23 +; MIR64-NOT: $v24 +; MIR64-NOT: $v25 +; MIR64-NOT: $v26 +; MIR64-NOT: $v27 +; MIR64-NOT: $v28 +; MIR64-NOT: $v29 +; MIR64-NOT: $v30 +; MIR64-NOT: $v31 diff --git a/llvm/test/CodeGen/PowerPC/aix-inlineasm-reserved-reg-dflt-warn.ll b/llvm/test/CodeGen/PowerPC/aix-inlineasm-reserved-reg-dflt-warn.ll new file mode 100644 index 0000000..645de08 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-inlineasm-reserved-reg-dflt-warn.ll @@ -0,0 +1,14 @@ +; RUN: llc < %s -mtriple=powerpc-unknown-aix-xcoff -verify-machineinstrs \ +; RUN: -mcpu=pwr7 -mattr=+altivec 2>&1 | \ +; RUN: FileCheck --check-prefix=DFLTWRN %s + +; RUN: llc < %s -mtriple=powerpc64-unknown-aix-xcoff -verify-machineinstrs \ +; RUN: -mcpu=pwr7 -mattr=+altivec 2>&1 | \ +; RUN: FileCheck --check-prefix=DFLTWRN %s +define dso_local void @vec_warn() { +entry: + call void asm sideeffect "", "~{v23}"() + ret void +} + +; DFLTWRN: warning: vector registers 20 to 32 are reserved in the default AIX AltiVec ABI and cannot be used diff --git a/llvm/test/CodeGen/PowerPC/aix-vec-abi.ll b/llvm/test/CodeGen/PowerPC/aix-vec-abi.ll deleted file mode 100644 index 9dac55c..0000000 --- a/llvm/test/CodeGen/PowerPC/aix-vec-abi.ll +++ /dev/null @@ -1,8 +0,0 @@ -; RUN: not --crash llc < %s -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr8 2>&1 | FileCheck %s --check-prefix=DFLTERROR -; RUN: not --crash llc < %s -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr8 2>&1 | FileCheck %s --check-prefix=DFLTERROR - -define void @vec_callee(<4 x i32> %vec1) { - ret void -} - -; DFLTERROR: LLVM ERROR: the default Altivec AIX ABI is not yet supported -- 2.7.4