Skip to content

Commit 833bdbe

Browse files
committed
[LV] Support sinking recipe in replicate region after another region.
This patch handles sinking a replicate region after another replicate region. In that case, we can connect the sink region after the target region. This properly handles the case for which an assertion has been added in 337d765. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34842. Reviewed By: Ayal Differential Revision: https://reviews.llvm.org/D103514
1 parent 25bb616 commit 833bdbe

File tree

2 files changed

+136
-39
lines changed

2 files changed

+136
-39
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9192,52 +9192,60 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
91929192
auto GetReplicateRegion = [](VPRecipeBase *R) -> VPRegionBlock * {
91939193
auto *Region =
91949194
dyn_cast_or_null<VPRegionBlock>(R->getParent()->getParent());
9195-
if (Region && Region->isReplicator())
9195+
if (Region && Region->isReplicator()) {
9196+
assert(Region->getNumSuccessors() == 1 &&
9197+
Region->getNumPredecessors() == 1 && "Expected SESE region!");
9198+
assert(R->getParent()->size() == 1 &&
9199+
"A recipe in an original replicator region must be the only "
9200+
"recipe in its block");
91969201
return Region;
9202+
}
91979203
return nullptr;
91989204
};
9199-
9200-
// If the target is in a replication region, make sure to move Sink to the
9201-
// block after it, not into the replication region itself.
9202-
if (auto *TargetRegion = GetReplicateRegion(Target)) {
9203-
assert(TargetRegion->getNumSuccessors() == 1 && "Expected SESE region!");
9204-
assert(!GetReplicateRegion(Sink) &&
9205-
"cannot sink a region into another region yet");
9206-
VPBasicBlock *NextBlock =
9207-
cast<VPBasicBlock>(TargetRegion->getSuccessors().front());
9208-
Sink->moveBefore(*NextBlock, NextBlock->getFirstNonPhi());
9209-
continue;
9210-
}
9211-
9205+
auto *TargetRegion = GetReplicateRegion(Target);
92129206
auto *SinkRegion = GetReplicateRegion(Sink);
9213-
// Unless the sink source is in a replicate region, sink the recipe
9214-
// directly.
92159207
if (!SinkRegion) {
9216-
Sink->moveAfter(Target);
9208+
// If the sink source is not a replicate region, sink the recipe directly.
9209+
if (TargetRegion) {
9210+
// The target is in a replication region, make sure to move Sink to
9211+
// the block after it, not into the replication region itself.
9212+
VPBasicBlock *NextBlock =
9213+
cast<VPBasicBlock>(TargetRegion->getSuccessors().front());
9214+
Sink->moveBefore(*NextBlock, NextBlock->getFirstNonPhi());
9215+
} else
9216+
Sink->moveAfter(Target);
92179217
continue;
92189218
}
92199219

9220-
// If the sink source is in a replicate region, we need to move the whole
9221-
// replicate region, which should only contain a single recipe in the main
9222-
// block.
9223-
assert(Sink->getParent()->size() == 1 &&
9224-
"parent must be a replicator with a single recipe");
9225-
auto *SplitBlock =
9226-
Target->getParent()->splitAt(std::next(Target->getIterator()));
9227-
9228-
auto *Pred = SinkRegion->getSinglePredecessor();
9229-
auto *Succ = SinkRegion->getSingleSuccessor();
9230-
VPBlockUtils::disconnectBlocks(Pred, SinkRegion);
9231-
VPBlockUtils::disconnectBlocks(SinkRegion, Succ);
9232-
VPBlockUtils::connectBlocks(Pred, Succ);
9233-
9234-
auto *SplitPred = SplitBlock->getSinglePredecessor();
9235-
9236-
VPBlockUtils::disconnectBlocks(SplitPred, SplitBlock);
9237-
VPBlockUtils::connectBlocks(SplitPred, SinkRegion);
9238-
VPBlockUtils::connectBlocks(SinkRegion, SplitBlock);
9239-
if (VPBB == SplitPred)
9240-
VPBB = SplitBlock;
9220+
// The sink source is in a replicate region. Unhook the region from the CFG.
9221+
auto *SinkPred = SinkRegion->getSinglePredecessor();
9222+
auto *SinkSucc = SinkRegion->getSingleSuccessor();
9223+
VPBlockUtils::disconnectBlocks(SinkPred, SinkRegion);
9224+
VPBlockUtils::disconnectBlocks(SinkRegion, SinkSucc);
9225+
VPBlockUtils::connectBlocks(SinkPred, SinkSucc);
9226+
9227+
if (TargetRegion) {
9228+
// The target recipe is also in a replicate region, move the sink region
9229+
// after the target region.
9230+
auto *TargetSucc = TargetRegion->getSingleSuccessor();
9231+
VPBlockUtils::disconnectBlocks(TargetRegion, TargetSucc);
9232+
VPBlockUtils::connectBlocks(TargetRegion, SinkRegion);
9233+
VPBlockUtils::connectBlocks(SinkRegion, TargetSucc);
9234+
} else {
9235+
// The sink source is in a replicate region, we need to move the whole
9236+
// replicate region, which should only contain a single recipe in the main
9237+
// block.
9238+
auto *SplitBlock =
9239+
Target->getParent()->splitAt(std::next(Target->getIterator()));
9240+
9241+
auto *SplitPred = SplitBlock->getSinglePredecessor();
9242+
9243+
VPBlockUtils::disconnectBlocks(SplitPred, SplitBlock);
9244+
VPBlockUtils::connectBlocks(SplitPred, SinkRegion);
9245+
VPBlockUtils::connectBlocks(SinkRegion, SplitBlock);
9246+
if (VPBB == SplitPred)
9247+
VPBB = SplitBlock;
9248+
}
92419249
}
92429250

