Skip to content

Commit 1c42d13

Browse files
committed
[LoopIdiom] check for safety while expanding
Loop Idiom recognition was generating memset in a case that would result generating a division operation to an unsafe location. Differential Revision: https://reviews.llvm.org/D32674 llvm-svn: 302238
1 parent e608f6a commit 1c42d13

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,11 @@ bool LoopIdiomRecognize::processLoopStridedStore(
783783
if (NegStride)
784784
Start = getStartForNegStride(Start, BECount, IntPtr, StoreSize, SE);
785785

786+
// TODO: ideally we should still be able to generate memset if SCEV expander
787+
// is taught to generate the dependencies at the latest point.
788+
if (!isSafeToExpand(Start, *SE))
789+
return false;
790+
786791
// Okay, we have a strided store "p[i]" of a splattable value. We can turn
787792
// this into a memset in the loop preheader now if we want. However, this
788793
// would be unsafe to do if there is anything else in the loop that may read
@@ -814,6 +819,11 @@ bool LoopIdiomRecognize::processLoopStridedStore(
814819
SCEV::FlagNUW);
815820
}
816821

822+
// TODO: ideally we should still be able to generate memset if SCEV expander
823+
// is taught to generate the dependencies at the latest point.
824+
if (!isSafeToExpand(NumBytesS, *SE))
825+
return false;
826+
817827
Value *NumBytes =
818828
Expander.expandCodeFor(NumBytesS, IntPtr, Preheader->getTerminator());
819829

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; RUN: opt -S < %s -loop-idiom | FileCheck %s
2+
; CHECK-NOT: memset
3+
; check that memset is not generated (for stores) because that will result
4+
; in udiv hoisted out of the loop by the SCEV Expander
5+
; TODO: ideally we should be able to generate memset
6+
; if SCEV expander is taught to generate the dependencies
7+
; at the right point.
8+
9+
@a = global i32 0, align 4
10+
@b = global i32 0, align 4
11+
@c = external local_unnamed_addr global [1 x i8], align 1
12+
13+
define void @e() local_unnamed_addr {
14+
entry:
15+
%d0 = load i32, i32* @a, align 4
16+
%d1 = load i32, i32* @b, align 4
17+
br label %for.cond1thread-pre-split
18+
19+
for.cond1thread-pre-split: ; preds = %for.body5, %entry
20+
%div = udiv i32 %d0, %d1
21+
br label %for.body5
22+
23+
for.body5: ; preds = %for.body5, %for.cond1thread-pre-split
24+
%indvars.iv = phi i64 [ 0, %for.cond1thread-pre-split ], [ %indvars.iv.next, %for.body5 ]
25+
%divx = sext i32 %div to i64
26+
%0 = add nsw i64 %divx, %indvars.iv
27+
%arrayidx = getelementptr inbounds [1 x i8], [1 x i8]* @c, i64 0, i64 %0
28+
store i8 0, i8* %arrayidx, align 1
29+
%indvars.iv.next = add nsw i64 %indvars.iv, 1
30+
%1 = trunc i64 %indvars.iv.next to i32
31+
%tobool4 = icmp eq i32 %1, 0
32+
br i1 %tobool4, label %for.cond1thread-pre-split, label %for.body5
33+
}
34+
35+
; The loop's trip count is depending on an unsafe operation
36+
; udiv. SCEV expander hoists it out of the loop, so loop-idiom
37+
; should check that the memset is not generated in this case.
38+
define void @f(i32 %a, i32 %b, i8* nocapture %x) local_unnamed_addr {
39+
entry:
40+
br label %for.body
41+
42+
for.body: ; preds = %for.body6, %entry
43+
%div = udiv i32 %a, %b
44+
%conv = zext i32 %div to i64
45+
br label %for.body6
46+
47+
for.body6: ; preds = %for.body6, %for.body
48+
%i.09 = phi i64 [ %inc, %for.body6 ], [ 0, %for.body ]
49+
%arrayidx = getelementptr inbounds i8, i8* %x, i64 %i.09
50+
store i8 0, i8* %arrayidx, align 1
51+
%inc = add nuw nsw i64 %i.09, 1
52+
%cmp3 = icmp slt i64 %inc, %conv
53+
br i1 %cmp3, label %for.body6, label %for.body
54+
}
55+

0 commit comments

Comments
 (0)