summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Wala <wala@google.com>2015-07-23 20:53:46 +0000
committerMatt Wala <wala@google.com>2015-07-23 20:53:46 +0000
commit878c144f8a32336daa2c0124017ec707924cfcc0 (patch)
tree493fd905076a1bcffc30f824a77fef030cc580a3
parentdccc30a7efe2e20b4263ca50171aaae55ef6b5a2 (diff)
downloadbcm5719-llvm-878c144f8a32336daa2c0124017ec707924cfcc0.tar.gz
bcm5719-llvm-878c144f8a32336daa2c0124017ec707924cfcc0.zip
[Scalarizer] Fix potential for stale data in Scattered across invocations
Summary: Scalarizer has two data structures that hold information about changes to the function, Gathered and Scattered. These are cleared in finish() at the end of runOnFunction() if finish() detects any changes to the function. However, finish() was checking for changes by only checking if Gathered was non-empty. The function visitStore() only modifies Scattered without touching Gathered. As a result, Scattered could have ended up having stale data if Scalarizer only scalarized store instructions. Since the data in Scattered is used during the execution of the pass, this introduced dangling pointer errors. The fix is to check whether both Scattered and Gathered are empty before deciding what to do in finish(). This also fixes a problem where the Function can be modified although the pass returns false. Reviewers: rnk Subscribers: rnk, srhines, llvm-commits Differential Revision: http://reviews.llvm.org/D10459 llvm-svn: 243040
-rw-r--r--llvm/lib/Transforms/Scalar/Scalarizer.cpp5
-rw-r--r--llvm/test/Transforms/Scalarizer/store-bug.ll25
2 files changed, 29 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Scalar/Scalarizer.cpp b/llvm/lib/Transforms/Scalar/Scalarizer.cpp
index d55dc6a20a0..3b8307c4316 100644
--- a/llvm/lib/Transforms/Scalar/Scalarizer.cpp
+++ b/llvm/lib/Transforms/Scalar/Scalarizer.cpp
@@ -247,6 +247,7 @@ bool Scalarizer::doInitialization(Module &M) {
}
bool Scalarizer::runOnFunction(Function &F) {
+ assert(Gathered.empty() && Scattered.empty());
for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
BasicBlock *BB = BBI;
for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE;) {
@@ -636,7 +637,9 @@ bool Scalarizer::visitStoreInst(StoreInst &SI) {
// Delete the instructions that we scalarized. If a full vector result
// is still needed, recreate it using InsertElements.
bool Scalarizer::finish() {
- if (Gathered.empty())
+ // The presence of data in Gathered or Scattered indicates changes
+ // made to the Function.
+ if (Gathered.empty() && Scattered.empty())
return false;
for (GatherList::iterator GMI = Gathered.begin(), GME = Gathered.end();
GMI != GME; ++GMI) {
diff --git a/llvm/test/Transforms/Scalarizer/store-bug.ll b/llvm/test/Transforms/Scalarizer/store-bug.ll
new file mode 100644
index 00000000000..84c2b3f840a
--- /dev/null
+++ b/llvm/test/Transforms/Scalarizer/store-bug.ll
@@ -0,0 +1,25 @@
+; RUN: opt -scalarizer -scalarize-load-store -S < %s | FileCheck %s
+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-S128"
+
+; This input caused the scalarizer not to clear cached results
+; properly.
+;
+; Any regressions should trigger an assert in the scalarizer.
+
+define void @func(<4 x float> %val, <4 x float> *%ptr) {
+ store <4 x float> %val, <4 x float> *%ptr
+ ret void
+; CHECK: store float %val.i0, float* %ptr.i0, align 16
+; CHECK: store float %val.i1, float* %ptr.i1, align 4
+; CHECK: store float %val.i2, float* %ptr.i2, align 8
+; CHECK: store float %val.i3, float* %ptr.i3, align 4
+}
+
+define void @func.copy(<4 x float> %val, <4 x float> *%ptr) {
+ store <4 x float> %val, <4 x float> *%ptr
+ ret void
+; CHECK: store float %val.i0, float* %ptr.i0, align 16
+; CHECK: store float %val.i1, float* %ptr.i1, align 4
+; CHECK: store float %val.i2, float* %ptr.i2, align 8
+; CHECK: store float %val.i3, float* %ptr.i3, align 4
+}
OpenPOWER on IntegriCloud