You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
@ -1,110 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -verify-loop-info -verify-dom-info -S \
|
||||
; RUN: < %s | FileCheck %s
|
||||
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -loop-vectorize -force-vector-width=4 \
|
||||
; RUN: -verify-loop-info -verify-dom-info -S < %s | \
|
||||
; RUN: FileCheck --check-prefix=VECTORIZE %s
|
||||
|
||||
; The memcheck version of basic.ll. We should distribute and vectorize the
|
||||
; second part of this loop with 5 memchecks (A+1 x {C, D, E} + C x {A, B})
|
||||
;
|
||||
; for (i = 0; i < n; i++) {
|
||||
; A[i + 1] = A[i] * B[i];
|
||||
; -------------------------------
|
||||
; C[i] = D[i] * E[i];
|
||||
; }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
@B = common global i32* null, align 8
|
||||
@A = common global i32* null, align 8
|
||||
@C = common global i32* null, align 8
|
||||
@D = common global i32* null, align 8
|
||||
@E = common global i32* null, align 8
|
||||
|
||||
define void @f() {
|
||||
entry:
|
||||
%a = load i32*, i32** @A, align 8
|
||||
%b = load i32*, i32** @B, align 8
|
||||
%c = load i32*, i32** @C, align 8
|
||||
%d = load i32*, i32** @D, align 8
|
||||
%e = load i32*, i32** @E, align 8
|
||||
br label %for.body
|
||||
|
||||
; We have two compares for each array overlap check.
|
||||
; Since the checks to A and A + 4 get merged, this will give us a
|
||||
; total of 8 compares.
|
||||
;
|
||||
; CHECK: for.body.lver.check:
|
||||
; CHECK: = icmp
|
||||
; CHECK: = icmp
|
||||
|
||||
; CHECK: = icmp
|
||||
; CHECK: = icmp
|
||||
|
||||
; CHECK: = icmp
|
||||
; CHECK: = icmp
|
||||
|
||||
; CHECK: = icmp
|
||||
; CHECK: = icmp
|
||||
|
||||
; CHECK-NOT: = icmp
|
||||
; CHECK: br i1 %memcheck.conflict, label %for.body.ph.lver.orig, label %for.body.ph.ldist1
|
||||
|
||||
; The non-distributed loop that the memchecks fall back on.
|
||||
|
||||
; CHECK: for.body.ph.lver.orig:
|
||||
; CHECK: br label %for.body.lver.orig
|
||||
; CHECK: for.body.lver.orig:
|
||||
; CHECK: br i1 %exitcond.lver.orig, label %for.end, label %for.body.lver.orig
|
||||
|
||||
; Verify the two distributed loops.
|
||||
|
||||
; CHECK: for.body.ph.ldist1:
|
||||
; CHECK: br label %for.body.ldist1
|
||||
; CHECK: for.body.ldist1:
|
||||
; CHECK: %mulA.ldist1 = mul i32 %loadB.ldist1, %loadA.ldist1
|
||||
; CHECK: br i1 %exitcond.ldist1, label %for.body.ph, label %for.body.ldist1
|
||||
|
||||
; CHECK: for.body.ph:
|
||||
; CHECK: br label %for.body
|
||||
; CHECK: for.body:
|
||||
; CHECK: %mulC = mul i32 %loadD, %loadE
|
||||
; CHECK: for.end:
|
||||
|
||||
|
||||
; VECTORIZE: mul <4 x i32>
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -verify-loop-info -verify-dom-info -S \
|
||||
; RUN: < %s | FileCheck %s
|
||||
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -verify-loop-info -verify-dom-info \
|
||||
; RUN: -loop-accesses -analyze < %s | FileCheck %s --check-prefix=ANALYSIS
|
||||
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -loop-vectorize -force-vector-width=4 -S \
|
||||
; RUN: < %s | FileCheck %s --check-prefix=VECTORIZE
|
||||
|
||||
; We should distribute this loop into a safe (2nd statement) and unsafe loop
|
||||
; (1st statement):
|
||||
; for (i = 0; i < n; i++) {
|
||||
; A[i + 1] = A[i] * B[i];
|
||||
; =======================
|
||||
; C[i] = D[i] * E[i];
|
||||
; }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
define void @f(i32* noalias %a,
|
||||
i32* noalias %b,
|
||||
i32* noalias %c,
|
||||
i32* noalias %d,
|
||||
i32* noalias %e) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
; Verify the two distributed loops.
|
||||
|
||||
; CHECK: entry.split.ldist1:
|
||||
; CHECK: br label %for.body.ldist1
|
||||
; CHECK: for.body.ldist1:
|
||||
; CHECK: %mulA.ldist1 = mul i32 %loadB.ldist1, %loadA.ldist1
|
||||
; CHECK: br i1 %exitcond.ldist1, label %entry.split, label %for.body.ldist1
|
||||
|
||||
; CHECK: entry.split:
|
||||
; CHECK: br label %for.body
|
||||
; CHECK: for.body:
|
||||
; CHECK: %mulC = mul i32 %loadD, %loadE
|
||||
; CHECK: for.end:
|
||||
|
||||
|
||||
; ANALYSIS: for.body:
|
||||
; ANALYSIS-NEXT: Memory dependences are safe{{$}}
|
||||
; ANALYSIS: for.body.ldist1:
|
||||
; ANALYSIS-NEXT: Report: unsafe dependent memory operations in loop
|
||||
|
||||
|
||||
; VECTORIZE: mul <4 x i32>
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -S < %s | FileCheck %s
|
||||
|
||||
; When emitting the memchecks for:
|
||||
;
|
||||
; for (i = 0; i < n; i++) {
|
||||
; A[i + 1] = A[i] * B[i];
|
||||
; =======================
|
||||
; C[i] = D[i] * E[i];
|
||||
; }
|
||||
;
|
||||
; we had a bug when expanding the bounds for A and C. These are expanded
|
||||
; multiple times and rely on the caching in SCEV expansion to avoid any
|
||||
; redundancy. However, due to logic in SCEVExpander::ReuseOrCreateCast, we
|
||||
; can get earlier expanded values invalidated when casts are used. This test
|
||||
; ensure that we are not using the invalidated values.
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
||||
define void @f(i32* %a1, i32* %a2,
|
||||
i32* %b,
|
||||
i32* %c1, i32* %c2,
|
||||
i32* %d,
|
||||
i32* %e) {
|
||||
entry:
|
||||
|
||||
%cond = icmp eq i32* %e, null
|
||||
br i1 %cond, label %one, label %two
|
||||
one:
|
||||
br label %join
|
||||
two:
|
||||
br label %join
|
||||
join:
|
||||
|
||||
; The pointers need to be defined by PHIs in order for the bug to trigger.
|
||||
; Because of the PHIs the existing casts won't be at the desired location so a
|
||||
; new cast will be emitted and the old cast will get invalidated.
|
||||
;
|
||||
; These are the steps:
|
||||
;
|
||||
; 1. After the bounds for A and C are first expanded:
|
||||
;
|
||||
; join:
|
||||
; %a = phi i32* [ %a1, %one ], [ %a2, %two ]
|
||||
; %c = phi i32* [ %c1, %one ], [ %c2, %two ]
|
||||
; %c5 = bitcast i32* %c to i8*
|
||||
; %a3 = bitcast i32* %a to i8*
|
||||
;
|
||||
; 2. After A is expanded again:
|
||||
;
|
||||
; join: ; preds = %two, %one
|
||||
; %a = phi i32* [ %a1, %one ], [ %a2, %two ]
|
||||
; %c = phi i32* [ %c1, %one ], [ %c2, %two ]
|
||||
; %a3 = bitcast i32* %a to i8* <--- new
|
||||
; %c5 = bitcast i32* %c to i8*
|
||||
; %0 = bitcast i32* undef to i8* <--- old, invalidated
|
||||
;
|
||||
; 3. Finally, when C is expanded again:
|
||||
;
|
||||
; join: ; preds = %two, %one
|
||||
; %a = phi i32* [ %a1, %one ], [ %a2, %two ]
|
||||
; %c = phi i32* [ %c1, %one ], [ %c2, %two ]
|
||||
; %c5 = bitcast i32* %c to i8* <--- new
|
||||
; %a3 = bitcast i32* %a to i8*
|
||||
; %0 = bitcast i32* undef to i8* <--- old, invalidated
|
||||
; %1 = bitcast i32* undef to i8*
|
||||
|
||||
%a = phi i32* [%a1, %one], [%a2, %two]
|
||||
%c = phi i32* [%c1, %one], [%c2, %two]
|
||||
br label %for.body
|
||||
|
||||
|
||||
; CHECK: [[VALUE:%[0-9a-z]+]] = bitcast i32* undef to i8*
|
||||
; CHECK-NOT: [[VALUE]]
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %join ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -loop-vectorize -force-vector-width=4 \
|
||||
; RUN: -verify-loop-info -verify-dom-info -S < %s | FileCheck %s
|
||||
|
||||
; If only A and B can alias here, we don't need memchecks to distribute since
|
||||
; A and B are in the same partition. This used to cause a crash in the
|
||||
; memcheck generation.
|
||||
;
|
||||
; for (i = 0; i < n; i++) {
|
||||
; A[i + 1] = A[i] * B[i];
|
||||
; ------------------------------
|
||||
; C[i] = D[i] * E[i];
|
||||
; }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
define void @f(i32* %a,
|
||||
i32* %b,
|
||||
i32* noalias %c,
|
||||
i32* noalias %d,
|
||||
i32* noalias %e) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
; CHECK-NOT: memcheck:
|
||||
; CHECK: mul <4 x i32>
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
; RUN: opt -loop-simplify -loop-distribute -enable-loop-distribute -S -pass-remarks-missed=loop-distribute \
|
||||
; RUN: -pass-remarks-analysis=loop-distribute \
|
||||
; RUN: -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS
|
||||
; RUN: opt -loop-simplify -loop-distribute -enable-loop-distribute -S -pass-remarks-missed=loop-distribute \
|
||||
; RUN: -pass-remarks-analysis=loop-distribute \
|
||||
; RUN: < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS
|
||||
|
||||
; RUN: opt -passes='loop-simplify,require<aa>,loop-distribute' -S -pass-remarks-missed=loop-distribute \
|
||||
; RUN: -pass-remarks-analysis=loop-distribute \
|
||||
; RUN: -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS
|
||||
; RUN: opt -passes='loop-simplify,require<aa>,loop-distribute' -S -pass-remarks-missed=loop-distribute \
|
||||
; RUN: -pass-remarks-analysis=loop-distribute \
|
||||
; RUN: < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS
|
||||
|
||||
; This is the input program:
|
||||
;
|
||||
; 1 void forced (char *A, char *B, char *C, int N) {
|
||||
; 2 #pragma clang loop distribute(enable)
|
||||
; 3 for(int i = 0; i < N; i++) {
|
||||
; 4 A[i] = B[i] * C[i];
|
||||
; 5 }
|
||||
; 6 }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.11.0"
|
||||
|
||||
; HOTNESS: remark: /tmp/t.c:3:3: loop not distributed: use -Rpass-analysis=loop-distribute for more info (hotness: 300)
|
||||
; HOTNESS: remark: /tmp/t.c:3:3: loop not distributed: memory operations are safe for vectorization (hotness: 300)
|
||||
; NO_HOTNESS: remark: /tmp/t.c:3:3: loop not distributed: use -Rpass-analysis=loop-distribute for more info{{$}}
|
||||
; NO_HOTNESS: remark: /tmp/t.c:3:3: loop not distributed: memory operations are safe for vectorization{{$}}
|
||||
|
||||
define void @forced(i8* %A, i8* %B, i8* %C, i32 %N) !dbg !7 !prof !22 {
|
||||
entry:
|
||||
%cmp12 = icmp sgt i32 %N, 0, !dbg !9
|
||||
br i1 %cmp12, label %ph, label %for.cond.cleanup, !dbg !10, !prof !23
|
||||
|
||||
ph:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ]
|
||||
%arrayidx = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !12
|
||||
%0 = load i8, i8* %arrayidx, align 1, !dbg !12, !tbaa !13
|
||||
%arrayidx2 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !16
|
||||
%1 = load i8, i8* %arrayidx2, align 1, !dbg !16, !tbaa !13
|
||||
%mul = mul i8 %1, %0, !dbg !17
|
||||
%arrayidx6 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !18
|
||||
store i8 %mul, i8* %arrayidx6, align 1, !dbg !19, !tbaa !13
|
||||
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10
|
||||
%lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !10
|
||||
%exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !10
|
||||
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !10, !llvm.loop !20, !prof !24
|
||||
|
||||
for.cond.cleanup:
|
||||
ret void, !dbg !11
|
||||
}
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 267633) (llvm/trunk 267675)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
|
||||
!1 = !DIFile(filename: "/tmp/t.c", directory: "/tmp")
|
||||
!2 = !{}
|
||||
!3 = !{i32 2, !"Dwarf Version", i32 2}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!7 = distinct !DISubprogram(name: "forced", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
|
||||
!8 = !DISubroutineType(types: !2)
|
||||
!9 = !DILocation(line: 3, column: 20, scope: !7)
|
||||
!10 = !DILocation(line: 3, column: 3, scope: !7)
|
||||
!11 = !DILocation(line: 6, column: 1, scope: !7)
|
||||
!12 = !DILocation(line: 4, column: 12, scope: !7)
|
||||
!13 = !{!14, !14, i64 0}
|
||||
!14 = !{!"omnipotent char", !15, i64 0}
|
||||
!15 = !{!"Simple C/C++ TBAA"}
|
||||
!16 = !DILocation(line: 4, column: 19, scope: !7)
|
||||
!17 = !DILocation(line: 4, column: 17, scope: !7)
|
||||
!18 = !DILocation(line: 4, column: 5, scope: !7)
|
||||
!19 = !DILocation(line: 4, column: 10, scope: !7)
|
||||
!20 = distinct !{!20, !21}
|
||||
!21 = !{!"llvm.loop.distribute.enable", i1 true}
|
||||
!22 = !{!"function_entry_count", i64 3}
|
||||
!23 = !{!"branch_weights", i32 99, i32 1}
|
||||
!24 = !{!"branch_weights", i32 1, i32 99}
|
@ -1,179 +0,0 @@
|
||||
; RUN: opt -loop-simplify -loop-distribute -enable-loop-distribute -S < %s 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=ALWAYS --check-prefix=NO_REMARKS
|
||||
; RUN: opt -loop-simplify -loop-distribute -enable-loop-distribute -S \
|
||||
; RUN: -pass-remarks-missed=loop-distribute < %s 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=ALWAYS --check-prefix=MISSED_REMARKS
|
||||
; RUN: opt -loop-simplify -loop-distribute -enable-loop-distribute -S \
|
||||
; RUN: -pass-remarks-analysis=loop-distribute < %s 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=ALWAYS --check-prefix=ANALYSIS_REMARKS
|
||||
; RUN: opt -loop-simplify -loop-distribute -enable-loop-distribute -S \
|
||||
; RUN: -pass-remarks=loop-distribute < %s 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=ALWAYS --check-prefix=REMARKS
|
||||
|
||||
; This is the input program:
|
||||
;
|
||||
; 1 void forced (char *A, char *B, char *C, int N) {
|
||||
; 2 #pragma clang loop distribute(enable)
|
||||
; 3 for(int i = 0; i < N; i++) {
|
||||
; 4 A[i] = B[i] * C[i];
|
||||
; 5 }
|
||||
; 6 }
|
||||
; 7
|
||||
; 8 void not_forced (char *A, char *B, char *C, int N) {
|
||||
; 9 for(int i = 0; i < N; i++) {
|
||||
; 10 A[i] = B[i] * C[i];
|
||||
; 11 }
|
||||
; 12 }
|
||||
; 13
|
||||
; 14 void success (char *A, char *B, char *C, char *D, char *E, int N) {
|
||||
; 15 for(int i = 0; i < N; i++) {
|
||||
; 16 A[i + 1] = A[i] + B[i];
|
||||
; 17 C[i] = D[i] * E[i];
|
||||
; 18 }
|
||||
; 19 }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.11.0"
|
||||
|
||||
; MISSED_REMARKS: remark: /tmp/t.c:3:3: loop not distributed: use -Rpass-analysis=loop-distribute for more info
|
||||
; ALWAYS: remark: /tmp/t.c:3:3: loop not distributed: memory operations are safe for vectorization
|
||||
; ALWAYS: warning: /tmp/t.c:3:3: loop not distributed: failed explicitly specified loop distribution
|
||||
|
||||
define void @forced(i8* %A, i8* %B, i8* %C, i32 %N) !dbg !7 {
|
||||
entry:
|
||||
%cmp12 = icmp sgt i32 %N, 0, !dbg !9
|
||||
br i1 %cmp12, label %ph, label %for.cond.cleanup, !dbg !10
|
||||
|
||||
ph:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ]
|
||||
%arrayidx = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !12
|
||||
%0 = load i8, i8* %arrayidx, align 1, !dbg !12, !tbaa !13
|
||||
%arrayidx2 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !16
|
||||
%1 = load i8, i8* %arrayidx2, align 1, !dbg !16, !tbaa !13
|
||||
%mul = mul i8 %1, %0, !dbg !17
|
||||
%arrayidx6 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !18
|
||||
store i8 %mul, i8* %arrayidx6, align 1, !dbg !19, !tbaa !13
|
||||
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10
|
||||
%lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !10
|
||||
%exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !10
|
||||
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !10, !llvm.loop !20
|
||||
|
||||
for.cond.cleanup:
|
||||
ret void, !dbg !11
|
||||
}
|
||||
|
||||
; NO_REMARKS-NOT: remark: /tmp/t.c:9:3: loop not distributed: memory operations are safe for vectorization
|
||||
; MISSED_REMARKS: remark: /tmp/t.c:9:3: loop not distributed: use -Rpass-analysis=loop-distribute for more info
|
||||
; ANALYSIS_REMARKS: remark: /tmp/t.c:9:3: loop not distributed: memory operations are safe for vectorization
|
||||
; ALWAYS-NOT: warning: /tmp/t.c:9:3: loop not distributed: failed explicitly specified loop distribution
|
||||
|
||||
define void @not_forced(i8* %A, i8* %B, i8* %C, i32 %N) !dbg !22 {
|
||||
entry:
|
||||
%cmp12 = icmp sgt i32 %N, 0, !dbg !23
|
||||
br i1 %cmp12, label %ph, label %for.cond.cleanup, !dbg !24
|
||||
|
||||
ph:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ]
|
||||
%arrayidx = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !26
|
||||
%0 = load i8, i8* %arrayidx, align 1, !dbg !26, !tbaa !13
|
||||
%arrayidx2 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !27
|
||||
%1 = load i8, i8* %arrayidx2, align 1, !dbg !27, !tbaa !13
|
||||
%mul = mul i8 %1, %0, !dbg !28
|
||||
%arrayidx6 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !29
|
||||
store i8 %mul, i8* %arrayidx6, align 1, !dbg !30, !tbaa !13
|
||||
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !24
|
||||
%lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !24
|
||||
%exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !24
|
||||
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !24
|
||||
|
||||
for.cond.cleanup:
|
||||
ret void, !dbg !25
|
||||
}
|
||||
|
||||
; REMARKS: remark: /tmp/t.c:15:3: distributed loop
|
||||
|
||||
define void @success(i8* %A, i8* %B, i8* %C, i8* %D, i8* %E, i32 %N) !dbg !31 {
|
||||
entry:
|
||||
%cmp28 = icmp sgt i32 %N, 0, !dbg !32
|
||||
br i1 %cmp28, label %ph, label %for.cond.cleanup, !dbg !33
|
||||
|
||||
ph:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ]
|
||||
%arrayidx = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !35
|
||||
%0 = load i8, i8* %arrayidx, align 1, !dbg !35, !tbaa !13
|
||||
%arrayidx2 = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !36
|
||||
%1 = load i8, i8* %arrayidx2, align 1, !dbg !36, !tbaa !13
|
||||
%add = add i8 %1, %0, !dbg !37
|
||||
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !33
|
||||
%arrayidx7 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv.next, !dbg !38
|
||||
store i8 %add, i8* %arrayidx7, align 1, !dbg !39, !tbaa !13
|
||||
%arrayidx9 = getelementptr inbounds i8, i8* %D, i64 %indvars.iv, !dbg !40
|
||||
%2 = load i8, i8* %arrayidx9, align 1, !dbg !40, !tbaa !13
|
||||
%arrayidx12 = getelementptr inbounds i8, i8* %E, i64 %indvars.iv, !dbg !41
|
||||
%3 = load i8, i8* %arrayidx12, align 1, !dbg !41, !tbaa !13
|
||||
%mul = mul i8 %3, %2, !dbg !42
|
||||
%arrayidx16 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !43
|
||||
store i8 %mul, i8* %arrayidx16, align 1, !dbg !44, !tbaa !13
|
||||
%lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !33
|
||||
%exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !33
|
||||
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !33
|
||||
|
||||
for.cond.cleanup:
|
||||
ret void, !dbg !34
|
||||
}
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 267633) (llvm/trunk 267675)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
|
||||
!1 = !DIFile(filename: "/tmp/t.c", directory: "/tmp")
|
||||
!2 = !{}
|
||||
!3 = !{i32 2, !"Dwarf Version", i32 2}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!7 = distinct !DISubprogram(name: "forced", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
|
||||
!8 = !DISubroutineType(types: !2)
|
||||
!9 = !DILocation(line: 3, column: 20, scope: !7)
|
||||
!10 = !DILocation(line: 3, column: 3, scope: !7)
|
||||
!11 = !DILocation(line: 6, column: 1, scope: !7)
|
||||
!12 = !DILocation(line: 4, column: 12, scope: !7)
|
||||
!13 = !{!14, !14, i64 0}
|
||||
!14 = !{!"omnipotent char", !15, i64 0}
|
||||
!15 = !{!"Simple C/C++ TBAA"}
|
||||
!16 = !DILocation(line: 4, column: 19, scope: !7)
|
||||
!17 = !DILocation(line: 4, column: 17, scope: !7)
|
||||
!18 = !DILocation(line: 4, column: 5, scope: !7)
|
||||
!19 = !DILocation(line: 4, column: 10, scope: !7)
|
||||
!20 = distinct !{!20, !21}
|
||||
!21 = !{!"llvm.loop.distribute.enable", i1 true}
|
||||
!22 = distinct !DISubprogram(name: "not_forced", scope: !1, file: !1, line: 8, type: !8, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
|
||||
!23 = !DILocation(line: 9, column: 20, scope: !22)
|
||||
!24 = !DILocation(line: 9, column: 3, scope: !22)
|
||||
!25 = !DILocation(line: 12, column: 1, scope: !22)
|
||||
!26 = !DILocation(line: 10, column: 12, scope: !22)
|
||||
!27 = !DILocation(line: 10, column: 19, scope: !22)
|
||||
!28 = !DILocation(line: 10, column: 17, scope: !22)
|
||||
!29 = !DILocation(line: 10, column: 5, scope: !22)
|
||||
!30 = !DILocation(line: 10, column: 10, scope: !22)
|
||||
!31 = distinct !DISubprogram(name: "success", scope: !1, file: !1, line: 14, type: !8, isLocal: false, isDefinition: true, scopeLine: 14, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
|
||||
!32 = !DILocation(line: 15, column: 20, scope: !31)
|
||||
!33 = !DILocation(line: 15, column: 3, scope: !31)
|
||||
!34 = !DILocation(line: 19, column: 1, scope: !31)
|
||||
!35 = !DILocation(line: 16, column: 16, scope: !31)
|
||||
!36 = !DILocation(line: 16, column: 23, scope: !31)
|
||||
!37 = !DILocation(line: 16, column: 21, scope: !31)
|
||||
!38 = !DILocation(line: 16, column: 5, scope: !31)
|
||||
!39 = !DILocation(line: 16, column: 14, scope: !31)
|
||||
!40 = !DILocation(line: 17, column: 12, scope: !31)
|
||||
!41 = !DILocation(line: 17, column: 19, scope: !31)
|
||||
!42 = !DILocation(line: 17, column: 17, scope: !31)
|
||||
!43 = !DILocation(line: 17, column: 5, scope: !31)
|
||||
!44 = !DILocation(line: 17, column: 10, scope: !31)
|
@ -1,149 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute=0 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=EXPLICIT --check-prefix=DEFAULT_OFF
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute=1 -S < %s | FileCheck %s --check-prefix=CHECK --check-prefix=EXPLICIT --check-prefix=DEFAULT_ON
|
||||
|
||||
; Same loop as in basic.ll. Check that distribution is enabled/disabled
|
||||
; properly according to -enable-loop-distribute=0/1 and the
|
||||
; llvm.loop.distribute.enable metadata.
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
; CHECK-LABEL: @explicit_on(
|
||||
define void @explicit_on(i32* noalias %a,
|
||||
i32* noalias %b,
|
||||
i32* noalias %c,
|
||||
i32* noalias %d,
|
||||
i32* noalias %e) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
; EXPLICIT: for.body.ldist1:
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @explicit_off(
|
||||
define void @explicit_off(i32* noalias %a,
|
||||
i32* noalias %b,
|
||||
i32* noalias %c,
|
||||
i32* noalias %d,
|
||||
i32* noalias %e) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
; EXPLICIT-NOT: for.body.ldist1:
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !2
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @default_distribute(
|
||||
define void @default_distribute(i32* noalias %a,
|
||||
i32* noalias %b,
|
||||
i32* noalias %c,
|
||||
i32* noalias %d,
|
||||
i32* noalias %e) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
; Verify the two distributed loops.
|
||||
|
||||
; DEFAULT_ON: for.body.ldist1:
|
||||
; DEFAULT_OFF-NOT: for.body.ldist1:
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
||||
|
||||
!0 = distinct !{!0, !1}
|
||||
!1 = !{!"llvm.loop.distribute.enable", i1 true}
|
||||
!2 = distinct !{!2, !3}
|
||||
!3 = !{!"llvm.loop.distribute.enable", i1 false}
|
@ -1,95 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -verify-loop-info -verify-dom-info -S < %s \
|
||||
; RUN: | FileCheck %s
|
||||
|
||||
; We should distribute this loop along === but not along ---. The last
|
||||
; partition won't be vectorized due to conditional stores so it's better to
|
||||
; keep it with the second partition which has a dependence cycle.
|
||||
|
||||
; (1st statement):
|
||||
; for (i = 0; i < n; i++) {
|
||||
; C[i] = D[i] * E[i];
|
||||
;=============================
|
||||
; A[i + 1] = A[i] * B[i];
|
||||
;-----------------------------
|
||||
; if (F[i])
|
||||
; G[i] = H[i] * J[i];
|
||||
; }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
define void @f(i32* noalias %a,
|
||||
i32* noalias %b,
|
||||
i32* noalias %c,
|
||||
i32* noalias %d,
|
||||
i32* noalias %e,
|
||||
i32* noalias %g,
|
||||
i32* noalias %h,
|
||||
i32* noalias %j,
|
||||
i64 %x) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
; Ensure that we have only two partitions, the first with one multiplication
|
||||
; and the second with two.
|
||||
|
||||
; CHECK: for.body.ldist1:
|
||||
; CHECK: %mulC.ldist1 = mul i32 %loadD.ldist1, %loadE.ldist1
|
||||
; CHECK: br i1 %exitcond.ldist1, label %entry.split, label %for.body.ldist1
|
||||
; CHECK: entry.split:
|
||||
; CHECK: br label %for.body
|
||||
; CHECK: for.body:
|
||||
; CHECK: %mulA = mul i32 %loadB, %loadA
|
||||
; CHECK: %mulG = mul i32 %loadH, %loadJ
|
||||
; CHECK: for.end:
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %if.end ]
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%if.cond = icmp eq i64 %ind, %x
|
||||
br i1 %if.cond, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
%arrayidxH = getelementptr inbounds i32, i32* %h, i64 %ind
|
||||
%loadH = load i32, i32* %arrayidxH, align 4
|
||||
|
||||
%arrayidxJ = getelementptr inbounds i32, i32* %j, i64 %ind
|
||||
%loadJ = load i32, i32* %arrayidxJ, align 4
|
||||
|
||||
%mulG = mul i32 %loadH, %loadJ
|
||||
|
||||
%arrayidxG = getelementptr inbounds i32, i32* %g, i64 %ind
|
||||
store i32 %mulG, i32* %arrayidxG, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
; RUN: opt -loop-distribute -enable-loop-distribute -verify-loop-info -verify-dom-info -S < %s \
|
||||
; RUN: | FileCheck %s
|
||||
|
||||
; Check that definitions used outside the loop are handled correctly: (1) they
|
||||
; are not dropped (2) when version the loop, a phi is added to merge the value
|
||||
; from the non-distributed loop and the distributed loop.
|
||||
;
|
||||
; for (i = 0; i < n; i++) {
|
||||
; A[i + 1] = A[i] * B[i];
|
||||
; ==========================
|
||||
; sum += C[i];
|
||||
; }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
@B = common global i32* null, align 8
|
||||
@A = common global i32* null, align 8
|
||||
@C = common global i32* null, align 8
|
||||
@D = common global i32* null, align 8
|
||||
@E = common global i32* null, align 8
|
||||
@SUM = common global i32 0, align 8
|
||||
|
||||
define void @f() {
|
||||
entry:
|
||||
%a = load i32*, i32** @A, align 8
|
||||
%b = load i32*, i32** @B, align 8
|
||||
%c = load i32*, i32** @C, align 8
|
||||
%d = load i32*, i32** @D, align 8
|
||||
%e = load i32*, i32** @E, align 8
|
||||
|
||||
br label %for.body
|
||||
|
||||
; CHECK: for.body.ldist1:
|
||||
; CHECK: %mulA.ldist1 = mul i32 %loadB.ldist1, %loadA.ldist1
|
||||
; CHECK: for.body.ph:
|
||||
; CHECK: for.body:
|
||||
; CHECK: %sum_add = add nuw nsw i32 %sum, %loadC
|
||||
; CHECK: for.end:
|
||||
; CHECK: %sum_add.lver = phi i32 [ %sum_add, %for.body ], [ %sum_add.lver.orig, %for.body.lver.orig ]
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
%sum = phi i32 [ 0, %entry ], [ %sum_add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
%loadC = load i32, i32* %arrayidxC, align 4
|
||||
|
||||
%sum_add = add nuw nsw i32 %sum, %loadC
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
store i32 %sum_add, i32* @SUM, align 4
|
||||
ret void
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -verify-loop-info -verify-dom-info -S \
|
||||
; RUN: < %s | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define void @fn1(i64 %a, i64* %b) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%add75.epil = phi i64 [ %add7.epil, %for.body ], [ %a, %entry ]
|
||||
%add1.epil = add nsw i64 %add75.epil, 268435457
|
||||
%arrayidx.epil = getelementptr inbounds i64, i64* %b, i64 %add1.epil
|
||||
%load = load i64, i64* %arrayidx.epil, align 8
|
||||
%add5.epil = add nsw i64 %add75.epil, 805306369
|
||||
%arrayidx6.epil = getelementptr inbounds i64, i64* %b, i64 %add5.epil
|
||||
store i64 %load, i64* %arrayidx6.epil, align 8
|
||||
%add7.epil = add nsw i64 %add75.epil, 2
|
||||
%epil.iter.cmp = icmp eq i64 %add7.epil, 0
|
||||
br i1 %epil.iter.cmp, label %for.end, label %for.body
|
||||
|
||||
; CHECK: %[[phi:.*]] = phi i64
|
||||
; CHECK: %[[add1:.*]] = add nsw i64 %[[phi]], 268435457
|
||||
; CHECK: %[[gep1:.*]] = getelementptr inbounds i64, i64* %b, i64 %[[add1]]
|
||||
; CHECK: %[[load:.*]] = load i64, i64* %[[gep1]], align 8
|
||||
; CHECK: %[[add2:.*]] = add nsw i64 %[[phi]], 805306369
|
||||
; CHECK: %[[gep2:.*]] = getelementptr inbounds i64, i64* %b, i64 %[[add2]]
|
||||
; CHECK: store i64 %[[load]], i64* %[[gep2]], align 8
|
||||
; CHECK: %[[incr:.*]] = add nsw i64 %[[phi]], 2
|
||||
; CHECK: %[[cmp:.*]] = icmp eq i64 %[[incr]], 0
|
||||
; CHECK: br i1 %[[cmp]]
|
||||
|
||||
for.end:
|
||||
ret void
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
; RUN: opt -loop-distribute -enable-loop-distribute -S -verify-loop-info -verify-dom-info < %s \
|
||||
; RUN: | FileCheck %s
|
||||
|
||||
; Distributing this loop to avoid the dependence cycle would require to
|
||||
; reorder S1 and S2 to form the two partitions: {S2} | {S1, S3}. The analysis
|
||||
; provided by LoopAccessAnalysis does not allow us to reorder memory
|
||||
; operations so make sure we bail on this loop.
|
||||
;
|
||||
; for (i = 0; i < n; i++) {
|
||||
; S1: d = D[i];
|
||||
; S2: A[i + 1] = A[i] * B[i];
|
||||
; S3: C[i] = d * E[i];
|
||||
; }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
define void @f(i32* noalias %a,
|
||||
i32* noalias %b,
|
||||
i32* noalias %c,
|
||||
i32* noalias %d,
|
||||
i32* noalias %e) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
; CHECK: entry:
|
||||
; CHECK: br label %for.body
|
||||
; CHECK: for.body:
|
||||
; CHECK: br i1 %exitcond, label %for.end, label %for.body
|
||||
; CHECK: for.end:
|
||||
; CHECK: ret void
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
|
||||
%arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
|
||||
%loadE = load i32, i32* %arrayidxE, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadE
|
||||
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -S < %s | \
|
||||
; RUN: FileCheck %s --check-prefix=ALL --check-prefix=STRIDE_SPEC
|
||||
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -S -enable-mem-access-versioning=0 < %s | \
|
||||
; RUN: FileCheck %s --check-prefix=ALL --check-prefix=NO_STRIDE_SPEC
|
||||
|
||||
; If we don't speculate stride for 1 we can't distribute along the line
|
||||
; because we could have a backward dependence:
|
||||
;
|
||||
; for (i = 0; i < n; i++) {
|
||||
; A[i + 1] = A[i] * B[i];
|
||||
; =======================
|
||||
; C[i] = D[i] * A[stride * i];
|
||||
; }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.10.0"
|
||||
|
||||
; ALL-LABEL: @f(
|
||||
define void @f(i32* noalias %a,
|
||||
i32* noalias %b,
|
||||
i32* noalias %c,
|
||||
i32* noalias %d,
|
||||
i64 %stride) {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
; STRIDE_SPEC: %ident.check = icmp ne i64 %stride, 1
|
||||
|
||||
; STRIDE_SPEC: for.body.ldist1:
|
||||
; NO_STRIDE_SPEC-NOT: for.body.ldist1:
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulA = mul i32 %loadB, %loadA
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
|
||||
%loadD = load i32, i32* %arrayidxD, align 4
|
||||
|
||||
%mul = mul i64 %ind, %stride
|
||||
%arrayidxStridedA = getelementptr inbounds i32, i32* %a, i64 %mul
|
||||
%loadStridedA = load i32, i32* %arrayidxStridedA, align 4
|
||||
|
||||
%mulC = mul i32 %loadD, %loadStridedA
|
||||
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
; RUN: opt -basicaa -loop-distribute -enable-loop-distribute -S < %s | FileCheck %s
|
||||
|
||||
; If we can't find the bounds for one of the arrays in order to generate the
|
||||
; memchecks (e.g., C[i * i] below), loop shold not get distributed.
|
||||
;
|
||||
; for (i = 0; i < n; i++) {
|
||||
; A[i + 1] = A[i] * 3;
|
||||
; -------------------------------
|
||||
; C[i * i] = B[i] * 2;
|
||||
; }
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
||||
; Verify that we didn't distribute by checking that we still have the original
|
||||
; number of branches.
|
||||
|
||||
@A = common global i32* null, align 8
|
||||
@B = common global i32* null, align 8
|
||||
@C = common global i32* null, align 8
|
||||
|
||||
define void @f() {
|
||||
entry:
|
||||
%a = load i32*, i32** @A, align 8
|
||||
%b = load i32*, i32** @B, align 8
|
||||
%c = load i32*, i32** @C, align 8
|
||||
br label %for.body
|
||||
; CHECK: br
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
|
||||
%arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
|
||||
%loadA = load i32, i32* %arrayidxA, align 4
|
||||
|
||||
%mulA = mul i32 %loadA, 3
|
||||
|
||||
%add = add nuw nsw i64 %ind, 1
|
||||
%arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
|
||||
store i32 %mulA, i32* %arrayidxA_plus_4, align 4
|
||||
|
||||
%arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
|
||||
%loadB = load i32, i32* %arrayidxB, align 4
|
||||
|
||||
%mulC = mul i32 %loadB, 2
|
||||
|
||||
%ind_2 = mul i64 %ind, %ind
|
||||
%arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind_2
|
||||
store i32 %mulC, i32* %arrayidxC, align 4
|
||||
|
||||
%exitcond = icmp eq i64 %add, 20
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
; CHECK: br
|
||||
; CHECK-NOT: br
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
Reference in New Issue
Block a user