[llvm] c9cb8ed - [PowerPC] Allow scalars for asm constraint "v" with VSX

Nemanja Ivanovic via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 23 15:03:13 PST 2021


Author: Nemanja Ivanovic
Date: 2021-11-23T17:03:04-06:00
New Revision: c9cb8edc519e4fa80b28fb4e0cc2bd8423742d21

URL: https://github.com/llvm/llvm-project/commit/c9cb8edc519e4fa80b28fb4e0cc2bd8423742d21
DIFF: https://github.com/llvm/llvm-project/commit/c9cb8edc519e4fa80b28fb4e0cc2bd8423742d21.diff

LOG: [PowerPC] Allow scalars for asm constraint "v" with VSX

Similarly to what GCC does, we should allow scalars with
the "v" constraint rather than introducing unnecessary
new constraints for scalars in Altivec registers.

Differential revision: https://reviews.llvm.org/D113635

Added: 
    llvm/test/CodeGen/PowerPC/scalars-in-altivec-regs.ll

Modified: 
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/lib/Target/PowerPC/PPCISelLowering.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index ac952b240a485..541e50d8dcce4 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15966,8 +15966,11 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
       }
       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);
@@ -17664,6 +17667,24 @@ PPC::AddrMode PPCTargetLowering::SelectForceXFormMode(SDValue N, SDValue &Disp,
   return Mode;
 }
 
