1; REQUIRES: asserts 2 3; RUN: opt -passes=loop-vectorize -force-vector-interleave=2 -force-vector-width=1 -debug -disable-output %s 2>&1 | FileCheck %s 4 5target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" 6 7; Make sure recipes with side-effects are not sunk. 8define void @sink_with_sideeffects(i1 %c, ptr %ptr) { 9; CHECK-LABEL: sink_with_sideeffects 10; CHECK: VPlan 'Initial VPlan for VF={1},UF>=1' { 11; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF 12; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count 13; CHECK-NEXT: ir<1024> = original trip-count 14; CHECK-EMPTY: 15; CHECK-NEXT: ir-bb<entry>: 16; CHECK-NEXT: Successor(s): vector.ph 17; CHECK-EMPTY: 18; CHECK-NEXT: vector.ph: 19; CHECK-NEXT: vp<[[END:%.+]]> = DERIVED-IV ir<1024> + vp<[[VEC_TC]]> * ir<-1> 20; CHECK-NEXT: Successor(s): vector loop 21; CHECK-EMPTY: 22; CHECK-NEXT: <x1> vector loop: { 23; CHECK-NEXT: vector.body: 24; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION 25; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> 26; CHECK-NEXT: CLONE ir<%tmp2> = getelementptr ir<%ptr>, vp<[[STEPS]]> 27; CHECK-NEXT: CLONE ir<%tmp3> = load ir<%tmp2> 28; CHECK-NEXT: CLONE store ir<0>, ir<%tmp2> 29; CHECK-NEXT: Successor(s): pred.store 30 31; CHECK: <xVFxUF> pred.store: { 32; CHECK-NEXT: pred.store.entry: 33; CHECK-NEXT: BRANCH-ON-MASK ir<%c> 34; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue 35 36; CHECK: pred.store.if: 37; CHECK-NEXT: CLONE store ir<%tmp3>, ir<%tmp2> 38; CHECK-NEXT: Successor(s): pred.store.continue 39 40; CHECK: pred.store.continue: 41; CHECK-NEXT: No successors 42; CHECK-NEXT: } 43 44; CHECK: if.then.0: 45; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> 46; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> 47; CHECK-NEXT: No successors 48; CHECK-NEXT: } 49; CHECK-NEXT: Successor(s): middle.block 50; CHECK-EMPTY: 51; CHECK-NEXT: middle.block: 52; CHECK-NEXT: EMIT vp<[[CMP:%.+]]> = icmp eq ir<1024>, vp<[[VEC_TC]]> 53; CHECK-NEXT: EMIT branch-on-cond vp<[[CMP]]> 54; CHECK-NEXT: Successor(s): ir-bb<for.end>, scalar.ph 55; CHECK-EMPTY: 56; CHECK-NEXT: scalar.ph: 57; CHECK-NEXT: EMIT vp<[[RESUME1:%.+]]> = resume-phi vp<[[VEC_TC]]>, ir<0> 58; CHECK-NEXT: EMIT vp<[[RESUME2:%.+]]>.1 = resume-phi vp<[[END]]>, ir<1024> 59; CHECK-NEXT: Successor(s): ir-bb<for.body> 60; CHECK-EMPTY: 61; CHECK-NEXT: ir-bb<for.body>: 62; CHECK-NEXT: IR %tmp0 = phi i64 [ %tmp6, %for.inc ], [ 0, %entry ] (extra operand: vp<[[RESUME1]]> from scalar.ph) 63; CHECK-NEXT: IR %tmp1 = phi i64 [ %tmp7, %for.inc ], [ 1024, %entry ] (extra operand: vp<[[RESUME2]]>.1 from scalar.ph) 64; CHECK: IR %tmp5 = trunc i32 %tmp4 to i8 65; CHECK-NEXT: No successors 66; CHECK-EMPTY: 67; CHECK-NEXT: ir-bb<for.end>: 68; CHECK-NEXT: No successors 69; CHECK-NEXT: } 70; 71entry: 72 br label %for.body 73 74for.body: 75 %tmp0 = phi i64 [ %tmp6, %for.inc ], [ 0, %entry ] 76 %tmp1 = phi i64 [ %tmp7, %for.inc ], [ 1024, %entry ] 77 %tmp2 = getelementptr i8, ptr %ptr, i64 %tmp0 78 %tmp3 = load i8, ptr %tmp2, align 1 79 store i8 0, ptr %tmp2 80 %tmp4 = zext i8 %tmp3 to i32 81 %tmp5 = trunc i32 %tmp4 to i8 82 br i1 %c, label %if.then, label %for.inc 83 84if.then: 85 store i8 %tmp5, ptr %tmp2, align 1 86 br label %for.inc 87 88for.inc: 89 %tmp6 = add nuw nsw i64 %tmp0, 1 90 %tmp7 = add i64 %tmp1, -1 91 %tmp8 = icmp eq i64 %tmp7, 0 92 br i1 %tmp8, label %for.end, label %for.body 93 94for.end: 95 ret void 96} 97