Skip to content

Commit 7670633

Browse files
MrSidimsAlexeySotkin
authored andcommitted
Replace assumptions during llvm.loop translation with checks
There were 3 assumptions made during translation of llvm.loop metadata into LoopMerge instruction: 1. A latch block for 'for' and 'while' loop ends with a unconditional branch instruction; 2. A latch block for 'do-while' loop ends with a conditional branch instruction; 3. For a 'conditional' latch basic block it assumes, that the first successor is the loop header and the second one is the exit block. All three of them can be violated in a case of an optimized IR is passed to the translator. In this case LoopMerge: a. can be placed in a wrong basic block; b. have continue target and merge block parameters sharing the same id. This patch makes the translator to assume less and do more checks via LLVM LoopInfo infrustructure. Signed-off-by: Dmitry Sidorov <[email protected]>
1 parent 8f59b42 commit 7670633

File tree

2 files changed

+105
-27
lines changed

2 files changed

+105
-27
lines changed

lib/SPIRV/SPIRVWriter.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,11 @@
6060
#include "llvm/ADT/DenseMap.h"
6161
#include "llvm/ADT/StringSwitch.h"
6262
#include "llvm/ADT/Triple.h"
63+
#include "llvm/Analysis/LoopInfo.h"
6364
#include "llvm/Analysis/ValueTracking.h"
6465
#include "llvm/IR/Constants.h"
6566
#include "llvm/IR/DerivedTypes.h"
67+
#include "llvm/IR/Dominators.h"
6668
#include "llvm/IR/Function.h"
6769
#include "llvm/IR/InlineAsm.h"
6870
#include "llvm/IR/InstrTypes.h"
@@ -1618,7 +1620,7 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
16181620
spv::LoopControlMask LoopControl = getLoopControl(Branch, Parameters);
16191621

16201622
if (Branch->isUnconditional()) {
1621-
// For "for" and "while" loops llvm.loop metadata is attached to
1623+
// Usually for "for" and "while" loops llvm.loop metadata is attached to
16221624
// an unconditional branch instruction.
16231625
if (LoopControl != spv::LoopControlMaskNone) {
16241626
// SuccessorTrue is the loop header BB.
@@ -1640,15 +1642,28 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
16401642
}
16411643
return mapValue(V, BM->addBranchInst(SuccessorTrue, BB));
16421644
}
1643-
// For "do-while" loops llvm.loop metadata is attached to a conditional
1644-
// branch instructions
1645+
// For "do-while" and in some cases for "for" and "while" loops llvm.loop
1646+
// metadata is attached to a conditional branch instructions
16451647
SPIRVLabel *SuccessorFalse =
16461648
static_cast<SPIRVLabel *>(transValue(Branch->getSuccessor(1), BB));
1647-
if (LoopControl != spv::LoopControlMaskNone)
1648-
// SuccessorTrue is the loop header BB.
1649-
BM->addLoopMergeInst(SuccessorFalse->getId(), // Merge Block
1650-
BB->getId(), // Continue Target
1651-
LoopControl, Parameters, SuccessorTrue);
1649+
if (LoopControl != spv::LoopControlMaskNone) {
1650+
Function *Fun = Branch->getParent()->getParent();
1651+
DominatorTree DomTree(*Fun);
1652+
LoopInfo LI(DomTree);
1653+
for (const auto *LoopObj : LI.getLoopsInPreorder()) {
1654+
// Check whether SuccessorFalse or SuccessorTrue is the loop header BB
1655+
if (LoopObj->getHeader() == Branch->getSuccessor(1))
1656+
// SuccessorFalse is the loop header BB.
1657+
BM->addLoopMergeInst(SuccessorTrue->getId(), // Merge Block
1658+
BB->getId(), // Continue Target
1659+
LoopControl, Parameters, SuccessorFalse);
1660+
else
1661+
// SuccessorTrue is the loop header BB.
1662+
BM->addLoopMergeInst(SuccessorFalse->getId(), // Merge Block
1663+
BB->getId(), // Continue Target
1664+
LoopControl, Parameters, SuccessorTrue);
1665+
}
1666+
}
16521667
return mapValue(
16531668
V, BM->addBranchConditionalInst(transValue(Branch->getCondition(), BB),
16541669
SuccessorTrue, SuccessorFalse, BB));

