[llvm] [X86][LV] Prefer tail folding for i64 div/rem loops (PR #227721)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 06:54:04 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Archit Gupta (Architag1503)

<details>
<summary>Changes</summary>

### Problem
Vectorized 64-bit integer division/remainder (`udiv`, `urem`, `sdiv`, `srem`) loops on X86 targets with AVX-512 currently generate a scalar epilogue loop when the trip count is not a multiple of the vector factor. 

### Current behavior
When `LoopVectorize` vectorizes loops containing 64-bit integer division/remainder operations on AVX-512 targets, it defaults to creating a scalar epilogue loop.

 **Why current behavior is suboptimal**
For 64-bit integer div/rem operations on AVX-512, scalar remainder loop iterations execute high-latency scalar div/rem instructions (or scalar magic multiplication sequences) for leftover elements. Using tail-folding via mask registers (`k` registers) avoids the overhead and branch mispredictions of scalar epilogue execution.

### Root cause
`X86TTIImpl::preferTailFoldingOverEpilogue` used default target transform behavior, which did not signal a target preference for tail folding on 64-bit integer div/rem loops on AVX-512.

### Fix
Override `X86TTIImpl::preferTailFoldingOverEpilogue` to prefer tail folding for loops containing 64-bit integer division/remainder operations on AVX-512 targets when vectorization is enabled and no interleaved access groups are present (`!TFI->IAI || !TFI->IAI->hasGroups()`).

### Testing
- `llvm/test/Transforms/LoopVectorize/X86/i64-div-tail-folding.ll`
- `llvm/test/Transforms/LoopVectorize/X86/i64-div-interleaved-access.ll`
- `llvm/test/Transforms/LoopVectorize/X86/idiv-by-const.ll`

Related issue: #<!-- -->223218

---

Patch is 60.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/227721.diff


5 Files Affected:

- (modified) llvm/lib/Target/X86/X86TargetTransformInfo.cpp (+26) 
- (modified) llvm/lib/Target/X86/X86TargetTransformInfo.h (+2) 
- (added) llvm/test/Transforms/LoopVectorize/X86/i64-div-interleaved-access.ll (+45) 
- (added) llvm/test/Transforms/LoopVectorize/X86/i64-div-tail-folding.ll (+41) 
- (modified) llvm/test/Transforms/LoopVectorize/X86/idiv-by-const.ll (+150-425) 


``````````diff
diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
index c8e23089473cb..8de508ad8d2c7 100644
--- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
+++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
@@ -57,6 +57,7 @@
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/Transforms/Vectorize/LoopVectorizationLegality.h"
 #include <optional>
 
 using namespace llvm;
@@ -8064,3 +8065,28 @@ bool X86TTIImpl::useFastCCForInternalCall(Function &F) const {
 
   return true;
 }
+
+bool X86TTIImpl::preferTailFoldingOverEpilogue(TailFoldingInfo *TFI) const {
+  if (!ST->hasAVX512() || !TFI || !TFI->LVL)
+    return false;
+
+  if (TFI->IAI && TFI->IAI->hasGroups())
+    return false;
+
+  Loop *L = TFI->LVL->getLoop();
+  if (!L)
+    return false;
+
+  for (BasicBlock *BB : L->getBlocks()) {
+    for (Instruction &I : *BB) {
+      unsigned Opcode = I.getOpcode();
+      if (Opcode == Instruction::UDiv || Opcode == Instruction::SDiv ||
+          Opcode == Instruction::URem || Opcode == Instruction::SRem) {
+        if (I.getType()->getScalarSizeInBits() == 64)
+          return true;
+      }
+    }
+  }
+
+  return false;
+}
diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.h b/llvm/lib/Target/X86/X86TargetTransformInfo.h
index 422e4aad2316c..4ee09564d0d1f 100644
--- a/llvm/lib/Target/X86/X86TargetTransformInfo.h
+++ b/llvm/lib/Target/X86/X86TargetTransformInfo.h
@@ -265,6 +265,8 @@ class X86TTIImpl final : public BasicTTIImplBase<X86TTIImpl> {
                              Align Alignment,
                              unsigned AddrSpace) const override;
 
+  bool preferTailFoldingOverEpilogue(TailFoldingInfo *TFI) const override;
+
   bool useFastCCForInternalCall(Function &F) const override;
 
 private:
diff --git a/llvm/test/Transforms/LoopVectorize/X86/i64-div-interleaved-access.ll b/llvm/test/Transforms/LoopVectorize/X86/i64-div-interleaved-access.ll
new file mode 100644
index 0000000000000..2de0bccb671e8
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/X86/i64-div-interleaved-access.ll
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt --passes=loop-vectorize -mtriple x86_64 -mcpu=skylake-avx512 -S %s | FileCheck %s
+;
+; Verify that on AVX-512, an i64 udiv loop with interleaved struct accesses
+; is NOT tail-folded. X86TTIImpl::preferTailFoldingOverEpilogue checks
+; TFI->IAI->hasGroups() and returns false when interleaved access groups
+; are present. A scalar epilogue must be generated instead.
+;
+; The loop reads {x, y} = struct Point{i64 x, i64 y} fields and computes
+; sum += x / y, forming an interleaved access group.
+
+%struct.Point = type { i64, i64 }
+
+define i64 @udiv_i64_interleaved_group(ptr %p, i32 %n) {
+; CHECK-LABEL: define i64 @udiv_i64_interleaved_group(
+; CHECK: vector.body:
+; CHECK: shufflevector
+; CHECK: udiv <{{[0-9]+}} x i64>
+; CHECK: middle.block:
+; CHECK: vec.epilog.scalar.ph:
+entry:
+  %cmp6 = icmp sgt i32 %n, 0
+  br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup
+
+for.body.preheader:
+  %wide.trip.count = zext i32 %n to i64
+  br label %for.body
+
+for.cond.cleanup:
+  %sum.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ]
+  ret i64 %sum.0.lcssa
+
+for.body:
+  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
+  %sum.07 = phi i64 [ 0, %for.body.preheader ], [ %add, %for.body ]
+  %x = getelementptr inbounds %struct.Point, ptr %p, i64 %indvars.iv, i32 0
+  %0 = load i64, ptr %x, align 8
+  %y = getelementptr inbounds %struct.Point, ptr %p, i64 %indvars.iv, i32 1
+  %1 = load i64, ptr %y, align 8
+  %div = udiv i64 %0, %1
+  %add = add i64 %div, %sum.07
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count
+  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
+}
diff --git a/llvm/test/Transforms/LoopVectorize/X86/i64-div-tail-folding.ll b/llvm/test/Transforms/LoopVectorize/X86/i64-div-tail-folding.ll
new file mode 100644
index 0000000000000..9378b71ed13ac
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/X86/i64-div-tail-folding.ll
@@ -0,0 +1,41 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt --passes=loop-vectorize -mtriple x86_64 -mcpu=skylake-avx512 -S %s | FileCheck %s
+;
+; Verify that on AVX-512, a simple i64 udiv reduction loop is tail-folded
+; (X86TTIImpl::preferTailFoldingOverEpilogue returns true for i64 div/rem).
+; The vectorized loop must use masked loads and a masked udiv intrinsic.
+; There must be no scalar epilogue (scalar.ph / for.body blocks).
+
+define i64 @udiv_i64_reduction(ptr %a, ptr %b, i32 %n) {
+; CHECK-LABEL: define i64 @udiv_i64_reduction(
+; CHECK: vector.body:
+; CHECK: llvm.masked.load
+; CHECK: llvm.masked.udiv
+; CHECK: middle.block:
+; CHECK-NOT: scalar.ph:
+; CHECK-NOT: for.body:
+entry:
+  %cmp8 = icmp sgt i32 %n, 0
+  br i1 %cmp8, label %for.body.preheader, label %for.cond.cleanup
+
+for.body.preheader:
+  %wide.trip.count = zext i32 %n to i64
+  br label %for.body
+
+for.cond.cleanup:
+  %x.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ]
+  ret i64 %x.0.lcssa
+
+for.body:
+  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
+  %x.09 = phi i64 [ 0, %for.body.preheader ], [ %add, %for.body ]
+  %arrayidx = getelementptr inbounds i64, ptr %a, i64 %indvars.iv
+  %0 = load i64, ptr %arrayidx, align 8
+  %arrayidx2 = getelementptr inbounds i64, ptr %b, i64 %indvars.iv
+  %1 = load i64, ptr %arrayidx2, align 8
+  %div = udiv i64 %0, %1
+  %add = add i64 %div, %x.09
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count
+  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
+}
diff --git a/llvm/test/Transforms/LoopVectorize/X86/idiv-by-const.ll b/llvm/test/Transforms/LoopVectorize/X86/idiv-by-const.ll
index 9e645996a7c7c..672e3c7a2c17c 100644
--- a/llvm/test/Transforms/LoopVectorize/X86/idiv-by-const.ll
+++ b/llvm/test/Transforms/LoopVectorize/X86/idiv-by-const.ll
@@ -115,233 +115,92 @@ define void @udiv_by_const(ptr noalias %o, ptr noalias %i, i64 %n) {
 ;
 ; AVX512F-LABEL: define void @udiv_by_const(
 ; AVX512F-SAME: ptr noalias [[O:%.*]], ptr noalias [[I:%.*]], i64 [[N:%.*]]) #[[ATTR0:[0-9]+]] {
-; AVX512F-NEXT:  [[ITER_CHECK:.*]]:
-; AVX512F-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 8
-; AVX512F-NEXT:    br i1 [[MIN_ITERS_CHECK]], label %[[VEC_EPILOG_SCALAR_PH:.*]], label %[[VECTOR_MAIN_LOOP_ITER_CHECK:.*]]
-; AVX512F:       [[VECTOR_MAIN_LOOP_ITER_CHECK]]:
-; AVX512F-NEXT:    [[MIN_ITERS_CHECK1:%.*]] = icmp ult i64 [[N]], 32
-; AVX512F-NEXT:    br i1 [[MIN_ITERS_CHECK1]], label %[[VEC_EPILOG_PH:.*]], label %[[VECTOR_PH:.*]]
-; AVX512F:       [[VECTOR_PH]]:
-; AVX512F-NEXT:    [[N_MOD_VF:%.*]] = and i64 [[N]], 31
-; AVX512F-NEXT:    [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]
+; AVX512F-NEXT:  [[VECTOR_PH:.*:]]
 ; AVX512F-NEXT:    br label %[[VECTOR_BODY:.*]]
 ; AVX512F:       [[VECTOR_BODY]]:
-; AVX512F-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
-; AVX512F-NEXT:    [[TMP0:%.*]] = getelementptr i64, ptr [[I]], i64 [[INDEX]]
-; AVX512F-NEXT:    [[TMP1:%.*]] = getelementptr i64, ptr [[TMP0]], i64 8
-; AVX512F-NEXT:    [[TMP2:%.*]] = getelementptr i64, ptr [[TMP0]], i64 16
-; AVX512F-NEXT:    [[TMP3:%.*]] = getelementptr i64, ptr [[TMP0]], i64 24
-; AVX512F-NEXT:    [[WIDE_LOAD:%.*]] = load <8 x i64>, ptr [[TMP0]], align 8
-; AVX512F-NEXT:    [[WIDE_LOAD2:%.*]] = load <8 x i64>, ptr [[TMP1]], align 8
-; AVX512F-NEXT:    [[WIDE_LOAD3:%.*]] = load <8 x i64>, ptr [[TMP2]], align 8
-; AVX512F-NEXT:    [[WIDE_LOAD4:%.*]] = load <8 x i64>, ptr [[TMP3]], align 8
-; AVX512F-NEXT:    [[TMP4:%.*]] = udiv <8 x i64> [[WIDE_LOAD]], splat (i64 1000000007)
-; AVX512F-NEXT:    [[TMP5:%.*]] = udiv <8 x i64> [[WIDE_LOAD2]], splat (i64 1000000007)
-; AVX512F-NEXT:    [[TMP6:%.*]] = udiv <8 x i64> [[WIDE_LOAD3]], splat (i64 1000000007)
-; AVX512F-NEXT:    [[TMP7:%.*]] = udiv <8 x i64> [[WIDE_LOAD4]], splat (i64 1000000007)
-; AVX512F-NEXT:    [[TMP8:%.*]] = getelementptr i64, ptr [[O]], i64 [[INDEX]]
-; AVX512F-NEXT:    [[TMP9:%.*]] = getelementptr i64, ptr [[TMP8]], i64 8
-; AVX512F-NEXT:    [[TMP10:%.*]] = getelementptr i64, ptr [[TMP8]], i64 16
-; AVX512F-NEXT:    [[TMP11:%.*]] = getelementptr i64, ptr [[TMP8]], i64 24
-; AVX512F-NEXT:    store <8 x i64> [[TMP4]], ptr [[TMP8]], align 8
-; AVX512F-NEXT:    store <8 x i64> [[TMP5]], ptr [[TMP9]], align 8
-; AVX512F-NEXT:    store <8 x i64> [[TMP6]], ptr [[TMP10]], align 8
-; AVX512F-NEXT:    store <8 x i64> [[TMP7]], ptr [[TMP11]], align 8
-; AVX512F-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 32
-; AVX512F-NEXT:    [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-; AVX512F-NEXT:    br i1 [[TMP12]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
-; AVX512F:       [[MIDDLE_BLOCK]]:
-; AVX512F-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]
-; AVX512F-NEXT:    br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[VEC_EPILOG_ITER_CHECK:.*]]
-; AVX512F:       [[VEC_EPILOG_ITER_CHECK]]:
-; AVX512F-NEXT:    [[MIN_EPILOG_ITERS_CHECK:%.*]] = icmp ult i64 [[N_MOD_VF]], 8
-; AVX512F-NEXT:    br i1 [[MIN_EPILOG_ITERS_CHECK]], label %[[VEC_EPILOG_SCALAR_PH]], label %[[VEC_EPILOG_PH]], !prof [[PROF3:![0-9]+]]
-; AVX512F:       [[VEC_EPILOG_PH]]:
-; AVX512F-NEXT:    [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[VECTOR_MAIN_LOOP_ITER_CHECK]] ]
-; AVX512F-NEXT:    [[N_MOD_VF5:%.*]] = and i64 [[N]], 7
-; AVX512F-NEXT:    [[N_VEC6:%.*]] = sub i64 [[N]], [[N_MOD_VF5]]
+; AVX512F-NEXT:    [[N_RND_UP:%.*]] = add i64 [[N]], 7
+; AVX512F-NEXT:    [[TMP0:%.*]] = and i64 [[N_RND_UP]], 7
+; AVX512F-NEXT:    [[N_VEC6:%.*]] = sub i64 [[N_RND_UP]], [[TMP0]]
+; AVX512F-NEXT:    [[TRIP_COUNT_MINUS_1:%.*]] = sub i64 [[N]], 1
+; AVX512F-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[TRIP_COUNT_MINUS_1]], i64 0
+; AVX512F-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <8 x i64> [[BROADCAST_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
 ; AVX512F-NEXT:    br label %[[VEC_EPILOG_VECTOR_BODY:.*]]
 ; AVX512F:       [[VEC_EPILOG_VECTOR_BODY]]:
-; AVX512F-NEXT:    [[INDEX7:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], %[[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT9:%.*]], %[[VEC_EPILOG_VECTOR_BODY]] ]
+; AVX512F-NEXT:    [[INDEX7:%.*]] = phi i64 [ 0, %[[VECTOR_BODY]] ], [ [[INDEX_NEXT9:%.*]], %[[VEC_EPILOG_VECTOR_BODY]] ]
+; AVX512F-NEXT:    [[VEC_IND:%.*]] = phi <8 x i64> [ <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7>, %[[VECTOR_BODY]] ], [ [[VEC_IND_NEXT:%.*]], %[[VEC_EPILOG_VECTOR_BODY]] ]
+; AVX512F-NEXT:    [[TMP1:%.*]] = icmp ule <8 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
 ; AVX512F-NEXT:    [[TMP13:%.*]] = getelementptr i64, ptr [[I]], i64 [[INDEX7]]
-; AVX512F-NEXT:    [[WIDE_LOAD8:%.*]] = load <8 x i64>, ptr [[TMP13]], align 8
+; AVX512F-NEXT:    [[WIDE_LOAD8:%.*]] = call <8 x i64> @llvm.masked.load.v8i64.p0(ptr align 8 [[TMP13]], <8 x i1> [[TMP1]], <8 x i64> poison)
 ; AVX512F-NEXT:    [[TMP14:%.*]] = udiv <8 x i64> [[WIDE_LOAD8]], splat (i64 1000000007)
 ; AVX512F-NEXT:    [[TMP15:%.*]] = getelementptr i64, ptr [[O]], i64 [[INDEX7]]
-; AVX512F-NEXT:    store <8 x i64> [[TMP14]], ptr [[TMP15]], align 8
-; AVX512F-NEXT:    [[INDEX_NEXT9]] = add nuw i64 [[INDEX7]], 8
+; AVX512F-NEXT:    call void @llvm.masked.store.v8i64.p0(<8 x i64> [[TMP14]], ptr align 8 [[TMP15]], <8 x i1> [[TMP1]])
+; AVX512F-NEXT:    [[INDEX_NEXT9]] = add i64 [[INDEX7]], 8
+; AVX512F-NEXT:    [[VEC_IND_NEXT]] = add nuw <8 x i64> [[VEC_IND]], splat (i64 8)
 ; AVX512F-NEXT:    [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT9]], [[N_VEC6]]
-; AVX512F-NEXT:    br i1 [[TMP16]], label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
-; AVX512F:       [[VEC_EPILOG_MIDDLE_BLOCK]]:
-; AVX512F-NEXT:    [[CMP_N10:%.*]] = icmp eq i64 [[N]], [[N_VEC6]]
-; AVX512F-NEXT:    br i1 [[CMP_N10]], label %[[EXIT]], label %[[VEC_EPILOG_SCALAR_PH]]
+; AVX512F-NEXT:    br i1 [[TMP16]], label %[[VEC_EPILOG_SCALAR_PH:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
 ; AVX512F:       [[VEC_EPILOG_SCALAR_PH]]:
-; AVX512F-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC6]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[N_VEC]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ]
 ; AVX512F-NEXT:    br label %[[LOOP:.*]]
 ; AVX512F:       [[LOOP]]:
-; AVX512F-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_N:%.*]], %[[LOOP]] ]
-; AVX512F-NEXT:    [[P:%.*]] = getelementptr i64, ptr [[I]], i64 [[IV]]
-; AVX512F-NEXT:    [[V:%.*]] = load i64, ptr [[P]], align 8
-; AVX512F-NEXT:    [[D:%.*]] = udiv i64 [[V]], 1000000007
-; AVX512F-NEXT:    [[Q:%.*]] = getelementptr i64, ptr [[O]], i64 [[IV]]
-; AVX512F-NEXT:    store i64 [[D]], ptr [[Q]], align 8
-; AVX512F-NEXT:    [[IV_N]] = add i64 [[IV]], 1
-; AVX512F-NEXT:    [[C:%.*]] = icmp eq i64 [[IV_N]], [[N]]
-; AVX512F-NEXT:    br i1 [[C]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]]
-; AVX512F:       [[EXIT]]:
 ; AVX512F-NEXT:    ret void
 ;
 ; AVX512DQ-LABEL: define void @udiv_by_const(
 ; AVX512DQ-SAME: ptr noalias [[O:%.*]], ptr noalias [[I:%.*]], i64 [[N:%.*]]) #[[ATTR0:[0-9]+]] {
