Skip to content

Commit b21fa18

Browse files
[LoopVersioning] Add a check to see if the input loop is in LCSSA form (#116443)
Loop Optimizations expect the input loop to be in LCSSA form. But it seems that LoopVersioning doesn't have any check to see if the loop is actually in LCSSA form. As a result, if we give it a loop which is not in LCSSA form but still correct semantically, the resulting transformation fails to pass through verifier pass with the following error. Instruction does not dominate all uses! %inc = add nsw i16 undef, 1 store i16 %inc, ptr @c, align 1 As the loop is not in LCSSA form, LoopVersioning's transformations leads to invalid IR! As some instructions do not dominate all their uses. This patch checks if a loop is in LCSSA form, if not it will call formLCSSARecursively on the loop before passing it to LoopVersioning. Fixes: #36998
1 parent 0954c67 commit b21fa18

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

llvm/lib/Transforms/Utils/LoopVersioning.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/Support/CommandLine.h"
2727
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
2828
#include "llvm/Transforms/Utils/Cloning.h"
29+
#include "llvm/Transforms/Utils/LoopUtils.h"
2930
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
3031

3132
using namespace llvm;
@@ -278,6 +279,9 @@ bool runImpl(LoopInfo *LI, LoopAccessInfoManager &LAIs, DominatorTree *DT,
278279
if (!LAI.hasConvergentOp() &&
279280
(LAI.getNumRuntimePointerChecks() ||
280281
!LAI.getPSE().getPredicate().isAlwaysTrue())) {
282+
if (!L->isLCSSAForm(*DT))
283+
formLCSSARecursively(*L, *DT, LI, SE);
284+
281285
LoopVersioning LVer(LAI, LAI.getRuntimePointerChecking()->getChecks(), L,
282286
LI, DT, SE);
283287
LVer.versionLoop();
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=loop-versioning -aa-pipeline='' -S < %s | FileCheck %s
3+
4+
@a = external global i16, align 1
5+
@b = external global i16, align 1
6+
@c = external global i16, align 1
7+
8+
define i16 @f2(i16 %a) {
9+
; CHECK-LABEL: define i16 @f2(
10+
; CHECK-SAME: i16 [[A:%.*]]) {
11+
; CHECK-NEXT: [[FOR_BODY_LVER_CHECK:.*:]]
12+
; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr @b, getelementptr inbounds nuw (i8, ptr @a, i64 2)
13+
; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr @a, getelementptr inbounds nuw (i8, ptr @b, i64 2)
14+
; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
15+
; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label %[[FOR_BODY_PH_LVER_ORIG:.*]], label %[[FOR_BODY_PH:.*]]
16+
; CHECK: [[FOR_BODY_PH_LVER_ORIG]]:
17+
; CHECK-NEXT: br label %[[FOR_BODY_LVER_ORIG:.*]]
18+
; CHECK: [[FOR_BODY_LVER_ORIG]]:
19+
; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @a, align 1
20+
; CHECK-NEXT: store i16 [[TMP0]], ptr @b, align 1
21+
; CHECK-NEXT: [[INC_LVER_ORIG:%.*]] = add nsw i16 [[A]], 1
22+
; CHECK-NEXT: br i1 false, label %[[FOR_BODY_LVER_ORIG]], label %[[FOR_COND_FOR_END_CRIT_EDGE_LOOPEXIT:.*]]
23+
; CHECK: [[FOR_BODY_PH]]:
24+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
25+
; CHECK: [[FOR_BODY]]:
26+
; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr @a, align 1, !alias.scope [[META0:![0-9]+]]
27+
; CHECK-NEXT: store i16 [[TMP1]], ptr @b, align 1, !alias.scope [[META3:![0-9]+]], !noalias [[META0]]
28+
; CHECK-NEXT: [[INC:%.*]] = add nsw i16 [[A]], 1
29+
; CHECK-NEXT: br i1 false, label %[[FOR_BODY]], label %[[FOR_COND_FOR_END_CRIT_EDGE_LOOPEXIT1:.*]]
30+
; CHECK: [[FOR_COND_FOR_END_CRIT_EDGE_LOOPEXIT]]:
31+
; CHECK-NEXT: [[INC_LCSSA_PH:%.*]] = phi i16 [ [[INC_LVER_ORIG]], %[[FOR_BODY_LVER_ORIG]] ]
32+
; CHECK-NEXT: [[SPLIT2_PH:%.*]] = phi i16 [ [[INC_LVER_ORIG]], %[[FOR_BODY_LVER_ORIG]] ]
33+
; CHECK-NEXT: br label %[[FOR_COND_FOR_END_CRIT_EDGE:.*]]
34+
; CHECK: [[FOR_COND_FOR_END_CRIT_EDGE_LOOPEXIT1]]:
35+
; CHECK-NEXT: [[INC_LCSSA_PH2:%.*]] = phi i16 [ [[INC]], %[[FOR_BODY]] ]
36+
; CHECK-NEXT: [[SPLIT2_PH3:%.*]] = phi i16 [ [[INC]], %[[FOR_BODY]] ]
37+
; CHECK-NEXT: br label %[[FOR_COND_FOR_END_CRIT_EDGE]]
38+
; CHECK: [[FOR_COND_FOR_END_CRIT_EDGE]]:
39+
; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i16 [ [[INC_LCSSA_PH]], %[[FOR_COND_FOR_END_CRIT_EDGE_LOOPEXIT]] ], [ [[INC_LCSSA_PH2]], %[[FOR_COND_FOR_END_CRIT_EDGE_LOOPEXIT1]] ]
40+
; CHECK-NEXT: [[SPLIT2:%.*]] = phi i16 [ [[SPLIT2_PH]], %[[FOR_COND_FOR_END_CRIT_EDGE_LOOPEXIT]] ], [ [[SPLIT2_PH3]], %[[FOR_COND_FOR_END_CRIT_EDGE_LOOPEXIT1]] ]
41+
; CHECK-NEXT: store i16 [[INC_LCSSA]], ptr @c, align 1
42+
; CHECK-NEXT: ret i16 [[SPLIT2]]
43+
;
44+
entry:
45+
br label %for.body
46+
47+
for.body: ; preds = %for.body, %entry
48+
%0 = load i16, ptr @a, align 1
49+
store i16 %0, ptr @b, align 1
50+
%inc = add nsw i16 %a, 1
51+
br i1 false, label %for.body, label %for.cond.for.end_crit_edge
52+
53+
for.cond.for.end_crit_edge: ; preds = %for.body
54+
%split2 = phi i16 [ %inc, %for.body ]
55+
store i16 %inc, ptr @c, align 1
56+
ret i16 %split2
57+
}
58+
;.
59+
; CHECK: [[META0]] = !{[[META1:![0-9]+]]}
60+
; CHECK: [[META1]] = distinct !{[[META1]], [[META2:![0-9]+]]}
61+
; CHECK: [[META2]] = distinct !{[[META2]], !"LVerDomain"}
62+
; CHECK: [[META3]] = !{[[META4:![0-9]+]]}
63+
; CHECK: [[META4]] = distinct !{[[META4]], [[META2]]}
64+
;.

0 commit comments

Comments
 (0)