[llvm] r276800 - [Hexagon] Post-increment loads/stores enhancements

Krzysztof Parzyszek via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 26 13:30:31 PDT 2016


Author: kparzysz
Date: Tue Jul 26 15:30:30 2016
New Revision: 276800

URL: http://llvm.org/viewvc/llvm-project?rev=276800&view=rev
Log:
[Hexagon] Post-increment loads/stores enhancements

- Generate vector post-increment stores more aggressively.
- Predicate post-increment and vector stores in early if-conversion.

Added:
    llvm/trunk/test/CodeGen/Hexagon/early-if-vecpi.ll
Modified:
    llvm/trunk/lib/Target/Hexagon/HexagonEarlyIfConv.cpp
    llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
    llvm/trunk/lib/Target/Hexagon/HexagonInstrInfoV60.td
    llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
    llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.h

Modified: llvm/trunk/lib/Target/Hexagon/HexagonEarlyIfConv.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonEarlyIfConv.cpp?rev=276800&r1=276799&r2=276800&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonEarlyIfConv.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonEarlyIfConv.cpp Tue Jul 26 15:30:30 2016
@@ -134,7 +134,7 @@ namespace {
   public:
     static char ID;
     HexagonEarlyIfConversion() : MachineFunctionPass(ID),
-        TII(0), TRI(0), MFN(0), MRI(0), MDT(0), MLI(0) {
+        HII(0), TRI(0), MFN(0), MRI(0), MDT(0), MLI(0) {
       initializeHexagonEarlyIfConversionPass(*PassRegistry::getPassRegistry());
     }
     const char *getPassName() const override {
@@ -185,7 +185,7 @@ namespace {
     void mergeBlocks(MachineBasicBlock *PredB, MachineBasicBlock *SuccB);
     void simplifyFlowGraph(const FlowPattern &FP);
 
-    const TargetInstrInfo *TII;
+    const HexagonInstrInfo *HII;
     const TargetRegisterInfo *TRI;
     MachineFunction *MFN;
     MachineRegisterInfo *MRI;
@@ -443,7 +443,7 @@ unsigned HexagonEarlyIfConversion::compu
     }
     MachineInstr *Def1 = MRI->getVRegDef(RO1.getReg());
     MachineInstr *Def3 = MRI->getVRegDef(RO3.getReg());
-    if (!TII->isPredicable(*Def1) || !TII->isPredicable(*Def3))
+    if (!HII->isPredicable(*Def1) || !HII->isPredicable(*Def3))
       Cost++;
   }
   return Cost;
@@ -612,29 +612,26 @@ bool HexagonEarlyIfConversion::visitLoop
 
 bool HexagonEarlyIfConversion::isPredicableStore(const MachineInstr *MI)
       const {
-  // Exclude post-increment stores. Those return a value, so we cannot
-  // predicate them.
+  // HexagonInstrInfo::isPredicable will consider these stores are non-
+  // -predicable if the offset would become constant-extended after
+  // predication.
   unsigned Opc = MI->getOpcode();
-  using namespace Hexagon;
   switch (Opc) {
-    // Store byte:
-    case S2_storerb_io: case S4_storerb_rr:
-    case S2_storerbabs: case S4_storeirb_io:  case S2_storerbgp:
-    // Store halfword:
-    case S2_storerh_io: case S4_storerh_rr:
-    case S2_storerhabs: case S4_storeirh_io:  case S2_storerhgp:
-    // Store upper halfword:
-    case S2_storerf_io: case S4_storerf_rr:
-    case S2_storerfabs: case S2_storerfgp:
-    // Store word:
-    case S2_storeri_io: case S4_storeri_rr:
-    case S2_storeriabs: case S4_storeiri_io:  case S2_storerigp:
-    // Store doubleword:
-    case S2_storerd_io: case S4_storerd_rr:
-    case S2_storerdabs: case S2_storerdgp:
+    case Hexagon::S2_storerb_io:
+    case Hexagon::S2_storerbnew_io:
+    case Hexagon::S2_storerh_io:
+    case Hexagon::S2_storerhnew_io:
+    case Hexagon::S2_storeri_io:
+    case Hexagon::S2_storerinew_io:
+    case Hexagon::S2_storerd_io:
+    case Hexagon::S4_storeirb_io:
+    case Hexagon::S4_storeirh_io:
+    case Hexagon::S4_storeiri_io:
       return true;
   }
-  return false;
+
+  // TargetInstrInfo::isPredicable takes a non-const pointer.
+  return MI->mayStore() && HII->isPredicable(const_cast<MachineInstr&>(*MI));
 }
 
 
@@ -653,53 +650,7 @@ bool HexagonEarlyIfConversion::isSafeToS
 
 unsigned HexagonEarlyIfConversion::getCondStoreOpcode(unsigned Opc,
       bool IfTrue) const {
-  // Exclude post-increment stores.
-  using namespace Hexagon;
-  switch (Opc) {
-    case S2_storerb_io:
-      return IfTrue ? S2_pstorerbt_io : S2_pstorerbf_io;
-    case S4_storerb_rr:
-      return IfTrue ? S4_pstorerbt_rr : S4_pstorerbf_rr;
-    case S2_storerbabs:
-    case S2_storerbgp:
-      return IfTrue ? S4_pstorerbt_abs : S4_pstorerbf_abs;
-    case S4_storeirb_io:
-      return IfTrue ? S4_storeirbt_io : S4_storeirbf_io;
-    case S2_storerh_io:
-      return IfTrue ? S2_pstorerht_io : S2_pstorerhf_io;
-    case S4_storerh_rr:
-      return IfTrue ? S4_pstorerht_rr : S4_pstorerhf_rr;
-    case S2_storerhabs:
-    case S2_storerhgp:
-      return IfTrue ? S4_pstorerht_abs : S4_pstorerhf_abs;
-    case S2_storerf_io:
-      return IfTrue ? S2_pstorerft_io : S2_pstorerff_io;
-    case S4_storerf_rr:
-      return IfTrue ? S4_pstorerft_rr : S4_pstorerff_rr;
-    case S2_storerfabs:
-    case S2_storerfgp:
-      return IfTrue ? S4_pstorerft_abs : S4_pstorerff_abs;
-    case S4_storeirh_io:
-      return IfTrue ? S4_storeirht_io : S4_storeirhf_io;
-    case S2_storeri_io:
-      return IfTrue ? S2_pstorerit_io : S2_pstorerif_io;
-    case S4_storeri_rr:
-      return IfTrue ? S4_pstorerit_rr : S4_pstorerif_rr;
-    case S2_storeriabs:
-    case S2_storerigp:
-      return IfTrue ? S4_pstorerit_abs : S4_pstorerif_abs;
-    case S4_storeiri_io:
-      return IfTrue ? S4_storeirit_io : S4_storeirif_io;
-    case S2_storerd_io:
-      return IfTrue ? S2_pstorerdt_io : S2_pstorerdf_io;
-    case S4_storerd_rr:
-      return IfTrue ? S4_pstorerdt_rr : S4_pstorerdf_rr;
-    case S2_storerdabs:
-    case S2_storerdgp:
-      return IfTrue ? S4_pstorerdt_abs : S4_pstorerdf_abs;
-  }
-  llvm_unreachable("Unexpected opcode");
-  return 0;
+  return HII->getCondOpcode(Opc, !IfTrue);
 }
 
 
@@ -717,9 +668,14 @@ void HexagonEarlyIfConversion::predicate
   if (isPredicableStore(MI)) {
     unsigned COpc = getCondStoreOpcode(Opc, IfTrue);
     assert(COpc);
-    MachineInstrBuilder MIB = BuildMI(*ToB, At, DL, TII->get(COpc))
-      .addReg(PredR);
-    for (MIOperands MO(*MI); MO.isValid(); ++MO)
+    MachineInstrBuilder MIB = BuildMI(*ToB, At, DL, HII->get(COpc));
+    MIOperands MO(*MI);
+    if (HII->isPostIncrement(MI)) {
+      MIB.addOperand(*MO);
+      ++MO;
+    }
+    MIB.addReg(PredR);
+    for (; MO.isValid(); ++MO)
       MIB.addOperand(*MO);
 
     // Set memory references.
@@ -733,7 +689,7 @@ void HexagonEarlyIfConversion::predicate
 
   if (Opc == Hexagon::J2_jump) {
     MachineBasicBlock *TB = MI->getOperand(0).getMBB();
-    const MCInstrDesc &D = TII->get(IfTrue ? Hexagon::J2_jumpt
+    const MCInstrDesc &D = HII->get(IfTrue ? Hexagon::J2_jumpt
                                            : Hexagon::J2_jumpf);
     BuildMI(*ToB, At, DL, D)
       .addReg(PredR)
@@ -801,8 +757,22 @@ void HexagonEarlyIfConversion::updatePhi
     using namespace Hexagon;
     unsigned DR = PN->getOperand(0).getReg();
     const TargetRegisterClass *RC = MRI->getRegClass(DR);
-    const MCInstrDesc &D = RC == &IntRegsRegClass ? TII->get(C2_mux)
-                                                  : TII->get(MUX64_rr);
+    unsigned Opc = 0;
+    if (RC == &IntRegsRegClass)
+      Opc = C2_mux;
+    else if (RC == &DoubleRegsRegClass)
+      Opc = MUX64_rr;
+    else if (RC == &VectorRegsRegClass)
+      Opc = VSelectPseudo_V6;
+    else if (RC == &VecDblRegsRegClass)
+      Opc = VSelectDblPseudo_V6;
+    else if (RC == &VectorRegs128BRegClass)
+      Opc = VSelectPseudo_V6_128B;
+    else if (RC == &VecDblRegs128BRegClass)
+      Opc = VSelectDblPseudo_V6_128B;
+    else
+      llvm_unreachable("unexpected register type");
+    const MCInstrDesc &D = HII->get(Opc);
 
     MachineBasicBlock::iterator MuxAt = FP.SplitB->getFirstTerminator();
     DebugLoc DL;
@@ -870,21 +840,21 @@ void HexagonEarlyIfConversion::convert(c
   // generated.
   if (FP.JoinB) {
     assert(!SSB || SSB == FP.JoinB);
-    BuildMI(*FP.SplitB, FP.SplitB->end(), DL, TII->get(Hexagon::J2_jump))
+    BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jump))
       .addMBB(FP.JoinB);
     FP.SplitB->addSuccessor(FP.JoinB);
   } else {
     bool HasBranch = false;
     if (TSB) {
-      BuildMI(*FP.SplitB, FP.SplitB->end(), DL, TII->get(Hexagon::J2_jumpt))
+      BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jumpt))
         .addReg(FP.PredR)
         .addMBB(TSB);
       FP.SplitB->addSuccessor(TSB);
       HasBranch = true;
     }
     if (FSB) {
-      const MCInstrDesc &D = HasBranch ? TII->get(Hexagon::J2_jump)
-                                       : TII->get(Hexagon::J2_jumpf);
+      const MCInstrDesc &D = HasBranch ? HII->get(Hexagon::J2_jump)
+                                       : HII->get(Hexagon::J2_jumpf);
       MachineInstrBuilder MIB = BuildMI(*FP.SplitB, FP.SplitB->end(), DL, D);
       if (!HasBranch)
         MIB.addReg(FP.PredR);
@@ -896,7 +866,7 @@ void HexagonEarlyIfConversion::convert(c
       // successor blocks of the TrueB and FalseB (or null of the TrueB
       // or FalseB block is null). SSB is the potential successor block
       // of the SplitB that is neither TrueB nor FalseB.
-      BuildMI(*FP.SplitB, FP.SplitB->end(), DL, TII->get(Hexagon::J2_jump))
+      BuildMI(*FP.SplitB, FP.SplitB->end(), DL, HII->get(Hexagon::J2_jump))
         .addMBB(SSB);
       FP.SplitB->addSuccessor(SSB);
     }
@@ -963,7 +933,7 @@ void HexagonEarlyIfConversion::eliminate
       const DebugLoc &DL = PN->getDebugLoc();
       const TargetRegisterClass *RC = MRI->getRegClass(DefR);
       NewR = MRI->createVirtualRegister(RC);
-      NonPHI = BuildMI(*B, NonPHI, DL, TII->get(TargetOpcode::COPY), NewR)
+      NonPHI = BuildMI(*B, NonPHI, DL, HII->get(TargetOpcode::COPY), NewR)
         .addReg(UseR, 0, UseSR);
     }
     MRI->replaceRegWith(DefR, NewR);
@@ -993,7 +963,7 @@ void HexagonEarlyIfConversion::mergeBloc
                << PrintMB(SuccB) << "\n");
   bool TermOk = hasUncondBranch(SuccB);
   eliminatePhis(SuccB);
-  TII->RemoveBranch(*PredB);
+  HII->RemoveBranch(*PredB);
   PredB->removeSuccessor(SuccB);
   PredB->splice(PredB->end(), SuccB, SuccB->begin(), SuccB->end());
   MachineBasicBlock::succ_iterator I, E = SuccB->succ_end();
@@ -1035,8 +1005,8 @@ bool HexagonEarlyIfConversion::runOnMach
   if (skipFunction(*MF.getFunction()))
     return false;
 
-  auto &ST = MF.getSubtarget();
-  TII = ST.getInstrInfo();
+  auto &ST = MF.getSubtarget<HexagonSubtarget>();
+  HII = ST.getInstrInfo();
   TRI = ST.getRegisterInfo();
   MFN = &MF;
   MRI = &MF.getRegInfo();

Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp?rev=276800&r1=276799&r2=276800&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp Tue Jul 26 15:30:30 2016
@@ -2055,13 +2055,20 @@ HexagonTargetLowering::HexagonTargetLowe
 
   // Handling of indexed loads/stores: default is "expand".
   //
-  for (MVT LSXTy : {MVT::i8, MVT::i16, MVT::i32, MVT::i64}) {
-    setIndexedLoadAction(ISD::POST_INC, LSXTy, Legal);
-    setIndexedStoreAction(ISD::POST_INC, LSXTy, Legal);
+  for (MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64}) {
+    setIndexedLoadAction(ISD::POST_INC, VT, Legal);
+    setIndexedStoreAction(ISD::POST_INC, VT, Legal);
   }
 
-  if (UseHVXDbl) {
-    for (MVT VT : {MVT::v128i8, MVT::v64i16, MVT::v32i32, MVT::v16i64}) {
+  if (UseHVXSgl) {
+    for (MVT VT : {MVT::v64i8,  MVT::v32i16, MVT::v16i32, MVT::v8i64,
+                   MVT::v128i8, MVT::v64i16, MVT::v32i32, MVT::v16i64}) {
+      setIndexedLoadAction(ISD::POST_INC, VT, Legal);
+      setIndexedStoreAction(ISD::POST_INC, VT, Legal);
+    }
+  } else if (UseHVXDbl) {
+    for (MVT VT : {MVT::v128i8, MVT::v64i16,  MVT::v32i32, MVT::v16i64,
+                   MVT::v256i8, MVT::v128i16, MVT::v64i32, MVT::v32i64}) {
       setIndexedLoadAction(ISD::POST_INC, VT, Legal);
       setIndexedStoreAction(ISD::POST_INC, VT, Legal);
     }

Modified: llvm/trunk/lib/Target/Hexagon/HexagonInstrInfoV60.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonInstrInfoV60.td?rev=276800&r1=276799&r2=276800&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonInstrInfoV60.td (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonInstrInfoV60.td Tue Jul 26 15:30:30 2016
@@ -219,6 +219,8 @@ let isNVStorable = 1 in {
   def V6_vS32b_npred_ai_128B   : T_vstore_pred_ai_128B <"vmem", "vS32b_ai", 1>,
                                  V6_vS32b_npred_ai_128B_enc;
 }
+
+
 let isNVStorable = 1, isNonTemporal = 1 in {
   def V6_vS32b_nt_pred_ai  : T_vstore_pred_ai_64B <"vmem", "vS32b_ai", 0, 1>,
                              V6_vS32b_nt_pred_ai_enc;
@@ -1031,27 +1033,29 @@ class VSELInst<dag outs, dag ins, string
               IType type = TypeCVI_VA_DV>
   : InstHexagon<outs, ins, asmstr, pattern, cstr, itin, type>;
 
-let isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in {
-def VSelectPseudo_V6 : VSELInst<(outs VectorRegs:$dst),
-            (ins PredRegs:$src1, VectorRegs:$src2, VectorRegs:$src3),
-            ".error \"should not emit\" ",
-            []>,
-            Requires<[HasV60T,UseHVXSgl]>;
-def VSelectDblPseudo_V6 : VSELInst<(outs VecDblRegs:$dst),
-               (ins PredRegs:$src1, VecDblRegs:$src2, VecDblRegs:$src3),
-               ".error \"should not emit\" ",
-               []>,
-               Requires<[HasV60T,UseHVXSgl]>;
-}
+multiclass VSelect<RegisterClass RC, ValueType V> {
+  let isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in {
+    def NAME : VSELInst<(outs RC:$dst),
+                        (ins PredRegs:$src1, RC:$src2, RC:$src3),
+                        ".error \"should not emit\" ",
+                        []>;
+  }
 
-def : Pat <(v16i32 (selectcc (i32 IntRegs:$lhs), (i32 IntRegs:$rhs),
-                             (v16i32 VectorRegs:$tval),
-                             (v16i32 VectorRegs:$fval), SETEQ)),
-      (v16i32 (VSelectPseudo_V6 (i32 (C2_cmpeq (i32 IntRegs:$lhs),
-                                (i32 IntRegs:$rhs))),
-                                (v16i32 VectorRegs:$tval),
-                                (v16i32 VectorRegs:$fval)))>;
+  def : Pat <(V (selectcc (i32 IntRegs:$lhs), (i32 IntRegs:$rhs), (V RC:$tval),
+                          (V RC:$fval), SETEQ)),
+             (V (!cast<Instruction>(NAME) (i32 (C2_cmpeq (i32 IntRegs:$lhs),
+                                               (i32 IntRegs:$rhs))),
+                                          (V RC:$tval), (V RC:$fval)))>;
+}
 
+defm VSelectPseudo_V6 : VSelect<VectorRegs, v16i32>,
+                        Requires<[HasV60T,UseHVXSgl]>;
+defm VSelectDblPseudo_V6 : VSelect<VecDblRegs, v32i32>,
+                           Requires<[HasV60T,UseHVXSgl]>;
+defm VSelectPseudo_V6_128B : VSelect<VectorRegs128B, v32i32>,
+                             Requires<[HasV60T,UseHVXDbl]>;
+defm VSelectDblPseudo_V6_128B : VSelect<VecDblRegs128B, v64i32>,
+                                Requires<[HasV60T,UseHVXDbl]>;
 
 let hasNewValue = 1 in
 class T_vmpy <string asmString, RegisterClass RCout, RegisterClass RCin>

Modified: llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp?rev=276800&r1=276799&r2=276800&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp Tue Jul 26 15:30:30 2016
@@ -326,7 +326,13 @@ static bool doesModifyCalleeSavedReg(con
 // TODO: MI->isIndirectBranch() and IsRegisterJump(MI)
 // Returns true if an instruction can be promoted to .new predicate or
 // new-value store.
-bool HexagonPacketizerList::isNewifiable(const MachineInstr* MI) {
+bool HexagonPacketizerList::isNewifiable(const MachineInstr* MI,
+      const TargetRegisterClass *NewRC) {
+  // Vector stores can be predicated, and can be new-value stores, but
+  // they cannot be predicated on a .new predicate value.
+  if (NewRC == &Hexagon::PredRegsRegClass)
+    if (HII->isV60VectorInstruction(MI) && MI->mayStore())
+      return false;
   return HII->isCondInst(MI) || MI->isReturn() || HII->mayBeNewStore(MI);
 }
 
@@ -767,7 +773,7 @@ bool HexagonPacketizerList::canPromoteTo
   if (HII->isDotNewInst(MI) && !HII->mayBeNewStore(MI))
     return false;
 
-  if (!isNewifiable(MI))
+  if (!isNewifiable(MI, RC))
     return false;
 
   const MachineInstr *PI = PacketSU->getInstr();

Modified: llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.h?rev=276800&r1=276799&r2=276800&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.h (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonVLIWPacketizer.h Tue Jul 26 15:30:30 2016
@@ -98,7 +98,7 @@ protected:
   void useCalleesSP(MachineInstr *MI);
   bool arePredicatesComplements(MachineInstr &MI1, MachineInstr &MI2);
   bool restrictingDepExistInPacket(MachineInstr*, unsigned);
-  bool isNewifiable(const MachineInstr *MI);
+  bool isNewifiable(const MachineInstr *MI, const TargetRegisterClass *NewRC);
   bool isCurifiable(MachineInstr* MI);
   bool cannotCoexist(const MachineInstr *MI, const MachineInstr *MJ);
   inline bool isPromotedToDotNew() const {

Added: llvm/trunk/test/CodeGen/Hexagon/early-if-vecpi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/early-if-vecpi.ll?rev=276800&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/early-if-vecpi.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/early-if-vecpi.ll Tue Jul 26 15:30:30 2016
@@ -0,0 +1,69 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+
+target triple = "hexagon-unknown--elf"
+
+; Check that we can predicate base+offset vector stores.
+; CHECK-LABEL: sammy
+; CHECK: if{{.*}}vmem(r{{[0-9]+}}+#0) =
+define void @sammy(<16 x i32>* nocapture %p, <16 x i32>* nocapture readonly %q, i32 %n) #0 {
+entry:
+  %0 = load <16 x i32>, <16 x i32>* %q, align 64
+  %sub = add nsw i32 %n, -1
+  br label %for.body
+
+for.body:                                         ; preds = %if.end, %entry
+  %p.addr.011 = phi <16 x i32>* [ %p, %entry ], [ %incdec.ptr, %if.end ]
+  %i.010 = phi i32 [ 0, %entry ], [ %add, %if.end ]
+  %mul = mul nsw i32 %i.010, %sub
+  %add = add nuw nsw i32 %i.010, 1
+  %mul1 = mul nsw i32 %add, %n
+  %cmp2 = icmp slt i32 %mul, %mul1
+  br i1 %cmp2, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body
+  store <16 x i32> %0, <16 x i32>* %p.addr.011, align 64
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %for.body
+  %incdec.ptr = getelementptr inbounds <16 x i32>, <16 x i32>* %p.addr.011, i32 1
+  %exitcond = icmp eq i32 %add, 100
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %if.end
+  ret void
+}
+
+; Check that we can predicate post-increment vector stores.
+; CHECK-LABEL: danny
+; CHECK: if{{.*}}vmem(r{{[0-9]+}}++#1) =
+define void @danny(<16 x i32>* nocapture %p, <16 x i32>* nocapture readonly %q, i32 %n) #0 {
+entry:
+  %0 = load <16 x i32>, <16 x i32>* %q, align 64
+  %sub = add nsw i32 %n, -1
+  br label %for.body
+
+for.body:                                         ; preds = %if.end, %entry
+  %p.addr.012 = phi <16 x i32>* [ %p, %entry ], [ %incdec.ptr3, %if.end ]
+  %i.011 = phi i32 [ 0, %entry ], [ %add, %if.end ]
+  %mul = mul nsw i32 %i.011, %sub
+  %add = add nuw nsw i32 %i.011, 1
+  %mul1 = mul nsw i32 %add, %n
+  %cmp2 = icmp slt i32 %mul, %mul1
+  br i1 %cmp2, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body
+  %incdec.ptr = getelementptr inbounds <16 x i32>, <16 x i32>* %p.addr.012, i32 1
+  store <16 x i32> %0, <16 x i32>* %p.addr.012, align 64
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %for.body
+  %p.addr.1 = phi <16 x i32>* [ %incdec.ptr, %if.then ], [ %p.addr.012, %for.body ]
+  %incdec.ptr3 = getelementptr inbounds <16 x i32>, <16 x i32>* %p.addr.1, i32 1
+  %exitcond = icmp eq i32 %add, 100
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %if.end
+  ret void
+}
+
+attributes #0 = { norecurse nounwind "target-cpu"="hexagonv60" "target-features"="+hvx,-hvx-double" }




More information about the llvm-commits mailing list