1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=loop-predication < %s 2>&1 | FileCheck %s 3; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s 4 5declare void @llvm.experimental.guard(i1, ...) 6 7; Check the case when N on latch exit might be poison. 8define i32 @test1(i32 %length, i32 %nlimit) { 9; CHECK-LABEL: @test1( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[M:%.*]] = add nuw nsw i32 [[NLIMIT:%.*]], 2 12; CHECK-NEXT: [[N:%.*]] = xor i32 [[M]], 1 13; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]] 14; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 15; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 16; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]] 17; CHECK-NEXT: br label [[LOOP:%.*]] 18; CHECK: loop: 19; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[OK:%.*]] ], [ 0, [[ENTRY:%.*]] ] 20; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[OK]] ], [ 0, [[ENTRY]] ] 21; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] 22; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 23; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 24; CHECK-NEXT: [[TMP:%.*]] = icmp ult i32 [[NLIMIT]], 1000 25; CHECK-NEXT: br i1 [[TMP]], label [[OK]], label [[EXIT:%.*]] 26; CHECK: ok: 27; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 28; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1 29; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 30; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT]] 31; CHECK: exit: 32; CHECK-NEXT: ret i32 0 33; 34entry: 35 ; %n might be a poison. 36 %m = add nuw nsw i32 %nlimit, 2 37 %n = xor i32 %m, 1 38 br label %loop 39 40loop: 41 %i = phi i32 [ %i.next, %ok ], [ 0, %entry ] 42 %j = phi i32 [ %j.next, %ok ], [ 0, %entry ] 43 %within.bounds = icmp ult i32 %j, %length 44 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 45 46 ; This check guarantees %n is not a posion. 47 %tmp = icmp ult i32 %nlimit, 1000 48 br i1 %tmp, label %ok, label %exit 49 50ok: 51 %i.next = add i32 %i, 1 52 %j.next = add i32 %j, 1 53 %continue = icmp ult i32 %i.next, %n 54 br i1 %continue, label %loop, label %exit 55 56exit: 57 ret i32 0 58} 59 60 61; Check the case when start value of IV might be a poison. 62define i32 @test2(i32 noundef %length, i32 noundef %nlimit, i32 %istart) { 63; CHECK-LABEL: @test2( 64; CHECK-NEXT: entry: 65; CHECK-NEXT: [[M:%.*]] = add nuw nsw i32 [[ISTART:%.*]], 2 66; CHECK-NEXT: [[ISTART2:%.*]] = xor i32 [[M]], 1 67; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[ISTART2]], [[LENGTH:%.*]] 68; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -1 69; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i32 [[NLIMIT:%.*]], [[TMP1]] 70; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 1, [[LENGTH]] 71; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]] 72; CHECK-NEXT: [[TMP5:%.*]] = freeze i1 [[TMP4]] 73; CHECK-NEXT: br label [[LOOP:%.*]] 74; CHECK: loop: 75; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[OK:%.*]] ], [ [[ISTART2]], [[ENTRY:%.*]] ] 76; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[OK]] ], [ 1, [[ENTRY]] ] 77; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] 78; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP5]], i32 9) [ "deopt"() ] 79; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 80; CHECK-NEXT: [[TMP:%.*]] = icmp ult i32 [[ISTART]], 1000 81; CHECK-NEXT: br i1 [[TMP]], label [[OK]], label [[EXIT:%.*]] 82; CHECK: ok: 83; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 84; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1 85; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[NLIMIT]] 86; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT]] 87; CHECK: exit: 88; CHECK-NEXT: ret i32 0 89; 90entry: 91 ; %m might be a poison. 92 %m = add nuw nsw i32 %istart, 2 93 %istart2 = xor i32 %m, 1 94 br label %loop 95 96loop: 97 %i = phi i32 [ %i.next, %ok ], [ %istart2, %entry ] 98 %j = phi i32 [ %j.next, %ok ], [ 1, %entry ] 99 %within.bounds = icmp ult i32 %j, %length 100 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 101 ; This check guarantees %n is not a posion. 102 %tmp = icmp ult i32 %istart, 1000 103 br i1 %tmp, label %ok, label %exit 104 105ok: 106 %i.next = add i32 %i, 1 107 %j.next = add i32 %j, 1 108 %continue = icmp ult i32 %i.next, %nlimit 109 br i1 %continue, label %loop, label %exit 110 111exit: 112 ret i32 0 113} 114