Dependences: Bound the time dependence calculation is allowed to take

Count the number of computational steps that have been used to solve the
dependence problem and abort in case we reach the "compute-out". This ensures we
do not hang forever in cases the dependence problem is too difficult to solve.
There is just a single case in the LLVM test-suite that runs into the
compute-out. Even in this case, we can probably coalesce some of the parameters
(i32 b, i32 b zext i64, ...) to simplify the problem enough to not hit the
compute out. However, for now we set the compute out in place to address the
general issue. The compute out was choosen such that it stops on a recent laptop
after about 8 seconds.

llvm-svn: 200156
This commit is contained in:
Tobias Grosser 2014-01-26 19:38:34 +00:00
parent a38c92406c
commit b917f47fc4
2 changed files with 114 additions and 3 deletions

View File

@ -26,8 +26,10 @@
#include "polly/ScopInfo.h"
#include "polly/Support/GICHelper.h"
#include <isl/aff.h>
#include <isl/ctx.h>
#include <isl/flow.h>
#include <isl/map.h>
#include <isl/options.h>
#include <isl/set.h>
#define DEBUG_TYPE "polly-dependence"
@ -36,6 +38,12 @@
using namespace polly;
using namespace llvm;
static cl::opt<int>
OptComputeOut("polly-dependences-computeout",
cl::desc("Bound the dependence analysis by a maximal amount of "
"computational steps"),
cl::Hidden, cl::init(100000), cl::cat(PollyCategory));
static cl::opt<bool>
LegalityCheckDisabled("disable-polly-legality",
cl::desc("Disable polly legality check"), cl::Hidden,
@ -96,11 +104,17 @@ void Dependences::calculateDependences(Scop &S) {
Write = isl_union_map_coalesce(Write);
MayWrite = isl_union_map_coalesce(MayWrite);
long MaxOpsOld = isl_ctx_get_max_operations(S.getIslCtx());
isl_ctx_set_max_operations(S.getIslCtx(), OptComputeOut);
isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE);
DEBUG(dbgs() << "Read: " << Read << "\n";
dbgs() << "Write: " << Write << "\n";
dbgs() << "MayWrite: " << MayWrite << "\n";
dbgs() << "Schedule: " << Schedule << "\n");
WAW = WAW = WAR;
if (OptAnalysisType == VALUE_BASED_ANALYSIS) {
isl_union_map_compute_flow(
isl_union_map_copy(Read), isl_union_map_copy(Write),
@ -143,6 +157,17 @@ void Dependences::calculateDependences(Scop &S) {
WAW = isl_union_map_coalesce(WAW);
WAR = isl_union_map_coalesce(WAR);
if (isl_ctx_last_error(S.getIslCtx()) == isl_error_quota) {
isl_union_map_free(RAW);
isl_union_map_free(WAW);
isl_union_map_free(WAR);
RAW = WAW = WAR = NULL;
isl_ctx_reset_error(S.getIslCtx());
}
isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT);
isl_ctx_reset_operations(S.getIslCtx());
isl_ctx_set_max_operations(S.getIslCtx(), MaxOpsOld);
DEBUG(printScop(dbgs()));
}
@ -262,9 +287,23 @@ bool Dependences::isParallelDimension(__isl_take isl_set *ScheduleSubset,
}
void Dependences::printScop(raw_ostream &OS) const {
OS << "\tRAW dependences:\n\t\t" << RAW << "\n";
OS << "\tWAR dependences:\n\t\t" << WAR << "\n";
OS << "\tWAW dependences:\n\t\t" << WAW << "\n";
OS << "\tRAW dependences:\n\t\t";
if (RAW)
OS << RAW << "\n";
else
OS << "n/a\n";
OS << "\tWAR dependences:\n\t\t";
if (WAR)
OS << WAR << "\n";
else
OS << "n/a\n";
OS << "\tWAW dependences:\n\t\t";
if (WAW)
OS << WAW << "\n";
else
OS << "n/a\n";
}
void Dependences::releaseMemory() {

View File

@ -0,0 +1,72 @@
; RUN: opt -S %loadPolly -basicaa -polly-dependences -analyze < %s | FileCheck %s -check-prefix=VALUE
; RUN: opt -S %loadPolly -basicaa -polly-dependences -analyze -polly-dependences-computeout=1 < %s | FileCheck %s -check-prefix=TIMEOUT
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"
target triple = "x86_64-pc-linux-gnu"
; for(i = 0; i < 100; i++ )
; S1: A[i] = 2;
;
; for (i = 0; i < 10; i++ )
; S2: A[i] = 5;
;
; for (i = 0; i < 200; i++ )
; S3: A[i] = 5;
define void @sequential_writes() {
entry:
%A = alloca [200 x i32]
br label %S1
S1:
%indvar.1 = phi i64 [ 0, %entry ], [ %indvar.next.1, %S1 ]
%arrayidx.1 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.1
store i32 2, i32* %arrayidx.1
%indvar.next.1 = add i64 %indvar.1, 1
%exitcond.1 = icmp ne i64 %indvar.next.1, 100
br i1 %exitcond.1, label %S1, label %exit.1
exit.1:
br label %S2
S2:
%indvar.2 = phi i64 [ 0, %exit.1 ], [ %indvar.next.2, %S2 ]
%arrayidx.2 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.2
store i32 5, i32* %arrayidx.2
%indvar.next.2 = add i64 %indvar.2, 1
%exitcond.2 = icmp ne i64 %indvar.next.2, 10
br i1 %exitcond.2, label %S2, label %exit.2
exit.2:
br label %S3
S3:
%indvar.3 = phi i64 [ 0, %exit.2 ], [ %indvar.next.3, %S3 ]
%arrayidx.3 = getelementptr [200 x i32]* %A, i64 0, i64 %indvar.3
store i32 7, i32* %arrayidx.3
%indvar.next.3 = add i64 %indvar.3, 1
%exitcond.3 = icmp ne i64 %indvar.next.3, 200
br i1 %exitcond.3, label %S3 , label %exit.3
exit.3:
ret void
}
; VALUE: region: 'S1 => exit.3' in function 'sequential_writes':
; VALUE: RAW dependences:
; VALUE: { }
; VALUE: WAR dependences:
; VALUE: { }
; VALUE: WAW dependences:
; VALUE: {
; VALUE: Stmt_S1[i0] -> Stmt_S2[i0] : i0 >= 0 and i0 <= 9;
; VALUE: Stmt_S2[i0] -> Stmt_S3[i0] : i0 >= 0 and i0 <= 9;
; VALUE: Stmt_S1[i0] -> Stmt_S3[i0] : i0 >= 10 and i0 <= 99
; VALUE: }
; TIMEOUT: region: 'S1 => exit.3' in function 'sequential_writes':
; TIMEOUT: RAW dependences:
; TIMEOUT: n/a
; TIMEOUT: WAR dependences:
; TIMEOUT: n/a
; TIMEOUT: WAW dependences:
; TIMEOUT: n/a