363 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=slp-vectorizer -slp-threshold=-999 -S -mtriple=x86_64-unknown-linux-gnu -mcpu=skylake < %s | FileCheck %s3 4declare i64 @may_inf_loop_ro() nounwind readonly5declare i64 @may_inf_loop_rw() nounwind6declare i64 @may_throw() willreturn7 8; Base case with no interesting control dependencies9define void @test_no_control(ptr %a, ptr %b, ptr %c) {10; CHECK-LABEL: @test_no_control(11; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr [[A:%.*]], align 812; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i64>, ptr [[C:%.*]], align 813; CHECK-NEXT: [[TMP3:%.*]] = add <2 x i64> [[TMP1]], [[TMP2]]14; CHECK-NEXT: store <2 x i64> [[TMP3]], ptr [[B:%.*]], align 815; CHECK-NEXT: ret void16;17 %v1 = load i64, ptr %a18 %a2 = getelementptr i64, ptr %a, i32 119 %v2 = load i64, ptr %a220 21 %c1 = load i64, ptr %c22 %ca2 = getelementptr i64, ptr %c, i32 123 %c2 = load i64, ptr %ca224 %add1 = add i64 %v1, %c125 %add2 = add i64 %v2, %c226 27 store i64 %add1, ptr %b28 %b2 = getelementptr i64, ptr %b, i32 129 store i64 %add2, ptr %b230 ret void31}32 33define void @test1(ptr %a, ptr %b, ptr %c) {34; CHECK-LABEL: @test1(35; CHECK-NEXT: [[C1:%.*]] = load i64, ptr [[C:%.*]], align 836; CHECK-NEXT: [[C2:%.*]] = call i64 @may_inf_loop_ro()37; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr [[A:%.*]], align 838; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i64> poison, i64 [[C1]], i32 039; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> [[TMP2]], i64 [[C2]], i32 140; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i64> [[TMP1]], [[TMP3]]41; CHECK-NEXT: store <2 x i64> [[TMP4]], ptr [[B:%.*]], align 842; CHECK-NEXT: ret void43;44 %v1 = load i64, ptr %a45 %a2 = getelementptr i64, ptr %a, i32 146 %v2 = load i64, ptr %a247 48 %c1 = load i64, ptr %c49 %c2 = call i64 @may_inf_loop_ro()50 %add1 = add i64 %v1, %c151 %add2 = add i64 %v2, %c252 53 store i64 %add1, ptr %b54 %b2 = getelementptr i64, ptr %b, i32 155 store i64 %add2, ptr %b256 ret void57}58 59define void @test2(ptr %a, ptr %b, ptr %c) {60; CHECK-LABEL: @test2(61; CHECK-NEXT: [[C1:%.*]] = load i64, ptr [[C:%.*]], align 862; CHECK-NEXT: [[C2:%.*]] = call i64 @may_inf_loop_ro()63; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr [[A:%.*]], align 864; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i64> poison, i64 [[C1]], i32 065; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> [[TMP2]], i64 [[C2]], i32 166; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i64> [[TMP1]], [[TMP3]]67; CHECK-NEXT: store <2 x i64> [[TMP4]], ptr [[B:%.*]], align 868; CHECK-NEXT: ret void69;70 %c1 = load i64, ptr %c71 %c2 = call i64 @may_inf_loop_ro()72 73 %v1 = load i64, ptr %a74 %a2 = getelementptr i64, ptr %a, i32 175 %v2 = load i64, ptr %a276 77 %add1 = add i64 %v1, %c178 %add2 = add i64 %v2, %c279 80 store i64 %add1, ptr %b81 %b2 = getelementptr i64, ptr %b, i32 182 store i64 %add2, ptr %b283 ret void84}85 86define void @test3(ptr %a, ptr %b, ptr %c) {87; CHECK-LABEL: @test3(88; CHECK-NEXT: [[C1:%.*]] = load i64, ptr [[C:%.*]], align 889; CHECK-NEXT: [[C2:%.*]] = call i64 @may_inf_loop_ro()90; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr [[A:%.*]], align 891; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i64> poison, i64 [[C1]], i32 092; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> [[TMP2]], i64 [[C2]], i32 193; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i64> [[TMP1]], [[TMP3]]94; CHECK-NEXT: store <2 x i64> [[TMP4]], ptr [[B:%.*]], align 895; CHECK-NEXT: ret void96;97 %v1 = load i64, ptr %a98 %c1 = load i64, ptr %c99 %add1 = add i64 %v1, %c1100 101 %a2 = getelementptr i64, ptr %a, i32 1102 %v2 = load i64, ptr %a2103 %c2 = call i64 @may_inf_loop_ro()104 %add2 = add i64 %v2, %c2105 106 store i64 %add1, ptr %b107 %b2 = getelementptr i64, ptr %b, i32 1108 store i64 %add2, ptr %b2109 ret void110}111 112define void @test4(ptr %a, ptr %b, ptr %c) {113; CHECK-LABEL: @test4(114; CHECK-NEXT: [[C1:%.*]] = load i64, ptr [[C:%.*]], align 8115; CHECK-NEXT: [[C2:%.*]] = call i64 @may_inf_loop_ro()116; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr [[A:%.*]], align 8117; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i64> poison, i64 [[C1]], i32 0118; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> [[TMP2]], i64 [[C2]], i32 1119; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i64> [[TMP1]], [[TMP3]]120; CHECK-NEXT: store <2 x i64> [[TMP4]], ptr [[B:%.*]], align 8121; CHECK-NEXT: ret void122;123 %v1 = load i64, ptr %a124 %c1 = load i64, ptr %c125 %add1 = add i64 %v1, %c1126 127 %c2 = call i64 @may_inf_loop_ro()128 %a2 = getelementptr i64, ptr %a, i32 1129 %v2 = load i64, ptr %a2130 %add2 = add i64 %v2, %c2131 132 store i64 %add1, ptr %b133 %b2 = getelementptr i64, ptr %b, i32 1134 store i64 %add2, ptr %b2135 ret void136}137 138define void @test5(ptr %a, ptr %b, ptr %c) {139; CHECK-LABEL: @test5(140; CHECK-NEXT: [[C2:%.*]] = call i64 @may_inf_loop_ro()141; CHECK-NEXT: [[C1:%.*]] = load i64, ptr [[C:%.*]], align 8142; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr [[A:%.*]], align 8143; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i64> poison, i64 [[C1]], i32 0144; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> [[TMP2]], i64 [[C2]], i32 1145; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i64> [[TMP1]], [[TMP3]]146; CHECK-NEXT: store <2 x i64> [[TMP4]], ptr [[B:%.*]], align 8147; CHECK-NEXT: ret void148;149 %a2 = getelementptr i64, ptr %a, i32 1150 %v2 = load i64, ptr %a2151 %c2 = call i64 @may_inf_loop_ro()152 %add2 = add i64 %v2, %c2153 154 %v1 = load i64, ptr %a155 %c1 = load i64, ptr %c156 %add1 = add i64 %v1, %c1157 158 store i64 %add1, ptr %b159 %b2 = getelementptr i64, ptr %b, i32 1160 store i64 %add2, ptr %b2161 ret void162}163 164define void @test6(ptr %a, ptr %b, ptr %c) {165; CHECK-LABEL: @test6(166; CHECK-NEXT: [[TMP1:%.*]] = call i64 @may_inf_loop_ro()167; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i64>, ptr [[A:%.*]], align 8168; CHECK-NEXT: [[TMP3:%.*]] = load <2 x i64>, ptr [[C:%.*]], align 8169; CHECK-NEXT: [[TMP4:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]]170; CHECK-NEXT: store <2 x i64> [[TMP4]], ptr [[B:%.*]], align 8171; CHECK-NEXT: ret void172;173 %v1 = load i64, ptr %a174 call i64 @may_inf_loop_ro()175 %a2 = getelementptr i64, ptr %a, i32 1176 %v2 = load i64, ptr %a2177 178 %c1 = load i64, ptr %c179 %ca2 = getelementptr i64, ptr %c, i32 1180 %c2 = load i64, ptr %ca2181 %add1 = add i64 %v1, %c1182 %add2 = add i64 %v2, %c2183 184 store i64 %add1, ptr %b185 %b2 = getelementptr i64, ptr %b, i32 1186 store i64 %add2, ptr %b2187 ret void188}189 190; In this case, we can't vectorize the load pair because there's no valid191; scheduling point which respects both memory and control dependence. If192; we scheduled the second load before the store holding the first one in place,193; we'd have hoisted a potentially faulting load above a potentially infinite194; call and thus have introduced a possible fault into a program which didn't195; previously exist.196define void @test7(ptr %a, ptr %b, ptr %c) {197; CHECK-LABEL: @test7(198; CHECK-NEXT: [[A2:%.*]] = getelementptr i64, ptr [[A:%.*]], i32 1199; CHECK-NEXT: [[V1:%.*]] = load i64, ptr [[A]], align 8200; CHECK-NEXT: store i64 0, ptr [[A]], align 8201; CHECK-NEXT: [[TMP1:%.*]] = call i64 @may_inf_loop_ro()202; CHECK-NEXT: [[V2:%.*]] = load i64, ptr [[A2]], align 8203; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i64>, ptr [[C:%.*]], align 8204; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> poison, i64 [[V1]], i32 0205; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> [[TMP3]], i64 [[V2]], i32 1206; CHECK-NEXT: [[TMP5:%.*]] = add <2 x i64> [[TMP4]], [[TMP2]]207; CHECK-NEXT: store <2 x i64> [[TMP5]], ptr [[B:%.*]], align 8208; CHECK-NEXT: ret void209;210 %v1 = load i64, ptr %a211 store i64 0, ptr %a212 call i64 @may_inf_loop_ro()213 %a2 = getelementptr i64, ptr %a, i32 1214 %v2 = load i64, ptr %a2215 216 %c1 = load i64, ptr %c217 %ca2 = getelementptr i64, ptr %c, i32 1218 %c2 = load i64, ptr %ca2219 %add1 = add i64 %v1, %c1220 %add2 = add i64 %v2, %c2221 222 store i64 %add1, ptr %b223 %b2 = getelementptr i64, ptr %b, i32 1224 store i64 %add2, ptr %b2225 ret void226}227 228; Same as test7, but with a throwing call229define void @test8(ptr %a, ptr %b, ptr %c) {230; CHECK-LABEL: @test8(231; CHECK-NEXT: [[A2:%.*]] = getelementptr i64, ptr [[A:%.*]], i32 1232; CHECK-NEXT: [[V1:%.*]] = load i64, ptr [[A]], align 8233; CHECK-NEXT: store i64 0, ptr [[A]], align 8234; CHECK-NEXT: [[TMP1:%.*]] = call i64 @may_throw() #[[ATTR4:[0-9]+]]235; CHECK-NEXT: [[V2:%.*]] = load i64, ptr [[A2]], align 8236; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i64>, ptr [[C:%.*]], align 8237; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> poison, i64 [[V1]], i32 0238; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> [[TMP3]], i64 [[V2]], i32 1239; CHECK-NEXT: [[TMP5:%.*]] = add <2 x i64> [[TMP4]], [[TMP2]]240; CHECK-NEXT: store <2 x i64> [[TMP5]], ptr [[B:%.*]], align 8241; CHECK-NEXT: ret void242;243 %v1 = load i64, ptr %a244 store i64 0, ptr %a245 call i64 @may_throw() readonly246 %a2 = getelementptr i64, ptr %a, i32 1247 %v2 = load i64, ptr %a2248 249 %c1 = load i64, ptr %c250 %ca2 = getelementptr i64, ptr %c, i32 1251 %c2 = load i64, ptr %ca2252 %add1 = add i64 %v1, %c1253 %add2 = add i64 %v2, %c2254 255 store i64 %add1, ptr %b256 %b2 = getelementptr i64, ptr %b, i32 1257 store i64 %add2, ptr %b2258 ret void259}260 261; Same as test8, but with a readwrite maythrow call262define void @test9(ptr %a, ptr %b, ptr %c) {263; CHECK-LABEL: @test9(264; CHECK-NEXT: [[A2:%.*]] = getelementptr i64, ptr [[A:%.*]], i32 1265; CHECK-NEXT: [[V1:%.*]] = load i64, ptr [[A]], align 8266; CHECK-NEXT: store i64 0, ptr [[A]], align 8267; CHECK-NEXT: [[TMP1:%.*]] = call i64 @may_throw()268; CHECK-NEXT: [[V2:%.*]] = load i64, ptr [[A2]], align 8269; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i64>, ptr [[C:%.*]], align 8270; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> poison, i64 [[V1]], i32 0271; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> [[TMP3]], i64 [[V2]], i32 1272; CHECK-NEXT: [[TMP5:%.*]] = add <2 x i64> [[TMP4]], [[TMP2]]273; CHECK-NEXT: store <2 x i64> [[TMP5]], ptr [[B:%.*]], align 8274; CHECK-NEXT: ret void275;276 %v1 = load i64, ptr %a277 store i64 0, ptr %a278 call i64 @may_throw()279 %a2 = getelementptr i64, ptr %a, i32 1280 %v2 = load i64, ptr %a2281 282 %c1 = load i64, ptr %c283 %ca2 = getelementptr i64, ptr %c, i32 1284 %c2 = load i64, ptr %ca2285 %add1 = add i64 %v1, %c1286 %add2 = add i64 %v2, %c2287 288 store i64 %add1, ptr %b289 %b2 = getelementptr i64, ptr %b, i32 1290 store i64 %add2, ptr %b2291 ret void292}293 294; A variant of test7 which shows the same problem with a non-load instruction295define void @test10(ptr %a, ptr %b, ptr %c) {296; CHECK-LABEL: @test10(297; CHECK-NEXT: [[V1:%.*]] = load i64, ptr [[A:%.*]], align 8298; CHECK-NEXT: [[A2:%.*]] = getelementptr i64, ptr [[A]], i32 1299; CHECK-NEXT: [[V2:%.*]] = load i64, ptr [[A2]], align 8300; CHECK-NEXT: [[U1:%.*]] = udiv i64 200, [[V1]]301; CHECK-NEXT: store i64 [[U1]], ptr [[A]], align 8302; CHECK-NEXT: [[TMP1:%.*]] = call i64 @may_inf_loop_ro()303; CHECK-NEXT: [[U2:%.*]] = udiv i64 200, [[V2]]304; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i64>, ptr [[C:%.*]], align 8305; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> poison, i64 [[U1]], i32 0306; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> [[TMP3]], i64 [[U2]], i32 1307; CHECK-NEXT: [[TMP5:%.*]] = add <2 x i64> [[TMP4]], [[TMP2]]308; CHECK-NEXT: store <2 x i64> [[TMP5]], ptr [[B:%.*]], align 8309; CHECK-NEXT: ret void310;311 %v1 = load i64, ptr %a312 %a2 = getelementptr i64, ptr %a, i32 1313 %v2 = load i64, ptr %a2314 315 %u1 = udiv i64 200, %v1316 store i64 %u1, ptr %a317 call i64 @may_inf_loop_ro()318 %u2 = udiv i64 200, %v2319 320 %c1 = load i64, ptr %c321 %ca2 = getelementptr i64, ptr %c, i32 1322 %c2 = load i64, ptr %ca2323 %add1 = add i64 %u1, %c1324 %add2 = add i64 %u2, %c2325 326 store i64 %add1, ptr %b327 %b2 = getelementptr i64, ptr %b, i32 1328 store i64 %add2, ptr %b2329 ret void330}331 332; Variant of test10 block invariant operands to the udivs333; FIXME: This is wrong, we're hoisting a faulting udiv above an infinite loop.334define void @test11(i64 %x, i64 %y, ptr %b, ptr %c) {335; CHECK-LABEL: @test11(336; CHECK-NEXT: [[U1:%.*]] = udiv i64 200, [[X:%.*]]337; CHECK-NEXT: store i64 [[U1]], ptr [[B:%.*]], align 8338; CHECK-NEXT: [[TMP1:%.*]] = call i64 @may_inf_loop_ro()339; CHECK-NEXT: [[U2:%.*]] = udiv i64 200, [[Y:%.*]]340; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i64>, ptr [[C:%.*]], align 8341; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i64> poison, i64 [[U1]], i32 0342; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> [[TMP3]], i64 [[U2]], i32 1343; CHECK-NEXT: [[TMP5:%.*]] = add <2 x i64> [[TMP4]], [[TMP2]]344; CHECK-NEXT: store <2 x i64> [[TMP5]], ptr [[B]], align 8345; CHECK-NEXT: ret void346;347 %u1 = udiv i64 200, %x348 store i64 %u1, ptr %b349 call i64 @may_inf_loop_ro()350 %u2 = udiv i64 200, %y351 352 %c1 = load i64, ptr %c353 %ca2 = getelementptr i64, ptr %c, i32 1354 %c2 = load i64, ptr %ca2355 %add1 = add i64 %u1, %c1356 %add2 = add i64 %u2, %c2357 358 store i64 %add1, ptr %b359 %b2 = getelementptr i64, ptr %b, i32 1360 store i64 %add2, ptr %b2361 ret void362}363