Skip to content

Commit f925e54

Browse files
authored
[VPlan] Fix mutating whilst iterating over users in EVL transform (#122885)
This fixes a miscompilation extracted from 525.x264_r, where we were failing to update the runtime VF of a VPReverseVectorPointerRecipe. We were removing a use of VF whilst iterating over the users() iterator, which messed up the iterator in-flight and caused us to miss some recipes. This fixes it by copying the users into a SmallVector first. Fixes #122681 Fixes #122682
1 parent c1de9b9 commit f925e54

File tree

2 files changed

+122
-1
lines changed

2 files changed

+122
-1
lines changed

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1603,7 +1603,7 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
16031603
LLVMContext &Ctx = CanonicalIVType->getContext();
16041604
VPValue *AllOneMask = Plan.getOrAddLiveIn(ConstantInt::getTrue(Ctx));
16051605

1606-
for (VPUser *U : Plan.getVF().users()) {
1606+
for (VPUser *U : to_vector(Plan.getVF().users())) {
16071607
if (auto *R = dyn_cast<VPReverseVectorPointerRecipe>(U))
16081608
R->setOperand(1, &EVL);
16091609
}

llvm/test/Transforms/LoopVectorize/RISCV/vectorize-force-tail-with-evl-reverse-load-store.ll

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,124 @@ loopend:
249249
ret void
250250
}
251251

252+
; From a miscompile originally reported at
253+
; https://github.com/llvm/llvm-project/issues/122681
254+
255+
define void @multiple_reverse_vector_pointer(ptr noalias %a, ptr noalias %b, ptr noalias %c, ptr noalias %d) {
256+
; IF-EVL-LABEL: @multiple_reverse_vector_pointer(
257+
; IF-EVL-NEXT: entry:
258+
; IF-EVL-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
259+
; IF-EVL: vector.ph:
260+
; IF-EVL-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
261+
; IF-EVL-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 16
262+
; IF-EVL-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], 1
263+
; IF-EVL-NEXT: [[N_RND_UP:%.*]] = add i64 1025, [[TMP2]]
264+
; IF-EVL-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], [[TMP1]]
265+
; IF-EVL-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]]
266+
; IF-EVL-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64()
267+
; IF-EVL-NEXT: [[TMP4:%.*]] = mul i64 [[TMP3]], 16
268+
; IF-EVL-NEXT: [[TMP5:%.*]] = sub i64 1024, [[N_VEC]]
269+
; IF-EVL-NEXT: br label [[VECTOR_BODY:%.*]]
270+
; IF-EVL: vector.body:
271+
; IF-EVL-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
272+
; IF-EVL-NEXT: [[EVL_BASED_IV:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_EVL_NEXT:%.*]], [[VECTOR_BODY]] ]
273+
; IF-EVL-NEXT: [[AVL:%.*]] = sub i64 1025, [[EVL_BASED_IV]]
274+
; IF-EVL-NEXT: [[TMP6:%.*]] = call i32 @llvm.experimental.get.vector.length.i64(i64 [[AVL]], i32 16, i1 true)
275+
; IF-EVL-NEXT: [[OFFSET_IDX:%.*]] = sub i64 1024, [[EVL_BASED_IV]]
276+
; IF-EVL-NEXT: [[TMP7:%.*]] = add i64 [[OFFSET_IDX]], 0
277+
; IF-EVL-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[TMP7]]
278+
; IF-EVL-NEXT: [[TMP9:%.*]] = zext i32 [[TMP6]] to i64
279+
; IF-EVL-NEXT: [[TMP10:%.*]] = mul i64 0, [[TMP9]]
280+
; IF-EVL-NEXT: [[TMP11:%.*]] = sub i64 1, [[TMP9]]
281+
; IF-EVL-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[TMP8]], i64 [[TMP10]]
282+
; IF-EVL-NEXT: [[TMP13:%.*]] = getelementptr i8, ptr [[TMP12]], i64 [[TMP11]]
283+
; IF-EVL-NEXT: [[VP_OP_LOAD:%.*]] = call <vscale x 16 x i8> @llvm.vp.load.nxv16i8.p0(ptr align 1 [[TMP13]], <vscale x 16 x i1> splat (i1 true), i32 [[TMP6]])
284+
; IF-EVL-NEXT: [[VP_REVERSE:%.*]] = call <vscale x 16 x i8> @llvm.experimental.vp.reverse.nxv16i8(<vscale x 16 x i8> [[VP_OP_LOAD]], <vscale x 16 x i1> splat (i1 true), i32 [[TMP6]])
285+
; IF-EVL-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[B:%.*]], <vscale x 16 x i8> [[VP_REVERSE]]
286+
; IF-EVL-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <vscale x 16 x i8> @llvm.vp.gather.nxv16i8.nxv16p0(<vscale x 16 x ptr> align 1 [[TMP14]], <vscale x 16 x i1> splat (i1 true), i32 [[TMP6]])
287+
; IF-EVL-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[C:%.*]], i64 [[TMP7]]
288+
; IF-EVL-NEXT: [[TMP16:%.*]] = zext i32 [[TMP6]] to i64
289+
; IF-EVL-NEXT: [[TMP17:%.*]] = mul i64 0, [[TMP16]]
290+
; IF-EVL-NEXT: [[TMP18:%.*]] = sub i64 1, [[TMP16]]
291+
; IF-EVL-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[TMP15]], i64 [[TMP17]]
292+
; IF-EVL-NEXT: [[TMP20:%.*]] = getelementptr i8, ptr [[TMP19]], i64 [[TMP18]]
293+
; IF-EVL-NEXT: [[VP_REVERSE1:%.*]] = call <vscale x 16 x i8> @llvm.experimental.vp.reverse.nxv16i8(<vscale x 16 x i8> [[WIDE_MASKED_GATHER]], <vscale x 16 x i1> splat (i1 true), i32 [[TMP6]])
294+
; IF-EVL-NEXT: call void @llvm.vp.store.nxv16i8.p0(<vscale x 16 x i8> [[VP_REVERSE1]], ptr align 1 [[TMP20]], <vscale x 16 x i1> splat (i1 true), i32 [[TMP6]])
295+
; IF-EVL-NEXT: [[TMP21:%.*]] = getelementptr i8, ptr [[D:%.*]], i64 [[TMP7]]
296+
; IF-EVL-NEXT: [[TMP22:%.*]] = zext i32 [[TMP6]] to i64
297+
; IF-EVL-NEXT: [[TMP23:%.*]] = mul i64 0, [[TMP22]]
298+
; IF-EVL-NEXT: [[TMP24:%.*]] = sub i64 1, [[TMP22]]
299+
; IF-EVL-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[TMP21]], i64 [[TMP23]]
300+
; IF-EVL-NEXT: [[TMP26:%.*]] = getelementptr i8, ptr [[TMP25]], i64 [[TMP24]]
301+
; IF-EVL-NEXT: [[VP_REVERSE2:%.*]] = call <vscale x 16 x i8> @llvm.experimental.vp.reverse.nxv16i8(<vscale x 16 x i8> [[WIDE_MASKED_GATHER]], <vscale x 16 x i1> splat (i1 true), i32 [[TMP6]])
302+
; IF-EVL-NEXT: call void @llvm.vp.store.nxv16i8.p0(<vscale x 16 x i8> [[VP_REVERSE2]], ptr align 1 [[TMP26]], <vscale x 16 x i1> splat (i1 true), i32 [[TMP6]])
303+
; IF-EVL-NEXT: [[TMP27:%.*]] = zext i32 [[TMP6]] to i64
304+
; IF-EVL-NEXT: [[INDEX_EVL_NEXT]] = add nuw i64 [[TMP27]], [[EVL_BASED_IV]]
305+
; IF-EVL-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP4]]
306+
; IF-EVL-NEXT: [[TMP28:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
307+
; IF-EVL-NEXT: br i1 [[TMP28]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
308+
; IF-EVL: middle.block:
309+
; IF-EVL-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]]
310+
; IF-EVL: scalar.ph:
311+
; IF-EVL-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP5]], [[MIDDLE_BLOCK]] ], [ 1024, [[ENTRY:%.*]] ]
312+
; IF-EVL-NEXT: br label [[LOOP:%.*]]
313+
; IF-EVL: loop:
314+
; IF-EVL-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
315+
; IF-EVL-NEXT: [[GEP_A:%.*]] = getelementptr i8, ptr [[A]], i64 [[IV]]
316+
; IF-EVL-NEXT: [[X:%.*]] = load i8, ptr [[GEP_A]], align 1
317+
; IF-EVL-NEXT: [[GEP_B:%.*]] = getelementptr i8, ptr [[B]], i8 [[X]]
318+
; IF-EVL-NEXT: [[Y:%.*]] = load i8, ptr [[GEP_B]], align 1
319+
; IF-EVL-NEXT: [[GEP_C:%.*]] = getelementptr i8, ptr [[C]], i64 [[IV]]
320+
; IF-EVL-NEXT: store i8 [[Y]], ptr [[GEP_C]], align 1
321+
; IF-EVL-NEXT: [[GEP_D:%.*]] = getelementptr i8, ptr [[D]], i64 [[IV]]
322+
; IF-EVL-NEXT: store i8 [[Y]], ptr [[GEP_D]], align 1
323+
; IF-EVL-NEXT: [[IV_NEXT]] = add i64 [[IV]], -1
324+
; IF-EVL-NEXT: [[CMP_NOT:%.*]] = icmp eq i64 [[IV]], 0
325+
; IF-EVL-NEXT: br i1 [[CMP_NOT]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP7:![0-9]+]]
326+
; IF-EVL: exit:
327+
; IF-EVL-NEXT: ret void
328+
;
329+
; NO-VP-LABEL: @multiple_reverse_vector_pointer(
330+
; NO-VP-NEXT: entry:
331+
; NO-VP-NEXT: br label [[LOOP:%.*]]
332+
; NO-VP: loop:
333+
; NO-VP-NEXT: [[IV:%.*]] = phi i64 [ 1024, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
334+
; NO-VP-NEXT: [[GEP_A:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[IV]]
335+
; NO-VP-NEXT: [[X:%.*]] = load i8, ptr [[GEP_A]], align 1
336+
; NO-VP-NEXT: [[GEP_B:%.*]] = getelementptr i8, ptr [[B:%.*]], i8 [[X]]
337+
; NO-VP-NEXT: [[Y:%.*]] = load i8, ptr [[GEP_B]], align 1
338+
; NO-VP-NEXT: [[GEP_C:%.*]] = getelementptr i8, ptr [[C:%.*]], i64 [[IV]]
339+
; NO-VP-NEXT: store i8 [[Y]], ptr [[GEP_C]], align 1
340+
; NO-VP-NEXT: [[GEP_D:%.*]] = getelementptr i8, ptr [[D:%.*]], i64 [[IV]]
341+
; NO-VP-NEXT: store i8 [[Y]], ptr [[GEP_D]], align 1
342+
; NO-VP-NEXT: [[IV_NEXT]] = add i64 [[IV]], -1
343+
; NO-VP-NEXT: [[CMP_NOT:%.*]] = icmp eq i64 [[IV]], 0
344+
; NO-VP-NEXT: br i1 [[CMP_NOT]], label [[EXIT:%.*]], label [[LOOP]]
345+
; NO-VP: exit:
346+
; NO-VP-NEXT: ret void
347+
;
348+
entry:
349+
br label %loop
350+
351+
loop:
352+
%iv = phi i64 [ 1024, %entry ], [ %iv.next, %loop ]
353+
354+
%gep.a = getelementptr i8, ptr %a, i64 %iv
355+
%x = load i8, ptr %gep.a
356+
357+
%gep.b = getelementptr i8, ptr %b, i8 %x
358+
%y = load i8, ptr %gep.b
359+
360+
%gep.c = getelementptr i8, ptr %c, i64 %iv
361+
store i8 %y, ptr %gep.c
362+
363+
%gep.d = getelementptr i8, ptr %d, i64 %iv
364+
store i8 %y, ptr %gep.d
365+
366+
%iv.next = add i64 %iv, -1
367+
%cmp.not = icmp eq i64 %iv, 0
368+
br i1 %cmp.not, label %exit, label %loop
369+
370+
exit:
371+
ret void
372+
}

0 commit comments

Comments
 (0)