mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
78ffabf782
This pass interchanges loops to provide a more cache-friendly memory access. For e.g. given a loop like - for(int i=0;i<N;i++) for(int j=0;j<N;j++) A[j][i] = A[j][i]+B[j][i]; is interchanged to - for(int j=0;j<N;j++) for(int i=0;i<N;i++) A[j][i] = A[j][i]+B[j][i]; This pass is currently disabled by default. To give a brief introduction it consists of 3 stages- LoopInterchangeLegality : Checks the legality of loop interchange based on Dependency matrix. LoopInterchangeProfitability: A very basic heuristic has been added to check for profitibility. This will evolve over time. LoopInterchangeTransform : Which does the actual transform. LNT Performance tests shows improvement in Polybench/linear-algebra/kernels/mvt and Polybench/linear-algebra/kernels/gemver becnmarks. TODO: 1) Add support for reductions and lcssa phi. 2) Improve profitability model. 3) Improve loop selection algorithm to select best loop for interchange. Currently the innermost loop is selected for interchange. 4) Improve compile time regression found in llvm lnt due to this pass. 5) Fix issues in Dependency Analysis module. A special thanks to Hal for reviewing this code. Review: http://reviews.llvm.org/D7499 llvm-svn: 231458
59 lines
2.5 KiB
LLVM
59 lines
2.5 KiB
LLVM
; RUN: opt < %s -basicaa -loop-interchange -S | FileCheck %s
|
|
;; These are test that fail to interchange due to current limitation. This will go off once we extend the loop interchange pass.
|
|
|
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
@A = common global [100 x [100 x i32]] zeroinitializer
|
|
@B = common global [100 x [100 x [100 x i32]]] zeroinitializer
|
|
|
|
;;--------------------------------------Test case 01------------------------------------
|
|
;; [FIXME] This loop though valid is currently not interchanged due to the limitation that we cannot split the inner loop latch due to multiple use of inner induction
|
|
;; variable.(used to increment the loop counter and to access A[j+1][i+1]
|
|
;; for(int i=0;i<N-1;i++)
|
|
;; for(int j=1;j<N-1;j++)
|
|
;; A[j+1][i+1] = A[j+1][i+1] + k;
|
|
|
|
define void @interchange_01(i32 %k, i32 %N) {
|
|
entry:
|
|
%sub = add nsw i32 %N, -1
|
|
%cmp26 = icmp sgt i32 %N, 1
|
|
br i1 %cmp26, label %for.cond1.preheader.lr.ph, label %for.end17
|
|
|
|
for.cond1.preheader.lr.ph:
|
|
%cmp324 = icmp sgt i32 %sub, 1
|
|
%0 = add i32 %N, -2
|
|
%1 = sext i32 %sub to i64
|
|
br label %for.cond1.preheader
|
|
|
|
for.cond.loopexit:
|
|
%cmp = icmp slt i64 %indvars.iv.next29, %1
|
|
br i1 %cmp, label %for.cond1.preheader, label %for.end17
|
|
|
|
for.cond1.preheader:
|
|
%indvars.iv28 = phi i64 [ 0, %for.cond1.preheader.lr.ph ], [ %indvars.iv.next29, %for.cond.loopexit ]
|
|
%indvars.iv.next29 = add nuw nsw i64 %indvars.iv28, 1
|
|
br i1 %cmp324, label %for.body4, label %for.cond.loopexit
|
|
|
|
for.body4:
|
|
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body4 ], [ 1, %for.cond1.preheader ]
|
|
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
|
|
%arrayidx7 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %indvars.iv.next, i64 %indvars.iv.next29
|
|
%2 = load i32, i32* %arrayidx7
|
|
%add8 = add nsw i32 %2, %k
|
|
store i32 %add8, i32* %arrayidx7
|
|
%lftr.wideiv = trunc i64 %indvars.iv to i32
|
|
%exitcond = icmp eq i32 %lftr.wideiv, %0
|
|
br i1 %exitcond, label %for.cond.loopexit, label %for.body4
|
|
|
|
for.end17:
|
|
ret void
|
|
}
|
|
;; Inner loop not split so it is not interchanged.
|
|
; CHECK-LABEL: @interchange_01
|
|
; CHECK: for.body4:
|
|
; CHECK-NEXT: %indvars.iv = phi i64 [ %indvars.iv.next, %for.body4 ], [ 1, %for.body4.preheader ]
|
|
; CHECK-NEXT: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
|
|
; CHECK-NEXT: %arrayidx7 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %indvars.iv.next, i64 %indvars.iv.next29
|
|
|