1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -loop-reduce -S | FileCheck %s 3 4target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" 5target triple = "riscv64" 6 7 8define void @icmp_zero(i64 %N, ptr %p) { 9; CHECK-LABEL: @icmp_zero( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 12; CHECK: vector.body: 13; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[N:%.*]], [[ENTRY:%.*]] ] 14; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 15; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 16; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 17; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 18; CHECK: exit: 19; CHECK-NEXT: ret void 20; 21entry: 22 br label %vector.body 23 24vector.body: 25 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 26 store i64 0, ptr %p 27 %iv.next = add i64 %iv, 2 28 %done = icmp eq i64 %iv.next, %N 29 br i1 %done, label %exit, label %vector.body 30 31exit: 32 ret void 33} 34 35define void @icmp_zero_urem_nonzero_con(i64 %N, ptr %p) { 36; CHECK-LABEL: @icmp_zero_urem_nonzero_con( 37; CHECK-NEXT: entry: 38; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], 16 39; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 40; CHECK: vector.body: 41; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ] 42; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 43; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 44; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 45; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 46; CHECK: exit: 47; CHECK-NEXT: ret void 48; 49entry: 50 %urem = urem i64 %N, 16 51 br label %vector.body 52 53vector.body: 54 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 55 store i64 0, ptr %p 56 %iv.next = add i64 %iv, 2 57 %done = icmp eq i64 %iv.next, %urem 58 br i1 %done, label %exit, label %vector.body 59 60exit: 61 ret void 62} 63 64; FIXME: We could handle this case even though we don't know %M. The 65; faulting instruction is already outside the loop! 66define void @icmp_zero_urem_invariant(i64 %N, i64 %M, ptr %p) { 67; CHECK-LABEL: @icmp_zero_urem_invariant( 68; CHECK-NEXT: entry: 69; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]] 70; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 71; CHECK: vector.body: 72; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ] 73; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 74; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2 75; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]] 76; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 77; CHECK: exit: 78; CHECK-NEXT: ret void 79; 80entry: 81 %urem = urem i64 %N, %M 82 br label %vector.body 83 84vector.body: 85 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 86 store i64 0, ptr %p 87 %iv.next = add i64 %iv, 2 88 %done = icmp eq i64 %iv.next, %urem 89 br i1 %done, label %exit, label %vector.body 90 91exit: 92 ret void 93} 94 95; Negative test - We can not hoist because we don't know value of %M. 96define void @icmp_zero_urem_nohoist(i64 %N, i64 %M, ptr %p) { 97; CHECK-LABEL: @icmp_zero_urem_nohoist( 98; CHECK-NEXT: entry: 99; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 100; CHECK: vector.body: 101; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ] 102; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 103; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2 104; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]] 105; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]] 106; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 107; CHECK: exit: 108; CHECK-NEXT: ret void 109; 110entry: 111 br label %vector.body 112 113vector.body: 114 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 115 store i64 0, ptr %p 116 %iv.next = add i64 %iv, 2 117 %urem = urem i64 %N, %M 118 %done = icmp eq i64 %iv.next, %urem 119 br i1 %done, label %exit, label %vector.body 120 121exit: 122 ret void 123} 124 125define void @icmp_zero_urem_nonzero(i64 %N, i64 %M, ptr %p) { 126; CHECK-LABEL: @icmp_zero_urem_nonzero( 127; CHECK-NEXT: entry: 128; CHECK-NEXT: [[NONZERO:%.*]] = add nuw i64 [[M:%.*]], 1 129; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[NONZERO]] 130; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 131; CHECK: vector.body: 132; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ] 133; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 134; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2 135; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]] 136; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 137; CHECK: exit: 138; CHECK-NEXT: ret void 139; 140entry: 141 %nonzero = add nuw i64 %M, 1 142 %urem = urem i64 %N, %nonzero 143 br label %vector.body 144 145vector.body: 146 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 147 store i64 0, ptr %p 148 %iv.next = add i64 %iv, 2 149 %done = icmp eq i64 %iv.next, %urem 150 br i1 %done, label %exit, label %vector.body 151 152exit: 153 ret void 154} 155 156; FIXME: We can hoist this because vscale is never equal to zero 157define void @icmp_zero_urem_vscale(i64 %N, ptr %p) { 158; CHECK-LABEL: @icmp_zero_urem_vscale( 159; CHECK-NEXT: entry: 160; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() 161; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[VSCALE]] 162; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 163; CHECK: vector.body: 164; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ] 165; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 166; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2 167; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]] 168; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 169; CHECK: exit: 170; CHECK-NEXT: ret void 171; 172entry: 173 %vscale = call i64 @llvm.vscale.i64() 174 %urem = urem i64 %N, %vscale 175 br label %vector.body 176 177vector.body: 178 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 179 store i64 0, ptr %p 180 %iv.next = add i64 %iv, 2 181 %done = icmp eq i64 %iv.next, %urem 182 br i1 %done, label %exit, label %vector.body 183 184exit: 185 ret void 186} 187 188declare i64 @llvm.vscale.i64() 189