385 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -loop-reduce -S | FileCheck %s3 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 815; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -216; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 017; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]18; CHECK: exit:19; CHECK-NEXT: ret void20;21entry:22 br label %vector.body23 24vector.body:25 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]26 store i64 0, ptr %p27 %iv.next = add i64 %iv, 228 %done = icmp eq i64 %iv.next, %N29 br i1 %done, label %exit, label %vector.body30 31exit:32 ret void33}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:%.*]], 1639; 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 843; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -244; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 045; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]46; CHECK: exit:47; CHECK-NEXT: ret void48;49entry:50 %urem = urem i64 %N, 1651 br label %vector.body52 53vector.body:54 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]55 store i64 0, ptr %p56 %iv.next = add i64 %iv, 257 %done = icmp eq i64 %iv.next, %urem58 br i1 %done, label %exit, label %vector.body59 60exit:61 ret void62}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 872; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -273; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 074; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]75; CHECK: exit:76; CHECK-NEXT: ret void77;78entry:79 %urem = urem i64 %N, %M80 br label %vector.body81 82vector.body:83 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]84 store i64 0, ptr %p85 %iv.next = add i64 %iv, 286 %done = icmp eq i64 %iv.next, %urem87 br i1 %done, label %exit, label %vector.body88 89exit:90 ret void91}92 93; We have to be careful here as SCEV can only compute a subtraction from94; two pointers with the same base. If we hide %end inside a unknown, we95; can no longer compute the subtract.96define void @icmp_zero_urem_invariant_ptr(i64 %N, i64 %M, ptr %p) {97; CHECK-LABEL: @icmp_zero_urem_invariant_ptr(98; CHECK-NEXT: entry:99; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]]100; CHECK-NEXT: [[END:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[UREM]]101; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]102; CHECK: vector.body:103; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[P]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ]104; CHECK-NEXT: store i64 0, ptr [[P]], align 8105; CHECK-NEXT: [[IV_NEXT]] = getelementptr i64, ptr [[IV]], i64 1106; CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[IV_NEXT]], [[END]]107; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]108; CHECK: exit:109; CHECK-NEXT: ret void110;111entry:112 %urem = urem i64 %N, %M113 %end = getelementptr i64, ptr %p, i64 %urem114 br label %vector.body115 116vector.body:117 %iv = phi ptr [ %p, %entry ], [ %iv.next, %vector.body ]118 store i64 0, ptr %p119 %iv.next = getelementptr i64, ptr %iv, i64 1120 %done = icmp eq ptr %iv.next, %end121 br i1 %done, label %exit, label %vector.body122 123exit:124 ret void125}126 127; Negative test - We can not hoist because we don't know value of %M.128define void @icmp_zero_urem_nohoist(i64 %N, i64 %M, ptr %p) {129; CHECK-LABEL: @icmp_zero_urem_nohoist(130; CHECK-NEXT: entry:131; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]132; CHECK: vector.body:133; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ]134; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8135; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2136; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]]137; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]]138; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]139; CHECK: exit:140; CHECK-NEXT: ret void141;142entry:143 br label %vector.body144 145vector.body:146 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]147 store i64 0, ptr %p148 %iv.next = add i64 %iv, 2149 %urem = urem i64 %N, %M150 %done = icmp eq i64 %iv.next, %urem151 br i1 %done, label %exit, label %vector.body152 153exit:154 ret void155}156 157define void @icmp_zero_urem_nonzero(i64 %N, i64 %M, ptr %p) {158; CHECK-LABEL: @icmp_zero_urem_nonzero(159; CHECK-NEXT: entry:160; CHECK-NEXT: [[NONZERO:%.*]] = add nuw i64 [[M:%.*]], 1161; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[NONZERO]]162; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]163; CHECK: vector.body:164; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]165; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8166; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2167; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0168; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]169; CHECK: exit:170; CHECK-NEXT: ret void171;172entry:173 %nonzero = add nuw i64 %M, 1174 %urem = urem i64 %N, %nonzero175 br label %vector.body176 177vector.body:178 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]179 store i64 0, ptr %p180 %iv.next = add i64 %iv, 2181 %done = icmp eq i64 %iv.next, %urem182 br i1 %done, label %exit, label %vector.body183 184exit:185 ret void186}187 188define void @icmp_zero_urem_vscale(i64 %N, ptr %p) {189; CHECK-LABEL: @icmp_zero_urem_vscale(190; CHECK-NEXT: entry:191; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()192; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[VSCALE]]193; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]194; CHECK: vector.body:195; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]196; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8197; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2198; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0199; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]200; CHECK: exit:201; CHECK-NEXT: ret void202;203entry:204 %vscale = call i64 @llvm.vscale.i64()205 %urem = urem i64 %N, %vscale206 br label %vector.body207 208vector.body:209 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]210 store i64 0, ptr %p211 %iv.next = add i64 %iv, 2212 %done = icmp eq i64 %iv.next, %urem213 br i1 %done, label %exit, label %vector.body214 215exit:216 ret void217}218 219define void @icmp_zero_urem_vscale_mul8(i64 %N, ptr %p) {220; CHECK-LABEL: @icmp_zero_urem_vscale_mul8(221; CHECK-NEXT: entry:222; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()223; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[VSCALE]], 8224; 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 8229; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2230; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0231; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]232; CHECK: exit:233; CHECK-NEXT: ret void234;235entry:236 %vscale = call i64 @llvm.vscale.i64()237 %mul = mul nuw nsw i64 %vscale, 8238 %urem = urem i64 %N, %mul239 br label %vector.body240 241vector.body:242 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]243 store i64 0, ptr %p244 %iv.next = add i64 %iv, 2245 %done = icmp eq i64 %iv.next, %urem246 br i1 %done, label %exit, label %vector.body247 248exit:249 ret void250}251 252 253define void @icmp_zero_urem_vscale_mul64(i64 %N, ptr %p) {254; CHECK-LABEL: @icmp_zero_urem_vscale_mul64(255; CHECK-NEXT: entry:256; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()257; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[VSCALE]], 64258; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[MUL]]259; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]260; CHECK: vector.body:261; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]262; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8263; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2264; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0265; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]266; CHECK: exit:267; CHECK-NEXT: ret void268;269entry:270 %vscale = call i64 @llvm.vscale.i64()271 %mul = mul nuw nsw i64 %vscale, 64272 %urem = urem i64 %N, %mul273 br label %vector.body274 275vector.body:276 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]277 store i64 0, ptr %p278 %iv.next = add i64 %iv, 2279 %done = icmp eq i64 %iv.next, %urem280 br i1 %done, label %exit, label %vector.body281 282exit:283 ret void284}285 286define void @icmp_zero_urem_vscale_shl3(i64 %N, ptr %p) {287; CHECK-LABEL: @icmp_zero_urem_vscale_shl3(288; CHECK-NEXT: entry:289; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()290; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VSCALE]], 3291; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[SHL]]292; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]293; CHECK: vector.body:294; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]295; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8296; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2297; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0298; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]299; CHECK: exit:300; CHECK-NEXT: ret void301;302entry:303 %vscale = call i64 @llvm.vscale.i64()304 %shl = shl i64 %vscale, 3305 %urem = urem i64 %N, %shl306 br label %vector.body307 308vector.body:309 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]310 store i64 0, ptr %p311 %iv.next = add i64 %iv, 2312 %done = icmp eq i64 %iv.next, %urem313 br i1 %done, label %exit, label %vector.body314 315exit:316 ret void317}318 319define void @icmp_zero_urem_vscale_shl6(i64 %N, ptr %p) {320; CHECK-LABEL: @icmp_zero_urem_vscale_shl6(321; CHECK-NEXT: entry:322; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()323; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[VSCALE]], 6324; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[SHL]]325; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]326; CHECK: vector.body:327; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]328; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8329; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2330; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0331; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]332; CHECK: exit:333; CHECK-NEXT: ret void334;335entry:336 %vscale = call i64 @llvm.vscale.i64()337 %shl = shl i64 %vscale, 6338 %urem = urem i64 %N, %shl339 br label %vector.body340 341vector.body:342 %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]343 store i64 0, ptr %p344 %iv.next = add i64 %iv, 2345 %done = icmp eq i64 %iv.next, %urem346 br i1 %done, label %exit, label %vector.body347 348exit:349 ret void350}351 352; Loop invariant does not neccessarily mean dominating the loop. Forming353; an ICmpZero from this example would be illegal even though the operands354; to the compare are loop invariant.355define void @loop_invariant_definition(i64 %arg) {356; CHECK-LABEL: @loop_invariant_definition(357; CHECK-NEXT: entry:358; CHECK-NEXT: br label [[T1:%.*]]359; CHECK: t1:360; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[T1]] ], [ -1, [[ENTRY:%.*]] ]361; CHECK-NEXT: [[LSR_IV_NEXT]] = add nsw i64 [[LSR_IV]], 1362; CHECK-NEXT: br i1 true, label [[T4:%.*]], label [[T1]]363; CHECK: t4:364; CHECK-NEXT: [[T5:%.*]] = trunc i64 [[LSR_IV_NEXT]] to i32365; CHECK-NEXT: [[T6:%.*]] = add i32 [[T5]], 1366; CHECK-NEXT: [[T7:%.*]] = icmp eq i32 [[T5]], [[T6]]367; CHECK-NEXT: ret void368;369entry:370 br label %t1371 372t1: ; preds = %1, %0373 %t2 = phi i64 [ %t3, %t1 ], [ 0, %entry ]374 %t3 = add nuw i64 %t2, 1375 br i1 true, label %t4, label %t1376 377t4: ; preds = %1378 %t5 = trunc i64 %t2 to i32379 %t6 = add i32 %t5, 1380 %t7 = icmp eq i32 %t5, %t6381 ret void382}383 384declare i64 @llvm.vscale.i64()385