aboutsummaryrefslogtreecommitdiffstats
path: root/test/Transforms/IndVarSimplify/lftr-reuse.ll
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/IndVarSimplify/lftr-reuse.ll')
-rw-r--r--test/Transforms/IndVarSimplify/lftr-reuse.ll230
1 files changed, 230 insertions, 0 deletions
diff --git a/test/Transforms/IndVarSimplify/lftr-reuse.ll b/test/Transforms/IndVarSimplify/lftr-reuse.ll
new file mode 100644
index 0000000..6ccd1a4
--- /dev/null
+++ b/test/Transforms/IndVarSimplify/lftr-reuse.ll
@@ -0,0 +1,230 @@
+; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s
+;
+; Make sure that indvars can perform LFTR without a canonical IV.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+; Perform LFTR using the original pointer-type IV.
+
+; for(char* p = base; p < base + n; ++p) {
+; *p = p-base;
+; }
+define void @ptriv(i8* %base, i32 %n) nounwind {
+entry:
+ %idx.ext = sext i32 %n to i64
+ %add.ptr = getelementptr inbounds i8* %base, i64 %idx.ext
+ %cmp1 = icmp ult i8* %base, %add.ptr
+ br i1 %cmp1, label %for.body, label %for.end
+
+; CHECK: for.body:
+; CHECK: phi i8*
+; CHECK-NOT: phi
+; CHECK-NOT: add
+; CHECK: icmp ne i8*
+; CHECK: br i1
+for.body:
+ %p.02 = phi i8* [ %base, %entry ], [ %incdec.ptr, %for.body ]
+ ; cruft to make the IV useful
+ %sub.ptr.lhs.cast = ptrtoint i8* %p.02 to i64
+ %sub.ptr.rhs.cast = ptrtoint i8* %base to i64
+ %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+ %conv = trunc i64 %sub.ptr.sub to i8
+ store i8 %conv, i8* %p.02
+ %incdec.ptr = getelementptr inbounds i8* %p.02, i32 1
+ %cmp = icmp ult i8* %incdec.ptr, %add.ptr
+ br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+ ret void
+}
+
+; It would be nice if SCEV and any loop analysis could assume that
+; preheaders exist. Unfortunately it is not always the case. This test
+; checks that SCEVExpander can handle an outer loop that has not yet
+; been simplified. As a result, the inner loop's exit test will not be
+; rewritten.
+define void @expandOuterRecurrence(i32 %arg) nounwind {
+entry:
+ %sub1 = sub nsw i32 %arg, 1
+ %cmp1 = icmp slt i32 0, %sub1
+ br i1 %cmp1, label %outer, label %exit
+
+outer:
+ %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
+ %sub2 = sub nsw i32 %arg, %i
+ %sub3 = sub nsw i32 %sub2, 1
+ %cmp2 = icmp slt i32 0, %sub3
+ br i1 %cmp2, label %inner.ph, label %outer.inc
+
+inner.ph:
+ br label %inner
+
+; CHECK: inner:
+; CHECK: icmp slt
+; CHECK: br i1
+inner:
+ %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
+ %j.inc = add nsw i32 %j, 1
+ %cmp3 = icmp slt i32 %j.inc, %sub3
+ br i1 %cmp3, label %inner, label %outer.inc
+
+; CHECK: outer.inc:
+; CHECK: icmp ne
+; CHECK: br i1
+outer.inc:
+ %i.inc = add nsw i32 %i, 1
+ %cmp4 = icmp slt i32 %i.inc, %sub1
+ br i1 %cmp4, label %outer, label %exit
+
+exit:
+ ret void
+}
+
+; Force SCEVExpander to look for an existing well-formed phi.
+; Perform LFTR without generating extra preheader code.
+define void @guardedloop([0 x double]* %matrix, [0 x double]* %vector,
+ i32 %irow, i32 %ilead) nounwind {
+; CHECK: entry:
+; CHECK-NOT: zext
+; CHECK-NOT: add
+; CHECK: loop:
+; CHECK: phi i64
+; CHECK: phi i64
+; CHECK-NOT: phi
+; CHECK: icmp ne
+; CHECK: br i1
+entry:
+ %cmp = icmp slt i32 1, %irow
+ br i1 %cmp, label %loop, label %return
+
+loop:
+ %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
+ %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+ %diagidx = add nsw i32 %rowidx, %i
+ %diagidxw = sext i32 %diagidx to i64
+ %matrixp = getelementptr inbounds [0 x double]* %matrix, i32 0, i64 %diagidxw
+ %v1 = load double* %matrixp
+ %iw = sext i32 %i to i64
+ %vectorp = getelementptr inbounds [0 x double]* %vector, i32 0, i64 %iw
+ %v2 = load double* %vectorp
+ %row.inc = add nsw i32 %rowidx, %ilead
+ %i.inc = add nsw i32 %i, 1
+ %cmp196 = icmp slt i32 %i.inc, %irow
+ br i1 %cmp196, label %loop, label %return
+
+return:
+ ret void
+}
+
+; Avoid generating extra code to materialize a trip count. Skip LFTR.
+define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector,
+ i32 %irow, i32 %ilead) nounwind {
+entry:
+ br label %loop
+
+; CHECK: entry:
+; CHECK-NOT: zext
+; CHECK-NOT: add
+; CHECK: loop:
+; CHECK: phi i64
+; CHECK: phi i64
+; CHECK-NOT: phi
+; CHECK: icmp slt
+; CHECK: br i1
+loop:
+ %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
+ %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+ %diagidx = add nsw i32 %rowidx, %i
+ %diagidxw = sext i32 %diagidx to i64
+ %matrixp = getelementptr inbounds [0 x double]* %matrix, i32 0, i64 %diagidxw
+ %v1 = load double* %matrixp
+ %iw = sext i32 %i to i64
+ %vectorp = getelementptr inbounds [0 x double]* %vector, i32 0, i64 %iw
+ %v2 = load double* %vectorp
+ %row.inc = add nsw i32 %rowidx, %ilead
+ %i.inc = add nsw i32 %i, 1
+ %cmp196 = icmp slt i32 %i.inc, %irow
+ br i1 %cmp196, label %loop, label %return
+
+return:
+ ret void
+}
+
+; Remove %i which is only used by the exit test.
+; Verify that SCEV can still compute a backedge count from the sign
+; extended %n, used for pointer comparison by LFTR.
+define void @geplftr(i8* %base, i32 %x, i32 %y, i32 %n) nounwind {
+entry:
+ %x.ext = sext i32 %x to i64
+ %add.ptr = getelementptr inbounds i8* %base, i64 %x.ext
+ %y.ext = sext i32 %y to i64
+ %add.ptr10 = getelementptr inbounds i8* %add.ptr, i64 %y.ext
+ %lim = add i32 %x, %n
+ %cmp.ph = icmp ult i32 %x, %lim
+ br i1 %cmp.ph, label %loop, label %exit
+
+; CHECK: loop:
+; CHECK: phi i8*
+; CHECK-NOT: phi
+; CHECK: getelementptr
+; CHECK: store
+; CHECK: icmp ne i8*
+; CHECK: br i1
+loop:
+ %i = phi i32 [ %x, %entry ], [ %inc, %loop ]
+ %aptr = phi i8* [ %add.ptr10, %entry ], [ %incdec.ptr, %loop ]
+ %incdec.ptr = getelementptr inbounds i8* %aptr, i32 1
+ store i8 3, i8* %aptr
+ %inc = add i32 %i, 1
+ %cmp = icmp ult i32 %inc, %lim
+ br i1 %cmp, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+; Exercise backedge taken count verification with a never-taken loop.
+define void @nevertaken() nounwind uwtable ssp {
+entry:
+ br label %loop
+
+; CHECK: loop:
+; CHECK-NOT: phi
+; CHECK-NOT: add
+; CHECK-NOT: icmp
+; CHECK: exit:
+loop:
+ %i = phi i32 [ 0, %entry ], [ %inc, %loop ]
+ %inc = add nsw i32 %i, 1
+ %cmp = icmp sle i32 %inc, 0
+ br i1 %cmp, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+; Test LFTR on an IV whose recurrence start is a non-unit pointer type.
+define void @aryptriv([256 x i8]* %base, i32 %n) nounwind {
+entry:
+ %ivstart = getelementptr inbounds [256 x i8]* %base, i32 0, i32 0
+ %ivend = getelementptr inbounds [256 x i8]* %base, i32 0, i32 %n
+ %cmp.ph = icmp ult i8* %ivstart, %ivend
+ br i1 %cmp.ph, label %loop, label %exit
+
+; CHECK: loop:
+; CHECK: phi i8*
+; CHECK-NOT: phi
+; CHECK: getelementptr
+; CHECK: store
+; CHECK: icmp ne i8*
+; CHECK: br i1
+loop:
+ %aptr = phi i8* [ %ivstart, %entry ], [ %incdec.ptr, %loop ]
+ %incdec.ptr = getelementptr inbounds i8* %aptr, i32 1
+ store i8 3, i8* %aptr
+ %cmp = icmp ult i8* %incdec.ptr, %ivend
+ br i1 %cmp, label %loop, label %exit
+
+exit:
+ ret void
+}