Files
clang-p2996/polly/test/ForwardOpTree/forward_synthesizable_useinloop.ll
Michael Kruse 9f6e41cdba [ForwardOpTree] Support synthesizable values.
This allows -polly-optree to move instructions that depend on
synthesizable values.

The difficulty for synthesizable values is that their value depends on
the location. When it is moved over a loop header, and the SCEV
expression depends on the loop induction variable (SCEVAddRecExpr), it
would use the current induction variable instead of the last one.

At the moment we cannot forward PHI nodes such that crossing the header
of loops referenced by SCEVAddRecExpr is not possible (assuming the loop
header has at least two incoming blocks: for entering the loop and the
backedge, such any instruction to be forwarded must have a phi between
use and definition).

A remaining issue is when the forwarded value is used after the loop,
but is only synthesizable inside the loop. This happens e.g. if
ScalarEvolution is unable to determine the number of loop iterations or
the initial loop value. We do not forward in this situation.

Differential Revision: https://reviews.llvm.org/D36102

llvm-svn: 309609
2017-07-31 19:46:21 +00:00

81 lines
1.9 KiB
LLVM

; RUN: opt %loadPolly -polly-optree -analyze < %s | FileCheck %s -match-full-lines
;
; Synthesizable values defined outside of a loop can be used
; inside the loop.
;
; for (int j = 0; j < n; j += 1) {
; bodyA:
; double val = j;
;
; for (int i = 0; i < n; i += 1) {
; bodyB:
; A[0] = val;
; }
; }
;
define void @func(i32 %n, double* noalias nonnull %A) {
entry:
br label %for
for:
%j = phi i32 [0, %entry], [%j.inc, %inc]
%j.cmp = icmp slt i32 %j, %n
br i1 %j.cmp, label %bodyA, label %exit
bodyA:
%val = sitofp i32 %j to double
br label %inner.for
inner.for:
%i = phi i32 [0, %bodyA], [%i.inc, %inner.inc]
%i.cmp = icmp slt i32 %i, %n
br i1 %i.cmp, label %bodyB, label %inner.exit
bodyB:
store double %val, double* %A
br label %inner.inc
inner.inc:
%i.inc = add nuw nsw i32 %i, 1
br label %inner.for
inner.exit:
br label %inc
inc:
%j.inc = add nuw nsw i32 %j, 1
br label %for
exit:
br label %return
return:
ret void
}
; CHECK: Statistics {
; CHECK: Instructions copied: 1
; CHECK: Operand trees forwarded: 1
; CHECK: Statements with forwarded operand trees: 1
; CHECK: }
; CHECK: After statements {
; CHECK-NEXT: Stmt_bodyA
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1]
; CHECK-NEXT: [n] -> { Stmt_bodyA[i0] -> MemRef_val[] };
; CHECK-NEXT: Instructions {
; CHECK-NEXT: %val = sitofp i32 %j to double
; CHECK-NEXT: }
; CHECK-NEXT: Stmt_bodyB
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [n] -> { Stmt_bodyB[i0, i1] -> MemRef_A[0] };
; CHECK-NEXT: Instructions {
; CHECK-NEXT: %val = sitofp i32 %j to double
; CHECK-NEXT: store double %val, double* %A
; CHECK-NEXT: }
; CHECK-NEXT: }