diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -1139,6 +1139,10 @@ PPC::AddrMode SelectForceXFormMode(SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG) const; + bool + splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, + SDValue *Parts, unsigned NumParts, MVT PartVT, + Optional CC) const override; /// Structure that collects some common arguments that get passed around /// between the functions for call lowering. struct CallFlags { diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -15989,8 +15989,11 @@ } break; case 'v': - if (Subtarget.hasAltivec()) + if (Subtarget.hasAltivec() && VT.isVector()) return std::make_pair(0U, &PPC::VRRCRegClass); + else if (Subtarget.hasVSX()) + // Scalars in Altivec registers only make sense with VSX. + return std::make_pair(0U, &PPC::VFRCRegClass); break; case 'y': // crrc return std::make_pair(0U, &PPC::CRRCRegClass); @@ -17687,6 +17690,20 @@ return Mode; } +bool PPCTargetLowering::splitValueIntoRegisterParts( + SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, + unsigned NumParts, MVT PartVT, Optional CC) const { + EVT ValVT = Val.getValueType(); + if (PartVT == MVT::f64 && + (ValVT == MVT::i32 || ValVT == MVT::i16 || ValVT == MVT::i8)) { + Val = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Val); + Val = DAG.getNode(ISD::BITCAST, DL, MVT::f64, Val); + Parts[0] = Val; + return true; + } + return false; +} + // If we happen to match to an aligned D-Form, check if the Frame Index is // adequately aligned. If it is not, reset the mode to match to X-Form. static void setXFormForUnalignedFI(SDValue N, unsigned Flags, diff --git a/llvm/test/CodeGen/PowerPC/scalars-in-altivec-regs.ll b/llvm/test/CodeGen/PowerPC/scalars-in-altivec-regs.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/scalars-in-altivec-regs.ll @@ -0,0 +1,247 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=powerpc64-unknown-aix-xcoff -verify-machineinstrs \ +; RUN: -mcpu=pwr8 < %s | FileCheck --check-prefix=AIX64 %s +; RUN: llc -mtriple=powerpc-unknown-aix-xcoff -verify-machineinstrs \ +; RUN: -mcpu=pwr8 < %s | FileCheck --check-prefix=AIX32 %s +; RUN: llc -mtriple=powerpc64le-- -verify-machineinstrs -mcpu=pwr8 | \ +; RUN: FileCheck --check-prefix=LE %s + +define dso_local void @test1(<2 x double>* %v, i64 %a) local_unnamed_addr #0 { +; AIX64-LABEL: test1: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: mtvsrd 34, 4 +; AIX64-NEXT: #APP +; AIX64-NEXT: stvx 2, 0, 3 +; AIX64-NEXT: #NO_APP +; AIX64-NEXT: blr +; +; AIX32-LABEL: test1: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: stw 5, -4(1) +; AIX32-NEXT: stw 4, -8(1) +; AIX32-NEXT: lfd 0, -8(1) +; AIX32-NEXT: xxlor 34, 0, 0 +; AIX32-NEXT: #APP +; AIX32-NEXT: stvx 2, 0, 3 +; AIX32-NEXT: #NO_APP +; AIX32-NEXT: blr +; +; LE-LABEL: test1: +; LE: # %bb.0: # %entry +; LE-NEXT: mtvsrd 34, 4 +; LE-NEXT: #APP +; LE-NEXT: stvx 2, 0, 3 +; LE-NEXT: #NO_APP +; LE-NEXT: blr +entry: + tail call void asm sideeffect "stvx $0,0,$1", "v,r,~{memory}"(i64 %a, <2 x double>* %v) + ret void +} + +define dso_local void @test2(<2 x double>* %v, i32 signext %a) local_unnamed_addr #0 { +; AIX64-LABEL: test2: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: clrldi 4, 4, 32 +; AIX64-NEXT: mtvsrd 34, 4 +; AIX64-NEXT: #APP +; AIX64-NEXT: stvx 2, 0, 3 +; AIX64-NEXT: #NO_APP +; AIX64-NEXT: blr +; +; AIX32-LABEL: test2: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: li 5, 0 +; AIX32-NEXT: stw 4, -4(1) +; AIX32-NEXT: stw 5, -8(1) +; AIX32-NEXT: lfd 0, -8(1) +; AIX32-NEXT: xxlor 34, 0, 0 +; AIX32-NEXT: #APP +; AIX32-NEXT: stvx 2, 0, 3 +; AIX32-NEXT: #NO_APP +; AIX32-NEXT: blr +; +; LE-LABEL: test2: +; LE: # %bb.0: # %entry +; LE-NEXT: clrldi 4, 4, 32 +; LE-NEXT: mtvsrd 34, 4 +; LE-NEXT: #APP +; LE-NEXT: stvx 2, 0, 3 +; LE-NEXT: #NO_APP +; LE-NEXT: blr +entry: + tail call void asm sideeffect "stvx $0,0,$1", "v,r,~{memory}"(i32 %a, <2 x double>* %v) + ret void +} + +define dso_local void @test3(<2 x double>* %v, i16 signext %a) local_unnamed_addr #0 { +; AIX64-LABEL: test3: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: clrldi 4, 4, 48 +; AIX64-NEXT: mtvsrd 34, 4 +; AIX64-NEXT: #APP +; AIX64-NEXT: stvx 2, 0, 3 +; AIX64-NEXT: #NO_APP +; AIX64-NEXT: blr +; +; AIX32-LABEL: test3: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: li 5, 0 +; AIX32-NEXT: clrlwi 4, 4, 16 +; AIX32-NEXT: stw 5, -8(1) +; AIX32-NEXT: stw 4, -4(1) +; AIX32-NEXT: lfd 0, -8(1) +; AIX32-NEXT: xxlor 34, 0, 0 +; AIX32-NEXT: #APP +; AIX32-NEXT: stvx 2, 0, 3 +; AIX32-NEXT: #NO_APP +; AIX32-NEXT: blr +; +; LE-LABEL: test3: +; LE: # %bb.0: # %entry +; LE-NEXT: clrldi 4, 4, 48 +; LE-NEXT: mtvsrd 34, 4 +; LE-NEXT: #APP +; LE-NEXT: stvx 2, 0, 3 +; LE-NEXT: #NO_APP +; LE-NEXT: blr +entry: + tail call void asm sideeffect "stvx $0,0,$1", "v,r,~{memory}"(i16 %a, <2 x double>* %v) + ret void +} + +define dso_local void @test4(<2 x double>* %v, i8 signext %a) local_unnamed_addr #0 { +; AIX64-LABEL: test4: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: clrldi 4, 4, 56 +; AIX64-NEXT: mtvsrd 34, 4 +; AIX64-NEXT: #APP +; AIX64-NEXT: stvx 2, 0, 3 +; AIX64-NEXT: #NO_APP +; AIX64-NEXT: blr +; +; AIX32-LABEL: test4: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: li 5, 0 +; AIX32-NEXT: clrlwi 4, 4, 24 +; AIX32-NEXT: stw 5, -8(1) +; AIX32-NEXT: stw 4, -4(1) +; AIX32-NEXT: lfd 0, -8(1) +; AIX32-NEXT: xxlor 34, 0, 0 +; AIX32-NEXT: #APP +; AIX32-NEXT: stvx 2, 0, 3 +; AIX32-NEXT: #NO_APP +; AIX32-NEXT: blr +; +; LE-LABEL: test4: +; LE: # %bb.0: # %entry +; LE-NEXT: clrldi 4, 4, 56 +; LE-NEXT: mtvsrd 34, 4 +; LE-NEXT: #APP +; LE-NEXT: stvx 2, 0, 3 +; LE-NEXT: #NO_APP +; LE-NEXT: blr +entry: + tail call void asm sideeffect "stvx $0,0,$1", "v,r,~{memory}"(i8 %a, <2 x double>* %v) + ret void +} + +define dso_local void @test6(<2 x double>* %v, i32 zeroext %a) local_unnamed_addr #0 { +; AIX64-LABEL: test6: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: mtvsrd 34, 4 +; AIX64-NEXT: #APP +; AIX64-NEXT: stvx 2, 0, 3 +; AIX64-NEXT: #NO_APP +; AIX64-NEXT: blr +; +; AIX32-LABEL: test6: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: li 5, 0 +; AIX32-NEXT: stw 4, -4(1) +; AIX32-NEXT: stw 5, -8(1) +; AIX32-NEXT: lfd 0, -8(1) +; AIX32-NEXT: xxlor 34, 0, 0 +; AIX32-NEXT: #APP +; AIX32-NEXT: stvx 2, 0, 3 +; AIX32-NEXT: #NO_APP +; AIX32-NEXT: blr +; +; LE-LABEL: test6: +; LE: # %bb.0: # %entry +; LE-NEXT: mtvsrd 34, 4 +; LE-NEXT: #APP +; LE-NEXT: stvx 2, 0, 3 +; LE-NEXT: #NO_APP +; LE-NEXT: blr +entry: + tail call void asm sideeffect "stvx $0,0,$1", "v,r,~{memory}"(i32 %a, <2 x double>* %v) + ret void +} + +define dso_local void @test7(<2 x double>* %v, i16 zeroext %a) local_unnamed_addr #0 { +; AIX64-LABEL: test7: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: mtvsrd 34, 4 +; AIX64-NEXT: #APP +; AIX64-NEXT: stvx 2, 0, 3 +; AIX64-NEXT: #NO_APP +; AIX64-NEXT: blr +; +; AIX32-LABEL: test7: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: li 5, 0 +; AIX32-NEXT: stw 4, -4(1) +; AIX32-NEXT: stw 5, -8(1) +; AIX32-NEXT: lfd 0, -8(1) +; AIX32-NEXT: xxlor 34, 0, 0 +; AIX32-NEXT: #APP +; AIX32-NEXT: stvx 2, 0, 3 +; AIX32-NEXT: #NO_APP +; AIX32-NEXT: blr +; +; LE-LABEL: test7: +; LE: # %bb.0: # %entry +; LE-NEXT: mtvsrd 34, 4 +; LE-NEXT: #APP +; LE-NEXT: stvx 2, 0, 3 +; LE-NEXT: #NO_APP +; LE-NEXT: blr +entry: + tail call void asm sideeffect "stvx $0,0,$1", "v,r,~{memory}"(i16 %a, <2 x double>* %v) + ret void +} + +define dso_local void @test8(<2 x double>* %v, i8 zeroext %a) local_unnamed_addr #0 { +; AIX64-LABEL: test8: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT: mtvsrd 34, 4 +; AIX64-NEXT: #APP +; AIX64-NEXT: stvx 2, 0, 3 +; AIX64-NEXT: #NO_APP +; AIX64-NEXT: blr +; +; AIX32-LABEL: test8: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT: li 5, 0 +; AIX32-NEXT: stw 4, -4(1) +; AIX32-NEXT: stw 5, -8(1) +; AIX32-NEXT: lfd 0, -8(1) +; AIX32-NEXT: xxlor 34, 0, 0 +; AIX32-NEXT: #APP +; AIX32-NEXT: stvx 2, 0, 3 +; AIX32-NEXT: #NO_APP +; AIX32-NEXT: blr +; +; LE-LABEL: test8: +; LE: # %bb.0: # %entry +; LE-NEXT: mtvsrd 34, 4 +; LE-NEXT: #APP +; LE-NEXT: stvx 2, 0, 3 +; LE-NEXT: #NO_APP +; LE-NEXT: blr +entry: + tail call void asm sideeffect "stvx $0,0,$1", "v,r,~{memory}"(i8 %a, <2 x double>* %v) + ret void +} + +attributes #0 = { nounwind }