[DeLICM] Properly handle PHI writes becoming empty partial writes.

It is possible that partial writes are empty (write is never executed).
In this case, when in PHINode's incoming edge is never taken such that
the incoming write becomes an empty partial write, if enabled. The
issue is that when converting the union_map to an map, it's space
cannot be derived from the union_map itself. Rather, we need to
determine its space independently.

This fixes test-suite's MultiSource/Benchmarks/ASC_Sequoia/CrystalMk.

llvm-svn: 310348
This commit is contained in:
Michael Kruse 2017-08-08 11:27:12 +00:00
parent 4003a98eec
commit 27c010a22e
2 changed files with 88 additions and 3 deletions

View File

@ -1048,6 +1048,9 @@ private:
void mapPHI(const ScopArrayInfo *SAI, isl::map ReadTarget,
isl::union_map WriteTarget, isl::map Lifetime,
Knowledge Proposed) {
// { Element[] }
isl::space ElementSpace = ReadTarget.get_space().range();
// Redirect the PHI incoming writes.
for (auto *MA : S->getPHIIncomings(SAI)) {
// { DomainWrite[] }
@ -1055,11 +1058,13 @@ private:
// { DomainWrite[] -> Element[] }
auto NewAccRel = give(isl_union_map_intersect_domain(
WriteTarget.copy(), isl_union_set_from_set(Domain.take())));
WriteTarget.copy(), isl_union_set_from_set(Domain.copy())));
simplify(NewAccRel);
assert(isl_union_map_n_map(NewAccRel.keep()) == 1);
MA->setNewAccessRelation(isl::map::from_union_map(NewAccRel));
isl::space NewAccRelSpace =
Domain.get_space().map_from_domain_and_range(ElementSpace);
isl::map NewAccRelMap = singleton(NewAccRel, NewAccRelSpace);
MA->setNewAccessRelation(NewAccRelMap);
}
// Redirect the PHI read.

View File

@ -0,0 +1,80 @@
; RUN: opt %loadPolly -polly-flatten-schedule -polly-delicm-overapproximate-writes=true -polly-delicm-compute-known=true -polly-delicm -analyze < %s | FileCheck %s
;
; Verify that delicm can cope with never taken PHI incoming edges.
; The edge %body -> %body_phi is never taken, hence the access MemoryKind::PHI,
; WRITE in %body for %phi is never used.
; When mapping %phi, the write's access relation is the empty set.
;
; void func(double *A) {
; for (int j = 0; j < 2; j += 1) { /* outer */
; for (int i = 0; i < 4; i += 1) { /* reduction */
; double phi = 21.0;
; if (j < 10) // Tautology, since 0<=j<2
; phi = 42.0;
; }
; A[j] = phi;
; }
; }
;
define void @func(double* noalias nonnull %A, double* noalias nonnull %dummy) {
entry:
br label %outer.preheader
outer.preheader:
br label %outer.for
outer.for:
%j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc]
%j.cmp = icmp slt i32 %j, 2
br i1 %j.cmp, label %reduction.preheader, label %outer.exit
reduction.preheader:
%A_idx = getelementptr inbounds double, double* %A, i32 %j
br label %reduction.for
reduction.for:
%i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc]
br label %body
body:
%cond = icmp slt i32 %j, 10
br i1 %cond, label %alwaystaken, label %body_phi
alwaystaken:
store double 0.0, double* %dummy
br label %body_phi
body_phi:
%phi = phi double [21.0, %body], [42.0, %alwaystaken]
br label %reduction.inc
reduction.inc:
%i.inc = add nuw nsw i32 %i, 1
%i.cmp = icmp slt i32 %i.inc, 4
br i1 %i.cmp, label %reduction.for, label %reduction.exit
reduction.exit:
store double %phi, double* %A_idx
br label %outer.inc
outer.inc:
%j.inc = add nuw nsw i32 %j, 1
br label %outer.for
outer.exit:
br label %return
return:
ret void
}
; CHECK: Statistics {
; CHECK: PHI scalars mapped: 1
; CHECK: }