Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit a740af8

Browse files
committed
[IRCE] Avoid loop optimizations on pre and post loops
Summary: This patch will add loop metadata on the pre and post loops generated by IRCE. Currently, we have metadata for disabling optimizations such as vectorization, unrolling, loop distribution and LICM versioning (and confirmed that these optimizations check for the metadata before proceeding with the transformation). The pre and post loops generated by IRCE need not go through loop opts (since these are slow paths). Added two test cases as well. Reviewers: sanjoy, reames Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D26806 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289588 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d2b07a0 commit a740af8

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,34 @@ void InductiveRangeCheck::extractRangeChecksFromBranch(
399399
Checks, Visited);
400400
}
401401

402+
// Add metadata to the loop L to disable loop optimizations. Callers need to
403+
// confirm that optimizing loop L is not beneficial.
404+
static void DisableAllLoopOptsOnLoop(Loop &L) {
405+
// We do not care about any existing loopID related metadata for L, since we
406+
// are setting all loop metadata to false.
407+
LLVMContext &Context = L.getHeader()->getContext();
408+
// Reserve first location for self reference to the LoopID metadata node.
409+
MDNode *Dummy = MDNode::get(Context, {});
410+
MDNode *DisableUnroll = MDNode::get(
411+
Context, {MDString::get(Context, "llvm.loop.unroll.disable")});
412+
Metadata *FalseVal =
413+
ConstantAsMetadata::get(ConstantInt::get(Type::getInt1Ty(Context), 0));
414+
MDNode *DisableVectorize = MDNode::get(
415+
Context,
416+
{MDString::get(Context, "llvm.loop.vectorize.enable"), FalseVal});
417+
MDNode *DisableLICMVersioning = MDNode::get(
418+
Context, {MDString::get(Context, "llvm.loop.licm_versioning.disable")});
419+
MDNode *DisableDistribution= MDNode::get(
420+
Context,
421+
{MDString::get(Context, "llvm.loop.distribute.enable"), FalseVal});
422+
MDNode *NewLoopID =
423+
MDNode::get(Context, {Dummy, DisableUnroll, DisableVectorize,
424+
DisableLICMVersioning, DisableDistribution});
425+
// Set operand 0 to refer to the loop id itself.
426+
NewLoopID->replaceOperandWith(0, NewLoopID);
427+
L.setLoopID(NewLoopID);
428+
}
429+
402430
namespace {
403431

404432
// Keeps track of the structure of a loop. This is similar to llvm::Loop,
@@ -1309,13 +1337,19 @@ bool LoopConstrainer::run() {
13091337
&OriginalLoop, OriginalLoop.getParentLoop(), PreLoop.Map);
13101338
formLCSSARecursively(*L, DT, &LI, &SE);
13111339
simplifyLoop(L, &DT, &LI, &SE, nullptr, true);
1340+
// Pre loops are slow paths, we do not need to perform any loop
1341+
// optimizations on them.
1342+
DisableAllLoopOptsOnLoop(*L);
13121343
}
13131344

13141345
if (!PostLoop.Blocks.empty()) {
13151346
auto *L = createClonedLoopStructure(
13161347
&OriginalLoop, OriginalLoop.getParentLoop(), PostLoop.Map);
13171348
formLCSSARecursively(*L, DT, &LI, &SE);
13181349
simplifyLoop(L, &DT, &LI, &SE, nullptr, true);
1350+
// Post loops are slow paths, we do not need to perform any loop
1351+
// optimizations on them.
1352+
DisableAllLoopOptsOnLoop(*L);
13191353
}
13201354

13211355
formLCSSARecursively(OriginalLoop, DT, &LI, &SE);
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
; RUN: opt -irce -S < %s 2>&1 | FileCheck %s
2+
3+
; test that the pre and post loops have loop metadata which disables any further
4+
; loop optimizations.
5+
6+
; generates a post loop, which should have metadata !llvm.loop !2
7+
; Function Attrs: alwaysinline
8+
define void @inner_loop(i32* %arr, i32* %a_len_ptr, i32 %n) #0 {
9+
; CHECK-LABEL: inner_loop(
10+
; CHECK-LABEL: in.bounds.postloop
11+
; CHECK: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit.loopexit, !llvm.loop !2, !irce.loop.clone !7
12+
13+
entry:
14+
%len = load i32, i32* %a_len_ptr, !range !0
15+
%first.itr.check = icmp sgt i32 %n, 0
16+
br i1 %first.itr.check, label %loop, label %exit
17+
18+
loop: ; preds = %in.bounds, %entry
19+
%idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
20+
%idx.next = add i32 %idx, 1
21+
%abc = icmp slt i32 %idx, %len
22+
br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
23+
24+
in.bounds: ; preds = %loop
25+
%addr = getelementptr i32, i32* %arr, i32 %idx
26+
store i32 0, i32* %addr
27+
%next = icmp slt i32 %idx.next, %n
28+
br i1 %next, label %loop, label %exit
29+
30+
out.of.bounds: ; preds = %loop
31+
ret void
32+
33+
exit: ; preds = %in.bounds, %entry
34+
ret void
35+
}
36+
37+
; add loop metadata for pre and post loops
38+
define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 %offset) {
39+
; CHECK-LABEL: @single_access_with_preloop(
40+
; CHECK-LABEL: in.bounds.preloop
41+
; CHECK: br i1 %14, label %loop.preloop, label %preloop.exit.selector, !llvm.loop !8, !irce.loop.clone !7
42+
; CHECK-LABEL: in.bounds.postloop
43+
; CHECK: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit.loopexit, !llvm.loop !9, !irce.loop.clone !7
44+
entry:
45+
%len = load i32, i32* %a_len_ptr, !range !0
46+
%first.itr.check = icmp sgt i32 %n, 0
47+
br i1 %first.itr.check, label %loop, label %exit
48+
49+
loop:
50+
%idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
51+
%idx.next = add i32 %idx, 1
52+
%array.idx = add i32 %idx, %offset
53+
%abc.high = icmp slt i32 %array.idx, %len
54+
%abc.low = icmp sge i32 %array.idx, 0
55+
%abc = and i1 %abc.low, %abc.high
56+
br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
57+
58+
in.bounds:
59+
%addr = getelementptr i32, i32* %arr, i32 %array.idx
60+
store i32 0, i32* %addr
61+
%next = icmp slt i32 %idx.next, %n
62+
br i1 %next, label %loop, label %exit
63+
64+
out.of.bounds:
65+
ret void
66+
67+
exit:
68+
ret void
69+
}
70+
attributes #0 = { alwaysinline }
71+
72+
!0 = !{i32 0, i32 2147483647}
73+
!1 = !{!"branch_weights", i32 64, i32 4}
74+
!2 = distinct !{!2, !3, !4, !5, !6}
75+
!3 = !{!"llvm.loop.unroll.disable"}
76+
!4 = !{!"llvm.loop.vectorize.enable", i1 false}
77+
!5 = !{!"llvm.loop.licm_versioning.disable"}
78+
!6 = !{!"llvm.loop.distribute.enable", i1 false}
79+
!7 = !{}
80+
!8 = distinct !{!8, !3, !4, !5}
81+
!9 = distinct !{!9, !3, !4, !5}

0 commit comments

Comments
 (0)