diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index 0f77a1410e83b..6e576e866b310 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -1170,6 +1170,15 @@ const SCEVConstant *DependenceInfo::collectConstantUpperBound(const Loop *L, return nullptr; } +/// Returns \p A - \p B if it guaranteed not to signed wrap. Otherwise returns +/// nullptr. \p A and \p B must have the same integer type. +static const SCEV *minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B, + ScalarEvolution &SE) { + if (SE.willNotOverflow(Instruction::Sub, /*Signed=*/true, A, B)) + return SE.getMinusSCEV(A, B); + return nullptr; +} + // testZIV - // When we have a pair of subscripts of the form [c1] and [c2], // where c1 and c2 are both loop invariant, we attack it using @@ -1626,7 +1635,9 @@ bool DependenceInfo::exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff, assert(0 < Level && Level <= CommonLevels && "Level out of range"); Level--; Result.Consistent = false; - const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst); + const SCEV *Delta = minusSCEVNoSignedOverflow(DstConst, SrcConst, *SE); + if (!Delta) + return false; LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n"); NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff), Delta, CurLoop); @@ -1716,6 +1727,7 @@ bool DependenceInfo::exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff, // explore directions unsigned NewDirection = Dependence::DVEntry::NONE; APInt LowerDistance, UpperDistance; + // TODO: Overflow check may be needed. if (TA.sgt(TB)) { LowerDistance = (TY - TX) + (TA - TB) * TL; UpperDistance = (TY - TX) + (TA - TB) * TU; diff --git a/llvm/test/Analysis/DependenceAnalysis/ExactSIV.ll b/llvm/test/Analysis/DependenceAnalysis/ExactSIV.ll index 2a809c32d7d21..e8e7cb11bb23e 100644 --- a/llvm/test/Analysis/DependenceAnalysis/ExactSIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/ExactSIV.ll @@ -841,7 +841,7 @@ define void @exact14(ptr %A) { ; CHECK-SIV-ONLY-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1 ; CHECK-SIV-ONLY-NEXT: da analyze - none! ; CHECK-SIV-ONLY-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 -; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: da analyze - output [*|<]! ; CHECK-SIV-ONLY-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 ; CHECK-SIV-ONLY-NEXT: da analyze - none! ; diff --git a/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll b/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll index cd044032e34f1..58dded965de27 100644 --- a/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5 ; RUN: opt < %s -disable-output "-passes=print" -aa-pipeline=basic-aa 2>&1 \ ; RUN: | FileCheck %s +; RUN: opt < %s -disable-output "-passes=print" -da-run-siv-routines-only 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-SIV-ONLY ; ModuleID = 'WeakCrossingSIV.bc' target 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" @@ -26,6 +28,20 @@ define void @weakcrossing0(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - none! ; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing0' +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx2, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - flow [0|<]! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: %0 = load i32, ptr %arrayidx2, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; entry: %cmp1 = icmp eq i64 %n, 0 br i1 %cmp1, label %for.end, label %for.body.preheader @@ -79,6 +95,21 @@ define void @weakcrossing1(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - none! ; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing1' +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx2, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - flow [<>] splitable! +; CHECK-SIV-ONLY-NEXT: da analyze - split level = 1, iteration = 0! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: %0 = load i32, ptr %arrayidx2, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; entry: %cmp1 = icmp eq i64 %n, 0 br i1 %cmp1, label %for.end, label %for.body.preheader @@ -130,6 +161,20 @@ define void @weakcrossing2(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 ; CHECK-NEXT: da analyze - none! ; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing2' +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; entry: br label %for.body @@ -172,6 +217,20 @@ define void @weakcrossing3(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 ; CHECK-NEXT: da analyze - none! ; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing3' +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - flow [0|<]! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; entry: br label %for.body @@ -214,6 +273,20 @@ define void @weakcrossing4(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 ; CHECK-NEXT: da analyze - none! ; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing4' +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; entry: br label %for.body @@ -256,6 +329,20 @@ define void @weakcrossing5(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: store i32 %1, ptr %B.addr.02, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - none! ; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing5' +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %1 = load i32, ptr %arrayidx2, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: %1 = load i32, ptr %arrayidx2, align 4 --> Dst: %1 = load i32, ptr %arrayidx2, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: %1 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %1, ptr %B.addr.02, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; entry: %cmp1 = icmp eq i64 %n, 0 br i1 %cmp1, label %for.end, label %for.body.preheader @@ -308,6 +395,21 @@ define void @weakcrossing6(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 ; CHECK-NEXT: da analyze - none! ; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing6' +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %conv, ptr %arrayidx, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - flow [<>] splitable! +; CHECK-SIV-ONLY-NEXT: da analyze - split level = 1, iteration = 2! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %conv, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: %0 = load i32, ptr %arrayidx1, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - confused! +; CHECK-SIV-ONLY-NEXT: Src: store i32 %0, ptr %B.addr.01, align 4 --> Dst: store i32 %0, ptr %B.addr.01, align 4 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; entry: br label %for.body @@ -329,3 +431,125 @@ for.body: ; preds = %entry, %for.body for.end: ; preds = %for.body ret void } + +;; max_i = INT64_MAX/3 // 3074457345618258602 +;; for (long long i = 0; i <= max_i; i++) { +;; A[-3*i + INT64_MAX] = 0; +;; if (i) +;; A[3*i - 2] = 1; +;; } +;; +;; FIXME: DependencyAnalsysis currently detects no dependency between +;; `A[-3*i + INT64_MAX]` and `A[3*i - 2]`, but it does exist. For example, +;; +;; memory location | -3*i + INT64_MAX | 3*i - 2 +;; ------------------|------------------|----------- +;; A[1] | i = max_i | i = 1 +;; A[INT64_MAX - 3] | i = 1 | i = max_i +;; +;; Actually, +;; * 1 = -3*max_i + INT64_MAX = 3*1 - 2 +;; * 9223372036854775804 = -3*1 + INT64_MAX = 3*max_i - 2 +;; + +define void @weakcrossing7(ptr %A) { +; CHECK-LABEL: 'weakcrossing7' +; CHECK-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1 +; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 +; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 +; CHECK-NEXT: da analyze - none! +; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing7' +; CHECK-SIV-ONLY-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; +entry: + br label %loop.header + +loop.header: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ] + %subscript.0 = phi i64 [ 9223372036854775807, %entry ], [ %subscript.0.next, %loop.latch ] + %subscript.1 = phi i64 [ -2, %entry ], [ %subscript.1.next, %loop.latch ] + %idx.0 = getelementptr inbounds i8, ptr %A, i64 %subscript.0 + store i8 0, ptr %idx.0 + %cond.store = icmp ne i64 %i, 0 + br i1 %cond.store, label %if.store, label %loop.latch + +if.store: + %idx.1 = getelementptr inbounds i8, ptr %A, i64 %subscript.1 + store i8 1, ptr %idx.1 + br label %loop.latch + +loop.latch: + %i.inc = add nuw nsw i64 %i, 1 + %subscript.0.next = add nsw i64 %subscript.0, -3 + %subscript.1.next = add nsw i64 %subscript.1, 3 + %exitcond = icmp sgt i64 %i.inc, 3074457345618258602 + br i1 %exitcond, label %exit, label %loop.header + +exit: + ret void +} + +;; A generalized version of @weakcrossing7. +;; +;; for (long long i = 0; i <= n / 3; i++) { +;; A[-3*i + n] = 0; +;; if (i) +;; A[3*i - 2] = 1; +;; } + +define void @weakcrossing8(ptr %A, i64 %n) { +; CHECK-LABEL: 'weakcrossing8' +; CHECK-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1 +; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 +; CHECK-NEXT: da analyze - output [*|<] splitable! +; CHECK-NEXT: da analyze - split level = 1, iteration = ((0 smax (2 + %n)) /u 6)! +; CHECK-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 +; CHECK-NEXT: da analyze - none! +; +; CHECK-SIV-ONLY-LABEL: 'weakcrossing8' +; CHECK-SIV-ONLY-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; CHECK-SIV-ONLY-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 +; CHECK-SIV-ONLY-NEXT: da analyze - output [*|<] splitable! +; CHECK-SIV-ONLY-NEXT: da analyze - split level = 1, iteration = ((0 smax (2 + %n)) /u 6)! +; CHECK-SIV-ONLY-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1 +; CHECK-SIV-ONLY-NEXT: da analyze - none! +; +entry: + %bound = sdiv i64 %n, 3 + %guard = icmp sgt i64 %n, 0 + br i1 %guard, label %loop.header, label %exit + +loop.header: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ] + %subscript.0 = phi i64 [ %n, %entry ], [ %subscript.0.next, %loop.latch ] + %subscript.1 = phi i64 [ -2, %entry ], [ %subscript.1.next, %loop.latch ] + %idx.0 = getelementptr inbounds i8, ptr %A, i64 %subscript.0 + store i8 0, ptr %idx.0 + %cond.store = icmp ne i64 %i, 0 + br i1 %cond.store, label %if.store, label %loop.latch + +if.store: + %idx.1 = getelementptr inbounds i8, ptr %A, i64 %subscript.1 + store i8 1, ptr %idx.1 + br label %loop.latch + +loop.latch: + %i.inc = add nuw nsw i64 %i, 1 + %subscript.0.next = add nsw i64 %subscript.0, -3 + %subscript.1.next = add nsw i64 %subscript.1, 3 + %exitcond = icmp sgt i64 %i.inc, %bound + br i1 %exitcond, label %exit, label %loop.header + +exit: + ret void +}