-; AVX512DQ-NEXT:  [[ITER_CHECK:.*]]:
-; AVX512DQ-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 8
-; AVX512DQ-NEXT:    br i1 [[MIN_ITERS_CHECK]], label %[[VEC_EPILOG_SCALAR_PH:.*]], label %[[VECTOR_MAIN_LOOP_ITER_CHECK:.*]]
-; AVX512DQ:       [[VECTOR_MAIN_LOOP_ITER_CHECK]]:
-; AVX512DQ-NEXT:    [[MIN_ITERS_CHECK1:%.*]] = icmp ult i64 [[N]], 32
-; AVX512DQ-NEXT:    br i1 [[MIN_ITERS_CHECK1]], label %[[VEC_EPILOG_PH:.*]], label %[[VECTOR_PH:.*]]
-; AVX512DQ:       [[VECTOR_PH]]:
-; AVX512DQ-NEXT:    [[N_MOD_VF:%.*]] = and i64 [[N]], 31
-; AVX512DQ-NEXT:    [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]
+; AVX512DQ-NEXT:  [[VECTOR_PH:.*:]]
 ; AVX512DQ-NEXT:    br label %[[VECTOR_BODY:.*]]
 ; AVX512DQ:       [[VECTOR_BODY]]:
-; AVX512DQ-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
-; AVX512DQ-NEXT:    [[TMP0:%.*]] = getelementptr i64, ptr [[I]], i64 [[INDEX]]
-; AVX512DQ-NEXT:    [[TMP1:%.*]] = getelementptr i64, ptr [[TMP0]], i64 8
-; AVX512DQ-NEXT:    [[TMP2:%.*]] = getelementptr i64, ptr [[TMP0]], i64 16
-; AVX512DQ-NEXT:    [[TMP3:%.*]] = getelementptr i64, ptr [[TMP0]], i64 24
-; AVX512DQ-NEXT:    [[WIDE_LOAD:%.*]] = load <8 x i64>, ptr [[TMP0]], align 8
-; AVX512DQ-NEXT:    [[WIDE_LOAD2:%.*]] = load <8 x i64>, ptr [[TMP1]], align 8
-; AVX512DQ-NEXT:    [[WIDE_LOAD3:%.*]] = load <8 x i64>, ptr [[TMP2]], align 8
-; AVX512DQ-NEXT:    [[WIDE_LOAD4:%.*]] = load <8 x i64>, ptr [[TMP3]], align 8
-; AVX512DQ-NEXT:    [[TMP4:%.*]] = udiv <8 x i64> [[WIDE_LOAD]], splat (i64 1000000007)
-; AVX512DQ-NEXT:    [[TMP5:%.*]] = udiv <8 x i64> [[WIDE_LOAD2]], splat (i64 1000000007)
-; AVX512DQ-NEXT:    [[TMP6:%.*]] = udiv <8 x i64> [[WIDE_LOAD3]], splat (i64 1000000007)
-; AVX512DQ-NEXT:    [[TMP7:%.*]] = udiv <8 x i64> [[WIDE_LOAD4]], splat (i64 1000000007)
-; AVX512DQ-NEXT:    [[TMP8:%.*]] = getelementptr i64, ptr [[O]], i64 [[INDEX]]
-; AVX512DQ-NEXT:    [[TMP9:%.*]] = getelementptr i64, ptr [[TMP8]], i64 8
-; AVX512DQ-NEXT:    [[TMP10:%.*]] = getelementptr i64, ptr [[TMP8]], i64 16
-; AVX512DQ-NEXT:    [[TMP11:%.*]] = getelementptr i64, ptr [[TMP8]], i64 24
-; AVX512DQ-NEXT:    store <8 x i64> [[TMP4]], ptr [[TMP8]], align 8
-; AVX512DQ-NEXT:    store <8 x i64> [[TMP5]], ptr [[TMP9]], align 8
-; AVX512DQ-NEXT:    store <8 x i64> [[TMP6]], ptr [[TMP10]], align 8
-; AVX512DQ-NEXT:    store <8 x i64> [[TMP7]], ptr [[TMP11]], align 8
-; AVX512DQ-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 32
-; AVX512DQ-NEXT:    [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-; AVX512DQ-NEXT:    br i1 [[TMP12]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
-; AVX512DQ:       [[MIDDLE_BLOCK]]:
-; AVX512DQ-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]
-; AVX512DQ-NEXT:    br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[VEC_EPILOG_ITER_CHECK:.*]]
-; AVX512DQ:       [[VEC_EPILOG_ITER_CHECK]]:
-; AVX512DQ-NEXT:    [[MIN_EPILOG_ITERS_CHECK:%.*]] = icmp ult i64 [[N_MOD_VF]], 8
-; AVX512DQ-NEXT:    br i1 [[MIN_EPILOG_ITERS_CHECK]], label %[[VEC_EPILOG_SCALAR_PH]], label %[[VEC_EPILOG_PH]], !prof [[PROF3:![0-9]+]]
-; AVX512DQ:       [[VEC_EPILOG_PH]]:
-; AVX512DQ-NEXT:    [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[VECTOR_MAIN_LOOP_ITER_CHECK]] ]
-; AVX512DQ-NEXT:    [[N_MOD_VF5:%.*]] = and i64 [[N]], 7
-; AVX512DQ-NEXT:    [[N_VEC6:%.*]] = sub i64 [[N]], [[N_MOD_VF5]]
+; AVX512DQ-NEXT:    [[N_RND_UP:%.*]] = add i64 [[N]], 7
+; AVX512DQ-NEXT:    [[TMP0:%.*]] = and i64 [[N_RND_UP]], 7
+; AVX512DQ-NEXT:    [[N_VEC6:%.*]] = sub i64 [[N_RND_UP]], [[TMP0]]
+; AVX512DQ-NEXT:    [[TRIP_COUNT_MINUS_1:%.*]] = sub i64 [[N]], 1
+; AVX512DQ-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <8 x i64> poison, i64 [[TRIP_COUNT_MINUS_1]], i64 0
+; AVX512DQ-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <8 x i64> [[BROADCAST_SPLATINSERT]], <8 x i64> poison, <8 x i32> zeroinitializer
 ; AVX512DQ-NEXT:    br label %[[VEC_EPILOG_VECTOR_BODY:.*]]
 ; AVX512DQ:       [[VEC_EPILOG_VECTOR_BODY]]:
