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 64define void @icmp_zero_urem_invariant(i64 %N, i64 %M, ptr %p) { 65; CHECK-LABEL: @icmp_zero_urem_invariant( 66; CHECK-NEXT: entry: 67; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]] 68; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 69; CHECK: vector.body: 70; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ] 71; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 72; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 73; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 74; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 75; CHECK: exit: 76; CHECK-NEXT: ret void 77; 78entry: 79 %urem = urem i64 %N, %M 80 br label %vector.body 81 82vector.body: 83 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 84 store i64 0, ptr %p 85 %iv.next = add i64 %iv, 2 86 %done = icmp eq i64 %iv.next, %urem 87 br i1 %done, label %exit, label %vector.body 88 89exit: 90 ret void 91} 92 93; Negative test - We can not hoist because we don't know value of %M. 94define void @icmp_zero_urem_nohoist(i64 %N, i64 %M, ptr %p) { 95; CHECK-LABEL: @icmp_zero_urem_nohoist( 96; CHECK-NEXT: entry: 97; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 98; CHECK: vector.body: 99; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ] 100; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 101; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2 102; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]] 103; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]] 104; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 105; CHECK: exit: 106; CHECK-NEXT: ret void 107; 108entry: 109 br label %vector.body 110 111vector.body: 112 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 113 store i64 0, ptr %p 114 %iv.next = add i64 %iv, 2 115 %urem = urem i64 %N, %M 116 %done = icmp eq i64 %iv.next, %urem 117 br i1 %done, label %exit, label %vector.body 118 119exit: 120 ret void 121} 122 123define void @icmp_zero_urem_nonzero(i64 %N, i64 %M, ptr %p) { 124; CHECK-LABEL: @icmp_zero_urem_nonzero( 125; CHECK-NEXT: entry: 126; CHECK-NEXT: [[NONZERO:%.*]] = add nuw i64 [[M:%.*]], 1 127; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[NONZERO]] 128; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 129; CHECK: vector.body: 130; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ] 131; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 132; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 133; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 134; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 135; CHECK: exit: 136; CHECK-NEXT: ret void 137; 138entry: 139 %nonzero = add nuw i64 %M, 1 140 %urem = urem i64 %N, %nonzero 141 br label %vector.body 142 143vector.body: 144 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 145 store i64 0, ptr %p 146 %iv.next = add i64 %iv, 2 147 %done = icmp eq i64 %iv.next, %urem 148 br i1 %done, label %exit, label %vector.body 149 150exit: 151 ret void 152} 153 154define void @icmp_zero_urem_vscale(i64 %N, ptr %p) { 155; CHECK-LABEL: @icmp_zero_urem_vscale( 156; CHECK-NEXT: entry: 157; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() 158; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[VSCALE]] 159; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 160; CHECK: vector.body: 161; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ] 162; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 163; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 164; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 165; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 166; CHECK: exit: 167; CHECK-NEXT: ret void 168; 169entry: 170 %vscale = call i64 @llvm.vscale.i64() 171 %urem = urem i64 %N, %vscale 172 br label %vector.body 173 174vector.body: 175 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 176 store i64 0, ptr %p 177 %iv.next = add i64 %iv, 2 178 %done = icmp eq i64 %iv.next, %urem 179 br i1 %done, label %exit, label %vector.body 180 181exit: 182 ret void 183} 184 185define void @icmp_zero_urem_vscale_mul8(i64 %N, ptr %p) { 186; CHECK-LABEL: @icmp_zero_urem_vscale_mul8( 187; CHECK-NEXT: entry: 188; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() 189; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[VSCALE]], 8 190; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[MUL]] 191; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 192; CHECK: vector.body: 193; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ] 194; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 195; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 196; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 197; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 198; CHECK: exit: 199; CHECK-NEXT: ret void 200; 201entry: 202 %vscale = call i64 @llvm.vscale.i64() 203 %mul = mul nuw nsw i64 %vscale, 8 204 %urem = urem i64 %N, %mul 205 br label %vector.body 206 207vector.body: 208 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 209 store i64 0, ptr %p 210 %iv.next = add i64 %iv, 2 211 %done = icmp eq i64 %iv.next, %urem 212 br i1 %done, label %exit, label %vector.body 213 214exit: 215 ret void 216} 217 218 219define void @icmp_zero_urem_vscale_mul64(i64 %N, ptr %p) { 220; CHECK-LABEL: @icmp_zero_urem_vscale_mul64( 221; CHECK-NEXT: entry: 222; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() 223; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[VSCALE]], 64 224; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[MUL]] 225; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 226; CHECK: vector.body: 227; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ] 228; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 229; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 230; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 231; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 232; CHECK: exit: 233; CHECK-NEXT: ret void 234; 235entry: 236 %vscale = call i64 @llvm.vscale.i64() 237 %mul = mul nuw nsw i64 %vscale, 64 238 %urem = urem i64 %N, %mul 239 br label %vector.body 240 241vector.body: 242 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 243 store i64 0, ptr %p 244 %iv.next = add i64 %iv, 2 245 %done = icmp eq i64 %iv.next, %urem 246 br i1 %done, label %exit, label %vector.body 247 248exit: 249 ret void 250} 251 252define void @icmp_zero_urem_vscale_shl3(i64 %N, ptr %p) { 253; CHECK-LABEL: @icmp_zero_urem_vscale_shl3( 254; CHECK-NEXT: entry: 255; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() 256; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VSCALE]], 3 257; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[SHL]] 258; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 259; CHECK: vector.body: 260; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ] 261; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 262; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 263; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 264; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 265; CHECK: exit: 266; CHECK-NEXT: ret void 267; 268entry: 269 %vscale = call i64 @llvm.vscale.i64() 270 %shl = shl i64 %vscale, 3 271 %urem = urem i64 %N, %shl 272 br label %vector.body 273 274vector.body: 275 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 276 store i64 0, ptr %p 277 %iv.next = add i64 %iv, 2 278 %done = icmp eq i64 %iv.next, %urem 279 br i1 %done, label %exit, label %vector.body 280 281exit: 282 ret void 283} 284 285define void @icmp_zero_urem_vscale_shl6(i64 %N, ptr %p) { 286; CHECK-LABEL: @icmp_zero_urem_vscale_shl6( 287; CHECK-NEXT: entry: 288; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() 289; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VSCALE]], 6 290; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[SHL]] 291; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 292; CHECK: vector.body: 293; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ] 294; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8 295; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2 296; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0 297; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]] 298; CHECK: exit: 299; CHECK-NEXT: ret void 300; 301entry: 302 %vscale = call i64 @llvm.vscale.i64() 303 %shl = shl i64 %vscale, 6 304 %urem = urem i64 %N, %shl 305 br label %vector.body 306 307vector.body: 308 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ] 309 store i64 0, ptr %p 310 %iv.next = add i64 %iv, 2 311 %done = icmp eq i64 %iv.next, %urem 312 br i1 %done, label %exit, label %vector.body 313 314exit: 315 ret void 316} 317 318declare i64 @llvm.vscale.i64() 319