658 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 32; RUN: opt -S -disable-output -passes='print<access-info>' %s 2>&1 | FileCheck %s3 4;5target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"6 7; A forwarding in the presence of symbolic strides.8define void @single_stride(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {9; CHECK-LABEL: 'single_stride'10; CHECK-NEXT: loop:11; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop12; CHECK-NEXT: Backward loop carried data dependence.13; CHECK-NEXT: Dependences:14; CHECK-NEXT: Backward:15; CHECK-NEXT: %load = load i32, ptr %gep.A, align 4 ->16; CHECK-NEXT: store i32 %add, ptr %gep.A.next, align 417; CHECK-EMPTY:18; CHECK-NEXT: Run-time memory checks:19; CHECK-NEXT: Grouped accesses:20; CHECK-EMPTY:21; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.22; CHECK-NEXT: SCEV assumptions:23; CHECK-NEXT: Equal predicate: %stride == 124; CHECK-EMPTY:25; CHECK-NEXT: Expressions re-written:26; CHECK-NEXT: [PSE] %gep.A = getelementptr inbounds i32, ptr %A, i64 %mul:27; CHECK-NEXT: {%A,+,(4 * %stride)}<%loop>28; CHECK-NEXT: --> {%A,+,4}<%loop>29;30entry:31 br label %loop32 33loop:34 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]35 %mul = mul i64 %iv, %stride36 %gep.A = getelementptr inbounds i32, ptr %A, i64 %mul37 %load = load i32, ptr %gep.A, align 438 %gep.B = getelementptr inbounds i32, ptr %B, i64 %iv39 %load_1 = load i32, ptr %gep.B, align 440 %add = add i32 %load_1, %load41 %iv.next = add nuw nsw i64 %iv, 142 %gep.A.next = getelementptr inbounds i32, ptr %A, i64 %iv.next43 store i32 %add, ptr %gep.A.next, align 444 %exitcond = icmp eq i64 %iv.next, %N45 br i1 %exitcond, label %exit, label %loop46 47exit: ; preds = %loop48 ret void49}50 51; A forwarding in the presence of symbolic strides,52; with nusw instead of inbounds on the GEPs.53define void @single_stride_nusw(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {54; CHECK-LABEL: 'single_stride_nusw'55; CHECK-NEXT: loop:56; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop57; CHECK-NEXT: Backward loop carried data dependence.58; CHECK-NEXT: Dependences:59; CHECK-NEXT: Backward:60; CHECK-NEXT: %load = load i32, ptr %gep.A, align 4 ->61; CHECK-NEXT: store i32 %add, ptr %gep.A.next, align 462; CHECK-EMPTY:63; CHECK-NEXT: Run-time memory checks:64; CHECK-NEXT: Grouped accesses:65; CHECK-EMPTY:66; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.67; CHECK-NEXT: SCEV assumptions:68; CHECK-NEXT: Equal predicate: %stride == 169; CHECK-EMPTY:70; CHECK-NEXT: Expressions re-written:71; CHECK-NEXT: [PSE] %gep.A = getelementptr nusw i32, ptr %A, i64 %mul:72; CHECK-NEXT: {%A,+,(4 * %stride)}<%loop>73; CHECK-NEXT: --> {%A,+,4}<%loop>74;75entry:76 br label %loop77 78loop:79 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]80 %mul = mul i64 %iv, %stride81 %gep.A = getelementptr nusw i32, ptr %A, i64 %mul82 %load = load i32, ptr %gep.A, align 483 %gep.B = getelementptr nusw i32, ptr %B, i64 %iv84 %load_1 = load i32, ptr %gep.B, align 485 %add = add i32 %load_1, %load86 %iv.next = add nuw nsw i64 %iv, 187 %gep.A.next = getelementptr nusw i32, ptr %A, i64 %iv.next88 store i32 %add, ptr %gep.A.next, align 489 %exitcond = icmp eq i64 %iv.next, %N90 br i1 %exitcond, label %exit, label %loop91 92exit: ; preds = %loop93 ret void94}95 96; Similar to @single_stride, but with struct types.97define void @single_stride_struct(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {98; CHECK-LABEL: 'single_stride_struct'99; CHECK-NEXT: loop:100; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop101; CHECK-NEXT: Backward loop carried data dependence.102; CHECK-NEXT: Dependences:103; CHECK-NEXT: Backward:104; CHECK-NEXT: %load = load { i32, i8 }, ptr %gep.A, align 4 ->105; CHECK-NEXT: store { i32, i8 } %ins, ptr %gep.A.next, align 4106; CHECK-EMPTY:107; CHECK-NEXT: Run-time memory checks:108; CHECK-NEXT: Grouped accesses:109; CHECK-EMPTY:110; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.111; CHECK-NEXT: SCEV assumptions:112; CHECK-NEXT: Equal predicate: %stride == 1113; CHECK-EMPTY:114; CHECK-NEXT: Expressions re-written:115; CHECK-NEXT: [PSE] %gep.A = getelementptr inbounds { i32, i8 }, ptr %A, i64 %mul:116; CHECK-NEXT: {%A,+,(8 * %stride)}<%loop>117; CHECK-NEXT: --> {%A,+,8}<%loop>118;119entry:120 br label %loop121 122loop:123 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]124 %mul = mul i64 %iv, %stride125 %gep.A = getelementptr inbounds { i32, i8 }, ptr %A, i64 %mul126 %load = load { i32, i8 }, ptr %gep.A, align 4127 %gep.B = getelementptr inbounds { i32, i8 }, ptr %B, i64 %iv128 %load_1 = load { i32, i8 }, ptr %gep.B, align 4129 %v1 = extractvalue { i32, i8 } %load, 0130 %v2 = extractvalue { i32, i8} %load_1, 0131 %add = add i32 %v1, %v2132 %ins = insertvalue { i32, i8 } undef, i32 %add, 0133 %iv.next = add nuw nsw i64 %iv, 1134 %gep.A.next = getelementptr inbounds { i32, i8 }, ptr %A, i64 %iv.next135 store { i32, i8 } %ins, ptr %gep.A.next, align 4136 %exitcond = icmp eq i64 %iv.next, %N137 br i1 %exitcond, label %exit, label %loop138 139exit:140 ret void141}142 143; Test with multiple GEP indices144define void @single_stride_array(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {145; CHECK-LABEL: 'single_stride_array'146; CHECK-NEXT: loop:147; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop148; CHECK-NEXT: Backward loop carried data dependence.149; CHECK-NEXT: Dependences:150; CHECK-NEXT: Backward:151; CHECK-NEXT: %load = load [2 x i32], ptr %gep.A, align 4 ->152; CHECK-NEXT: store [2 x i32] %ins, ptr %gep.A.next, align 4153; CHECK-EMPTY:154; CHECK-NEXT: Run-time memory checks:155; CHECK-NEXT: Grouped accesses:156; CHECK-EMPTY:157; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.158; CHECK-NEXT: SCEV assumptions:159; CHECK-NEXT: Equal predicate: %stride == 1160; CHECK-EMPTY:161; CHECK-NEXT: Expressions re-written:162; CHECK-NEXT: [PSE] %gep.A = getelementptr inbounds [2 x i32], ptr %A, i64 %mul, i64 1:163; CHECK-NEXT: {(4 + %A),+,(8 * %stride)}<%loop>164; CHECK-NEXT: --> {(4 + %A),+,8}<%loop>165;166entry:167 br label %loop168 169loop:170 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]171 %mul = mul i64 %iv, %stride172 %gep.A = getelementptr inbounds [2 x i32], ptr %A, i64 %mul, i64 1173 %load = load [2 x i32], ptr %gep.A, align 4174 %gep.B = getelementptr inbounds [2 x i32], ptr %B, i64 %iv175 %load_1 = load [2 x i32], ptr %gep.B, align 4176 %v1 = extractvalue [2 x i32] %load, 0177 %v2 = extractvalue [2 x i32] %load_1, 0178 %add = add i32 %v1, %v2179 %ins = insertvalue [2 x i32] poison, i32 %add, 0180 %iv.next = add nuw nsw i64 %iv, 1181 %gep.A.next = getelementptr inbounds [2 x i32], ptr %A, i64 %iv.next182 store [2 x i32] %ins, ptr %gep.A.next, align 4183 %exitcond = icmp eq i64 %iv.next, %N184 br i1 %exitcond, label %exit, label %loop185 186exit:187 ret void188}189 190define void @single_stride_castexpr(i32 %offset, ptr %src, ptr %dst, i1 %cond) {191; CHECK-LABEL: 'single_stride_castexpr'192; CHECK-NEXT: inner.loop:193; CHECK-NEXT: Memory dependences are safe with run-time checks194; CHECK-NEXT: Dependences:195; CHECK-NEXT: Run-time memory checks:196; CHECK-NEXT: Check 0:197; CHECK-NEXT: Comparing group GRP0:198; CHECK-NEXT: %gep.dst = getelementptr i32, ptr %dst, i64 %iv.2199; CHECK-NEXT: Against group GRP1:200; CHECK-NEXT: %gep.src = getelementptr inbounds i32, ptr %src, i32 %iv.3201; CHECK-NEXT: Grouped accesses:202; CHECK-NEXT: Group GRP0:203; CHECK-NEXT: (Low: ((4 * %iv.1) + %dst) High: (804 + (4 * %iv.1) + %dst))204; CHECK-NEXT: Member: {((4 * %iv.1) + %dst),+,4}<%inner.loop>205; CHECK-NEXT: Group GRP1:206; CHECK-NEXT: (Low: %src High: (804 + %src))207; CHECK-NEXT: Member: {%src,+,4}<nuw><%inner.loop>208; CHECK-EMPTY:209; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.210; CHECK-NEXT: SCEV assumptions:211; CHECK-NEXT: Equal predicate: %offset == 1212; CHECK-EMPTY:213; CHECK-NEXT: Expressions re-written:214; CHECK-NEXT: [PSE] %gep.dst = getelementptr i32, ptr %dst, i64 %iv.2:215; CHECK-NEXT: {((4 * %iv.1) + %dst),+,(4 * (sext i32 %offset to i64))<nsw>}<%inner.loop>216; CHECK-NEXT: --> {((4 * %iv.1) + %dst),+,4}<%inner.loop>217; CHECK-NEXT: outer.header:218; CHECK-NEXT: Report: loop is not the innermost loop219; CHECK-NEXT: Dependences:220; CHECK-NEXT: Run-time memory checks:221; CHECK-NEXT: Grouped accesses:222; CHECK-EMPTY:223; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.224; CHECK-NEXT: SCEV assumptions:225; CHECK-EMPTY:226; CHECK-NEXT: Expressions re-written:227;228entry:229 %offset.ext = sext i32 %offset to i64230 br label %outer.header231 232outer.header:233 %iv.1 = phi i64 [ 0, %entry ], [ %iv.2.next, %inner.loop ]234 br i1 %cond, label %inner.loop, label %exit235 236inner.loop:237 %iv.2 = phi i64 [ %iv.1, %outer.header ], [ %iv.2.next, %inner.loop ]238 %iv.3 = phi i32 [ 0, %outer.header ], [ %iv.3.next, %inner.loop ]239 %gep.src = getelementptr inbounds i32, ptr %src, i32 %iv.3240 %load = load i32, ptr %gep.src, align 8241 %gep.dst = getelementptr i32, ptr %dst, i64 %iv.2242 store i32 %load, ptr %gep.dst, align 8243 %iv.2.next = add i64 %iv.2, %offset.ext244 %iv.3.next = add i32 %iv.3, 1245 %ec = icmp eq i32 %iv.3, 200246 br i1 %ec, label %outer.header, label %inner.loop247 248exit:249 ret void250}251 252define void @single_stride_castexpr_multiuse(i32 %offset, ptr %src, ptr %dst, i1 %cond) {253; CHECK-LABEL: 'single_stride_castexpr_multiuse'254; CHECK-NEXT: inner.loop:255; CHECK-NEXT: Memory dependences are safe with run-time checks256; CHECK-NEXT: Dependences:257; CHECK-NEXT: Run-time memory checks:258; CHECK-NEXT: Check 0:259; CHECK-NEXT: Comparing group GRP0:260; CHECK-NEXT: %gep.dst = getelementptr i32, ptr %dst, i64 %iv.2261; CHECK-NEXT: Against group GRP1:262; CHECK-NEXT: %gep.src = getelementptr inbounds i32, ptr %src, i64 %iv.3263; CHECK-NEXT: Grouped accesses:264; CHECK-NEXT: Group GRP0:265; CHECK-NEXT: (Low: ((4 * %iv.1) + %dst) High: (804 + (4 * %iv.1) + (-4 * (zext i32 %offset to i64))<nsw> + %dst))266; CHECK-NEXT: Member: {((4 * %iv.1) + %dst),+,4}<%inner.loop>267; CHECK-NEXT: Group GRP1:268; CHECK-NEXT: (Low: (4 + %src) High: (808 + (-4 * (zext i32 %offset to i64))<nsw> + %src))269; CHECK-NEXT: Member: {(4 + %src),+,4}<%inner.loop>270; CHECK-EMPTY:271; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.272; CHECK-NEXT: SCEV assumptions:273; CHECK-NEXT: Equal predicate: %offset == 1274; CHECK-EMPTY:275; CHECK-NEXT: Expressions re-written:276; CHECK-NEXT: [PSE] %gep.src = getelementptr inbounds i32, ptr %src, i64 %iv.3:277; CHECK-NEXT: {((4 * (zext i32 %offset to i64))<nuw><nsw> + %src),+,4}<%inner.loop>278; CHECK-NEXT: --> {(4 + %src),+,4}<%inner.loop>279; CHECK-NEXT: [PSE] %gep.dst = getelementptr i32, ptr %dst, i64 %iv.2:280; CHECK-NEXT: {((4 * %iv.1) + %dst),+,(4 * (sext i32 %offset to i64))<nsw>}<%inner.loop>281; CHECK-NEXT: --> {((4 * %iv.1) + %dst),+,4}<%inner.loop>282; CHECK-NEXT: outer.header:283; CHECK-NEXT: Report: loop is not the innermost loop284; CHECK-NEXT: Dependences:285; CHECK-NEXT: Run-time memory checks:286; CHECK-NEXT: Grouped accesses:287; CHECK-EMPTY:288; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.289; CHECK-NEXT: SCEV assumptions:290; CHECK-EMPTY:291; CHECK-NEXT: Expressions re-written:292;293entry:294 %offset.ext = sext i32 %offset to i64295 %offset.zext = zext i32 %offset to i64296 br label %outer.header297 298outer.header:299 %iv.1 = phi i64 [ 0, %entry ], [ %iv.2.next, %inner.loop ]300 br i1 %cond, label %inner.loop, label %exit301 302inner.loop:303 %iv.2 = phi i64 [ %iv.1, %outer.header ], [ %iv.2.next, %inner.loop ]304 %iv.3 = phi i64 [ %offset.zext, %outer.header ], [ %iv.3.next, %inner.loop ]305 %gep.src = getelementptr inbounds i32, ptr %src, i64 %iv.3306 %load = load i32, ptr %gep.src, align 8307 %gep.dst = getelementptr i32, ptr %dst, i64 %iv.2308 store i32 %load, ptr %gep.dst, align 8309 %iv.2.next = add i64 %iv.2, %offset.ext310 %iv.3.next = add i64 %iv.3, 1311 %ec = icmp eq i64 %iv.3, 200312 br i1 %ec, label %outer.header, label %inner.loop313 314exit:315 ret void316}317 318define double @single_iteration_unknown_stride(i32 %x, ptr %y, i1 %cond) {319; CHECK-LABEL: 'single_iteration_unknown_stride'320; CHECK-NEXT: loop.body:321; CHECK-NEXT: Memory dependences are safe322; CHECK-NEXT: Dependences:323; CHECK-NEXT: Run-time memory checks:324; CHECK-NEXT: Grouped accesses:325; CHECK-EMPTY:326; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.327; CHECK-NEXT: SCEV assumptions:328; CHECK-NEXT: Equal predicate: %x == 1329; CHECK-EMPTY:330; CHECK-NEXT: Expressions re-written:331; CHECK-NEXT: [PSE] %gep10 = getelementptr double, ptr %gep8, i64 %mul:332; CHECK-NEXT: {(8 + %y),+,(8 * (sext i32 %x to i64))<nsw>}<%loop.body>333; CHECK-NEXT: --> {(8 + %y),+,8}<%loop.body>334;335entry:336 br i1 %cond, label %noloop.exit, label %loop.ph337 338loop.ph: ; preds = %entry339 %sext7 = sext i32 %x to i64340 %gep8 = getelementptr i8, ptr %y, i64 8341 br label %loop.body342 343loop.body: ; preds = %loop.body, %loop.ph344 %iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.body ]345 %mul = mul i64 %iv, %sext7346 %gep10 = getelementptr double, ptr %gep8, i64 %mul347 %load11 = load double, ptr %gep10, align 8348 store double %load11, ptr %y, align 8349 %iv.next = add i64 %iv, 1350 %icmp = icmp eq i64 %iv, 0351 br i1 %icmp, label %loop.exit, label %loop.body352 353noloop.exit: ; preds = %entry354 %sext = sext i32 %x to i64355 %gep = getelementptr double, ptr %y, i64 %sext356 %load5 = load double, ptr %gep, align 8357 ret double %load5358 359loop.exit: ; preds = %loop.body360 %sext2 = sext i32 %x to i64361 %gep2 = getelementptr double, ptr %y, i64 %sext2362 %load6 = load double, ptr %gep2, align 8363 ret double %load6364}365 366; A loop with two symbolic strides.367define void @two_strides(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride.1, i64 %stride.2) {368; CHECK-LABEL: 'two_strides'369; CHECK-NEXT: loop:370; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop371; CHECK-NEXT: Backward loop carried data dependence.372; CHECK-NEXT: Dependences:373; CHECK-NEXT: Backward:374; CHECK-NEXT: %load = load i32, ptr %gep.A, align 4 ->375; CHECK-NEXT: store i32 %add, ptr %gep.A.next, align 4376; CHECK-EMPTY:377; CHECK-NEXT: Run-time memory checks:378; CHECK-NEXT: Grouped accesses:379; CHECK-EMPTY:380; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.381; CHECK-NEXT: SCEV assumptions:382; CHECK-NEXT: Equal predicate: %stride.2 == 1383; CHECK-NEXT: Equal predicate: %stride.1 == 1384; CHECK-EMPTY:385; CHECK-NEXT: Expressions re-written:386; CHECK-NEXT: [PSE] %gep.A = getelementptr inbounds i32, ptr %A, i64 %mul:387; CHECK-NEXT: {%A,+,(4 * %stride.1)}<%loop>388; CHECK-NEXT: --> {%A,+,4}<%loop>389; CHECK-NEXT: [PSE] %gep.A.next = getelementptr inbounds i32, ptr %A, i64 %mul.2:390; CHECK-NEXT: {((4 * %stride.2) + %A),+,(4 * %stride.2)}<%loop>391; CHECK-NEXT: --> {(4 + %A),+,4}<%loop>392;393entry:394 br label %loop395 396loop:397 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]398 %mul = mul i64 %iv, %stride.1399 %gep.A = getelementptr inbounds i32, ptr %A, i64 %mul400 %load = load i32, ptr %gep.A, align 4401 %gep.B = getelementptr inbounds i32, ptr %B, i64 %iv402 %load_1 = load i32, ptr %gep.B, align 4403 %add = add i32 %load_1, %load404 %iv.next = add nuw nsw i64 %iv, 1405 %mul.2 = mul i64 %iv.next, %stride.2406 %gep.A.next = getelementptr inbounds i32, ptr %A, i64 %mul.2407 store i32 %add, ptr %gep.A.next, align 4408 %exitcond = icmp eq i64 %iv.next, %N409 br i1 %exitcond, label %exit, label %loop410 411exit:412 ret void413}414 415define void @single_stride_used_for_trip_count(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {416; CHECK-LABEL: 'single_stride_used_for_trip_count'417; CHECK-NEXT: loop:418; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop419; CHECK-NEXT: Unsafe indirect dependence.420; CHECK-NEXT: Dependences:421; CHECK-NEXT: IndirectUnsafe:422; CHECK-NEXT: %load = load i32, ptr %gep.A, align 4 ->423; CHECK-NEXT: store i32 %add, ptr %gep.A.next, align 4424; CHECK-EMPTY:425; CHECK-NEXT: Run-time memory checks:426; CHECK-NEXT: Grouped accesses:427; CHECK-EMPTY:428; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.429; CHECK-NEXT: SCEV assumptions:430; CHECK-EMPTY:431; CHECK-NEXT: Expressions re-written:432;433entry:434 br label %loop435 436loop:437 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]438 %mul = mul i64 %iv, %stride439 %gep.A = getelementptr inbounds i32, ptr %A, i64 %mul440 %load = load i32, ptr %gep.A, align 4441 %gep.B = getelementptr inbounds i32, ptr %B, i64 %iv442 %load_1 = load i32, ptr %gep.B, align 4443 %add = add i32 %load_1, %load444 %iv.next = add nuw nsw i64 %iv, 1445 %gep.A.next = getelementptr inbounds i32, ptr %A, i64 %iv.next446 store i32 %add, ptr %gep.A.next, align 4447 %exitcond = icmp eq i64 %iv.next, %stride448 br i1 %exitcond, label %exit, label %loop449 450exit: ; preds = %loop451 ret void452}453 454; Check the scenario where we have an unknown Stride, which happens to also be455; the loop iteration count. If we speculate Stride==1, it implies that the loop456; will iterate no more than a single iteration.457define void @unknown_stride_equalto_tc(i32 %N, ptr %A, ptr %B, i32 %j) {458; CHECK-LABEL: 'unknown_stride_equalto_tc'459; CHECK-NEXT: loop:460; CHECK-NEXT: Memory dependences are safe with run-time checks461; CHECK-NEXT: Dependences:462; CHECK-NEXT: Run-time memory checks:463; CHECK-NEXT: Check 0:464; CHECK-NEXT: Comparing group GRP0:465; CHECK-NEXT: ptr %A466; CHECK-NEXT: Against group GRP1:467; CHECK-NEXT: %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add468; CHECK-NEXT: Grouped accesses:469; CHECK-NEXT: Group GRP0:470; CHECK-NEXT: (Low: %A High: (4 + %A))471; CHECK-NEXT: Member: %A472; CHECK-NEXT: Group GRP1:473; CHECK-NEXT: (Low: (((2 * (sext i32 %j to i64))<nsw> + %B) umin ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + %N) to i64) * (sext i32 %N to i64)) + %B)) High: (2 + (((2 * (sext i32 %j to i64))<nsw> + %B) umax ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + %N) to i64) * (sext i32 %N to i64)) + %B))))474; CHECK-NEXT: Member: {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (sext i32 %N to i64))<nsw>}<%loop>475; CHECK-EMPTY:476; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.477; CHECK-NEXT: SCEV assumptions:478; CHECK-NEXT: {%j,+,%N}<%loop> Added Flags: <nssw>479; CHECK-EMPTY:480; CHECK-NEXT: Expressions re-written:481; CHECK-NEXT: [PSE] %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add:482; CHECK-NEXT: ((2 * (sext i32 {%j,+,%N}<%loop> to i64))<nsw> + %B)483; CHECK-NEXT: --> {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (sext i32 %N to i64))<nsw>}<%loop>484;485entry:486 %cmp = icmp eq i32 %N, 0487 br i1 %cmp, label %exit, label %loop488 489loop:490 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]491 %mul = mul i32 %iv, %N492 %add = add i32 %mul, %j493 %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add494 %load = load i16, ptr %arrayidx495 %sext = sext i16 %load to i32496 store i32 %sext, ptr %A497 %iv.next = add nuw i32 %iv, 1498 %exitcond = icmp eq i32 %iv.next, %N499 br i1 %exitcond, label %exit, label %loop500 501exit:502 ret void503}504 505 506; Check the scenario where we have an unknown Stride, which happens to also be507; the loop iteration count, but the TC is zero-extended from a narrower type.508define void @unknown_stride_equalto_zext_tc(i16 zeroext %N, ptr %A, ptr %B, i32 %j) {509; CHECK-LABEL: 'unknown_stride_equalto_zext_tc'510; CHECK-NEXT: loop:511; CHECK-NEXT: Memory dependences are safe with run-time checks512; CHECK-NEXT: Dependences:513; CHECK-NEXT: Run-time memory checks:514; CHECK-NEXT: Check 0:515; CHECK-NEXT: Comparing group GRP0:516; CHECK-NEXT: ptr %A517; CHECK-NEXT: Against group GRP1:518; CHECK-NEXT: %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add519; CHECK-NEXT: Grouped accesses:520; CHECK-NEXT: Group GRP0:521; CHECK-NEXT: (Low: %A High: (4 + %A))522; CHECK-NEXT: Member: %A523; CHECK-NEXT: Group GRP1:524; CHECK-NEXT: (Low: (((2 * (sext i32 %j to i64))<nsw> + %B) umin ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (zext i16 %N to i32))<nsw> to i64) * (zext i16 %N to i64)) + %B)) High: (2 + (((2 * (sext i32 %j to i64))<nsw> + %B) umax ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (zext i16 %N to i32))<nsw> to i64) * (zext i16 %N to i64)) + %B))))525; CHECK-NEXT: Member: {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (zext i16 %N to i64))<nuw><nsw>}<%loop>526; CHECK-EMPTY:527; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.528; CHECK-NEXT: SCEV assumptions:529; CHECK-NEXT: {%j,+,(zext i16 %N to i32)}<nw><%loop> Added Flags: <nssw>530; CHECK-EMPTY:531; CHECK-NEXT: Expressions re-written:532; CHECK-NEXT: [PSE] %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add:533; CHECK-NEXT: ((2 * (sext i32 {%j,+,(zext i16 %N to i32)}<nw><%loop> to i64))<nsw> + %B)534; CHECK-NEXT: --> {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (zext i16 %N to i64))<nuw><nsw>}<%loop>535;536entry:537 %N.ext = zext i16 %N to i32538 %cmp = icmp eq i16 %N, 0539 br i1 %cmp, label %exit, label %loop540 541loop:542 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]543 %mul = mul nuw i32 %iv, %N.ext544 %add = add i32 %mul, %j545 %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add546 %load = load i16, ptr %arrayidx547 %sext = sext i16 %load to i32548 store i32 %sext, ptr %A549 %iv.next = add nuw nsw i32 %iv, 1550 %exitcond = icmp eq i32 %iv.next, %N.ext551 br i1 %exitcond, label %exit, label %loop552 553exit:554 ret void555}556 557; Check the scenario where we have an unknown Stride, which happens to also be558; the loop iteration count, but the TC is sign-extended from a narrower type.559define void @unknown_stride_equalto_sext_tc(i16 %N, ptr %A, ptr %B, i32 %j) {560; CHECK-LABEL: 'unknown_stride_equalto_sext_tc'561; CHECK-NEXT: loop:562; CHECK-NEXT: Memory dependences are safe with run-time checks563; CHECK-NEXT: Dependences:564; CHECK-NEXT: Run-time memory checks:565; CHECK-NEXT: Check 0:566; CHECK-NEXT: Comparing group GRP0:567; CHECK-NEXT: ptr %A568; CHECK-NEXT: Against group GRP1:569; CHECK-NEXT: %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add570; CHECK-NEXT: Grouped accesses:571; CHECK-NEXT: Group GRP0:572; CHECK-NEXT: (Low: %A High: (4 + %A))573; CHECK-NEXT: Member: %A574; CHECK-NEXT: Group GRP1:575; CHECK-NEXT: (Low: (((2 * (sext i32 %j to i64))<nsw> + %B) umin ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (sext i16 %N to i32))<nsw> to i64) * (sext i16 %N to i64)) + %B)) High: (2 + (((2 * (sext i32 %j to i64))<nsw> + %B) umax ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (sext i16 %N to i32))<nsw> to i64) * (sext i16 %N to i64)) + %B))))576; CHECK-NEXT: Member: {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (sext i16 %N to i64))<nsw>}<%loop>577; CHECK-EMPTY:578; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.579; CHECK-NEXT: SCEV assumptions:580; CHECK-NEXT: {%j,+,(sext i16 %N to i32)}<nw><%loop> Added Flags: <nssw>581; CHECK-EMPTY:582; CHECK-NEXT: Expressions re-written:583; CHECK-NEXT: [PSE] %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add:584; CHECK-NEXT: ((2 * (sext i32 {%j,+,(sext i16 %N to i32)}<nw><%loop> to i64))<nsw> + %B)585; CHECK-NEXT: --> {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (sext i16 %N to i64))<nsw>}<%loop>586;587entry:588 %N.ext = sext i16 %N to i32589 %cmp = icmp eq i16 %N, 0590 br i1 %cmp, label %exit, label %loop591 592loop:593 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]594 %mul = mul nuw i32 %iv, %N.ext595 %add = add i32 %mul, %j596 %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add597 %load = load i16, ptr %arrayidx598 %sext = sext i16 %load to i32599 store i32 %sext, ptr %A600 %iv.next = add nuw nsw i32 %iv, 1601 %exitcond = icmp eq i32 %iv.next, %N.ext602 br i1 %exitcond, label %exit, label %loop603 604exit:605 ret void606}607 608; Check the scenario where we have an unknown Stride, which happens to also be609; the loop iteration count, but the TC is truncated from a wider type.610define void @unknown_stride_equalto_trunc_tc(i64 %N, ptr %A, ptr %B, i32 %j) {611; CHECK-LABEL: 'unknown_stride_equalto_trunc_tc'612; CHECK-NEXT: loop:613; CHECK-NEXT: Memory dependences are safe with run-time checks614; CHECK-NEXT: Dependences:615; CHECK-NEXT: Run-time memory checks:616; CHECK-NEXT: Check 0:617; CHECK-NEXT: Comparing group GRP0:618; CHECK-NEXT: ptr %A619; CHECK-NEXT: Against group GRP1:620; CHECK-NEXT: %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add621; CHECK-NEXT: Grouped accesses:622; CHECK-NEXT: Group GRP0:623; CHECK-NEXT: (Low: %A High: (4 + %A))624; CHECK-NEXT: Member: %A625; CHECK-NEXT: Group GRP1:626; CHECK-NEXT: (Low: (((2 * (sext i32 %j to i64))<nsw> + %B) umin ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (trunc i64 %N to i32)) to i64) * (sext i32 (trunc i64 %N to i32) to i64)) + %B)) High: (2 + (((2 * (sext i32 %j to i64))<nsw> + %B) umax ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (trunc i64 %N to i32)) to i64) * (sext i32 (trunc i64 %N to i32) to i64)) + %B))))627; CHECK-NEXT: Member: {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (sext i32 (trunc i64 %N to i32) to i64))<nsw>}<%loop>628; CHECK-EMPTY:629; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.630; CHECK-NEXT: SCEV assumptions:631; CHECK-NEXT: {%j,+,(trunc i64 %N to i32)}<nw><%loop> Added Flags: <nssw>632; CHECK-EMPTY:633; CHECK-NEXT: Expressions re-written:634; CHECK-NEXT: [PSE] %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add:635; CHECK-NEXT: ((2 * (sext i32 {%j,+,(trunc i64 %N to i32)}<nw><%loop> to i64))<nsw> + %B)636; CHECK-NEXT: --> {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (sext i32 (trunc i64 %N to i32) to i64))<nsw>}<%loop>637;638entry:639 %N.trunc = trunc i64 %N to i32640 %cmp = icmp eq i64 %N, 0641 br i1 %cmp, label %exit, label %loop642 643loop:644 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]645 %mul = mul nuw i32 %iv, %N.trunc646 %add = add i32 %mul, %j647 %arrayidx = getelementptr inbounds i16, ptr %B, i32 %add648 %load = load i16, ptr %arrayidx649 %sext = sext i16 %load to i32650 store i32 %sext, ptr %A651 %iv.next = add nuw nsw i32 %iv, 1652 %exitcond = icmp eq i32 %iv.next, %N.trunc653 br i1 %exitcond, label %exit, label %loop654 655exit:656 ret void657}658