test/transcoding/LoopUnroll.ll

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,18 @@
3030
; int x = i;
3131
; } while(i--> 0);
3232
; }
33+
;
34+
; for_count_unusual() is a synthetically written function
35+
;
3336
; Command:
3437
; clang -cc1 -triple spir64 -O0 LoopUnroll.cl -emit-llvm -o /test/SPIRV/transcoding/LoopUnroll.ll
3538

3639
; RUN: llvm-as < %s > %t.bc
37-
; RUN: llvm-spirv %t.bc -o - -spirv-text | FileCheck %s --check-prefix=CHECK-SPIRV
40+
; RUN: llvm-spirv %t.bc -o %t.spv
41+
; RUN: llvm-spirv -to-text %t.spv -o %t.spt
42+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
43+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
44+
; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefixes=CHECK-LLVM
3845

3946
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
4047
target triple = "spir64"
@@ -50,12 +57,12 @@ entry:
5057
br label %for.cond
5158

5259
for.cond: ; preds = %for.inc, %entry
53-
; CHECK-SPIRV: Label [[Header:[0-9]+]]
60+
; CHECK-SPIRV: Label [[#HEADER:]]
5461
%0 = load i32, i32* %i, align 4
5562
%cmp = icmp slt i32 %0, 1024
5663
; Per SPIRV spec p3.23 "DontUnroll" loop control = 0x2
57-
; CHECK-SPIRV: 4 LoopMerge [[MergeBlock:[0-9]+]] [[ContinueTarget:[0-9]+]] 2
58-
; CHECK-SPIRV: BranchConditional {{[0-9]+}} {{[0-9]+}} [[MergeBlock]]
64+
; CHECK-SPIRV: LoopMerge [[#MERGEBLOCK:]] [[#CONTINUE:]] 2
65+
; CHECK-SPIRV: BranchConditional [[#]] [[#]] [[#MERGEBLOCK]]
5966
br i1 %cmp, label %for.body, label %for.end
6067

6168
for.body: ; preds = %for.cond
@@ -76,15 +83,16 @@ if.end: ; preds = %for.body
7683
br label %for.inc
7784

7885
for.inc: ; preds = %if.end, %if.then
79-
; CHECK-SPIRV: Label [[ContinueTarget]]
86+
; CHECK-SPIRV: Label [[#CONTINUE]]
8087
%3 = load i32, i32* %i, align 4
8188
%inc = add nsw i32 %3, 1
8289
store i32 %inc, i32* %i, align 4
8390
br label %for.cond, !llvm.loop !5
84-
; CHECK-SPIRV: Branch [[Header]]
91+
; CHECK-LLVM: br label %for.cond, !llvm.loop ![[#UNROLLDISABLE:]]
92+
; CHECK-SPIRV: Branch [[#HEADER]]
8593

8694
for.end: ; preds = %for.cond
87-
; CHECK-SPIRV: Label [[MergeBlock]]
95+
; CHECK-SPIRV: Label [[#MERGEBLOCK]]
8896
ret void
8997
}
9098

@@ -99,14 +107,14 @@ entry:
99107
br label %while.cond
100108

101109
while.cond: ; preds = %if.end, %if.then, %entry
102-
; CHECK-SPIRV: Label [[Header:[0-9]+]]
110+
; CHECK-SPIRV: Label [[#HEADER:]]
103111
%0 = load i32, i32* %i, align 4
104112
%dec = add nsw i32 %0, -1
105113
store i32 %dec, i32* %i, align 4
106114
%cmp = icmp sgt i32 %0, 0
107115
; Per SPIRV spec p3.23 "Unroll" loop control = 0x1
108-
; CHECK-SPIRV: 5 LoopMerge [[MergeBlock:[0-9]+]] [[ContinueTarget:[0-9]+]] 256 8
109-
; CHECK-SPIRV: BranchConditional {{[0-9]+}} {{[0-9]+}} [[MergeBlock]]
116+
; CHECK-SPIRV: LoopMerge [[#MERGEBLOCK:]] [[#CONTINUE:]] 256 8
117+
; CHECK-SPIRV: BranchConditional [[#]] [[#]] [[#MERGEBLOCK]]
110118
br i1 %cmp, label %while.body, label %while.end
111119

112120
while.body: ; preds = %while.cond
@@ -118,12 +126,13 @@ while.body: ; preds = %while.cond
118126

119127
if.then: ; preds = %while.body
120128
; CHECK-SPIRV: Label
129+
; CHECK-LLVM: br label %while.cond, !llvm.loop ![[#UNROLLCOUNT:]]
121130
br label %while.cond, !llvm.loop !7
122131

123132
; loop-simplify pass will create extra basic block which is the only one in
124133
; loop having a back-edge to the header
125-
; CHECK-SPIRV: [[ContinueTarget]]
126-
; CHECK-SPIRV: Branch [[Header]]
134+
; CHECK-SPIRV: [[#CONTINUE]]
135+
; CHECK-SPIRV: Branch [[#HEADER]]
127136

128137
if.end: ; preds = %while.body
129138
; CHECK-SPIRV: Label
@@ -132,7 +141,7 @@ if.end: ; preds = %while.body
132141
br label %while.cond, !llvm.loop !7
133142

134143
while.end: ; preds = %while.cond
135-
; CHECK-SPIRV: [[MergeBlock]]
144+
; CHECK-SPIRV: [[#MERGEBLOCK]]
136145
ret void
137146
}
138147

@@ -144,15 +153,15 @@ entry:
144153
%i = alloca i32, align 4
145154
%x = alloca i32, align 4
146155
store i32 1024, i32* %i, align 4
147-
br label %do.body, !llvm.loop !9
156+
br label %do.body
148157

149158
do.body: ; preds = %do.cond, %entry
150-
; CHECK-SPIRV: Label [[Header:[0-9]+]]
159+
; CHECK-SPIRV: Label [[#HEADER:]]
151160
%0 = load i32, i32* %i, align 4
152161
%rem = srem i32 %0, 2
153162
%tobool = icmp ne i32 %rem, 0
154163
; Per SPIRV spec p3.23 "Unroll" loop control = 0x1
155-
; CHECK-SPIRV: 4 LoopMerge [[MergeBlock:[0-9]+]] [[ContinueTarget:[0-9]+]] 1
164+
; CHECK-SPIRV: LoopMerge [[#MERGEBLOCK:]] [[#CONTINUE:]] 1
156165
; CHECK-SPIRV: BranchConditional
157166
br i1 %tobool, label %if.then, label %if.end
158167

@@ -167,16 +176,62 @@ if.end: ; preds = %do.body
167176
br label %do.cond
168177

169178
do.cond: ; preds = %if.end, %if.then
170-
; CHECK-SPIRV: Label [[ContinueTarget]]
179+
; CHECK-SPIRV: Label [[#CONTINUE]]
171180
%2 = load i32, i32* %i, align 4
172181
%dec = add nsw i32 %2, -1
173182
store i32 %dec, i32* %i, align 4
174183
%cmp = icmp sgt i32 %2, 0
175-
; CHECK-SPIRV: BranchConditional {{[0-9]+}} [[Header]] [[MergeBlock]]
184+
; CHECK-SPIRV: BranchConditional [[#]] [[#HEADER]] [[#MERGEBLOCK]]
185+
; CHECK-LLVM: br i1 %cmp, label %do.body, label %do.end, !llvm.loop ![[#UNROLLENABLE1:]]
176186
br i1 %cmp, label %do.body, label %do.end, !llvm.loop !9
177187

178188
do.end: ; preds = %do.cond
179-
; CHECK-SPIRV: Label [[MergeBlock]]
189+
; CHECK-SPIRV: Label [[#MERGEBLOCK]]
190+
ret void
191+
}
192+
193+
; CHECK-SPIRV: Function
194+
; Function Attrs: noinline nounwind optnone
195+
define spir_func void @for_count_unusual() #0 {
196+
entry:
197+
; CHECK-SPIRV: Label
198+
%i = alloca i32, align 4
199+
%x = alloca i32, align 4
200+
store i32 1024, i32* %i, align 4
201+
br label %for.body
202+
203+
for.body: ; preds = %for.cond, %entry
204+
; CHECK-SPIRV: Label [[#HEADER:]]
205+
%0 = load i32, i32* %i, align 4
206+
%rem = srem i32 %0, 2
207+
%tobool = icmp ne i32 %rem, 0
208+
; Per SPIRV spec p3.23 "Unroll" loop control = 0x1
209+
; CHECK-SPIRV: LoopMerge [[#MERGEBLOCK:]] [[#CONTINUE:]] 1
210+
; CHECK-SPIRV: BranchConditional
211+
br i1 %tobool, label %if.then, label %if.end
212+
213+
if.then: ; preds = %for.body
214+
; CHECK-SPIRV: Label
215+
br label %for.cond
216+
217+
if.end: ; preds = %for.body
218+
; CHECK-SPIRV: Label
219+
%1 = load i32, i32* %i, align 4
220+
store i32 %1, i32* %x, align 4
221+
br label %for.cond
222+
223+
for.cond: ; preds = %if.end, %if.then
224+
; CHECK-SPIRV: Label [[#CONTINUE]]
225+
%2 = load i32, i32* %i, align 4
226+
%dec = add nsw i32 %2, -1
227+
store i32 %dec, i32* %i, align 4
228+
%cmp = icmp sgt i32 %2, 0
229+
; CHECK-SPIRV: BranchConditional [[#]] [[#MERGEBLOCK]] [[#HEADER]]
230+
; CHECK-LLVM: br i1 %cmp, label %for.end, label %for.body, !llvm.loop ![[#UNROLLENABLE2:]]
231+
br i1 %cmp, label %for.end, label %for.body, !llvm.loop !9
232+
233+
for.end: ; preds = %for.cond
234+
; CHECK-SPIRV: Label [[#MERGEBLOCK]]
180235
ret void
181236
}
182237

@@ -202,3 +257,11 @@ attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-ma
202257
!8 = !{!"llvm.loop.unroll.count", i32 8}
203258
!9 = distinct !{!9, !10}
204259
!10 = !{!"llvm.loop.unroll.enable"}
260+
261+
; CHECK-LLVM: ![[#UNROLLDISABLE]] = distinct !{![[#UNROLLDISABLE]], ![[#DISABLE:]]}
262+
; CHECK-LLVM: ![[#DISABLE]] = !{!"llvm.loop.unroll.disable"}
263+
; CHECK-LLVM: ![[#UNROLLCOUNT]] = distinct !{![[#UNROLLCOUNT]], ![[#COUNT:]]}
264+
; CHECK-LLVM: ![[#COUNT]] = !{!"llvm.loop.unroll.count", i32 8}
265+
; CHECK-LLVM: ![[#UNROLLENABLE1]] = distinct !{![[#UNROLLENABLE1]], ![[#ENABLE:]]}
266+
; CHECK-LLVM: ![[#ENABLE]] = !{!"llvm.loop.unroll.enable"}
267+
; CHECK-LLVM: ![[#UNROLLENABLE2]] = distinct !{![[#UNROLLENABLE2]], ![[#ENABLE]]}

0 commit comments

Comments
 (0)