635 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -o - -S -passes=load-store-vectorizer,dce %s | FileCheck %s3 4; Make sure LoadStoreVectorizer vectorizes the loads below.5; In order to prove that the vectorization is safe, it tries to6; match nested adds and find an expression that adds a constant7; value to an existing index and the result doesn't overflow.8 9target triple = "x86_64--"10 11define void @ld_v4i8_add_nsw(i32 %v0, i32 %v1, ptr %src, ptr %dst) {12; CHECK-LABEL: @ld_v4i8_add_nsw(13; CHECK-NEXT: bb:14; CHECK-NEXT: [[TMP:%.*]] = add nsw i32 [[V0:%.*]], -115; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[V1:%.*]], [[TMP]]16; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i6417; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP2]]18; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[TMP3]], align 119; CHECK-NEXT: [[TMP41:%.*]] = extractelement <4 x i8> [[TMP1]], i32 020; CHECK-NEXT: [[TMP82:%.*]] = extractelement <4 x i8> [[TMP1]], i32 121; CHECK-NEXT: [[TMP133:%.*]] = extractelement <4 x i8> [[TMP1]], i32 222; CHECK-NEXT: [[TMP184:%.*]] = extractelement <4 x i8> [[TMP1]], i32 323; CHECK-NEXT: [[TMP19:%.*]] = insertelement <4 x i8> undef, i8 [[TMP41]], i32 024; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i8> [[TMP19]], i8 [[TMP82]], i32 125; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP20]], i8 [[TMP133]], i32 226; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i8> [[TMP21]], i8 [[TMP184]], i32 327; CHECK-NEXT: store <4 x i8> [[TMP22]], ptr [[DST:%.*]]28; CHECK-NEXT: ret void29;30bb:31 %tmp = add nsw i32 %v0, -132 %tmp1 = add nsw i32 %v1, %tmp33 %tmp2 = sext i32 %tmp1 to i6434 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp235 %tmp4 = load i8, ptr %tmp3, align 136 %tmp5 = add nsw i32 %v1, %v037 %tmp6 = sext i32 %tmp5 to i6438 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp639 %tmp8 = load i8, ptr %tmp7, align 140 %tmp9 = add nsw i32 %v0, 141 %tmp10 = add nsw i32 %v1, %tmp942 %tmp11 = sext i32 %tmp10 to i6443 %tmp12 = getelementptr inbounds i8, ptr %src, i64 %tmp1144 %tmp13 = load i8, ptr %tmp12, align 145 %tmp14 = add nsw i32 %v0, 246 %tmp15 = add nsw i32 %v1, %tmp1447 %tmp16 = sext i32 %tmp15 to i6448 %tmp17 = getelementptr inbounds i8, ptr %src, i64 %tmp1649 %tmp18 = load i8, ptr %tmp17, align 150 %tmp19 = insertelement <4 x i8> undef, i8 %tmp4, i32 051 %tmp20 = insertelement <4 x i8> %tmp19, i8 %tmp8, i32 152 %tmp21 = insertelement <4 x i8> %tmp20, i8 %tmp13, i32 253 %tmp22 = insertelement <4 x i8> %tmp21, i8 %tmp18, i32 354 store <4 x i8> %tmp22, ptr %dst55 ret void56}57 58; Apply different operand orders for the nested add sequences59define void @ld_v4i8_add_nsw_operand_orders(i32 %v0, i32 %v1, ptr %src, ptr %dst) {60; CHECK-LABEL: @ld_v4i8_add_nsw_operand_orders(61; CHECK-NEXT: bb:62; CHECK-NEXT: [[TMP:%.*]] = add nsw i32 [[V0:%.*]], -163; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[V1:%.*]], [[TMP]]64; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i6465; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP2]]66; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[TMP3]], align 167; CHECK-NEXT: [[TMP41:%.*]] = extractelement <4 x i8> [[TMP1]], i32 068; CHECK-NEXT: [[TMP82:%.*]] = extractelement <4 x i8> [[TMP1]], i32 169; CHECK-NEXT: [[TMP133:%.*]] = extractelement <4 x i8> [[TMP1]], i32 270; CHECK-NEXT: [[TMP184:%.*]] = extractelement <4 x i8> [[TMP1]], i32 371; CHECK-NEXT: [[TMP19:%.*]] = insertelement <4 x i8> undef, i8 [[TMP41]], i32 072; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i8> [[TMP19]], i8 [[TMP82]], i32 173; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP20]], i8 [[TMP133]], i32 274; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i8> [[TMP21]], i8 [[TMP184]], i32 375; CHECK-NEXT: store <4 x i8> [[TMP22]], ptr [[DST:%.*]]76; CHECK-NEXT: ret void77;78bb:79 %tmp = add nsw i32 %v0, -180 %tmp1 = add nsw i32 %v1, %tmp81 %tmp2 = sext i32 %tmp1 to i6482 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp283 %tmp4 = load i8, ptr %tmp3, align 184 %tmp5 = add nsw i32 %v0, %v185 %tmp6 = sext i32 %tmp5 to i6486 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp687 %tmp8 = load i8, ptr %tmp7, align 188 %tmp9 = add nsw i32 %v0, 189 %tmp10 = add nsw i32 %tmp9, %v190 %tmp11 = sext i32 %tmp10 to i6491 %tmp12 = getelementptr inbounds i8, ptr %src, i64 %tmp1192 %tmp13 = load i8, ptr %tmp12, align 193 %tmp14 = add nsw i32 %v0, 294 %tmp15 = add nsw i32 %v1, %tmp1495 %tmp16 = sext i32 %tmp15 to i6496 %tmp17 = getelementptr inbounds i8, ptr %src, i64 %tmp1697 %tmp18 = load i8, ptr %tmp17, align 198 %tmp19 = insertelement <4 x i8> undef, i8 %tmp4, i32 099 %tmp20 = insertelement <4 x i8> %tmp19, i8 %tmp8, i32 1100 %tmp21 = insertelement <4 x i8> %tmp20, i8 %tmp13, i32 2101 %tmp22 = insertelement <4 x i8> %tmp21, i8 %tmp18, i32 3102 store <4 x i8> %tmp22, ptr %dst103 ret void104}105 106define void @ld_v4i8_add_known_bits(i32 %ind0, i32 %ind1, ptr %src, ptr %dst) {107; CHECK-LABEL: @ld_v4i8_add_known_bits(108; CHECK-NEXT: bb:109; CHECK-NEXT: [[V0:%.*]] = mul i32 [[IND0:%.*]], 4110; CHECK-NEXT: [[V1:%.*]] = mul i32 [[IND1:%.*]], 4111; CHECK-NEXT: [[TMP:%.*]] = add i32 [[V0]], -1112; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[V1]], [[TMP]]113; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64114; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP2]]115; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1116; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]117; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64118; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[TMP6]]119; CHECK-NEXT: [[TMP1:%.*]] = load <3 x i8>, ptr [[TMP7]], align 1120; CHECK-NEXT: [[TMP81:%.*]] = extractelement <3 x i8> [[TMP1]], i32 0121; CHECK-NEXT: [[TMP132:%.*]] = extractelement <3 x i8> [[TMP1]], i32 1122; CHECK-NEXT: [[TMP183:%.*]] = extractelement <3 x i8> [[TMP1]], i32 2123; CHECK-NEXT: [[TMP19:%.*]] = insertelement <4 x i8> undef, i8 [[TMP4]], i32 0124; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i8> [[TMP19]], i8 [[TMP81]], i32 1125; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP20]], i8 [[TMP132]], i32 2126; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i8> [[TMP21]], i8 [[TMP183]], i32 3127; CHECK-NEXT: store <4 x i8> [[TMP22]], ptr [[DST:%.*]]128; CHECK-NEXT: ret void129;130bb:131 %v0 = mul i32 %ind0, 4132 %v1 = mul i32 %ind1, 4133 %tmp = add i32 %v0, -1134 %tmp1 = add i32 %v1, %tmp135 %tmp2 = sext i32 %tmp1 to i64136 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2137 %tmp4 = load i8, ptr %tmp3, align 1138 %tmp5 = add i32 %v1, %v0139 %tmp6 = sext i32 %tmp5 to i64140 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6141 %tmp8 = load i8, ptr %tmp7, align 1142 %tmp9 = add i32 %v0, 1143 %tmp10 = add i32 %v1, %tmp9144 %tmp11 = sext i32 %tmp10 to i64145 %tmp12 = getelementptr inbounds i8, ptr %src, i64 %tmp11146 %tmp13 = load i8, ptr %tmp12, align 1147 %tmp14 = add i32 %v0, 2148 %tmp15 = add i32 %v1, %tmp14149 %tmp16 = sext i32 %tmp15 to i64150 %tmp17 = getelementptr inbounds i8, ptr %src, i64 %tmp16151 %tmp18 = load i8, ptr %tmp17, align 1152 %tmp19 = insertelement <4 x i8> undef, i8 %tmp4, i32 0153 %tmp20 = insertelement <4 x i8> %tmp19, i8 %tmp8, i32 1154 %tmp21 = insertelement <4 x i8> %tmp20, i8 %tmp13, i32 2155 %tmp22 = insertelement <4 x i8> %tmp21, i8 %tmp18, i32 3156 store <4 x i8> %tmp22, ptr %dst157 ret void158}159 160define void @ld_v4i8_add_known_bits1(i32 %ind0, i32 %ind1, ptr %src, ptr %dst) {161; CHECK-LABEL: @ld_v4i8_add_known_bits1(162; CHECK-NEXT: bb:163; CHECK-NEXT: [[V0:%.*]] = mul i32 [[IND0:%.*]], 4164; CHECK-NEXT: [[V1:%.*]] = mul i32 [[IND1:%.*]], 4165; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]166; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64167; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP6]]168; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[TMP7]], align 1169; CHECK-NEXT: [[TMP81:%.*]] = extractelement <4 x i8> [[TMP1]], i32 0170; CHECK-NEXT: [[TMP132:%.*]] = extractelement <4 x i8> [[TMP1]], i32 1171; CHECK-NEXT: [[TMP183:%.*]] = extractelement <4 x i8> [[TMP1]], i32 2172; CHECK-NEXT: [[TMP44:%.*]] = extractelement <4 x i8> [[TMP1]], i32 3173; CHECK-NEXT: [[TMP19:%.*]] = insertelement <4 x i8> undef, i8 [[TMP44]], i32 0174; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i8> [[TMP19]], i8 [[TMP81]], i32 1175; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP20]], i8 [[TMP132]], i32 2176; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i8> [[TMP21]], i8 [[TMP183]], i32 3177; CHECK-NEXT: store <4 x i8> [[TMP22]], ptr [[DST:%.*]]178; CHECK-NEXT: ret void179;180bb:181 %v0 = mul i32 %ind0, 4182 %v1 = mul i32 %ind1, 4183 %tmp = add i32 %v0, 3184 %tmp1 = add i32 %v1, %tmp185 %tmp2 = sext i32 %tmp1 to i64186 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2187 %tmp4 = load i8, ptr %tmp3, align 1188 %tmp5 = add i32 %v1, %v0189 %tmp6 = sext i32 %tmp5 to i64190 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6191 %tmp8 = load i8, ptr %tmp7, align 1192 %tmp9 = add i32 %v0, 1193 %tmp10 = add i32 %v1, %tmp9194 %tmp11 = sext i32 %tmp10 to i64195 %tmp12 = getelementptr inbounds i8, ptr %src, i64 %tmp11196 %tmp13 = load i8, ptr %tmp12, align 1197 %tmp14 = add i32 %v0, 2198 %tmp15 = add i32 %v1, %tmp14199 %tmp16 = sext i32 %tmp15 to i64200 %tmp17 = getelementptr inbounds i8, ptr %src, i64 %tmp16201 %tmp18 = load i8, ptr %tmp17, align 1202 %tmp19 = insertelement <4 x i8> undef, i8 %tmp4, i32 0203 %tmp20 = insertelement <4 x i8> %tmp19, i8 %tmp8, i32 1204 %tmp21 = insertelement <4 x i8> %tmp20, i8 %tmp13, i32 2205 %tmp22 = insertelement <4 x i8> %tmp21, i8 %tmp18, i32 3206 store <4 x i8> %tmp22, ptr %dst207 ret void208}209 210define void @ld_v4i8_add_known_bits_by_assume(i32 %ind0, i32 %ind1, ptr %src, ptr %dst) {211; CHECK-LABEL: @ld_v4i8_add_known_bits_by_assume(212; CHECK-NEXT: bb:213; CHECK-NEXT: [[V0:%.*]] = mul i32 [[IND0:%.*]], 3214; CHECK-NEXT: [[V1:%.*]] = mul i32 [[IND1:%.*]], 3215; CHECK-NEXT: [[AND_I:%.*]] = and i32 [[V0]], 3216; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq i32 [[AND_I]], 0217; CHECK-NEXT: [[AND_I_1:%.*]] = and i32 [[V1]], 3218; CHECK-NEXT: [[CMP_I_1:%.*]] = icmp eq i32 [[AND_I_1]], 0219; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_I]])220; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_I_1]])221; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]222; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64223; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP6]]224; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[TMP7]], align 1225; CHECK-NEXT: [[TMP81:%.*]] = extractelement <4 x i8> [[TMP1]], i32 0226; CHECK-NEXT: [[TMP132:%.*]] = extractelement <4 x i8> [[TMP1]], i32 1227; CHECK-NEXT: [[TMP183:%.*]] = extractelement <4 x i8> [[TMP1]], i32 2228; CHECK-NEXT: [[TMP44:%.*]] = extractelement <4 x i8> [[TMP1]], i32 3229; CHECK-NEXT: [[TMP19:%.*]] = insertelement <4 x i8> undef, i8 [[TMP44]], i32 0230; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i8> [[TMP19]], i8 [[TMP81]], i32 1231; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP20]], i8 [[TMP132]], i32 2232; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i8> [[TMP21]], i8 [[TMP183]], i32 3233; CHECK-NEXT: store <4 x i8> [[TMP22]], ptr [[DST:%.*]]234; CHECK-NEXT: ret void235;236bb:237 %v0 = mul i32 %ind0, 3238 %v1 = mul i32 %ind1, 3239 %and.i = and i32 %v0, 3240 %cmp.i = icmp eq i32 %and.i, 0241 %and.i.1 = and i32 %v1, 3242 %cmp.i.1 = icmp eq i32 %and.i.1, 0243 call void @llvm.assume(i1 %cmp.i)244 call void @llvm.assume(i1 %cmp.i.1)245 %tmp = add i32 %v0, 3246 %tmp1 = add i32 %v1, %tmp247 %tmp2 = sext i32 %tmp1 to i64248 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2249 %tmp4 = load i8, ptr %tmp3, align 1250 %tmp5 = add i32 %v1, %v0251 %tmp6 = sext i32 %tmp5 to i64252 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6253 %tmp8 = load i8, ptr %tmp7, align 1254 %tmp9 = add i32 %v0, 1255 %tmp10 = add i32 %v1, %tmp9256 %tmp11 = sext i32 %tmp10 to i64257 %tmp12 = getelementptr inbounds i8, ptr %src, i64 %tmp11258 %tmp13 = load i8, ptr %tmp12, align 1259 %tmp14 = add i32 %v0, 2260 %tmp15 = add i32 %v1, %tmp14261 %tmp16 = sext i32 %tmp15 to i64262 %tmp17 = getelementptr inbounds i8, ptr %src, i64 %tmp16263 %tmp18 = load i8, ptr %tmp17, align 1264 %tmp19 = insertelement <4 x i8> undef, i8 %tmp4, i32 0265 %tmp20 = insertelement <4 x i8> %tmp19, i8 %tmp8, i32 1266 %tmp21 = insertelement <4 x i8> %tmp20, i8 %tmp13, i32 2267 %tmp22 = insertelement <4 x i8> %tmp21, i8 %tmp18, i32 3268 store <4 x i8> %tmp22, ptr %dst269 ret void270}271 272declare void @llvm.assume(i1)273 274define void @ld_v4i8_add_assume_on_arg(i32 %v0, i32 %v1, ptr %src, ptr %dst) {275; CHECK-LABEL: @ld_v4i8_add_assume_on_arg(276; CHECK-NEXT: bb:277; CHECK-NEXT: [[AND_I:%.*]] = and i32 [[V0:%.*]], 3278; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq i32 [[AND_I]], 0279; CHECK-NEXT: [[AND_I_1:%.*]] = and i32 [[V1:%.*]], 3280; CHECK-NEXT: [[CMP_I_1:%.*]] = icmp eq i32 [[AND_I_1]], 0281; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_I]])282; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_I_1]])283; CHECK-NEXT: [[TMP:%.*]] = add nsw i32 [[V0]], -1284; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[V1]], [[TMP]]285; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64286; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP2]]287; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1288; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]289; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64290; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[TMP6]]291; CHECK-NEXT: [[TMP1:%.*]] = load <3 x i8>, ptr [[TMP7]], align 1292; CHECK-NEXT: [[TMP81:%.*]] = extractelement <3 x i8> [[TMP1]], i32 0293; CHECK-NEXT: [[TMP132:%.*]] = extractelement <3 x i8> [[TMP1]], i32 1294; CHECK-NEXT: [[TMP183:%.*]] = extractelement <3 x i8> [[TMP1]], i32 2295; CHECK-NEXT: [[TMP19:%.*]] = insertelement <4 x i8> undef, i8 [[TMP4]], i32 0296; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i8> [[TMP19]], i8 [[TMP81]], i32 1297; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP20]], i8 [[TMP132]], i32 2298; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i8> [[TMP21]], i8 [[TMP183]], i32 3299; CHECK-NEXT: store <4 x i8> [[TMP22]], ptr [[DST:%.*]]300; CHECK-NEXT: ret void301;302bb:303 %and.i = and i32 %v0, 3304 %cmp.i = icmp eq i32 %and.i, 0305 %and.i.1 = and i32 %v1, 3306 %cmp.i.1 = icmp eq i32 %and.i.1, 0307 call void @llvm.assume(i1 %cmp.i)308 call void @llvm.assume(i1 %cmp.i.1)309 %tmp = add nsw i32 %v0, -1310 %tmp1 = add i32 %v1, %tmp311 %tmp2 = sext i32 %tmp1 to i64312 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2313 %tmp4 = load i8, ptr %tmp3, align 1314 %tmp5 = add i32 %v1, %v0315 %tmp6 = sext i32 %tmp5 to i64316 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6317 %tmp8 = load i8, ptr %tmp7, align 1318 %tmp9 = add nsw i32 %v0, 1319 %tmp10 = add i32 %v1, %tmp9320 %tmp11 = sext i32 %tmp10 to i64321 %tmp12 = getelementptr inbounds i8, ptr %src, i64 %tmp11322 %tmp13 = load i8, ptr %tmp12, align 1323 %tmp14 = add nsw i32 %v0, 2324 %tmp15 = add i32 %v1, %tmp14325 %tmp16 = sext i32 %tmp15 to i64326 %tmp17 = getelementptr inbounds i8, ptr %src, i64 %tmp16327 %tmp18 = load i8, ptr %tmp17, align 1328 %tmp19 = insertelement <4 x i8> undef, i8 %tmp4, i32 0329 %tmp20 = insertelement <4 x i8> %tmp19, i8 %tmp8, i32 1330 %tmp21 = insertelement <4 x i8> %tmp20, i8 %tmp13, i32 2331 %tmp22 = insertelement <4 x i8> %tmp21, i8 %tmp18, i32 3332 store <4 x i8> %tmp22, ptr %dst333 ret void334}335 336define void @ld_v4i8_add_assume_on_arg1(i32 %v0, i32 %v1, ptr %src, ptr %dst) {337; CHECK-LABEL: @ld_v4i8_add_assume_on_arg1(338; CHECK-NEXT: bb:339; CHECK-NEXT: [[AND_I:%.*]] = and i32 [[V0:%.*]], 3340; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq i32 [[AND_I]], 0341; CHECK-NEXT: [[AND_I_1:%.*]] = and i32 [[V1:%.*]], 3342; CHECK-NEXT: [[CMP_I_1:%.*]] = icmp eq i32 [[AND_I_1]], 0343; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_I]])344; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_I_1]])345; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]346; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64347; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP6]]348; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[TMP7]], align 1349; CHECK-NEXT: [[TMP81:%.*]] = extractelement <4 x i8> [[TMP1]], i32 0350; CHECK-NEXT: [[TMP132:%.*]] = extractelement <4 x i8> [[TMP1]], i32 1351; CHECK-NEXT: [[TMP183:%.*]] = extractelement <4 x i8> [[TMP1]], i32 2352; CHECK-NEXT: [[TMP44:%.*]] = extractelement <4 x i8> [[TMP1]], i32 3353; CHECK-NEXT: [[TMP19:%.*]] = insertelement <4 x i8> undef, i8 [[TMP44]], i32 0354; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i8> [[TMP19]], i8 [[TMP81]], i32 1355; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP20]], i8 [[TMP132]], i32 2356; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i8> [[TMP21]], i8 [[TMP183]], i32 3357; CHECK-NEXT: store <4 x i8> [[TMP22]], ptr [[DST:%.*]]358; CHECK-NEXT: ret void359;360bb:361 %and.i = and i32 %v0, 3362 %cmp.i = icmp eq i32 %and.i, 0363 %and.i.1 = and i32 %v1, 3364 %cmp.i.1 = icmp eq i32 %and.i.1, 0365 call void @llvm.assume(i1 %cmp.i)366 call void @llvm.assume(i1 %cmp.i.1)367 %tmp = add nsw i32 %v0, 3368 %tmp1 = add i32 %v1, %tmp369 %tmp2 = sext i32 %tmp1 to i64370 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2371 %tmp4 = load i8, ptr %tmp3, align 1372 %tmp5 = add i32 %v1, %v0373 %tmp6 = sext i32 %tmp5 to i64374 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6375 %tmp8 = load i8, ptr %tmp7, align 1376 %tmp9 = add nsw i32 %v0, 1377 %tmp10 = add i32 %v1, %tmp9378 %tmp11 = sext i32 %tmp10 to i64379 %tmp12 = getelementptr inbounds i8, ptr %src, i64 %tmp11380 %tmp13 = load i8, ptr %tmp12, align 1381 %tmp14 = add nsw i32 %v0, 2382 %tmp15 = add i32 %v1, %tmp14383 %tmp16 = sext i32 %tmp15 to i64384 %tmp17 = getelementptr inbounds i8, ptr %src, i64 %tmp16385 %tmp18 = load i8, ptr %tmp17, align 1386 %tmp19 = insertelement <4 x i8> undef, i8 %tmp4, i32 0387 %tmp20 = insertelement <4 x i8> %tmp19, i8 %tmp8, i32 1388 %tmp21 = insertelement <4 x i8> %tmp20, i8 %tmp13, i32 2389 %tmp22 = insertelement <4 x i8> %tmp21, i8 %tmp18, i32 3390 store <4 x i8> %tmp22, ptr %dst391 ret void392}393 394; Address computations are partly separated by control flow and with llvm.assume placed395; in the second basic block396 397define void @ld_v2i8_add_different_contexts(i32 %ind0, i32 %ind1, ptr %src, ptr %dst) {398; CHECK-LABEL: @ld_v2i8_add_different_contexts(399; CHECK-NEXT: bb:400; CHECK-NEXT: [[V0:%.*]] = mul i32 [[IND0:%.*]], 4401; CHECK-NEXT: [[V1:%.*]] = mul i32 [[IND1:%.*]], 3402; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]403; CHECK-NEXT: [[BIT_COND:%.*]] = icmp eq i32 [[V1]], 0404; CHECK-NEXT: br i1 [[BIT_COND]], label [[BB_LOADS:%.*]], label [[BB_SKIP:%.*]]405; CHECK: bb.loads:406; CHECK-NEXT: call void @llvm.assume(i1 [[BIT_COND]])407; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64408; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP6]]409; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[TMP7]], align 1410; CHECK-NEXT: [[TMP81:%.*]] = extractelement <2 x i8> [[TMP1]], i32 0411; CHECK-NEXT: [[TMP42:%.*]] = extractelement <2 x i8> [[TMP1]], i32 1412; CHECK-NEXT: [[TMP19:%.*]] = insertelement <2 x i8> undef, i8 [[TMP42]], i32 0413; CHECK-NEXT: [[TMP20:%.*]] = insertelement <2 x i8> [[TMP19]], i8 [[TMP81]], i32 1414; CHECK-NEXT: store <2 x i8> [[TMP20]], ptr [[DST:%.*]]415; CHECK-NEXT: br label [[BB_SKIP]]416; CHECK: bb.skip:417; CHECK-NEXT: ret void418;419bb:420 %v0 = mul i32 %ind0, 4421 %v1 = mul i32 %ind1, 3422 %tmp5 = add i32 %v1, %v0423 %bit_cond = icmp eq i32 %v1, 0424 br i1 %bit_cond, label %bb.loads, label %bb.skip425 426bb.loads:427 call void @llvm.assume(i1 %bit_cond)428 %tmp = add nsw i32 %v0, 1429 %tmp1 = add i32 %v1, %tmp430 %tmp2 = sext i32 %tmp1 to i64431 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2432 %tmp4 = load i8, ptr %tmp3, align 1433 %tmp6 = sext i32 %tmp5 to i64434 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6435 %tmp8 = load i8, ptr %tmp7, align 1436 %tmp19 = insertelement <2 x i8> undef, i8 %tmp4, i32 0437 %tmp20 = insertelement <2 x i8> %tmp19, i8 %tmp8, i32 1438 store <2 x i8> %tmp20, ptr %dst439 br label %bb.skip440 441bb.skip:442 ret void443}444 445; Same as ld_v2i8_add_different_contexts but with llvm.assume placed between loads446 447define void @ld_v2i8_add_different_contexts1(i32 %ind0, i32 %ind1, ptr %src, ptr %dst) {448; CHECK-LABEL: @ld_v2i8_add_different_contexts1(449; CHECK-NEXT: bb:450; CHECK-NEXT: [[V0:%.*]] = mul i32 [[IND0:%.*]], 4451; CHECK-NEXT: [[V1:%.*]] = mul i32 [[IND1:%.*]], 3452; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]453; CHECK-NEXT: [[BIT_COND:%.*]] = icmp eq i32 [[V1]], 0454; CHECK-NEXT: br i1 [[BIT_COND]], label [[BB_LOADS:%.*]], label [[BB_SKIP:%.*]]455; CHECK: bb.loads:456; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64457; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP6]]458; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[TMP7]], align 1459; CHECK-NEXT: [[TMP81:%.*]] = extractelement <2 x i8> [[TMP1]], i32 0460; CHECK-NEXT: [[TMP42:%.*]] = extractelement <2 x i8> [[TMP1]], i32 1461; CHECK-NEXT: call void @llvm.assume(i1 [[BIT_COND]])462; CHECK-NEXT: [[TMP19:%.*]] = insertelement <2 x i8> undef, i8 [[TMP42]], i32 0463; CHECK-NEXT: [[TMP20:%.*]] = insertelement <2 x i8> [[TMP19]], i8 [[TMP81]], i32 1464; CHECK-NEXT: store <2 x i8> [[TMP20]], ptr [[DST:%.*]]465; CHECK-NEXT: br label [[BB_SKIP]]466; CHECK: bb.skip:467; CHECK-NEXT: ret void468;469bb:470 %v0 = mul i32 %ind0, 4471 %v1 = mul i32 %ind1, 3472 %tmp5 = add i32 %v1, %v0473 %bit_cond = icmp eq i32 %v1, 0474 br i1 %bit_cond, label %bb.loads, label %bb.skip475 476bb.loads:477 %tmp6 = sext i32 %tmp5 to i64478 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6479 %tmp8 = load i8, ptr %tmp7, align 1480 call void @llvm.assume(i1 %bit_cond)481 %tmp = add nsw i32 %v0, 1482 %tmp1 = add i32 %v1, %tmp483 %tmp2 = sext i32 %tmp1 to i64484 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2485 %tmp4 = load i8, ptr %tmp3, align 1486 %tmp19 = insertelement <2 x i8> undef, i8 %tmp4, i32 0487 %tmp20 = insertelement <2 x i8> %tmp19, i8 %tmp8, i32 1488 store <2 x i8> %tmp20, ptr %dst489 br label %bb.skip490 491bb.skip:492 ret void493}494 495; llvm.assume is placed between loads in a single basic block496 497define void @ld_v2i8_add_context(i32 %ind0, i32 %ind1, ptr %src, ptr %dst) {498; CHECK-LABEL: @ld_v2i8_add_context(499; CHECK-NEXT: bb:500; CHECK-NEXT: [[V0:%.*]] = mul i32 [[IND0:%.*]], 4501; CHECK-NEXT: [[V1:%.*]] = mul i32 [[IND1:%.*]], 3502; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]503; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64504; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP6]]505; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[TMP7]], align 1506; CHECK-NEXT: [[TMP81:%.*]] = extractelement <2 x i8> [[TMP1]], i32 0507; CHECK-NEXT: [[TMP42:%.*]] = extractelement <2 x i8> [[TMP1]], i32 1508; CHECK-NEXT: [[BIT_COND:%.*]] = icmp eq i32 [[TMP5]], 0509; CHECK-NEXT: call void @llvm.assume(i1 [[BIT_COND]])510; CHECK-NEXT: [[TMP19:%.*]] = insertelement <2 x i8> undef, i8 [[TMP42]], i32 0511; CHECK-NEXT: [[TMP20:%.*]] = insertelement <2 x i8> [[TMP19]], i8 [[TMP81]], i32 1512; CHECK-NEXT: store <2 x i8> [[TMP20]], ptr [[DST:%.*]]513; CHECK-NEXT: ret void514;515bb:516 %v0 = mul i32 %ind0, 4517 %v1 = mul i32 %ind1, 3518 %tmp5 = add i32 %v1, %v0519 %tmp6 = sext i32 %tmp5 to i64520 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6521 %tmp8 = load i8, ptr %tmp7, align 1522 %bit_cond = icmp eq i32 %tmp5, 0523 call void @llvm.assume(i1 %bit_cond)524 %tmp = add nsw i32 %v0, 1525 %tmp1 = add i32 %v1, %tmp526 %tmp2 = sext i32 %tmp1 to i64527 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2528 %tmp4 = load i8, ptr %tmp3, align 1529 %tmp19 = insertelement <2 x i8> undef, i8 %tmp4, i32 0530 %tmp20 = insertelement <2 x i8> %tmp19, i8 %tmp8, i32 1531 store <2 x i8> %tmp20, ptr %dst532 ret void533}534 535; Placing llvm.assume after all the loads and stores in the basic block still works536 537define void @ld_v2i8_add_context1(i32 %ind0, i32 %ind1, ptr %src, ptr %dst) {538; CHECK-LABEL: @ld_v2i8_add_context1(539; CHECK-NEXT: bb:540; CHECK-NEXT: [[V0:%.*]] = mul i32 [[IND0:%.*]], 4541; CHECK-NEXT: [[V1:%.*]] = mul i32 [[IND1:%.*]], 3542; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]543; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64544; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP6]]545; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[TMP7]], align 1546; CHECK-NEXT: [[TMP81:%.*]] = extractelement <2 x i8> [[TMP1]], i32 0547; CHECK-NEXT: [[TMP42:%.*]] = extractelement <2 x i8> [[TMP1]], i32 1548; CHECK-NEXT: [[TMP19:%.*]] = insertelement <2 x i8> undef, i8 [[TMP42]], i32 0549; CHECK-NEXT: [[TMP20:%.*]] = insertelement <2 x i8> [[TMP19]], i8 [[TMP81]], i32 1550; CHECK-NEXT: store <2 x i8> [[TMP20]], ptr [[DST:%.*]]551; CHECK-NEXT: [[BIT_COND:%.*]] = icmp eq i32 [[TMP5]], 0552; CHECK-NEXT: call void @llvm.assume(i1 [[BIT_COND]])553; CHECK-NEXT: ret void554;555bb:556 %v0 = mul i32 %ind0, 4557 %v1 = mul i32 %ind1, 3558 %tmp5 = add i32 %v1, %v0559 %tmp6 = sext i32 %tmp5 to i64560 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6561 %tmp8 = load i8, ptr %tmp7, align 1562 %tmp = add nsw i32 %v0, 1563 %tmp1 = add i32 %v1, %tmp564 %tmp2 = sext i32 %tmp1 to i64565 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2566 %tmp4 = load i8, ptr %tmp3, align 1567 %tmp19 = insertelement <2 x i8> undef, i8 %tmp4, i32 0568 %tmp20 = insertelement <2 x i8> %tmp19, i8 %tmp8, i32 1569 store <2 x i8> %tmp20, ptr %dst570 %bit_cond = icmp eq i32 %tmp5, 0571 call void @llvm.assume(i1 %bit_cond)572 ret void573}574 575; Make sure we don't vectorize the loads below because the source of576; sext instructions doesn't have the nsw flag or known bits allowing577; to apply the vectorization.578 579define void @ld_v4i8_add_not_safe(i32 %v0, i32 %v1, ptr %src, ptr %dst) {580; CHECK-LABEL: @ld_v4i8_add_not_safe(581; CHECK-NEXT: bb:582; CHECK-NEXT: [[TMP:%.*]] = add nsw i32 [[V0:%.*]], -1583; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[V1:%.*]], [[TMP]]584; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64585; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[SRC:%.*]], i64 [[TMP2]]586; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1587; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[V1]], [[V0]]588; CHECK-NEXT: [[TMP6:%.*]] = sext i32 [[TMP5]] to i64589; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[TMP6]]590; CHECK-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1591; CHECK-NEXT: [[TMP9:%.*]] = add nsw i32 [[V0]], 1592; CHECK-NEXT: [[TMP10:%.*]] = add i32 [[V1]], [[TMP9]]593; CHECK-NEXT: [[TMP11:%.*]] = sext i32 [[TMP10]] to i64594; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[TMP11]]595; CHECK-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP12]], align 1596; CHECK-NEXT: [[TMP14:%.*]] = add nsw i32 [[V0]], 2597; CHECK-NEXT: [[TMP15:%.*]] = add i32 [[V1]], [[TMP14]]598; CHECK-NEXT: [[TMP16:%.*]] = sext i32 [[TMP15]] to i64599; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 [[TMP16]]600; CHECK-NEXT: [[TMP18:%.*]] = load i8, ptr [[TMP17]], align 1601; CHECK-NEXT: [[TMP19:%.*]] = insertelement <4 x i8> undef, i8 [[TMP4]], i32 0602; CHECK-NEXT: [[TMP20:%.*]] = insertelement <4 x i8> [[TMP19]], i8 [[TMP8]], i32 1603; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i8> [[TMP20]], i8 [[TMP13]], i32 2604; CHECK-NEXT: [[TMP22:%.*]] = insertelement <4 x i8> [[TMP21]], i8 [[TMP18]], i32 3605; CHECK-NEXT: store <4 x i8> [[TMP22]], ptr [[DST:%.*]]606; CHECK-NEXT: ret void607;608bb:609 %tmp = add nsw i32 %v0, -1610 %tmp1 = add i32 %v1, %tmp611 %tmp2 = sext i32 %tmp1 to i64612 %tmp3 = getelementptr inbounds i8, ptr %src, i64 %tmp2613 %tmp4 = load i8, ptr %tmp3, align 1614 %tmp5 = add i32 %v1, %v0615 %tmp6 = sext i32 %tmp5 to i64616 %tmp7 = getelementptr inbounds i8, ptr %src, i64 %tmp6617 %tmp8 = load i8, ptr %tmp7, align 1618 %tmp9 = add nsw i32 %v0, 1619 %tmp10 = add i32 %v1, %tmp9620 %tmp11 = sext i32 %tmp10 to i64621 %tmp12 = getelementptr inbounds i8, ptr %src, i64 %tmp11622 %tmp13 = load i8, ptr %tmp12, align 1623 %tmp14 = add nsw i32 %v0, 2624 %tmp15 = add i32 %v1, %tmp14625 %tmp16 = sext i32 %tmp15 to i64626 %tmp17 = getelementptr inbounds i8, ptr %src, i64 %tmp16627 %tmp18 = load i8, ptr %tmp17, align 1628 %tmp19 = insertelement <4 x i8> undef, i8 %tmp4, i32 0629 %tmp20 = insertelement <4 x i8> %tmp19, i8 %tmp8, i32 1630 %tmp21 = insertelement <4 x i8> %tmp20, i8 %tmp13, i32 2631 %tmp22 = insertelement <4 x i8> %tmp21, i8 %tmp18, i32 3632 store <4 x i8> %tmp22, ptr %dst633 ret void634}635