[Polly] Never consider non-SCoP blocks as error blocks.
authorMichael Kruse <llvm-project@meinersbur.de>
Mon, 23 Aug 2021 00:23:51 +0000 (19:23 -0500)
committerMichael Kruse <llvm-project@meinersbur.de>
Mon, 23 Aug 2021 06:04:01 +0000 (01:04 -0500)
Code outside the SCoP will be executed recardless of the code versioning
runtime check introduced by CodeGeneration. Assumption made based on
that these are never executed in Polly-optimized code does not hold.

This fixes the miscompilation of MultiSource/Applications/lambda-0.1.3

polly/lib/Analysis/ScopBuilder.cpp
polly/lib/Analysis/ScopDetection.cpp
polly/test/ScopInfo/condition-after-error-block-before-scop.ll [new file with mode: 0644]

index cb15f59..78f4f53 100644 (file)
@@ -449,6 +449,9 @@ bool ScopBuilder::buildConditionSets(
   } else if (auto *PHI = dyn_cast<PHINode>(Condition)) {
     auto *Unique = dyn_cast<ConstantInt>(
         getUniqueNonErrorValue(PHI, &scop->getRegion(), &SD));
+    assert(Unique &&
+           "A PHINode condition should only be accepted by ScopDetection if "
+           "getUniqueNonErrorValue returns non-NULL");
 
     if (Unique->isZero())
       ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
index 1b4f3c9..51d8ddd 100644 (file)
@@ -1417,6 +1417,11 @@ static bool isErrorBlockImpl(BasicBlock &BB, const Region &R, LoopInfo &LI,
   if (LI.isLoopHeader(&BB))
     return false;
 
+  // Don't consider something outside the SCoP as error block. It will precede
+  // the code versioning runtime check.
+  if (!R.contains(&BB))
+    return false;
+
   // Basic blocks that are always executed are not considered error blocks,
   // as their execution can not be a rare event.
   bool DominatesAllPredecessors = true;
diff --git a/polly/test/ScopInfo/condition-after-error-block-before-scop.ll b/polly/test/ScopInfo/condition-after-error-block-before-scop.ll
new file mode 100644 (file)
index 0000000..1de4a64
--- /dev/null
@@ -0,0 +1,48 @@
+; RUN: opt %loadPolly -polly-scops -polly-codegen -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%class.node = type { i32 (...)**, %class.node* }
+
+define void @foobar(double* %A) {
+if.end:
+  br i1 undef, label %if.then29, label %lor.lhs.false
+
+lor.lhs.false:
+  %call25 = tail call i32 undef(%class.node* undef)
+  br i1 undef, label %if.then29, label %if.end30
+
+if.then29:
+  br label %if.end30
+
+if.end30:
+  %tobool76.not = phi i1 [ false, %lor.lhs.false ], [ true, %if.then29 ]
+  br label %if.end75
+
+if.end75:
+  br label %if.end79
+
+if.end79:
+  br label %if.then84
+
+if.then84:
+  br label %if.end91
+
+if.end91:
+  br i1 %tobool76.not, label %if.end98, label %if.then93
+
+if.then93:
+  store double 0.0, double* %A
+  br label %if.end98
+
+if.end98:
+  %tobool131 = phi i1 [ false, %if.end91 ], [ true, %if.then93 ]
+  ret void
+}
+
+
+; CHECK: polly.stmt.if.then93:
+; CHECK:   store double 0.000000e+00, double* %A
+; CHECK:   br label %polly.exiting
+