From 2e66afabcfd12605a9b78a34055386a62344685e Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Fri, 31 May 2019 16:54:38 +0000 Subject: [PATCH] [Tests] Add tests for loop predication of loops w/ne latch conditions git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362244 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Transforms/LoopPredication/basic.ll | 172 +++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/test/Transforms/LoopPredication/basic.ll b/test/Transforms/LoopPredication/basic.ll index 329b13bee00..0037dcdff91 100644 --- a/test/Transforms/LoopPredication/basic.ll +++ b/test/Transforms/LoopPredication/basic.ll @@ -1595,3 +1595,175 @@ exit: %result = phi i32 [ %loop.acc.next, %loop ] ret i32 %result } + +; NE Check (as produced by LFTR) where we can prove Start < End via simple +; instruction analysis +define i32 @ne_latch_zext(i32* %array, i32 %length, i16 %n16) { +; CHECK-LABEL: @ne_latch_zext( +; CHECK-NEXT: loop.preheader: +; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] +; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 +; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i32 0 +; +loop.preheader: + %n = zext i16 %n16 to i32 + br label %loop + +loop: + %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] + %within.bounds = icmp ult i32 %i, %length + call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] + + %i.next = add nuw i32 %i, 1 + %continue = icmp ne i32 %i.next, %n + br i1 %continue, label %loop, label %exit + +exit: + ret i32 0 +} + +; NE Check (as produced by LFTR) where we can prove Start < End via the +; condition guarding the loop entry. +define i32 @ne_latch_dom_check(i32* %array, i32 %length, i32 %n) { +; CHECK-LABEL: @ne_latch_dom_check( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] +; CHECK: loop.preheader: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] +; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 +; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK: exit.loopexit: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret i32 0 +; +entry: + %tmp5 = icmp sle i32 %n, 0 + br i1 %tmp5, label %exit, label %loop.preheader + +loop.preheader: + br label %loop + +loop: + %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] + %within.bounds = icmp ult i32 %i, %length + call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] + + %i.next = add nuw i32 %i, 1 + %continue = icmp ne i32 %i.next, %n + br i1 %continue, label %loop, label %exit + +exit: + ret i32 0 +} + +; NE latch - can't prove (end-start) mod step == 0 (i.e. might wrap +; around several times or even be infinite) +define i32 @neg_ne_latch_mod_step(i32* %array, i32 %length, i16 %n16) { +; CHECK-LABEL: @neg_ne_latch_mod_step( +; CHECK-NEXT: loop.preheader: +; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] +; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 3 +; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i32 0 +; +loop.preheader: + %n = zext i16 %n16 to i32 + br label %loop + +loop: + %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] + %within.bounds = icmp ult i32 %i, %length + call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] + + %i.next = add i32 %i, 3 + %continue = icmp ne i32 %i.next, %n + br i1 %continue, label %loop, label %exit + +exit: + ret i32 0 +} + +; NE latch - TODO: could prove (end-start) mod step == 0 +define i32 @ne_latch_mod_step(i32* %array, i32 %length) { +; CHECK-LABEL: @ne_latch_mod_step( +; CHECK-NEXT: loop.preheader: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] +; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 2 +; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], 400 +; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i32 0 +; +loop.preheader: + br label %loop + +loop: + %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] + %within.bounds = icmp ult i32 %i, %length + call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] + + %i.next = add nuw i32 %i, 2 + %continue = icmp ne i32 %i.next, 400 + br i1 %continue, label %loop, label %exit + +exit: + ret i32 0 +} + +; NE Latch - but end > start so wraps around and not equivelent to a ult +define i32 @neg_ne_latch_swapped_order(i32* %array, i32 %length) { +; CHECK-LABEL: @neg_ne_latch_swapped_order( +; CHECK-NEXT: loop.preheader: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] +; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 +; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], 0 +; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i32 0 +; +loop.preheader: + br label %loop + +loop: + %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ] + %within.bounds = icmp ult i32 %i, %length + call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] + + %i.next = add i32 %i, 1 + %continue = icmp ne i32 %i.next, 0 + br i1 %continue, label %loop, label %exit + +exit: + ret i32 0 +} + -- 2.50.1