-; AVX512DQ-NEXT:    [[INDEX7:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], %[[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT9:%.*]], %[[VEC_EPILOG_VECTOR_BODY]] ]
+; AVX512DQ-NEXT:    [[INDEX7:%.*]] = phi i64 [ 0, %[[VECTOR_BODY]] ], [ [[INDEX_NEXT9:%.*]], %[[VEC_EPILOG_VECTOR_BODY]] ]
+; AVX512DQ-NEXT:    [[VEC_IND:%.*]] = phi <8 x i64> [ <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7>, %[[VECTOR_BODY]] ], [ [[VEC_IND_NEXT:%.*]], %[[VEC_EPILOG_VECTOR_BODY]] ]
+; AVX512DQ-NEXT:    [[TMP1:%.*]] = icmp ule <8 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]]
 ; AVX512DQ-NEXT:    [[TMP13:%.*]] = getelementptr i64, ptr [[I]], i64 [[INDEX7]]
-; AVX512DQ-NEXT:    [[WIDE_LOAD8:%.*]] = load <8 x i64>, ptr [[TMP13]], align 8
+; AVX512DQ-NEXT:    [[WIDE_LOAD8:%.*]] = call <8 x i64> @llvm.masked.load.v8i64.p0(ptr align 8 [[TMP13]], <8 x i1> [[TMP1]], <8 x i64> poison)
 ; AVX512DQ-NEXT:    [[TMP14:%.*]] = udiv <8 x i64> [[WIDE_LOAD8]], splat (i64 1000000007)
 ; AVX512DQ-NEXT:    [[TMP15:%.*]] = getelementptr i64, ptr [[O]], i64 [[INDEX7]]
