[llvm] [VPlan] Use unsigned integers for lane start indices (PR #175231)
Aiden Grossman via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 9 11:58:46 PST 2026
https://github.com/boomanaiden154 created https://github.com/llvm/llvm-project/pull/175231
a83c89495ba6fe0134dcaa02372c320cc7ff0dbf caused assertion failures here as if we have a single bit induction variable and two lanes (0 and 1), then the second lane index (1) will be out of bounds of what a signed 1-bit integer can hold. Lane indices are always >0 according to VPlanHelpers.h:125, and the lane representation in this code is also unsigned.
The test case come from tensorflow/XLA.
>From ae8ddd49fdaf2171c2edde9f298d8ab7e0928c9d Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Fri, 9 Jan 2026 19:42:42 +0000
Subject: [PATCH] [VPlan] Use unsigned integers for lane start indices
a83c89495ba6fe0134dcaa02372c320cc7ff0dbf caused assertion failures here
as if we have a single bit induction variable and two lanes (0 and 1),
then the second lane index (1) will be out of bounds of what a signed
1-bit integer can hold. Lane indices are always >0 according to
VPlanHelpers.h:125, and the lane representation in this code is also
unsigned.
The test case come from tensorflow/XLA.
---
.../lib/Transforms/Vectorize/VPlanRecipes.cpp | 7 ++-
.../X86/vplan-single-bit-ind-var.ll | 47 +++++++++++++++++++
2 files changed, 50 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/Transforms/LoopVectorize/X86/vplan-single-bit-ind-var.ll
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index b9cd322d9ec69..e31e24fce5316 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -2346,9 +2346,8 @@ InstructionCost VPHeaderPHIRecipe::computeCost(ElementCount VF,
/// A helper function that returns an integer or floating-point constant with
/// value C.
-static Constant *getSignedIntOrFpConstant(Type *Ty, int64_t C) {
- return Ty->isIntegerTy() ? ConstantInt::getSigned(Ty, C)
- : ConstantFP::get(Ty, C);
+static Constant *getUnsignedIntOrFpConstant(Type *Ty, int64_t C) {
+ return Ty->isIntegerTy() ? ConstantInt::get(Ty, C) : ConstantFP::get(Ty, C);
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -2453,7 +2452,7 @@ void VPScalarIVStepsRecipe::execute(VPTransformState &State) {
for (unsigned Lane = StartLane; Lane < EndLane; ++Lane) {
Value *StartIdx = Builder.CreateBinOp(
- AddOp, StartIdx0, getSignedIntOrFpConstant(BaseIVTy, Lane));
+ AddOp, StartIdx0, getUnsignedIntOrFpConstant(BaseIVTy, Lane));
// The step returned by `createStepForVF` is a runtime-evaluated value
// when VF is scalable. Otherwise, it should be folded into a Constant.
assert((State.VF.isScalable() || isa<Constant>(StartIdx)) &&
diff --git a/llvm/test/Transforms/LoopVectorize/X86/vplan-single-bit-ind-var.ll b/llvm/test/Transforms/LoopVectorize/X86/vplan-single-bit-ind-var.ll
new file mode 100644
index 0000000000000..d501a485ac4db
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/X86/vplan-single-bit-ind-var.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=loop-vectorize -mcpu=znver3 -S %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-grtev4-linux-gnu"
+
+define ptr @copy_bitcast_fusion() {
+; CHECK-LABEL: define ptr @copy_bitcast_fusion(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[_PREHEADER7:.*:]]
+; CHECK-NEXT: br label %[[VECTOR_PH:.*]]
+; CHECK: [[VECTOR_PH]]:
+; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
+; CHECK: [[VECTOR_BODY]]:
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 false, i64 1, i64 0
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 true, i64 1, i64 0
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr float, ptr null, i64 [[TMP0]]
+; CHECK-NEXT: [[TMP3:%.*]] = getelementptr float, ptr null, i64 [[TMP1]]
+; CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[TMP2]], align 4
+; CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[TMP3]], align 4
+; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x float> poison, float [[TMP4]], i32 0
+; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[TMP5]], i32 1
+; CHECK-NEXT: store <2 x float> [[TMP7]], ptr null, align 4
+; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]
+; CHECK: [[MIDDLE_BLOCK]]:
+; CHECK-NEXT: br label %[[BB8:.*]]
+; CHECK: [[BB8]]:
+; CHECK-NEXT: ret ptr null
+;
+.preheader7:
+ br label %0
+
+0: ; preds = %0, %.preheader7
+ %1 = phi i64 [ 0, %.preheader7 ], [ %7, %0 ]
+ %2 = trunc i64 %1 to i1
+ %3 = select i1 %2, i64 1, i64 0
+ %4 = getelementptr float, ptr null, i64 %3
+ %5 = load float, ptr %4, align 4
+ %6 = getelementptr float, ptr null, i64 %1
+ store float %5, ptr %6, align 4
+ %7 = add i64 %1, 1
+ %exitcond.not = icmp eq i64 %1, 1
+ br i1 %exitcond.not, label %8, label %0
+
+8: ; preds = %0
+ ret ptr null
+}
More information about the llvm-commits
mailing list