Skip to content

Commit 8f891b7

Browse files
author
Serguei Katkov
committed
[LoopVectorize] Uninitialized phi node leads to a crash in SSAUpdater.
createInductionResumeValues creates a phi node placeholder without filling incoming values. Then it generates the incoming values. It includes triggering of SCEV expander which may invoke SSAUpdater. SSAUpdater has an optimization to detect number of predecessors basing on incoming values if there is phi node. In case phi node is not filled with incoming values - the number of predecessors is detected as 0 and this leads to segmentation fault. In other words SSAUpdater expects that phi is in good shape while LoopVectorizer breaks this requirement. The fix is just prepare all incoming values first and then build a phi node. Reviewed By: fhahn Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D128033
1 parent 5e9aed1 commit 8f891b7

File tree

2 files changed

+121
-6
lines changed

2 files changed

+121
-6
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3131,12 +3131,6 @@ void InnerLoopVectorizer::createInductionResumeValues(
31313131
PHINode *OrigPhi = InductionEntry.first;
31323132
InductionDescriptor II = InductionEntry.second;
31333133

3134-
// Create phi nodes to merge from the backedge-taken check block.
3135-
PHINode *BCResumeVal =
3136-
PHINode::Create(OrigPhi->getType(), 3, "bc.resume.val",
3137-
LoopScalarPreHeader->getTerminator());
3138-
// Copy original phi DL over to the new one.
3139-
BCResumeVal->setDebugLoc(OrigPhi->getDebugLoc());
31403134
Value *&EndValue = IVEndValues[OrigPhi];
31413135
Value *EndValueFromAdditionalBypass = AdditionalBypass.second;
31423136
if (OrigPhi == OldInduction) {
@@ -3172,6 +3166,14 @@ void InnerLoopVectorizer::createInductionResumeValues(
31723166
EndValueFromAdditionalBypass->setName("ind.end");
31733167
}
31743168
}
3169+
3170+
// Create phi nodes to merge from the backedge-taken check block.
3171+
PHINode *BCResumeVal =
3172+
PHINode::Create(OrigPhi->getType(), 3, "bc.resume.val",
3173+
LoopScalarPreHeader->getTerminator());
3174+
// Copy original phi DL over to the new one.
3175+
BCResumeVal->setDebugLoc(OrigPhi->getDebugLoc());
3176+
31753177
// The new PHI merges the original incoming value, in case of a bypass,
31763178
// or the value at the end of the vectorized loop.
31773179
BCResumeVal->addIncoming(EndValue, LoopMiddleBlock);
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -passes=loop-vectorize < %s | FileCheck %s
3+
4+
; This is a regression test. Without the fix it crashes on SSAUpdater due to
5+
; LoopVectroizer created a phi node placeholder without incoming values but
6+
; SSAUpdater expects that phi node is completely filled.
7+
8+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
9+
define void @test(i32 %arg, i32 %L1.limit, i32 %L2.switch, i1 %c) {
10+
; CHECK-LABEL: @test(
11+
; CHECK-NEXT: L1.preheader:
12+
; CHECK-NEXT: [[TMP0:%.*]] = sub i32 -1, [[ARG:%.*]]
13+
; CHECK-NEXT: br label [[L1_HEADER:%.*]]
14+
; CHECK: L1.header:
15+
; CHECK-NEXT: [[INDUCTION_IV:%.*]] = phi i32 [ [[INDUCTION_IV_NEXT:%.*]], [[L1_BACKEDGE:%.*]] ], [ [[TMP0]], [[L1_PREHEADER:%.*]] ]
16+
; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ [[INDVAR_NEXT:%.*]], [[L1_BACKEDGE]] ], [ 0, [[L1_PREHEADER]] ]
17+
; CHECK-NEXT: [[L1_SUM:%.*]] = phi i32 [ [[ARG]], [[L1_PREHEADER]] ], [ [[L1_SUM_NEXT:%.*]], [[L1_BACKEDGE]] ]
18+
; CHECK-NEXT: [[L1_IV:%.*]] = phi i32 [ 1, [[L1_PREHEADER]] ], [ [[L1_IV_NEXT:%.*]], [[L1_BACKEDGE]] ]
19+
; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i32 [[INDVAR]], -1
20+
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], -2
21+
; CHECK-NEXT: br i1 [[C:%.*]], label [[L1_BACKEDGE]], label [[L1_EARLY_EXIT:%.*]]
22+
; CHECK: L1.backedge:
23+
; CHECK-NEXT: [[L1_SUM_NEXT]] = add i32 [[L1_IV]], [[L1_SUM]]
24+
; CHECK-NEXT: [[L1_IV_NEXT]] = add nuw nsw i32 [[L1_IV]], 1
25+
; CHECK-NEXT: [[L1_EXIT_COND:%.*]] = icmp ult i32 [[L1_IV_NEXT]], [[L1_LIMIT:%.*]]
26+
; CHECK-NEXT: [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1
27+
; CHECK-NEXT: [[INDUCTION_IV_NEXT]] = add i32 [[INDUCTION_IV]], [[TMP2]]
28+
; CHECK-NEXT: br i1 [[L1_EXIT_COND]], label [[L1_HEADER]], label [[L1_EXIT:%.*]]
29+
; CHECK: L1.early.exit:
30+
; CHECK-NEXT: ret void
31+
; CHECK: L1.exit:
32+
; CHECK-NEXT: [[INDUCTION_IV_LCSSA3:%.*]] = phi i32 [ [[INDUCTION_IV]], [[L1_BACKEDGE]] ]
33+
; CHECK-NEXT: [[INDUCTION_IV_LCSSA1:%.*]] = phi i32 [ [[INDUCTION_IV]], [[L1_BACKEDGE]] ]
34+
; CHECK-NEXT: [[L1_EXIT_VAL:%.*]] = phi i32 [ [[L1_SUM_NEXT]], [[L1_BACKEDGE]] ]
35+
; CHECK-NEXT: br label [[L2_HEADER:%.*]]
36+
; CHECK: L2.header.loopexit:
37+
; CHECK-NEXT: br label [[L2_HEADER_BACKEDGE:%.*]]
38+
; CHECK: L2.header:
39+
; CHECK-NEXT: switch i32 [[L2_SWITCH:%.*]], label [[L2_HEADER_BACKEDGE]] [
40+
; CHECK-NEXT: i32 8, label [[L2_EXIT:%.*]]
41+
; CHECK-NEXT: i32 20, label [[L2_INNER_HEADER_PREHEADER:%.*]]
42+
; CHECK-NEXT: ]
43+
; CHECK: L2.header.backedge:
44+
; CHECK-NEXT: br label [[L2_HEADER]]
45+
; CHECK: L2.Inner.header.preheader:
46+
; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
47+
; CHECK: vector.ph:
48+
; CHECK-NEXT: [[TMP3:%.*]] = mul i32 12, [[INDUCTION_IV_LCSSA1]]
49+
; CHECK-NEXT: [[IND_END:%.*]] = add i32 1, [[TMP3]]
50+
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
51+
; CHECK: vector.body:
52+
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
53+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
54+
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 12
55+
; CHECK-NEXT: br i1 [[TMP4]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
56+
; CHECK: middle.block:
57+
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 12, 12
58+
; CHECK-NEXT: br i1 [[CMP_N]], label [[L2_HEADER_LOOPEXIT:%.*]], label [[SCALAR_PH]]
59+
; CHECK: scalar.ph:
60+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ 1, [[L2_INNER_HEADER_PREHEADER]] ]
61+
; CHECK-NEXT: [[BC_RESUME_VAL2:%.*]] = phi i64 [ 13, [[MIDDLE_BLOCK]] ], [ 1, [[L2_INNER_HEADER_PREHEADER]] ]
62+
; CHECK-NEXT: br label [[L2_INNER_HEADER:%.*]]
63+
; CHECK: L2.Inner.header:
64+
; CHECK-NEXT: [[L2_ACCUM:%.*]] = phi i32 [ [[L2_ACCUM_NEXT:%.*]], [[L2_INNER_HEADER]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ]
65+
; CHECK-NEXT: [[L2_IV:%.*]] = phi i64 [ [[L2_IV_NEXT:%.*]], [[L2_INNER_HEADER]] ], [ [[BC_RESUME_VAL2]], [[SCALAR_PH]] ]
66+
; CHECK-NEXT: [[L2_ACCUM_NEXT]] = sub i32 [[L2_ACCUM]], [[L1_EXIT_VAL]]
67+
; CHECK-NEXT: [[L2_DUMMY_BUT_NEED_IT:%.*]] = sext i32 [[L2_ACCUM_NEXT]] to i64
68+
; CHECK-NEXT: [[L2_IV_NEXT]] = add nuw nsw i64 [[L2_IV]], 1
69+
; CHECK-NEXT: [[L2_EXIT_COND:%.*]] = icmp ugt i64 [[L2_IV]], 11
70+
; CHECK-NEXT: br i1 [[L2_EXIT_COND]], label [[L2_HEADER_LOOPEXIT]], label [[L2_INNER_HEADER]], !llvm.loop [[LOOP2:![0-9]+]]
71+
; CHECK: L2.exit:
72+
; CHECK-NEXT: ret void
73+
;
74+
L1.preheader:
75+
br label %L1.header
76+
77+
L1.header: ; preds = %L1.preheader, %L1.backedge
78+
%L1.sum = phi i32 [ %arg, %L1.preheader ], [ %L1.sum.next, %L1.backedge ]
79+
%L1.iv = phi i32 [ 1, %L1.preheader ], [ %L1.iv.next, %L1.backedge ]
80+
br i1 %c, label %L1.backedge, label %L1.early.exit
81+
82+
L1.backedge: ; preds = %L1.header
83+
%L1.sum.next = add i32 %L1.iv, %L1.sum
84+
%L1.iv.next = add nuw nsw i32 %L1.iv, 1
85+
%L1.exit.cond = icmp ult i32 %L1.iv.next, %L1.limit
86+
br i1 %L1.exit.cond, label %L1.header, label %L1.exit
87+
88+
L1.early.exit: ; preds = %L1.header
89+
ret void
90+
91+
L1.exit: ; preds = %L1.backedge
92+
%L1.exit.val = phi i32 [ %L1.sum.next, %L1.backedge ]
93+
br label %L2.header
94+
95+
L2.header: ; preds = %L2.Inner.header, %L1.exit, %L2.header
96+
switch i32 %L2.switch, label %L2.header [
97+
i32 8, label %L2.exit
98+
i32 20, label %L2.Inner.header
99+
]
100+
101+
L2.Inner.header: ; preds = %L2.Inner.header, %L2.header
102+
%L2.accum = phi i32 [ %L2.accum.next, %L2.Inner.header ], [ 1, %L2.header ]
103+
%L2.iv = phi i64 [ %L2.iv.next, %L2.Inner.header ], [ 1, %L2.header ]
104+
%L2.accum.next = sub i32 %L2.accum, %L1.exit.val
105+
%L2.dummy.but.need.it = sext i32 %L2.accum.next to i64
106+
%L2.iv.next = add nuw nsw i64 %L2.iv, 1
107+
%L2.exit_cond = icmp ugt i64 %L2.iv, 11
108+
br i1 %L2.exit_cond, label %L2.header, label %L2.Inner.header
109+
110+
L2.exit: ; preds = %L2.header
111+
ret void
112+
}
113+

0 commit comments

Comments
 (0)