-; AVX512DQ-NEXT:    store <8 x i64> [[TMP14]], ptr [[TMP15]], align 8
-; AVX512DQ-NEXT:    [[INDEX_NEXT9]] = add nuw i64 [[INDEX7]], 8
+; AVX512DQ-NEXT:    call void @llvm.masked.store.v8i64.p0(<8 x i64> [[TMP14]], ptr align 8 [[TMP15]], <8 x i1> [[TMP1]])
+; AVX512DQ-NEXT:    [[INDEX_NEXT9]] = add i64 [[INDEX7]], 8
+; AVX512DQ-NEXT:    [[VEC_IND_NEXT]] = add nuw <8 x i64> [[VEC_IND]], splat (i64 8)
 ; AVX512DQ-NEXT:    [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT9]], [[N_VEC6]]
-; AVX512DQ-NEXT:    br i1 [[TMP16]], label %[[VEC_EPILOG_MIDDLE_BLOCK:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
-; AVX512DQ:       [[VEC_EPILOG_MIDDLE_BLOCK]]:
-; AVX512DQ-NEXT:    [[CMP_N10:%.*]] = icmp eq i64 [[N]], [[N_VEC6]]
-; AVX512DQ-NEXT:    br i1 [[CMP_N10]], label %[[EXIT]], label %[[VEC_EPILOG_SCALAR_PH]]
+; AVX512DQ-NEXT:    br i1 [[TMP16]], label %[[VEC_EPILOG_SCALAR_PH:.*]], label %[[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
 ; AVX512DQ:       [[VEC_EPILOG_SCALAR_PH]]:
-; AVX512DQ-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC6]], %[[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[N_VEC]], %[[VEC_EPILOG_ITER_CHECK]] ], [ 0, %[[ITER_CHECK]] ]
 ; AVX512DQ-NEXT:    br label %[[LOOP:.*]]
 ; AVX512DQ:       [[LOOP]]:
-; AVX512DQ-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_N:%.*]], %[[LOOP]] ]
-; AVX512DQ-NEXT:    [[P:%.*]] = getelementptr i64, ptr [[I]], i64 [[IV]]
-; AVX512DQ-NEXT:    [[V:%.*]] = load i64, ptr [[P]], align 8
-; AVX512DQ-NEXT:    [[D:%.*]] = udiv i64 [[V]], 1000000007
-; AVX512DQ-NEXT:    [[Q:%.*]] = getelementptr i64, ptr [[O]], i64 [[IV]]
-; AVX512DQ-NEXT:    store i64 [[D]], ptr [[Q]], align 8
-; AVX512DQ-NEXT:    [[IV_N]] = add i64 [[IV]], 1
-; AVX512DQ-NEXT:    [[C:%.*]] = icmp eq i64 [[IV_N]],...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/227721


More information about the llvm-commits mailing list