[llvm] [VPlan] Also expand pointer-typed SCEVAddExpr in VPSCEVExpander. (PR #206366)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 28 13:02:52 PDT 2026
https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/206366
Generalize the SCEVAddExpr handling in VPSCEVExpander::tryToExpand to also expand pointer-typed adds. The pointer base and the offset are expanded separately, matching IR SCEVExpander.
>From f6d310cff1cc8205a0f972c9020a2bd5f7aacc26 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sat, 27 Jun 2026 15:34:01 +0100
Subject: [PATCH] [VPlan] Also expand pointer-typed SCEVAddExpr in
VPSCEVExpander.
Generalize the SCEVAddExpr handling in VPSCEVExpander::tryToExpand to
also expand pointer-typed adds. The pointer base and the offset are
expanded separately, matching IR SCEVExpander.
---
llvm/lib/Transforms/Vectorize/VPlanUtils.cpp | 22 +++++++++++++---
.../RISCV/early-exit-live-out.ll | 2 +-
.../LoopVectorize/RISCV/pointer-induction.ll | 2 +-
.../RISCV/tail-folding-interleave.ll | 26 +++++++++----------
.../LoopVectorize/VPlan/RISCV/expand-scev.ll | 8 +++---
5 files changed, 37 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
index 263480924b796..5d50796461918 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
@@ -846,9 +846,25 @@ VPValue *VPSCEVExpander::tryToExpand(const SCEV *S) {
return Builder.createNaryOp(VPInstruction::VScale, {}, S->getType());
case scAddExpr:
case scMulExpr: {
- if (S->getType()->isPointerTy())
- return nullptr;
auto *NAry = cast<SCEVNAryExpr>(S);
+ VPIRFlags::WrapFlagsTy WrapFlags(NAry->hasNoUnsignedWrap(),
+ NAry->hasNoSignedWrap());
+
+ // Expanded poiner SCEVAddExpr as a ptradd of the pointer base and the
+ // integer offset, matching SCEVExpander.
+ if (S->getType()->isPointerTy()) {
+ VPValue *Base = tryToExpand(SE.getPointerBase(S));
+ if (!Base)
+ return nullptr;
+ VPValue *Offset = tryToExpand(SE.removePointerBase(S));
+ if (!Offset)
+ return nullptr;
+ GEPNoWrapFlags GEPFlags = WrapFlags.HasNUW
+ ? GEPNoWrapFlags::noUnsignedWrap()
+ : GEPNoWrapFlags::none();
+ return Builder.createNoWrapPtrAdd(Base, Offset, GEPFlags, DL);
+ }
+
unsigned Opcode =
S->getSCEVType() == scAddExpr ? Instruction::Add : Instruction::Mul;
// Iterate in reverse so that constants are emitted last.
@@ -859,8 +875,6 @@ VPValue *VPSCEVExpander::tryToExpand(const SCEV *S) {
return nullptr;
Ops.push_back(OpV);
}
- VPIRFlags::WrapFlagsTy WrapFlags(NAry->hasNoUnsignedWrap(),
- NAry->hasNoSignedWrap());
VPValue *Result = Ops.front();
for (VPValue *Op : drop_begin(Ops))
Result = Builder.createOverflowingOp(Opcode, {Result, Op}, WrapFlags, DL);
diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/early-exit-live-out.ll b/llvm/test/Transforms/LoopVectorize/RISCV/early-exit-live-out.ll
index c09ce83d02266..46055d50890f7 100644
--- a/llvm/test/Transforms/LoopVectorize/RISCV/early-exit-live-out.ll
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/early-exit-live-out.ll
@@ -176,10 +176,10 @@ define i64 @strided_search(ptr align 8 dereferenceable(14784) %p) {
; RV64-LABEL: define i64 @strided_search(
; RV64-SAME: ptr align 8 dereferenceable(14784) [[P:%.*]]) #[[ATTR0]] {
; RV64-NEXT: [[ENTRY:.*]]:
-; RV64-NEXT: [[SCEVGEP:%.*]] = getelementptr nuw i8, ptr [[P]], i64 88
; RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
; RV64-NEXT: [[TMP1:%.*]] = shl nuw i64 [[TMP0]], 1
; RV64-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP1]], i64 3)
+; RV64-NEXT: [[SCEVGEP:%.*]] = getelementptr nuw i8, ptr [[P]], i64 88
; RV64-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 132, [[UMAX]]
; RV64-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
; RV64: [[VECTOR_PH]]:
diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/pointer-induction.ll b/llvm/test/Transforms/LoopVectorize/RISCV/pointer-induction.ll
index 7462d58d632ca..3a3833a1ed2c8 100644
--- a/llvm/test/Transforms/LoopVectorize/RISCV/pointer-induction.ll
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/pointer-induction.ll
@@ -65,11 +65,11 @@ define i1 @scalarize_ptr_induction(ptr %start, ptr %end, ptr noalias %dst, i1 %c
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[START2:%.*]] = ptrtoint ptr [[START]] to i64
; CHECK-NEXT: [[END1:%.*]] = ptrtoint ptr [[END]] to i64
-; CHECK-NEXT: [[SCEVGEP6:%.*]] = getelementptr i8, ptr [[START]], i64 4
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[END1]], -12
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[START2]]
; CHECK-NEXT: [[TMP2:%.*]] = udiv i64 [[TMP1]], 12
; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 1
+; CHECK-NEXT: [[SCEVGEP6:%.*]] = getelementptr i8, ptr [[START]], i64 4
; CHECK-NEXT: br label %[[VECTOR_MEMCHECK:.*]]
; CHECK: [[VECTOR_MEMCHECK]]:
; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 2 x ptr> poison, ptr [[DST]], i64 0
diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/tail-folding-interleave.ll b/llvm/test/Transforms/LoopVectorize/RISCV/tail-folding-interleave.ll
index 379077061bbb4..2e0a77ff57f87 100644
--- a/llvm/test/Transforms/LoopVectorize/RISCV/tail-folding-interleave.ll
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/tail-folding-interleave.ll
@@ -554,7 +554,10 @@ exit:
define i32 @load_factor_4_reverse(i64 %n, ptr noalias %a) {
; IF-EVL-LABEL: @load_factor_4_reverse(
; IF-EVL-NEXT: entry:
-; IF-EVL-NEXT: [[TMP2:%.*]] = shl i64 [[N:%.*]], 4
+; IF-EVL-NEXT: [[TMP0:%.*]] = add nsw i64 [[N:%.*]], -1
+; IF-EVL-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP0]], i64 0)
+; IF-EVL-NEXT: [[TMP1:%.*]] = sub i64 [[N]], [[SMIN]]
+; IF-EVL-NEXT: [[TMP2:%.*]] = shl i64 [[N]], 4
; IF-EVL-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 12
; IF-EVL-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP3]]
; IF-EVL-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP2]], 8
@@ -562,9 +565,6 @@ define i32 @load_factor_4_reverse(i64 %n, ptr noalias %a) {
; IF-EVL-NEXT: [[TMP5:%.*]] = add nuw nsw i64 [[TMP2]], 4
; IF-EVL-NEXT: [[SCEVGEP3:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP5]]
; IF-EVL-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP2]]
-; IF-EVL-NEXT: [[TMP20:%.*]] = add nsw i64 [[N]], -1
-; IF-EVL-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP20]], i64 0)
-; IF-EVL-NEXT: [[TMP1:%.*]] = sub i64 [[N]], [[SMIN]]
; IF-EVL-NEXT: br label [[VECTOR_PH:%.*]]
; IF-EVL: vector.ph:
; IF-EVL-NEXT: br label [[VECTOR_BODY:%.*]]
@@ -600,20 +600,20 @@ define i32 @load_factor_4_reverse(i64 %n, ptr noalias %a) {
;
; NO-VP-LABEL: @load_factor_4_reverse(
; NO-VP-NEXT: entry:
-; NO-VP-NEXT: [[TMP7:%.*]] = shl i64 [[N:%.*]], 4
-; NO-VP-NEXT: [[TMP8:%.*]] = add nuw nsw i64 [[TMP7]], 12
-; NO-VP-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP8]]
-; NO-VP-NEXT: [[TMP9:%.*]] = add nuw nsw i64 [[TMP7]], 8
-; NO-VP-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP9]]
-; NO-VP-NEXT: [[TMP10:%.*]] = add nuw nsw i64 [[TMP7]], 4
-; NO-VP-NEXT: [[SCEVGEP3:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP10]]
-; NO-VP-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP7]]
-; NO-VP-NEXT: [[TMP27:%.*]] = add nsw i64 [[N]], -1
+; NO-VP-NEXT: [[TMP27:%.*]] = add nsw i64 [[N:%.*]], -1
; NO-VP-NEXT: [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP27]], i64 0)
; NO-VP-NEXT: [[TMP1:%.*]] = sub i64 [[N]], [[SMIN]]
; NO-VP-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()
; NO-VP-NEXT: [[TMP3:%.*]] = shl nuw i64 [[TMP2]], 2
; NO-VP-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP3]], i64 8)
+; NO-VP-NEXT: [[TMP8:%.*]] = shl i64 [[N]], 4
+; NO-VP-NEXT: [[TMP10:%.*]] = add nuw nsw i64 [[TMP8]], 12
+; NO-VP-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP10]]
+; NO-VP-NEXT: [[TMP7:%.*]] = add nuw nsw i64 [[TMP8]], 8
+; NO-VP-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP7]]
+; NO-VP-NEXT: [[TMP9:%.*]] = add nuw nsw i64 [[TMP8]], 4
+; NO-VP-NEXT: [[SCEVGEP3:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP9]]
+; NO-VP-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP8]]
; NO-VP-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], [[UMAX]]
; NO-VP-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
; NO-VP: vector.ph:
diff --git a/llvm/test/Transforms/LoopVectorize/VPlan/RISCV/expand-scev.ll b/llvm/test/Transforms/LoopVectorize/VPlan/RISCV/expand-scev.ll
index 9071db2923ab7..1d42aaf0aaae2 100644
--- a/llvm/test/Transforms/LoopVectorize/VPlan/RISCV/expand-scev.ll
+++ b/llvm/test/Transforms/LoopVectorize/VPlan/RISCV/expand-scev.ll
@@ -9,7 +9,7 @@ define void @scev_ptradd_strided(ptr noalias %a, ptr noalias %dst, i64 %n) {
; CHECK-NEXT: Live-in ir<%n> = original trip-count
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<entry>:
-; CHECK-NEXT: IR %scevgep = getelementptr nuw i8, ptr %a, i64 4
+; CHECK-NEXT: EMIT vp<[[VP2:%[0-9]+]]> = ptradd nuw ir<%a>, ir<4>
; CHECK-NEXT: Successor(s): vector.ph
;
entry:
@@ -35,9 +35,9 @@ define void @scev_ptradd_strided_var_offset(ptr noalias %a, ptr noalias %dst, i6
; CHECK-NEXT: Live-in ir<%n> = original trip-count
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<entry>:
-; CHECK-NEXT: IR %0 = shl i64 %m, 4
-; CHECK-NEXT: IR %1 = add nuw nsw i64 %0, 4
-; CHECK-NEXT: IR %scevgep = getelementptr i8, ptr %a, i64 %1
+; CHECK-NEXT: EMIT vp<[[VP2:%[0-9]+]]> = shl ir<%m>, ir<4>
+; CHECK-NEXT: EMIT vp<[[VP3:%[0-9]+]]> = add nuw nsw vp<[[VP2]]>, ir<4>
+; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = ptradd ir<%a>, vp<[[VP3]]>
; CHECK-NEXT: Successor(s): vector.ph
;
entry:
More information about the llvm-commits
mailing list