1; RUN: opt -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp < %s -codegenprepare -S | FileCheck -check-prefix=CHECK %s 2 3define void @sink_add_mul(i32* %s1, i32 %x, i32* %d, i32 %n) { 4; CHECK-LABEL: @sink_add_mul( 5; CHECK: vector.ph: 6; CHECK-NOT: [[BROADCAST_SPLATINSERT8:%.*]] = insertelement <4 x i32> undef, i32 [[X:%.*]], i32 0 7; CHECK-NOT: [[BROADCAST_SPLAT9:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT8]], <4 x i32> undef, <4 x i32> zeroinitializer 8; CHECK: vector.body: 9; CHECK: [[TMP2:%.*]] = insertelement <4 x i32> undef, i32 [[X:%.*]], i32 0 10; CHECK: [[TMP3:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> undef, <4 x i32> zeroinitializer 11; 12entry: 13 %cmp6 = icmp sgt i32 %n, 0 14 br i1 %cmp6, label %vector.ph, label %for.cond.cleanup 15 16vector.ph: ; preds = %for.body.preheader 17 %n.vec = and i32 %n, -4 18 %broadcast.splatinsert8 = insertelement <4 x i32> undef, i32 %x, i32 0 19 %broadcast.splat9 = shufflevector <4 x i32> %broadcast.splatinsert8, <4 x i32> undef, <4 x i32> zeroinitializer 20 br label %vector.body 21 22vector.body: ; preds = %vector.body, %vector.ph 23 %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ] 24 %0 = getelementptr inbounds i32, i32* %s1, i32 %index 25 %1 = bitcast i32* %0 to <4 x i32>* 26 %wide.load = load <4 x i32>, <4 x i32>* %1, align 4 27 %2 = mul nsw <4 x i32> %wide.load, %broadcast.splat9 28 %3 = getelementptr inbounds i32, i32* %d, i32 %index 29 %4 = bitcast i32* %3 to <4 x i32>* 30 %wide.load10 = load <4 x i32>, <4 x i32>* %4, align 4 31 %5 = add nsw <4 x i32> %wide.load10, %2 32 %6 = bitcast i32* %3 to <4 x i32>* 33 store <4 x i32> %5, <4 x i32>* %6, align 4 34 %index.next = add i32 %index, 4 35 %7 = icmp eq i32 %index.next, %n.vec 36 br i1 %7, label %for.cond.cleanup, label %vector.body 37 38for.cond.cleanup: ; preds = %for.body, %middle.block, %entry 39 ret void 40} 41 42define void @sink_add_mul_multiple(i32* %s1, i32* %s2, i32 %x, i32* %d, i32* %d2, i32 %n) { 43; CHECK-LABEL: @sink_add_mul_multiple( 44; CHECK: vector.ph: 45; CHECK-NOT: [[BROADCAST_SPLATINSERT8:%.*]] = insertelement <4 x i32> undef, i32 [[X:%.*]], i32 0 46; CHECK-NOT: [[BROADCAST_SPLAT9:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT8]], <4 x i32> undef, <4 x i32> zeroinitializer 47; CHECK: vector.body: 48; CHECK: [[TMP2:%.*]] = insertelement <4 x i32> undef, i32 %x, i32 0 49; CHECK: [[TMP3:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> undef, <4 x i32> zeroinitializer 50; CHECK: mul nsw <4 x i32> %wide.load, [[TMP3]] 51; CHECK: [[TMP2b:%.*]] = insertelement <4 x i32> undef, i32 %x, i32 0 52; CHECK: [[TMP3b:%.*]] = shufflevector <4 x i32> [[TMP2b]], <4 x i32> undef, <4 x i32> zeroinitializer 53; CHECK: mul nsw <4 x i32> %wide.load18, [[TMP3b]] 54; 55entry: 56 %cmp13 = icmp sgt i32 %n, 0 57 br i1 %cmp13, label %vector.ph, label %for.cond.cleanup 58 59vector.ph: ; preds = %for.body.preheader 60 %n.vec = and i32 %n, -4 61 %broadcast.splatinsert15 = insertelement <4 x i32> undef, i32 %x, i32 0 62 %broadcast.splat16 = shufflevector <4 x i32> %broadcast.splatinsert15, <4 x i32> undef, <4 x i32> zeroinitializer 63 br label %vector.body 64 65vector.body: ; preds = %vector.body, %vector.ph 66 %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ] 67 %0 = getelementptr inbounds i32, i32* %s1, i32 %index 68 %1 = bitcast i32* %0 to <4 x i32>* 69 %wide.load = load <4 x i32>, <4 x i32>* %1, align 4 70 %2 = mul nsw <4 x i32> %wide.load, %broadcast.splat16 71 %3 = getelementptr inbounds i32, i32* %d, i32 %index 72 %4 = bitcast i32* %3 to <4 x i32>* 73 %wide.load17 = load <4 x i32>, <4 x i32>* %4, align 4 74 %5 = add nsw <4 x i32> %wide.load17, %2 75 %6 = bitcast i32* %3 to <4 x i32>* 76 store <4 x i32> %5, <4 x i32>* %6, align 4 77 %7 = getelementptr inbounds i32, i32* %s2, i32 %index 78 %8 = bitcast i32* %7 to <4 x i32>* 79 %wide.load18 = load <4 x i32>, <4 x i32>* %8, align 4 80 %9 = mul nsw <4 x i32> %wide.load18, %broadcast.splat16 81 %10 = getelementptr inbounds i32, i32* %d2, i32 %index 82 %11 = bitcast i32* %10 to <4 x i32>* 83 %wide.load19 = load <4 x i32>, <4 x i32>* %11, align 4 84 %12 = add nsw <4 x i32> %wide.load19, %9 85 %13 = bitcast i32* %10 to <4 x i32>* 86 store <4 x i32> %12, <4 x i32>* %13, align 4 87 %index.next = add i32 %index, 4 88 %14 = icmp eq i32 %index.next, %n.vec 89 br i1 %14, label %for.cond.cleanup, label %vector.body 90 91for.cond.cleanup: ; preds = %for.body, %middle.block, %entry 92 ret void 93} 94 95 96define void @sink_add_sub_unsinkable(i32* %s1, i32* %s2, i32 %x, i32* %d, i32* %d2, i32 %n) { 97; CHECK-LABEL: @sink_add_sub_unsinkable( 98; CHECK-NEXT: entry: 99; CHECK-NEXT: [[CMP13:%.*]] = icmp sgt i32 [[N:%.*]], 0 100; CHECK-NEXT: br i1 [[CMP13]], label [[VECTOR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]] 101; CHECK: vector.ph: 102; CHECK-NEXT: [[N_VEC:%.*]] = and i32 [[N]], -4 103; CHECK-NEXT: [[BROADCAST_SPLATINSERT15:%.*]] = insertelement <4 x i32> undef, i32 [[X:%.*]], i32 0 104; CHECK-NEXT: [[BROADCAST_SPLAT16:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT15]], <4 x i32> undef, <4 x i32> zeroinitializer 105; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 106; 107entry: 108 %cmp13 = icmp sgt i32 %n, 0 109 br i1 %cmp13, label %vector.ph, label %for.cond.cleanup 110 111vector.ph: ; preds = %for.body.preheader 112 %n.vec = and i32 %n, -4 113 %broadcast.splatinsert15 = insertelement <4 x i32> undef, i32 %x, i32 0 114 %broadcast.splat16 = shufflevector <4 x i32> %broadcast.splatinsert15, <4 x i32> undef, <4 x i32> zeroinitializer 115 br label %vector.body 116 117vector.body: ; preds = %vector.body, %vector.ph 118 %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ] 119 %0 = getelementptr inbounds i32, i32* %s1, i32 %index 120 %1 = bitcast i32* %0 to <4 x i32>* 121 %wide.load = load <4 x i32>, <4 x i32>* %1, align 4 122 %2 = mul nsw <4 x i32> %wide.load, %broadcast.splat16 123 %3 = getelementptr inbounds i32, i32* %d, i32 %index 124 %4 = bitcast i32* %3 to <4 x i32>* 125 %wide.load17 = load <4 x i32>, <4 x i32>* %4, align 4 126 %5 = add nsw <4 x i32> %wide.load17, %2 127 %6 = bitcast i32* %3 to <4 x i32>* 128 store <4 x i32> %5, <4 x i32>* %6, align 4 129 %7 = getelementptr inbounds i32, i32* %s2, i32 %index 130 %8 = bitcast i32* %7 to <4 x i32>* 131 %wide.load18 = load <4 x i32>, <4 x i32>* %8, align 4 132 %9 = sub nsw <4 x i32> %broadcast.splat16, %wide.load18 133 %10 = getelementptr inbounds i32, i32* %d2, i32 %index 134 %11 = bitcast i32* %10 to <4 x i32>* 135 %wide.load19 = load <4 x i32>, <4 x i32>* %11, align 4 136 %12 = add nsw <4 x i32> %wide.load19, %9 137 %13 = bitcast i32* %10 to <4 x i32>* 138 store <4 x i32> %12, <4 x i32>* %13, align 4 139 %index.next = add i32 %index, 4 140 %14 = icmp eq i32 %index.next, %n.vec 141 br i1 %14, label %for.cond.cleanup, label %vector.body 142 143for.cond.cleanup: ; preds = %for.body, %middle.block, %entry 144 ret void 145} 146 147define void @sink_sub(i32* %s1, i32 %x, i32* %d, i32 %n) { 148; CHECK-LABEL: @sink_sub( 149; CHECK: vector.ph: 150; CHECK-NOT: [[BROADCAST_SPLATINSERT8:%.*]] = insertelement <4 x i32> undef, i32 [[X:%.*]], i32 0 151; CHECK-NOT: [[BROADCAST_SPLAT9:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT8]], <4 x i32> undef, <4 x i32> zeroinitializer 152; CHECK: vector.body: 153; CHECK: [[TMP2:%.*]] = insertelement <4 x i32> undef, i32 [[X:%.*]], i32 0 154; CHECK: [[TMP3:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> undef, <4 x i32> zeroinitializer 155; 156entry: 157 %cmp6 = icmp sgt i32 %n, 0 158 br i1 %cmp6, label %vector.ph, label %for.cond.cleanup 159 160vector.ph: ; preds = %for.body.preheader 161 %n.vec = and i32 %n, -4 162 %broadcast.splatinsert8 = insertelement <4 x i32> undef, i32 %x, i32 0 163 %broadcast.splat9 = shufflevector <4 x i32> %broadcast.splatinsert8, <4 x i32> undef, <4 x i32> zeroinitializer 164 br label %vector.body 165 166vector.body: ; preds = %vector.body, %vector.ph 167 %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ] 168 %0 = getelementptr inbounds i32, i32* %s1, i32 %index 169 %1 = bitcast i32* %0 to <4 x i32>* 170 %wide.load = load <4 x i32>, <4 x i32>* %1, align 4 171 %2 = sub nsw <4 x i32> %wide.load, %broadcast.splat9 172 %3 = getelementptr inbounds i32, i32* %d, i32 %index 173 %4 = bitcast i32* %3 to <4 x i32>* 174 store <4 x i32> %2, <4 x i32>* %4, align 4 175 %index.next = add i32 %index, 4 176 %5 = icmp eq i32 %index.next, %n.vec 177 br i1 %5, label %for.cond.cleanup, label %vector.body 178 179for.cond.cleanup: ; preds = %for.body, %middle.block, %entry 180 ret void 181} 182 183define void @sink_sub_unsinkable(i32* %s1, i32 %x, i32* %d, i32 %n) { 184entry: 185; CHECK-LABEL: @sink_sub_unsinkable( 186; CHECK: vector.ph: 187; CHECK-NEXT: [[N_VEC:%.*]] = and i32 [[N]], -4 188; CHECK-NEXT: [[BROADCAST_SPLATINSERT15:%.*]] = insertelement <4 x i32> undef, i32 [[X:%.*]], i32 0 189; CHECK-NEXT: [[BROADCAST_SPLAT16:%.*]] = shufflevector <4 x i32> [[BROADCAST_SPLATINSERT15]], <4 x i32> undef, <4 x i32> zeroinitializer 190; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 191; CHECK: vector.body: 192; CHECK-NOT: [[TMP2:%.*]] = insertelement <4 x i32> undef, i32 [[X:%.*]], i32 0 193; CHECK-NOT: [[TMP3:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> undef, <4 x i32> zeroinitializer 194; 195 %cmp6 = icmp sgt i32 %n, 0 196 br i1 %cmp6, label %vector.ph, label %for.cond.cleanup 197 198vector.ph: ; preds = %for.body.preheader 199 %n.vec = and i32 %n, -4 200 %broadcast.splatinsert8 = insertelement <4 x i32> undef, i32 %x, i32 0 201 %broadcast.splat9 = shufflevector <4 x i32> %broadcast.splatinsert8, <4 x i32> undef, <4 x i32> zeroinitializer 202 br label %vector.body 203 204vector.body: ; preds = %vector.body, %vector.ph 205 %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ] 206 %0 = getelementptr inbounds i32, i32* %s1, i32 %index 207 %1 = bitcast i32* %0 to <4 x i32>* 208 %wide.load = load <4 x i32>, <4 x i32>* %1, align 4 209 %2 = sub nsw <4 x i32> %broadcast.splat9, %wide.load 210 %3 = getelementptr inbounds i32, i32* %d, i32 %index 211 %4 = bitcast i32* %3 to <4 x i32>* 212 store <4 x i32> %2, <4 x i32>* %4, align 4 213 %index.next = add i32 %index, 4 214 %5 = icmp eq i32 %index.next, %n.vec 215 br i1 %5, label %for.cond.cleanup, label %vector.body 216 217for.cond.cleanup: ; preds = %for.body, %middle.block, %entry 218 ret void 219} 220