forked from OSchip/llvm-project
[Support/DepInfo] Introduce IslMaxOperationsGuard and make DepInfo use it. NFC.
IslMaxOperationsGuard defines a scope where ISL may abort operations because if it takes too many operations. Replace the call to the raw ISL interface by a use of the guard. IslMaxOperationsGuard provides a uniform way to define a maximal computation time for a code region in C++ using RAII. llvm-svn: 283744
This commit is contained in:
parent
1eb779b5ae
commit
8bfba1ff46
|
@ -19,6 +19,7 @@
|
||||||
#include "isl/aff.h"
|
#include "isl/aff.h"
|
||||||
#include "isl/ctx.h"
|
#include "isl/ctx.h"
|
||||||
#include "isl/map.h"
|
#include "isl/map.h"
|
||||||
|
#include "isl/options.h"
|
||||||
#include "isl/set.h"
|
#include "isl/set.h"
|
||||||
#include "isl/union_map.h"
|
#include "isl/union_map.h"
|
||||||
#include "isl/union_set.h"
|
#include "isl/union_set.h"
|
||||||
|
@ -425,6 +426,70 @@ isl_stat foreachPieceWithBreak(
|
||||||
NonowningIslPtr<isl_pw_aff> PwAff,
|
NonowningIslPtr<isl_pw_aff> PwAff,
|
||||||
const std::function<isl_stat(IslPtr<isl_set>, IslPtr<isl_aff>)> &F);
|
const std::function<isl_stat(IslPtr<isl_set>, IslPtr<isl_aff>)> &F);
|
||||||
|
|
||||||
|
/// Scoped limit of ISL operations.
|
||||||
|
///
|
||||||
|
/// Limits the number of ISL operations during the lifetime of this object. The
|
||||||
|
/// idea is to use this as an RAII guard for the scope where the code is aware
|
||||||
|
/// that ISL can return errors even when all input is valid. After leaving the
|
||||||
|
/// scope, it will return to the error setting as it was before. That also means
|
||||||
|
/// that the error setting should not be changed while in that scope.
|
||||||
|
///
|
||||||
|
/// Such scopes are not allowed to be nested because the previous operations
|
||||||
|
/// counter cannot be reset to the previous state, or one that adds the
|
||||||
|
/// operations while being in the nested scope. Use therefore is only allowed
|
||||||
|
/// while currently a no operations-limit is active.
|
||||||
|
class IslMaxOperationsGuard {
|
||||||
|
private:
|
||||||
|
/// The ISL context to set the operations limit.
|
||||||
|
///
|
||||||
|
/// If set to nullptr, there is no need for any action at the end of the
|
||||||
|
/// scope.
|
||||||
|
isl_ctx *IslCtx;
|
||||||
|
|
||||||
|
/// Old OnError setting; to reset to when the scope ends.
|
||||||
|
int OldOnError;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Enter a max operations scope.
|
||||||
|
///
|
||||||
|
/// @param IslCtx The ISL context to set the operations limit for.
|
||||||
|
/// @param LocalMaxOps Maximum number of operations allowed in the
|
||||||
|
/// scope. If set to zero, no operations limit is enforced.
|
||||||
|
IslMaxOperationsGuard(isl_ctx *IslCtx, unsigned long LocalMaxOps)
|
||||||
|
: IslCtx(IslCtx) {
|
||||||
|
assert(IslCtx);
|
||||||
|
assert(isl_ctx_get_max_operations(IslCtx) == 0 &&
|
||||||
|
"Nested max operations not supported");
|
||||||
|
|
||||||
|
if (LocalMaxOps == 0) {
|
||||||
|
// No limit on operations; also disable restoring on_error/max_operations.
|
||||||
|
this->IslCtx = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save previous state.
|
||||||
|
OldOnError = isl_options_get_on_error(IslCtx);
|
||||||
|
|
||||||
|
// Activate the new setting.
|
||||||
|
isl_ctx_set_max_operations(IslCtx, LocalMaxOps);
|
||||||
|
isl_ctx_reset_operations(IslCtx);
|
||||||
|
isl_options_set_on_error(IslCtx, ISL_ON_ERROR_CONTINUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Leave the max operations scope.
|
||||||
|
~IslMaxOperationsGuard() {
|
||||||
|
if (!IslCtx)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(isl_options_get_on_error(IslCtx) == ISL_ON_ERROR_CONTINUE &&
|
||||||
|
"Unexpected change of the on_error setting");
|
||||||
|
|
||||||
|
// Return to the previous error setting.
|
||||||
|
isl_ctx_set_max_operations(IslCtx, 0);
|
||||||
|
isl_options_set_on_error(IslCtx, OldOnError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace polly
|
} // end namespace polly
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -370,74 +370,71 @@ void Dependences::calculateDependences(Scop &S) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long MaxOpsOld = isl_ctx_get_max_operations(IslCtx.get());
|
{
|
||||||
if (OptComputeOut) {
|
IslMaxOperationsGuard MaxOpGuard(IslCtx.get(), OptComputeOut);
|
||||||
isl_ctx_reset_operations(IslCtx.get());
|
|
||||||
isl_ctx_set_max_operations(IslCtx.get(), OptComputeOut);
|
DEBUG(dbgs() << "Read: " << Read << "\n";
|
||||||
|
dbgs() << "Write: " << Write << "\n";
|
||||||
|
dbgs() << "MayWrite: " << MayWrite << "\n";
|
||||||
|
dbgs() << "Schedule: " << Schedule << "\n");
|
||||||
|
|
||||||
|
RAW = WAW = WAR = RED = nullptr;
|
||||||
|
|
||||||
|
if (OptAnalysisType == VALUE_BASED_ANALYSIS) {
|
||||||
|
isl_union_flow *Flow;
|
||||||
|
|
||||||
|
Flow = buildFlow(Read, Write, MayWrite, Schedule);
|
||||||
|
|
||||||
|
RAW = isl_union_flow_get_must_dependence(Flow);
|
||||||
|
isl_union_flow_free(Flow);
|
||||||
|
|
||||||
|
Flow = buildFlow(Write, Write, Read, Schedule);
|
||||||
|
|
||||||
|
WAW = isl_union_flow_get_must_dependence(Flow);
|
||||||
|
WAR = isl_union_flow_get_may_dependence(Flow);
|
||||||
|
|
||||||
|
// This subtraction is needed to obtain the same results as were given by
|
||||||
|
// isl_union_map_compute_flow. For large sets this may add some
|
||||||
|
// compile-time cost. As there does not seem to be a need to distinguish
|
||||||
|
// between WAW and WAR, refactoring Polly to only track general non-flow
|
||||||
|
// dependences may improve performance.
|
||||||
|
WAR = isl_union_map_subtract(WAR, isl_union_map_copy(WAW));
|
||||||
|
|
||||||
|
isl_union_flow_free(Flow);
|
||||||
|
isl_schedule_free(Schedule);
|
||||||
|
} else {
|
||||||
|
isl_union_flow *Flow;
|
||||||
|
|
||||||
|
Write = isl_union_map_union(Write, isl_union_map_copy(MayWrite));
|
||||||
|
|
||||||
|
Flow = buildFlow(Read, nullptr, Write, Schedule);
|
||||||
|
|
||||||
|
RAW = isl_union_flow_get_may_dependence(Flow);
|
||||||
|
isl_union_flow_free(Flow);
|
||||||
|
|
||||||
|
Flow = buildFlow(Write, nullptr, Read, Schedule);
|
||||||
|
|
||||||
|
WAR = isl_union_flow_get_may_dependence(Flow);
|
||||||
|
isl_union_flow_free(Flow);
|
||||||
|
|
||||||
|
Flow = buildFlow(Write, nullptr, Write, Schedule);
|
||||||
|
|
||||||
|
WAW = isl_union_flow_get_may_dependence(Flow);
|
||||||
|
isl_union_flow_free(Flow);
|
||||||
|
isl_schedule_free(Schedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
isl_union_map_free(MayWrite);
|
||||||
|
isl_union_map_free(Write);
|
||||||
|
isl_union_map_free(Read);
|
||||||
|
|
||||||
|
RAW = isl_union_map_coalesce(RAW);
|
||||||
|
WAW = isl_union_map_coalesce(WAW);
|
||||||
|
WAR = isl_union_map_coalesce(WAR);
|
||||||
|
|
||||||
|
// End of max_operations scope.
|
||||||
}
|
}
|
||||||
|
|
||||||
auto OnErrorStatus = isl_options_get_on_error(IslCtx.get());
|
|
||||||
isl_options_set_on_error(IslCtx.get(), ISL_ON_ERROR_CONTINUE);
|
|
||||||
|
|
||||||
DEBUG(dbgs() << "Read: " << Read << "\n";
|
|
||||||
dbgs() << "Write: " << Write << "\n";
|
|
||||||
dbgs() << "MayWrite: " << MayWrite << "\n";
|
|
||||||
dbgs() << "Schedule: " << Schedule << "\n");
|
|
||||||
|
|
||||||
RAW = WAW = WAR = RED = nullptr;
|
|
||||||
|
|
||||||
if (OptAnalysisType == VALUE_BASED_ANALYSIS) {
|
|
||||||
isl_union_flow *Flow;
|
|
||||||
|
|
||||||
Flow = buildFlow(Read, Write, MayWrite, Schedule);
|
|
||||||
|
|
||||||
RAW = isl_union_flow_get_must_dependence(Flow);
|
|
||||||
isl_union_flow_free(Flow);
|
|
||||||
|
|
||||||
Flow = buildFlow(Write, Write, Read, Schedule);
|
|
||||||
|
|
||||||
WAW = isl_union_flow_get_must_dependence(Flow);
|
|
||||||
WAR = isl_union_flow_get_may_dependence(Flow);
|
|
||||||
|
|
||||||
// This subtraction is needed to obtain the same results as were given by
|
|
||||||
// isl_union_map_compute_flow. For large sets this may add some compile-time
|
|
||||||
// cost. As there does not seem to be a need to distinguish between WAW and
|
|
||||||
// WAR, refactoring Polly to only track general non-flow dependences may
|
|
||||||
// improve performance.
|
|
||||||
WAR = isl_union_map_subtract(WAR, isl_union_map_copy(WAW));
|
|
||||||
|
|
||||||
isl_union_flow_free(Flow);
|
|
||||||
isl_schedule_free(Schedule);
|
|
||||||
} else {
|
|
||||||
isl_union_flow *Flow;
|
|
||||||
|
|
||||||
Write = isl_union_map_union(Write, isl_union_map_copy(MayWrite));
|
|
||||||
|
|
||||||
Flow = buildFlow(Read, nullptr, Write, Schedule);
|
|
||||||
|
|
||||||
RAW = isl_union_flow_get_may_dependence(Flow);
|
|
||||||
isl_union_flow_free(Flow);
|
|
||||||
|
|
||||||
Flow = buildFlow(Write, nullptr, Read, Schedule);
|
|
||||||
|
|
||||||
WAR = isl_union_flow_get_may_dependence(Flow);
|
|
||||||
isl_union_flow_free(Flow);
|
|
||||||
|
|
||||||
Flow = buildFlow(Write, nullptr, Write, Schedule);
|
|
||||||
|
|
||||||
WAW = isl_union_flow_get_may_dependence(Flow);
|
|
||||||
isl_union_flow_free(Flow);
|
|
||||||
isl_schedule_free(Schedule);
|
|
||||||
}
|
|
||||||
|
|
||||||
isl_union_map_free(MayWrite);
|
|
||||||
isl_union_map_free(Write);
|
|
||||||
isl_union_map_free(Read);
|
|
||||||
|
|
||||||
RAW = isl_union_map_coalesce(RAW);
|
|
||||||
WAW = isl_union_map_coalesce(WAW);
|
|
||||||
WAR = isl_union_map_coalesce(WAR);
|
|
||||||
|
|
||||||
if (isl_ctx_last_error(IslCtx.get()) == isl_error_quota) {
|
if (isl_ctx_last_error(IslCtx.get()) == isl_error_quota) {
|
||||||
isl_union_map_free(RAW);
|
isl_union_map_free(RAW);
|
||||||
isl_union_map_free(WAW);
|
isl_union_map_free(WAW);
|
||||||
|
@ -445,9 +442,6 @@ void Dependences::calculateDependences(Scop &S) {
|
||||||
RAW = WAW = WAR = nullptr;
|
RAW = WAW = WAR = nullptr;
|
||||||
isl_ctx_reset_error(IslCtx.get());
|
isl_ctx_reset_error(IslCtx.get());
|
||||||
}
|
}
|
||||||
isl_options_set_on_error(IslCtx.get(), OnErrorStatus);
|
|
||||||
isl_ctx_reset_operations(IslCtx.get());
|
|
||||||
isl_ctx_set_max_operations(IslCtx.get(), MaxOpsOld);
|
|
||||||
|
|
||||||
// Drop out early, as the remaining computations are only needed for
|
// Drop out early, as the remaining computations are only needed for
|
||||||
// reduction dependences or dependences that are finer than statement
|
// reduction dependences or dependences that are finer than statement
|
||||||
|
|
Loading…
Reference in New Issue