[llvm] c945d88 - Revert "[StructurizeCFG] Improve basic block ordering"
Brendon Cahoon via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 14 07:45:35 PDT 2022
Author: Brendon Cahoon
Date: 2022-07-14T09:40:51-05:00
New Revision: c945d88d2b88b8d95f8295e9fbf38ee6fb31e5d0
URL: https://github.com/llvm/llvm-project/commit/c945d88d2b88b8d95f8295e9fbf38ee6fb31e5d0
DIFF: https://github.com/llvm/llvm-project/commit/c945d88d2b88b8d95f8295e9fbf38ee6fb31e5d0.diff
LOG: Revert "[StructurizeCFG] Improve basic block ordering"
This reverts commit f1b05a0a2bbbea160002be709f8a1c59de366761.
Need to revert to due to issues identified with testing. The
transformation is incorrect for blocks that contain convergent
instructions.
Added:
Modified:
llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
llvm/test/CodeGen/AMDGPU/nested-loop-conditions.ll
Removed:
llvm/test/Transforms/StructurizeCFG/improve-order.ll
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
index f6525ad7de9bc..0b797abefe207 100644
--- a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
+++ b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
@@ -68,11 +68,6 @@ static cl::opt<bool>
cl::desc("Allow relaxed uniform region checks"),
cl::init(true));
-static cl::opt<unsigned>
- ReorderNodeSize("structurizecfg-node-reorder-size",
- cl::desc("Limit region size for reordering nodes"),
- cl::init(100), cl::Hidden);
-
// Definition of the complex types used in this pass.
using BBValuePair = std::pair<BasicBlock *, Value *>;
@@ -267,8 +262,6 @@ class StructurizeCFG {
void orderNodes();
- void reorderNodes();
-
void analyzeLoops(RegionNode *N);
Value *buildCondition(BranchInst *Term, unsigned Idx, bool Invert);
@@ -427,57 +420,6 @@ void StructurizeCFG::orderNodes() {
}
}
-/// Change the node ordering to decrease the range of live values, especially
-/// the values that capture the control flow path for branches. We do this
-/// by moving blocks with a single predecessor and successor to appear after
-/// predecessor. The motivation is to move some loop exit blocks into a loop.
-/// In cases where a loop has a large number of exit blocks, this reduces the
-/// amount of values needed across the loop boundary.
-void StructurizeCFG::reorderNodes() {
- SmallVector<RegionNode *, 8> NewOrder;
- DenseMap<BasicBlock *, unsigned> MoveTo;
- BitVector Moved(Order.size());
-
- // The benefits of reordering nodes occurs for large regions.
- if (Order.size() <= ReorderNodeSize)
- return;
-
- // The algorithm works with two passes over Order. The first pass identifies
- // the blocks to move and the position to move them to. The second pass
- // creates the new order based upon this information. We move blocks with
- // a single predecessor and successor. If there are multiple candidates then
- // maintain the original order.
- BBSet Seen;
- for (int I = Order.size() - 1; I >= 0; --I) {
- auto *BB = Order[I]->getEntry();
- Seen.insert(BB);
- auto *Pred = BB->getSinglePredecessor();
- auto *Succ = BB->getSingleSuccessor();
- // Consider only those basic blocks that have a predecessor in Order and a
- // successor that exits the region. The region may contain subregions that
- // have been structurized and are not included in Order.
- if (Pred && Succ && Seen.count(Pred) && Succ == ParentRegion->getExit() &&
- !MoveTo.count(Pred)) {
- MoveTo[Pred] = I;
- Moved.set(I);
- }
- }
-
- // If no blocks have been moved then the original order is good.
- if (!Moved.count())
- return;
-
- for (size_t I = 0, E = Order.size(); I < E; ++I) {
- auto *BB = Order[I]->getEntry();
- if (MoveTo.count(BB))
- NewOrder.push_back(Order[MoveTo[BB]]);
- if (!Moved[I])
- NewOrder.push_back(Order[I]);
- }
-
- Order.assign(NewOrder);
-}
-
/// Determine the end of the loops
void StructurizeCFG::analyzeLoops(RegionNode *N) {
if (N->isSubRegion()) {
@@ -1139,7 +1081,6 @@ bool StructurizeCFG::run(Region *R, DominatorTree *DT) {
ParentRegion = R;
orderNodes();
- reorderNodes();
collectInfos();
createFlow();
insertConditions(false);
diff --git a/llvm/test/CodeGen/AMDGPU/nested-loop-conditions.ll b/llvm/test/CodeGen/AMDGPU/nested-loop-conditions.ll
index 2869e996ec724..f3089e79ad378 100644
--- a/llvm/test/CodeGen/AMDGPU/nested-loop-conditions.ll
+++ b/llvm/test/CodeGen/AMDGPU/nested-loop-conditions.ll
@@ -1,4 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: opt -mtriple=amdgcn-- -S -structurizecfg -si-annotate-control-flow %s | FileCheck -check-prefix=IR %s
; RUN: llc -march=amdgcn -mcpu=hawaii -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
@@ -47,9 +48,9 @@ define amdgpu_kernel void @reduced_nested_loop_conditions(i64 addrspace(3)* noca
; GCN-NEXT: s_endpgm
; IR-LABEL: @reduced_nested_loop_conditions(
; IR-NEXT: bb:
-; IR-NEXT: [[MY_TMP:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x() #[[ATTR4:[0-9]+]]
+; IR-NEXT: [[MY_TMP:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x() #4
; IR-NEXT: [[MY_TMP1:%.*]] = getelementptr inbounds i64, i64 addrspace(3)* [[ARG:%.*]], i32 [[MY_TMP]]
-; IR-NEXT: [[MY_TMP2:%.*]] = load volatile i64, i64 addrspace(3)* [[MY_TMP1]], align 4
+; IR-NEXT: [[MY_TMP2:%.*]] = load volatile i64, i64 addrspace(3)* [[MY_TMP1]]
; IR-NEXT: br label [[BB5:%.*]]
; IR: bb3:
; IR-NEXT: br i1 true, label [[BB4:%.*]], label [[BB13:%.*]]
@@ -83,7 +84,7 @@ define amdgpu_kernel void @reduced_nested_loop_conditions(i64 addrspace(3)* noca
; IR: bb16:
; IR-NEXT: [[MY_TMP17:%.*]] = extractelement <2 x i32> [[MY_TMP15]], i64 1
; IR-NEXT: [[MY_TMP18:%.*]] = getelementptr inbounds i32, i32 addrspace(3)* undef, i32 [[MY_TMP17]]
-; IR-NEXT: [[MY_TMP19:%.*]] = load volatile i32, i32 addrspace(3)* [[MY_TMP18]], align 4
+; IR-NEXT: [[MY_TMP19:%.*]] = load volatile i32, i32 addrspace(3)* [[MY_TMP18]]
; IR-NEXT: br label [[BB20]]
; IR: bb20:
; IR-NEXT: [[MY_TMP21]] = phi i32 [ [[MY_TMP19]], [[BB16]] ], [ 0, [[BB13]] ]
@@ -92,7 +93,6 @@ define amdgpu_kernel void @reduced_nested_loop_conditions(i64 addrspace(3)* noca
; IR: bb23:
; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP6]])
; IR-NEXT: ret void
-;
bb:
%my.tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1
%my.tmp1 = getelementptr inbounds i64, i64 addrspace(3)* %arg, i32 %my.tmp
@@ -190,19 +190,19 @@ define amdgpu_kernel void @nested_loop_conditions(i64 addrspace(1)* nocapture %a
; GCN-NEXT: s_endpgm
; IR-LABEL: @nested_loop_conditions(
; IR-NEXT: bb:
-; IR-NEXT: [[MY_TMP:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x() #[[ATTR4]]
+; IR-NEXT: [[MY_TMP:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x() #4
; IR-NEXT: [[MY_TMP1:%.*]] = zext i32 [[MY_TMP]] to i64
; IR-NEXT: [[MY_TMP2:%.*]] = getelementptr inbounds i64, i64 addrspace(1)* [[ARG:%.*]], i64 [[MY_TMP1]]
; IR-NEXT: [[MY_TMP3:%.*]] = load i64, i64 addrspace(1)* [[MY_TMP2]], align 16
; IR-NEXT: [[MY_TMP932:%.*]] = load <4 x i32>, <4 x i32> addrspace(1)* undef, align 16
; IR-NEXT: [[MY_TMP1033:%.*]] = extractelement <4 x i32> [[MY_TMP932]], i64 0
-; IR-NEXT: [[MY_TMP1134:%.*]] = load volatile i32, i32 addrspace(1)* undef, align 4
+; IR-NEXT: [[MY_TMP1134:%.*]] = load volatile i32, i32 addrspace(1)* undef
; IR-NEXT: [[MY_TMP1235:%.*]] = icmp slt i32 [[MY_TMP1134]], 9
; IR-NEXT: br i1 [[MY_TMP1235]], label [[BB14_LR_PH:%.*]], label [[FLOW:%.*]]
; IR: bb14.lr.ph:
; IR-NEXT: br label [[BB14:%.*]]
; IR: Flow3:
-; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP20:%.*]])
+; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP21:%.*]])
; IR-NEXT: [[TMP0:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[TMP14:%.*]])
; IR-NEXT: [[TMP1:%.*]] = extractvalue { i1, i64 } [[TMP0]], 0
; IR-NEXT: [[TMP2:%.*]] = extractvalue { i1, i64 } [[TMP0]], 1
@@ -244,7 +244,7 @@ define amdgpu_kernel void @nested_loop_conditions(i64 addrspace(1)* nocapture %a
; IR-NEXT: [[TMP17:%.*]] = call i1 @llvm.amdgcn.loop.i64(i64 [[TMP16]])
; IR-NEXT: br i1 [[TMP17]], label [[FLOW2:%.*]], label [[BB14]]
; IR: bb18:
-; IR-NEXT: [[MY_TMP19:%.*]] = load volatile i32, i32 addrspace(1)* undef, align 4
+; IR-NEXT: [[MY_TMP19:%.*]] = load volatile i32, i32 addrspace(1)* undef
; IR-NEXT: [[MY_TMP20:%.*]] = icmp slt i32 [[MY_TMP19]], 9
; IR-NEXT: br i1 [[MY_TMP20]], label [[BB21]], label [[BB18]]
; IR: bb21:
@@ -261,22 +261,21 @@ define amdgpu_kernel void @nested_loop_conditions(i64 addrspace(1)* nocapture %a
; IR-NEXT: [[MY_TMP8:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32> addrspace(1)* undef, i64 [[MY_TMP7]]
; IR-NEXT: [[MY_TMP9]] = load <4 x i32>, <4 x i32> addrspace(1)* [[MY_TMP8]], align 16
; IR-NEXT: [[MY_TMP10]] = extractelement <4 x i32> [[MY_TMP9]], i64 0
-; IR-NEXT: [[MY_TMP11:%.*]] = load volatile i32, i32 addrspace(1)* undef, align 4
+; IR-NEXT: [[MY_TMP11:%.*]] = load volatile i32, i32 addrspace(1)* undef
; IR-NEXT: [[MY_TMP12]] = icmp sge i32 [[MY_TMP11]], 9
; IR-NEXT: br label [[FLOW1]]
; IR: Flow2:
; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP16]])
-; IR-NEXT: [[TMP18:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[TMP15]])
-; IR-NEXT: [[TMP19:%.*]] = extractvalue { i1, i64 } [[TMP18]], 0
-; IR-NEXT: [[TMP20]] = extractvalue { i1, i64 } [[TMP18]], 1
-; IR-NEXT: br i1 [[TMP19]], label [[BB31_LOOPEXIT:%.*]], label [[FLOW3]]
+; IR-NEXT: [[TMP19:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[TMP15]])
+; IR-NEXT: [[TMP20:%.*]] = extractvalue { i1, i64 } [[TMP19]], 0
+; IR-NEXT: [[TMP21]] = extractvalue { i1, i64 } [[TMP19]], 1
+; IR-NEXT: br i1 [[TMP20]], label [[BB31_LOOPEXIT:%.*]], label [[FLOW3]]
; IR: bb31.loopexit:
; IR-NEXT: br label [[FLOW3]]
; IR: bb31:
; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP7]])
-; IR-NEXT: store volatile i32 0, i32 addrspace(1)* undef, align 4
+; IR-NEXT: store volatile i32 0, i32 addrspace(1)* undef
; IR-NEXT: ret void
-;
bb:
%my.tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1
%my.tmp1 = zext i32 %my.tmp to i64
diff --git a/llvm/test/Transforms/StructurizeCFG/improve-order.ll b/llvm/test/Transforms/StructurizeCFG/improve-order.ll
deleted file mode 100644
index e40770cb2aa5b..0000000000000
--- a/llvm/test/Transforms/StructurizeCFG/improve-order.ll
+++ /dev/null
@@ -1,511 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -structurizecfg -structurizecfg-node-reorder-size=3 %s -o - | FileCheck %s
-; RUN: opt -S -passes=structurizecfg -structurizecfg-node-reorder-size=3 %s -o - | FileCheck %s
-
-; Test that exit blocks for a loop are reordered so that they
-; appear after their predecessors rather than after the loop.
-; This reduces the number of values needed after the loop
-; to record if the exit blocks are taken/not taken.
-
-define void @reorder_loop(i1 %PredEntry, i1 %PredA, i1 %PredC) {
-; CHECK-LABEL: @reorder_loop(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[G:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1:%.*]], [[FLOW1:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[B:%.*]], label [[FLOW:%.*]]
-; CHECK: B:
-; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0:[0-9]+]]
-; CHECK-NEXT: br label [[FLOW]]
-; CHECK: Flow:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ false, [[B]] ], [ true, [[A]] ]
-; CHECK-NEXT: br i1 [[TMP0]], label [[C:%.*]], label [[FLOW1]]
-; CHECK: C:
-; CHECK-NEXT: br i1 [[PREDC:%.*]], label [[D:%.*]], label [[FLOW2:%.*]]
-; CHECK: Flow1:
-; CHECK-NEXT: [[TMP1]] = phi i32 [ [[TMP5:%.*]], [[FLOW3:%.*]] ], [ undef, [[FLOW]] ]
-; CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ [[TMP6:%.*]], [[FLOW3]] ], [ false, [[FLOW]] ]
-; CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ [[TMP7:%.*]], [[FLOW3]] ], [ true, [[FLOW]] ]
-; CHECK-NEXT: br i1 [[TMP3]], label [[LOOP_EXIT_GUARD:%.*]], label [[A]]
-; CHECK: D:
-; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]
-; CHECK-NEXT: br label [[FLOW2]]
-; CHECK: Flow2:
-; CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[D]] ], [ true, [[C]] ]
-; CHECK-NEXT: br i1 [[TMP4]], label [[E:%.*]], label [[FLOW3]]
-; CHECK: E:
-; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[INC2]], 10
-; CHECK-NEXT: br label [[FLOW3]]
-; CHECK: F:
-; CHECK-NEXT: unreachable
-; CHECK: G:
-; CHECK-NEXT: ret void
-; CHECK: Flow3:
-; CHECK-NEXT: [[TMP5]] = phi i32 [ [[INC2]], [[E]] ], [ undef, [[FLOW2]] ]
-; CHECK-NEXT: [[TMP6]] = phi i1 [ true, [[E]] ], [ false, [[FLOW2]] ]
-; CHECK-NEXT: [[TMP7]] = phi i1 [ [[CMP]], [[E]] ], [ true, [[FLOW2]] ]
-; CHECK-NEXT: br label [[FLOW1]]
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: br i1 [[TMP2]], label [[G]], label [[F:%.*]]
-;
-entry:
- br i1 %PredEntry, label %A, label %G
-
-; A is the loop header.
-A:
- %inc1 = phi i32 [ 0, %entry ], [ %inc2, %E ]
- br i1 %PredA, label %B, label %C
-
-; B is a loop exit block. After reorderNodes in StructurizeCFG, this block
-; remains after A. Without reorderNodes, B is dependent on the Flow block for
-; the loop back edge. B is executes only when the loop exits from A. It does not
-; execute during the loop iterations.
-B:
- tail call fastcc void @check(i32 1) #0
- br label %loop.exit.guard
-
-C:
- br i1 %PredC, label %D, label %E
-
-; D is a loop exit block. After reorderNodes, this block remains in the loop
-; and is not dependent on the Flow block that contains the back edge to the
-; loop header.
-D:
- tail call fastcc void @check(i32 2) #0
- br label %loop.exit.guard
-
-; E is a latch and exiting block.
-E:
- %inc2 = add i32 %inc1, 1
- %cmp = icmp ult i32 %inc2, 10
- br i1 %cmp, label %A, label %loop.exit.guard
-
-; Paths fom the exit blocks come here through loop.exit.gaurd.
-F:
- unreachable
-
-G:
- ret void
-
-; loop.exit.guard is added by UnifyLoopExits as a common block for all loop
-; exits. After StructurizeCFG, the predecessor B will remain in the loop.
-loop.exit.guard:
- %Guard.G = phi i1 [ true, %E ], [ false, %B ], [ false, %D ]
- br i1 %Guard.G, label %G, label %F
-}
-
-; Test that the exit blocks for a nested loop are reordered so that they are
-; not dependent on the Flow block that contains the loop back edge. That
-; dependence forces the block to appear after the loop, which increases the
-; number of live values exiting the loop.
-
-define void @reorder_inner_loop(i1 %PredEntry, i1 %PredB, i1 %PredD) {
-; CHECK-LABEL: @reorder_inner_loop(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[PREDB_INV:%.*]] = xor i1 [[PREDB:%.*]], true
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[I:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[OUTER1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP5:%.*]], [[FLOW4:%.*]] ]
-; CHECK-NEXT: br label [[B:%.*]]
-; CHECK: B:
-; CHECK-NEXT: [[INNER1:%.*]] = phi i32 [ [[TMP1:%.*]], [[FLOW1:%.*]] ], [ 0, [[A]] ]
-; CHECK-NEXT: br i1 [[PREDB_INV]], label [[C:%.*]], label [[FLOW:%.*]]
-; CHECK: C:
-; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]
-; CHECK-NEXT: br label [[FLOW]]
-; CHECK: Flow:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ false, [[C]] ], [ true, [[B]] ]
-; CHECK-NEXT: br i1 [[TMP0]], label [[D:%.*]], label [[FLOW1]]
-; CHECK: D:
-; CHECK-NEXT: br i1 [[PREDD:%.*]], label [[E:%.*]], label [[FLOW2:%.*]]
-; CHECK: Flow1:
-; CHECK-NEXT: [[TMP1]] = phi i32 [ [[TMP8:%.*]], [[FLOW3:%.*]] ], [ undef, [[FLOW]] ]
-; CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ [[TMP9:%.*]], [[FLOW3]] ], [ false, [[FLOW]] ]
-; CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ [[TMP10:%.*]], [[FLOW3]] ], [ true, [[FLOW]] ]
-; CHECK-NEXT: br i1 [[TMP3]], label [[LOOP_EXIT_GUARD1:%.*]], label [[B]]
-; CHECK: E:
-; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]
-; CHECK-NEXT: br label [[FLOW2]]
-; CHECK: Flow2:
-; CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ false, [[E]] ], [ true, [[D]] ]
-; CHECK-NEXT: br i1 [[TMP4]], label [[F:%.*]], label [[FLOW3]]
-; CHECK: F:
-; CHECK-NEXT: [[INNER2:%.*]] = add i32 [[INNER1]], 1
-; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i32 [[INNER2]], 20
-; CHECK-NEXT: br label [[FLOW3]]
-; CHECK: G:
-; CHECK-NEXT: [[OUTER2:%.*]] = add i32 [[OUTER1]], 1
-; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i32 [[OUTER2]], 10
-; CHECK-NEXT: br label [[FLOW4]]
-; CHECK: H:
-; CHECK-NEXT: unreachable
-; CHECK: I:
-; CHECK-NEXT: ret void
-; CHECK: Flow4:
-; CHECK-NEXT: [[TMP5]] = phi i32 [ [[OUTER2]], [[G:%.*]] ], [ undef, [[LOOP_EXIT_GUARD1]] ]
-; CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, [[G]] ], [ false, [[LOOP_EXIT_GUARD1]] ]
-; CHECK-NEXT: [[TMP7:%.*]] = phi i1 [ [[CMP2]], [[G]] ], [ true, [[LOOP_EXIT_GUARD1]] ]
-; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP_EXIT_GUARD:%.*]], label [[A]]
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: br i1 [[TMP6]], label [[I]], label [[H:%.*]]
-; CHECK: Flow3:
-; CHECK-NEXT: [[TMP8]] = phi i32 [ [[INNER2]], [[F]] ], [ undef, [[FLOW2]] ]
-; CHECK-NEXT: [[TMP9]] = phi i1 [ true, [[F]] ], [ false, [[FLOW2]] ]
-; CHECK-NEXT: [[TMP10]] = phi i1 [ [[CMP1]], [[F]] ], [ true, [[FLOW2]] ]
-; CHECK-NEXT: br label [[FLOW1]]
-; CHECK: loop.exit.guard1:
-; CHECK-NEXT: br i1 [[TMP2]], label [[G]], label [[FLOW4]]
-;
-entry:
- br i1 %PredEntry, label %A, label %I
-
-; A is the outer loop header block.
-A:
- %outer1 = phi i32 [ 0, %entry ], [ %outer2, %G ]
- br label %B
-
-; B is the inner loop header block.
-B:
- %inner1 = phi i32 [ 0, %A ], [ %inner2, %F ]
- br i1 %PredB, label %D, label %C
-
-; C is a loop exit block. After reorderNodes in StructureCFG, this block
-; remains after B rather and is not dependent on the Flow block that contains
-; the back edge to the loop header.
-C:
- tail call fastcc void @check(i32 1) #0
- br label %loop.exit.guard1
-
-D:
- br i1 %PredD, label %E, label %F
-
-; E is a loop exit block. After reorderNodes in StructurizeCFG, this block
-; remains in the loop and is not dependent on the Flow block that contains
-; the back edge to the loop header.
-E:
- tail call fastcc void @check(i32 2) #0
- br label %loop.exit.guard1
-
-; F is a latch block for the inner loop.
-F:
- %inner2 = add i32 %inner1, 1
- %cmp1 = icmp ult i32 %inner2, 20
- br i1 %cmp1, label %B, label %loop.exit.guard1
-
-; G is a latch block for the outer loop.
-G:
- %outer2 = add i32 %outer1, 1
- %cmp2 = icmp ult i32 %outer2, 10
- br i1 %cmp2, label %A, label %loop.exit.guard
-
-; Paths from the exit blocks come here through loop.exit.gaurd.
-H:
- unreachable
-
-I:
- ret void
-
-; loop.exit.guard is added by UnifyLoopExits as a common block for all loop
-; exits. This instance is for the outer loop.
-loop.exit.guard:
- %Guard.I = phi i1 [ true, %G ], [ %Guard.I.moved, %loop.exit.guard1 ]
- br i1 %Guard.I, label %I, label %H
-
-; loop.exit.guard is added for the inner loop.
-loop.exit.guard1:
- %Guard.G = phi i1 [ true, %F ], [ false, %C ], [ false, %E ]
- %Guard.I.moved = phi i1 [ undef, %F ], [ false, %C ], [ false, %E ]
- br i1 %Guard.G, label %G, label %loop.exit.guard
-}
-
-; Test when the common successor is not unreachable. In particular, the common
-; successor is inside the region. In this case, it is still helpful to keep
-; the exit blocks inside the loop to reduce live values that exit the loop.
-
-define void @common_exit(i1 %PredEntry, i1 %PredA, i1 %PredB) {
-; CHECK-LABEL: @common_exit(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[PREDB_INV:%.*]] = xor i1 [[PREDB:%.*]], true
-; CHECK-NEXT: [[PREDA_INV:%.*]] = xor i1 [[PREDA:%.*]], true
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[G:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ [[TMP4:%.*]], [[FLOW:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA_INV]], label [[C:%.*]], label [[FLOW]]
-; CHECK: Flow3:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[D:%.*]] ], [ false, [[FLOW2:%.*]] ]
-; CHECK-NEXT: br i1 [[TMP6:%.*]], label [[B:%.*]], label [[FLOW4:%.*]]
-; CHECK: B:
-; CHECK-NEXT: tail call fastcc void @check1(i32 1) #[[ATTR1:[0-9]+]]
-; CHECK-NEXT: br label [[FLOW4]]
-; CHECK: C:
-; CHECK-NEXT: br i1 [[PREDB_INV]], label [[E:%.*]], label [[FLOW1:%.*]]
-; CHECK: Flow1:
-; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[INC2:%.*]], [[E]] ], [ undef, [[C]] ]
-; CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ [[CMP:%.*]], [[E]] ], [ true, [[C]] ]
-; CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ false, [[E]] ], [ true, [[C]] ]
-; CHECK-NEXT: br label [[FLOW]]
-; CHECK: Flow2:
-; CHECK-NEXT: br i1 [[TMP7:%.*]], label [[D]], label [[FLOW3:%.*]]
-; CHECK: D:
-; CHECK-NEXT: tail call fastcc void @check1(i32 2) #[[ATTR1]]
-; CHECK-NEXT: br label [[FLOW3]]
-; CHECK: Flow:
-; CHECK-NEXT: [[TMP4]] = phi i32 [ [[TMP1]], [[FLOW1]] ], [ undef, [[A]] ]
-; CHECK-NEXT: [[TMP5:%.*]] = phi i1 [ [[TMP2]], [[FLOW1]] ], [ true, [[A]] ]
-; CHECK-NEXT: [[TMP6]] = phi i1 [ false, [[FLOW1]] ], [ true, [[A]] ]
-; CHECK-NEXT: [[TMP7]] = phi i1 [ [[TMP3]], [[FLOW1]] ], [ false, [[A]] ]
-; CHECK-NEXT: br i1 [[TMP5]], label [[FLOW2]], label [[A]]
-; CHECK: E:
-; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 1
-; CHECK-NEXT: [[CMP]] = icmp uge i32 [[INC2]], 10
-; CHECK-NEXT: br label [[FLOW1]]
-; CHECK: Flow4:
-; CHECK-NEXT: [[TMP8:%.*]] = phi i1 [ true, [[B]] ], [ [[TMP0]], [[FLOW3]] ]
-; CHECK-NEXT: br i1 [[TMP8]], label [[F:%.*]], label [[FLOW5:%.*]]
-; CHECK: F:
-; CHECK-NEXT: br label [[FLOW5]]
-; CHECK: Flow5:
-; CHECK-NEXT: br label [[G]]
-; CHECK: G:
-; CHECK-NEXT: ret void
-;
-entry:
- br i1 %PredEntry, label %A, label %G
-
-; A is the loop header.
-A:
- %inc1 = phi i32 [ 0, %entry ], [ %inc2, %E ]
- br i1 %PredA, label %B, label %C
-
-; B is a loop exit block. After reorderNodes in StructurizeCFG, this block
-; remains after A rather than moving to after the loop due to a dependence on
-; the Flow block that contains the loop back edge.
-B:
- tail call fastcc void @check1(i32 1) #1
- br label %F
-
-C:
- br i1 %PredB, label %D, label %E
-
-; D is a loop exit block. After reorderNodes, this block remains in the loop
-; rather than moving to after the loop due to a dependence on the Flow block
-; that contains the loop back edge.
-D:
- tail call fastcc void @check1(i32 2) #1
- br label %F
-
-; E is a latch and exiting block.
-E:
- %inc2 = add i32 %inc1, 1
- %cmp = icmp ult i32 %inc2, 10
- br i1 %cmp, label %A, label %G
-
-; F is reached by the loop exit blocks, B and D.
-F:
- br label %G
-
-G:
- ret void
-}
-
-; Test when there are many loop exiting blocks. Previous tests have two exiting
-; blocks. This test contains five. Each of the exiting blocks remain in the loop
-; rather than being moved to after the loop.
-
-define void @many_exiting_blocks(i1 %PredEntry, i1 %PredA, i1 %PredC, i1 %PredE, i1 %PredG) {
-; CHECK-LABEL: @many_exiting_blocks(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[FLOW11:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ [[TMP1:%.*]], [[FLOW4:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[B:%.*]], label [[FLOW3:%.*]]
-; CHECK: B:
-; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]
-; CHECK-NEXT: br label [[FLOW3]]
-; CHECK: Flow3:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ false, [[B]] ], [ true, [[A]] ]
-; CHECK-NEXT: br i1 [[TMP0]], label [[C:%.*]], label [[FLOW4]]
-; CHECK: C:
-; CHECK-NEXT: br i1 [[PREDC:%.*]], label [[D:%.*]], label [[FLOW5:%.*]]
-; CHECK: Flow4:
-; CHECK-NEXT: [[TMP1]] = phi i32 [ [[TMP6:%.*]], [[FLOW6:%.*]] ], [ undef, [[FLOW3]] ]
-; CHECK-NEXT: [[TMP2:%.*]] = phi i1 [ [[TMP7:%.*]], [[FLOW6]] ], [ true, [[FLOW3]] ]
-; CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ [[TMP8:%.*]], [[FLOW6]] ], [ false, [[FLOW3]] ]
-; CHECK-NEXT: [[TMP4:%.*]] = phi i1 [ [[TMP9:%.*]], [[FLOW6]] ], [ true, [[FLOW3]] ]
-; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP_EXIT_GUARD:%.*]], label [[A]]
-; CHECK: D:
-; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]
-; CHECK-NEXT: br label [[FLOW5]]
-; CHECK: Flow5:
-; CHECK-NEXT: [[TMP5:%.*]] = phi i1 [ false, [[D]] ], [ true, [[C]] ]
-; CHECK-NEXT: br i1 [[TMP5]], label [[E:%.*]], label [[FLOW6]]
-; CHECK: E:
-; CHECK-NEXT: br i1 [[PREDE:%.*]], label [[F:%.*]], label [[FLOW7:%.*]]
-; CHECK: Flow6:
-; CHECK-NEXT: [[TMP6]] = phi i32 [ [[TMP12:%.*]], [[FLOW8:%.*]] ], [ undef, [[FLOW5]] ]
-; CHECK-NEXT: [[TMP7]] = phi i1 [ [[TMP13:%.*]], [[FLOW8]] ], [ true, [[FLOW5]] ]
-; CHECK-NEXT: [[TMP8]] = phi i1 [ [[TMP14:%.*]], [[FLOW8]] ], [ false, [[FLOW5]] ]
-; CHECK-NEXT: [[TMP9]] = phi i1 [ [[TMP15:%.*]], [[FLOW8]] ], [ true, [[FLOW5]] ]
-; CHECK-NEXT: br label [[FLOW4]]
-; CHECK: F:
-; CHECK-NEXT: tail call fastcc void @check(i32 3) #[[ATTR0]]
-; CHECK-NEXT: br label [[FLOW7]]
-; CHECK: Flow7:
-; CHECK-NEXT: [[TMP10:%.*]] = phi i1 [ false, [[F]] ], [ true, [[E]] ]
-; CHECK-NEXT: [[TMP11:%.*]] = phi i1 [ false, [[F]] ], [ true, [[E]] ]
-; CHECK-NEXT: br i1 [[TMP11]], label [[G:%.*]], label [[FLOW8]]
-; CHECK: G:
-; CHECK-NEXT: br i1 [[PREDG:%.*]], label [[H:%.*]], label [[FLOW9:%.*]]
-; CHECK: Flow8:
-; CHECK-NEXT: [[TMP12]] = phi i32 [ [[TMP19:%.*]], [[FLOW10:%.*]] ], [ undef, [[FLOW7]] ]
-; CHECK-NEXT: [[TMP13]] = phi i1 [ [[TMP20:%.*]], [[FLOW10]] ], [ [[TMP10]], [[FLOW7]] ]
-; CHECK-NEXT: [[TMP14]] = phi i1 [ [[TMP21:%.*]], [[FLOW10]] ], [ false, [[FLOW7]] ]
-; CHECK-NEXT: [[TMP15]] = phi i1 [ [[TMP22:%.*]], [[FLOW10]] ], [ true, [[FLOW7]] ]
-; CHECK-NEXT: br label [[FLOW6]]
-; CHECK: H:
-; CHECK-NEXT: tail call fastcc void @check(i32 4) #[[ATTR0]]
-; CHECK-NEXT: br label [[FLOW9]]
-; CHECK: Flow9:
-; CHECK-NEXT: [[TMP16:%.*]] = phi i1 [ false, [[H]] ], [ [[TMP10]], [[G]] ]
-; CHECK-NEXT: [[TMP17:%.*]] = phi i1 [ false, [[H]] ], [ true, [[G]] ]
-; CHECK-NEXT: br i1 [[TMP17]], label [[I:%.*]], label [[FLOW10]]
-; CHECK: I:
-; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[INC2]], 10
-; CHECK-NEXT: br label [[FLOW10]]
-; CHECK: Flow:
-; CHECK-NEXT: [[TMP18:%.*]] = phi i1 [ false, [[K:%.*]] ], [ true, [[LOOP_EXIT_GUARD1:%.*]] ]
-; CHECK-NEXT: br i1 [[TMP18]], label [[J:%.*]], label [[FLOW1:%.*]]
-; CHECK: J:
-; CHECK-NEXT: br label [[FLOW1]]
-; CHECK: K:
-; CHECK-NEXT: br label [[FLOW:%.*]]
-; CHECK: Flow1:
-; CHECK-NEXT: br label [[FLOW2:%.*]]
-; CHECK: Flow2:
-; CHECK-NEXT: br label [[FLOW11]]
-; CHECK: L:
-; CHECK-NEXT: ret void
-; CHECK: Flow10:
-; CHECK-NEXT: [[TMP19]] = phi i32 [ [[INC2]], [[I]] ], [ undef, [[FLOW9]] ]
-; CHECK-NEXT: [[TMP20]] = phi i1 [ false, [[I]] ], [ [[TMP16]], [[FLOW9]] ]
-; CHECK-NEXT: [[TMP21]] = phi i1 [ true, [[I]] ], [ false, [[FLOW9]] ]
-; CHECK-NEXT: [[TMP22]] = phi i1 [ [[CMP]], [[I]] ], [ true, [[FLOW9]] ]
-; CHECK-NEXT: br label [[FLOW8]]
-; CHECK: Flow11:
-; CHECK-NEXT: br label [[L:%.*]]
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: [[GUARD_L_INV:%.*]] = xor i1 [[TMP3]], true
-; CHECK-NEXT: [[GUARD_J_INV:%.*]] = xor i1 [[TMP2]], true
-; CHECK-NEXT: br i1 [[GUARD_L_INV]], label [[LOOP_EXIT_GUARD1]], label [[FLOW2]]
-; CHECK: loop.exit.guard1:
-; CHECK-NEXT: br i1 [[GUARD_J_INV]], label [[K]], label [[FLOW]]
-;
-entry:
- br i1 %PredEntry, label %A, label %L
-
-; A is the loop header block.
-A:
- %inc1 = phi i32 [ 0, %entry ], [ %inc2, %I ]
- br i1 %PredA, label %B, label %C
-
-; B is a loop exit block. After reorderNodes in StructurizeCFG, this block
-; remains after A rather than moving to after the loop due to a dependence
-; on the Flow block that contains the loop back edge.
-B:
- tail call fastcc void @check(i32 1) #0
- br label %loop.exit.guard
-
-C:
- br i1 %PredC, label %D, label %E
-
-; D is a loop exit block. After reorderNodes, this block remains in the loop
-; rather than moving to after the loop.
-D:
- tail call fastcc void @check(i32 2) #0
- br label %loop.exit.guard
-
-E:
- br i1 %PredE, label %F, label %G
-
-; F is a loop exit block. After reorderNodes, this block remains in the loop
-; rather than moving to after the loop.
-F:
- tail call fastcc void @check(i32 3) #0
- br label %loop.exit.guard
-
-G:
- br i1 %PredG, label %H, label %I
-
-; H is a loop exit block. After reorderNodes, this block remains in the loop
-; rather than moving to after the loop.
-H:
- tail call fastcc void @check(i32 4) #0
- br label %loop.exit.guard
-
-; I is a latch block.
-I:
- %inc2 = add i32 %inc1, 1
- %cmp = icmp ult i32 %inc2, 10
- br i1 %cmp, label %A, label %loop.exit.guard
-
-J:
- br label %L
-
-K:
- br label %L
-
-L:
- ret void
-
-loop.exit.guard:
- %Guard.L = phi i1 [ true, %I ], [ false, %B ], [ false, %D ], [ false, %F ], [ false, %H ]
- %Guard.J = phi i1 [ false, %I ], [ true, %B ], [ true, %D ], [ false, %F ], [ false, %H ]
- br i1 %Guard.L, label %L, label %loop.exit.guard1
-
-loop.exit.guard1:
- br i1 %Guard.J, label %J, label %K
-}
-
-declare void @check(i32 noundef) #0
-declare void @check1(i32 noundef) #1
-
-attributes #0 = { noreturn nounwind }
-attributes #1 = { nounwind }
-
-
-; When there are two blocks that can be moved closer to the predecessor,
-; maintain the original, relative order since swapping the order should not
-; provide any benefit. In this case both B and C have a single predecessor
-; and a single successor.
-
-define void @same_predecessor(i1 %PredA) {
-; CHECK-LABEL: @same_predecessor(
-; CHECK-NEXT: A:
-; CHECK-NEXT: [[PREDA_INV:%.*]] = xor i1 [[PREDA:%.*]], true
-; CHECK-NEXT: br i1 [[PREDA_INV]], label [[B:%.*]], label [[FLOW:%.*]]
-; CHECK: B:
-; CHECK-NEXT: br label [[FLOW]]
-; CHECK: Flow:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ false, [[B]] ], [ true, [[A:%.*]] ]
-; CHECK-NEXT: br i1 [[TMP0]], label [[C:%.*]], label [[D:%.*]]
-; CHECK: C:
-; CHECK-NEXT: br label [[D]]
-; CHECK: D:
-; CHECK-NEXT: ret void
-;
-A:
- br i1 %PredA, label %C, label %B
-
-B:
- br label %D
-
-C:
- br label %D
-
-D:
- ret void
-}
-
-
More information about the llvm-commits
mailing list