diff options
-rw-r--r-- | polly/lib/Transform/DeLICM.cpp | 14 | ||||
-rw-r--r-- | polly/test/DeLICM/noninjective_phi_relation.ll | 115 |
2 files changed, 128 insertions, 1 deletions
diff --git a/polly/lib/Transform/DeLICM.cpp b/polly/lib/Transform/DeLICM.cpp index e6e76ec9930..68dfac43b15 100644 --- a/polly/lib/Transform/DeLICM.cpp +++ b/polly/lib/Transform/DeLICM.cpp @@ -666,6 +666,19 @@ private: /// For each PHI instance we can directly determine which was the incoming /// block, and hence derive which value the PHI has. /// + /// The returned relation generally is injective, meaning that every PHI write + /// has at most one (or zero, if the incoming block's branch does not jump to + /// the PHI's block) PHI Read that reads it. However, due to the SCoP's + /// parameter context it is possible a statement instance that would overwrite + /// the PHI scalar is not in the statement's domain and thus a PHI write + /// appear to be used twice. This is a static property, at runtime the + /// runtime condition should avoid that a configuration is executed. Although + /// incorrect, it should not have any effect in DeLICM. If it passes the + /// conflict check, there are multiple locations, one for each PHI Read it + /// matches, it had to write to. MemoryAccess::getAddressFunction() will + /// select only one of them. That is, statically, not all necessary value are + /// written, but the runtime check guards it from ever being executed. + /// /// @param SAI The ScopArrayInfo representing the PHI's storage. /// /// @return { DomainPHIRead[] -> DomainPHIWrite[] } @@ -702,7 +715,6 @@ private: isl_union_map_from_map(LastPerPHIWrites.take()), isl_union_map_reverse(PHIWriteScatter.take()))); assert(isl_union_map_is_single_valued(Result.keep()) == isl_bool_true); - assert(isl_union_map_is_injective(Result.keep()) == isl_bool_true); return Result; } diff --git a/polly/test/DeLICM/noninjective_phi_relation.ll b/polly/test/DeLICM/noninjective_phi_relation.ll new file mode 100644 index 00000000000..dfe2d0f713d --- /dev/null +++ b/polly/test/DeLICM/noninjective_phi_relation.ll @@ -0,0 +1,115 @@ +; RUN: opt %loadPolly -polly-delicm -analyze < %s | FileCheck %s -match-full-lines +; +; llvm.org/PR34485 +; This produces a non-injective PHIRead -> PHIWrite map due to an invalid +; paramter assumption. It does not map anything because the result does pass +; the non-conflicting test. It would be a better test if it did to test whether +; correct code is generated. +; +; unsigned a; +; long b, d; +; short c; +; int e, f; +; void fn1() { +; for (;;) { +; for (; f;) +; for (;;) +; ; +; a -= 0 < b; +; for (; f <= 5; f++) { +; short *g = &c; +; *g = a++ ? e *= 4 : c; +; g = &f; +; d = *g; +; } +; } +; } +; +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" + +@f = common local_unnamed_addr global i32 0, align 4 +@b = common local_unnamed_addr global i32 0, align 4 +@a = common local_unnamed_addr global i32 0, align 4 +@c = common local_unnamed_addr global i16 0, align 2 +@e = common local_unnamed_addr global i32 0, align 4 +@d = common local_unnamed_addr global i32 0, align 4 + +define void @fn1() local_unnamed_addr { +entry: + br label %entry.split + +entry.split: ; preds = %entry + %.pr = load i32, i32* @f, align 4 + %tobool19 = icmp eq i32 %.pr, 0 + br i1 %tobool19, label %for.end.lr.ph, label %for.body + +for.end.lr.ph: ; preds = %entry.split + %0 = load i32, i32* @b, align 4 + %cmp = icmp sgt i32 %0, 0 + %conv = zext i1 %cmp to i32 + %a.promoted20 = load i32, i32* @a, align 4 + br label %for.end + +for.cond.for.body_crit_edge: ; preds = %for.end, %for.end12 + %inc.lcssa2125 = phi i32 [ %inc, %for.end12 ], [ %sub, %for.end ] + store i32 %inc.lcssa2125, i32* @a, align 4 + br label %for.body + +for.body: ; preds = %for.cond.for.body_crit_edge, %entry.split + br label %for.cond2 + +for.cond2: ; preds = %for.cond2, %for.body + br label %for.cond2 + +for.end: ; preds = %for.end.lr.ph, %for.end12 + %inc.lcssa22 = phi i32 [ %a.promoted20, %for.end.lr.ph ], [ %inc, %for.end12 ] + %sub = sub i32 %inc.lcssa22, %conv + %.pr15 = load i32, i32* @f, align 4 + %cmp416 = icmp slt i32 %.pr15, 6 + br i1 %cmp416, label %for.body6.lr.ph, label %for.cond.for.body_crit_edge + +for.body6.lr.ph: ; preds = %for.end + %c.promoted = load i16, i16* @c, align 2 + br label %for.body6 + +for.body6: ; preds = %for.body6.lr.ph, %cond.end + %conv918 = phi i16 [ %c.promoted, %for.body6.lr.ph ], [ %conv9, %cond.end ] + %inc17 = phi i32 [ %sub, %for.body6.lr.ph ], [ %inc, %cond.end ] + %1 = phi i32 [ %.pr15, %for.body6.lr.ph ], [ %inc11, %cond.end ] + %inc = add i32 %inc17, 1 + %tobool7 = icmp eq i32 %inc17, 0 + br i1 %tobool7, label %cond.false, label %cond.true + +cond.true: ; preds = %for.body6 + %2 = load i32, i32* @e, align 4 + %mul = shl nsw i32 %2, 2 + store i32 %mul, i32* @e, align 4 + br label %cond.end + +cond.false: ; preds = %for.body6 + %conv8 = sext i16 %conv918 to i32 + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi i32 [ %mul, %cond.true ], [ %conv8, %cond.false ] + %conv9 = trunc i32 %cond to i16 + %3 = load i16, i16* bitcast (i32* @f to i16*), align 4 + %inc11 = add nsw i32 %1, 1 + store i32 %inc11, i32* @f, align 4 + %cmp4 = icmp slt i32 %1, 5 + br i1 %cmp4, label %for.body6, label %for.end12 + +for.end12: ; preds = %cond.end + %conv10 = sext i16 %3 to i32 + store i16 %conv9, i16* @c, align 2 + store i32 %conv10, i32* @d, align 4 + %tobool = icmp eq i32 %inc11, 0 + br i1 %tobool, label %for.end, label %for.cond.for.body_crit_edge +} + + +; CHECK: Statistics { +; CHECK: Compatible overwrites: 1 +; CHECK: } + +; CHECK: No modification has been made |