+bool PPCTargetLowering::splitValueIntoRegisterParts(
+    SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts,
+    unsigned NumParts, MVT PartVT, Optional<CallingConv::ID> CC) const {
+  EVT ValVT = Val.getValueType();
+  // If we are splitting a scalar integer into f64 parts (i.e. so they
+  // can be placed into VFRC registers), we need to zero extend and
+  // bitcast the values. This will ensure the value is placed into a
+  // VSR using direct moves or stack operations as needed.
+  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/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 34dce2c3172d2..87b7f96112ec1 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -1139,6 +1139,10 @@ namespace llvm {
     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<CallingConv::ID> 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/test/CodeGen/PowerPC/scalars-in-altivec-regs.ll b/llvm/test/CodeGen/PowerPC/scalars-in-altivec-regs.ll
new file mode 100644
index 0000000000000..f1ace9d645165
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/scalars-in-altivec-regs.ll
@@ -0,0 +1,249 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=powerpc64-unknown-aix-xcoff -verify-machineinstrs \
+; RUN:   -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck \
+; RUN:   --check-prefix=AIX64 %s
+; RUN: llc -mtriple=powerpc-unknown-aix-xcoff -verify-machineinstrs \
+; RUN:   -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck \
+; RUN:   --check-prefix=AIX32 %s
+; RUN: llc -mtriple=powerpc64le-- -verify-machineinstrs \
+; RUN:   -ppc-asm-full-reg-names -mcpu=pwr8 < %s | 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 vs34, r4
+; AIX64-NEXT:    #APP
+; AIX64-NEXT:    stvx v2, 0, r3
+; AIX64-NEXT:    #NO_APP
+; AIX64-NEXT:    blr
+;
+; AIX32-LABEL: test1:
+; AIX32:       # %bb.0: # %entry
+; AIX32-NEXT:    stw r5, -4(r1)
+; AIX32-NEXT:    stw r4, -8(r1)
+; AIX32-NEXT:    lfd f0, -8(r1)
+; AIX32-NEXT:    xxlor vs34, f0, f0
+; AIX32-NEXT:    #APP
+; AIX32-NEXT:    stvx v2, 0, r3
+; AIX32-NEXT:    #NO_APP
+; AIX32-NEXT:    blr
+;
+; LE-LABEL: test1:
+; LE:       # %bb.0: # %entry
+; LE-NEXT:    mtvsrd vs34, r4
+; LE-NEXT:    #APP
+; LE-NEXT:    stvx v2, 0, r3
+; 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 r4, r4, 32
+; AIX64-NEXT:    mtvsrd vs34, r4
+; AIX64-NEXT:    #APP
+; AIX64-NEXT:    stvx v2, 0, r3
+; AIX64-NEXT:    #NO_APP
+; AIX64-NEXT:    blr
+;
+; AIX32-LABEL: test2:
+; AIX32:       # %bb.0: # %entry
+; AIX32-NEXT:    li r5, 0
+; AIX32-NEXT:    stw r4, -4(r1)
+; AIX32-NEXT:    stw r5, -8(r1)
+; AIX32-NEXT:    lfd f0, -8(r1)
+; AIX32-NEXT:    xxlor vs34, f0, f0
+; AIX32-NEXT:    #APP
+; AIX32-NEXT:    stvx v2, 0, r3
+; AIX32-NEXT:    #NO_APP
+; AIX32-NEXT:    blr
+;
+; LE-LABEL: test2:
+; LE:       # %bb.0: # %entry
+; LE-NEXT:    clrldi r4, r4, 32
+; LE-NEXT:    mtvsrd vs34, r4
+; LE-NEXT:    #APP
+; LE-NEXT:    stvx v2, 0, r3
+; 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 r4, r4, 48
+; AIX64-NEXT:    mtvsrd vs34, r4
+; AIX64-NEXT:    #APP
+; AIX64-NEXT:    stvx v2, 0, r3
+; AIX64-NEXT:    #NO_APP
+; AIX64-NEXT:    blr
+;
+; AIX32-LABEL: test3:
+; AIX32:       # %bb.0: # %entry
+; AIX32-NEXT:    li r5, 0
+; AIX32-NEXT:    clrlwi r4, r4, 16
+; AIX32-NEXT:    stw r5, -8(r1)
+; AIX32-NEXT:    stw r4, -4(r1)
+; AIX32-NEXT:    lfd f0, -8(r1)
+; AIX32-NEXT:    xxlor vs34, f0, f0
+; AIX32-NEXT:    #APP
+; AIX32-NEXT:    stvx v2, 0, r3
+; AIX32-NEXT:    #NO_APP
+; AIX32-NEXT:    blr
+;
+; LE-LABEL: test3:
+; LE:       # %bb.0: # %entry
+; LE-NEXT:    clrldi r4, r4, 48
+; LE-NEXT:    mtvsrd vs34, r4
+; LE-NEXT:    #APP
+; LE-NEXT:    stvx v2, 0, r3
+; 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 r4, r4, 56
+; AIX64-NEXT:    mtvsrd vs34, r4
+; AIX64-NEXT:    #APP
+; AIX64-NEXT:    stvx v2, 0, r3
+; AIX64-NEXT:    #NO_APP
+; AIX64-NEXT:    blr
+;
+; AIX32-LABEL: test4:
+; AIX32:       # %bb.0: # %entry
+; AIX32-NEXT:    li r5, 0
+; AIX32-NEXT:    clrlwi r4, r4, 24
+; AIX32-NEXT:    stw r5, -8(r1)
+; AIX32-NEXT:    stw r4, -4(r1)
+; AIX32-NEXT:    lfd f0, -8(r1)
+; AIX32-NEXT:    xxlor vs34, f0, f0
+; AIX32-NEXT:    #APP
+; AIX32-NEXT:    stvx v2, 0, r3
+; AIX32-NEXT:    #NO_APP
+; AIX32-NEXT:    blr
+;
+; LE-LABEL: test4:
+; LE:       # %bb.0: # %entry
+; LE-NEXT:    clrldi r4, r4, 56
+; LE-NEXT:    mtvsrd vs34, r4
+; LE-NEXT:    #APP
+; LE-NEXT:    stvx v2, 0, r3
+; 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 vs34, r4
+; AIX64-NEXT:    #APP
+; AIX64-NEXT:    stvx v2, 0, r3
+; AIX64-NEXT:    #NO_APP
+; AIX64-NEXT:    blr
+;
+; AIX32-LABEL: test6:
+; AIX32:       # %bb.0: # %entry
+; AIX32-NEXT:    li r5, 0
+; AIX32-NEXT:    stw r4, -4(r1)
+; AIX32-NEXT:    stw r5, -8(r1)
+; AIX32-NEXT:    lfd f0, -8(r1)
+; AIX32-NEXT:    xxlor vs34, f0, f0
+; AIX32-NEXT:    #APP
+; AIX32-NEXT:    stvx v2, 0, r3
+; AIX32-NEXT:    #NO_APP
+; AIX32-NEXT:    blr
+;
+; LE-LABEL: test6:
+; LE:       # %bb.0: # %entry
+; LE-NEXT:    mtvsrd vs34, r4
+; LE-NEXT:    #APP
+; LE-NEXT:    stvx v2, 0, r3
+; 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 vs34, r4
+; AIX64-NEXT:    #APP
+; AIX64-NEXT:    stvx v2, 0, r3
+; AIX64-NEXT:    #NO_APP
+; AIX64-NEXT:    blr
+;
+; AIX32-LABEL: test7:
+; AIX32:       # %bb.0: # %entry
+; AIX32-NEXT:    li r5, 0
+; AIX32-NEXT:    stw r4, -4(r1)
+; AIX32-NEXT:    stw r5, -8(r1)
+; AIX32-NEXT:    lfd f0, -8(r1)
+; AIX32-NEXT:    xxlor vs34, f0, f0
+; AIX32-NEXT:    #APP
+; AIX32-NEXT:    stvx v2, 0, r3
+; AIX32-NEXT:    #NO_APP
+; AIX32-NEXT:    blr
+;
+; LE-LABEL: test7:
+; LE:       # %bb.0: # %entry
+; LE-NEXT:    mtvsrd vs34, r4
+; LE-NEXT:    #APP
+; LE-NEXT:    stvx v2, 0, r3
+; 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 vs34, r4
+; AIX64-NEXT:    #APP
+; AIX64-NEXT:    stvx v2, 0, r3
+; AIX64-NEXT:    #NO_APP
+; AIX64-NEXT:    blr
+;
+; AIX32-LABEL: test8:
+; AIX32:       # %bb.0: # %entry
+; AIX32-NEXT:    li r5, 0
+; AIX32-NEXT:    stw r4, -4(r1)
+; AIX32-NEXT:    stw r5, -8(r1)
+; AIX32-NEXT:    lfd f0, -8(r1)
+; AIX32-NEXT:    xxlor vs34, f0, f0
+; AIX32-NEXT:    #APP
+; AIX32-NEXT:    stvx v2, 0, r3
+; AIX32-NEXT:    #NO_APP
+; AIX32-NEXT:    blr
+;
+; LE-LABEL: test8:
+; LE:       # %bb.0: # %entry
+; LE-NEXT:    mtvsrd vs34, r4
+; LE-NEXT:    #APP
+; LE-NEXT:    stvx v2, 0, r3
+; 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 }


        


More information about the llvm-commits mailing list