92439251
// Interleave memory: for each Interleave Group we marked earlier as relevant

llvm/test/Transforms/LoopVectorize/first-order-recurrence-sink-replicate-region.ll

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; REQUIRES: asserts
2-
; RUN: opt < %s -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -debug-only=loop-vectorize 2>&1 | FileCheck %s
2+
; RUN: opt < %s -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -disable-output -debug-only=loop-vectorize 2>&1 | FileCheck %s
33

44
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
55

@@ -306,3 +306,92 @@ loop:
306306
exit:
307307
ret void
308308
}
309+
310+
; Test case that requires sinking a recipe in a replicate region after another replicate region.
311+
define void @sink_replicate_region_after_replicate_region(i32* %ptr, i32 %x, i8 %y) optsize {
312+
; CHECK-LABEL: sink_replicate_region_after_replicate_region
313+
; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' {
314+
; CHECK-NEXT: loop:
315+
; CHECK-NEXT: WIDEN-PHI %recur = phi 0, %recur.next
316+
; CHECK-NEXT: WIDEN-INDUCTION %iv = phi 0, %iv.next
317+
; CHECK-NEXT: EMIT vp<%3> = icmp ule ir<%iv> vp<%0>
318+
; CHECK-NEXT: Successor(s): loop.0
319+
; CHECK-EMPTY:
320+
; CHECK-NEXT: loop.0:
321+
; CHECK-NEXT: Successor(s): loop.1
322+
; CHECK-EMPTY:
323+
; CHECK-NEXT: loop.1:
324+
; CHECK-NEXT: WIDEN ir<%recur.next> = sext ir<%y>
325+
; CHECK-NEXT: Successor(s): pred.srem
326+
; CHECK-EMPTY:
327+
; CHECK-NEXT: <xVFxUF> pred.srem: {
328+
; CHECK-NEXT: pred.srem.entry:
329+
; CHECK-NEXT: BRANCH-ON-MASK vp<%3>
330+
; CHECK-NEXT: Successor(s): pred.srem.if, pred.srem.continue
331+
; CHECK-NEXT: CondBit: vp<%3> (loop)
332+
; CHECK-EMPTY:
333+
; CHECK-NEXT: pred.srem.if:
334+
; CHECK-NEXT: REPLICATE ir<%rem> = srem ir<%recur>, ir<%x>
335+
; CHECK-NEXT: Successor(s): pred.srem.continue
336+
; CHECK-EMPTY:
337+
; CHECK-NEXT: pred.srem.continue:
338+
; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<%6> = ir<%rem>
339+
; CHECK-NEXT: No successors
340+
; CHECK-NEXT: }
341+
342+
; CHECK: <xVFxUF> pred.sdiv: {
343+
; CHECK-NEXT: pred.sdiv.entry:
344+
; CHECK-NEXT: BRANCH-ON-MASK vp<%3>
345+
; CHECK-NEXT: Successor(s): pred.sdiv.if, pred.sdiv.continue
346+
; CHECK-NEXT: CondBit: vp<%3> (loop)
347+
; CHECK-EMPTY:
348+
; CHECK-NEXT: pred.sdiv.if:
349+
; CHECK-NEXT: REPLICATE ir<%rem.div> = sdiv ir<20>, vp<%6>
350+
; CHECK-NEXT: Successor(s): pred.sdiv.continue
351+
; CHECK-EMPTY:
352+
; CHECK-NEXT: pred.sdiv.continue:
353+
; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<%8> = ir<%rem.div>
354+
; CHECK-NEXT: No successors
355+
; CHECK-NEXT: }
356+
; CHECK-NEXT: Successor(s): loop.1.split
357+
; CHECK-EMPTY:
358+
; CHECK-NEXT: loop.1.split:
359+
; CHECK-NEXT: Successor(s): pred.store
360+
; CHECK-EMPTY:
361+
; CHECK-NEXT: <xVFxUF> pred.store: {
362+
; CHECK-NEXT: pred.store.entry:
363+
; CHECK-NEXT: BRANCH-ON-MASK vp<%3>
364+
; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue
365+
; CHECK-NEXT: CondBit: vp<%3> (loop)
366+
; CHECK-EMPTY:
367+
; CHECK-NEXT: pred.store.if:
368+
; CHECK-NEXT: REPLICATE ir<%gep> = getelementptr ir<%ptr>, ir<%iv>
369+
; CHECK-NEXT: REPLICATE store vp<%8>, ir<%gep>
370+
; CHECK-NEXT: Successor(s): pred.store.continue
371+
; CHECK-EMPTY:
372+
; CHECK-NEXT: pred.store.continue:
373+
; CHECK-NEXT: No successors
374+
; CHECK-NEXT: }
375+
376+
; CHECK: loop.2:
377+
; CHECK-NEXT: No successors
378+
; CHECK-NEXT: }
379+
;
380+
entry:
381+
br label %loop
382+
383+
loop: ; preds = %loop, %entry
384+
%recur = phi i32 [ 0, %entry ], [ %recur.next, %loop ]
385+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
386+
%rem = srem i32 %recur, %x
387+
%rem.div = sdiv i32 20, %rem
388+
%recur.next = sext i8 %y to i32
389+
%gep = getelementptr i32, i32* %ptr, i32 %iv
390+
store i32 %rem.div, i32* %gep
391+
%iv.next = add nsw i32 %iv, 1
392+
%C = icmp sgt i32 %iv.next, %recur.next
393+
br i1 %C, label %exit, label %loop
394+
395+
exit: ; preds = %loop
396+
ret void
397+
}

0 commit comments

Comments
 (0)