aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2013-03-07 01:03:35 +0000
committerAndrew Trick <atrick@apple.com>2013-03-07 01:03:35 +0000
commit119003f2a22ee7c4f78fed5710f98edb36b237b5 (patch)
tree662fda67febaeb3b6fd32d391c9ec63ea8c991ef
parentfe9dbe0066ba4a35cb68fb281e6f6649ffa85ae9 (diff)
downloadexternal_llvm-119003f2a22ee7c4f78fed5710f98edb36b237b5.zip
external_llvm-119003f2a22ee7c4f78fed5710f98edb36b237b5.tar.gz
external_llvm-119003f2a22ee7c4f78fed5710f98edb36b237b5.tar.bz2
SimplifyCFG fix for volatile load/store.
Fixes rdar:13349374. Volatile loads and stores need to be preserved even if the language standard says they are undefined. "volatile" in this context means "get out of the way compiler, let my platform handle it". Additionally, this is the only way I know of with llvm to write to the first page (when hardware allows) without dropping to assembly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176599 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp6
-rw-r--r--test/Transforms/SimplifyCFG/volatile-phioper.ll48
2 files changed, 52 insertions, 2 deletions
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index a63d31d..a5c5c22 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3944,11 +3944,13 @@ static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I) {
// Load from null is undefined.
if (LoadInst *LI = dyn_cast<LoadInst>(Use))
- return LI->getPointerAddressSpace() == 0;
+ if (!LI->isVolatile())
+ return LI->getPointerAddressSpace() == 0;
// Store to null is undefined.
if (StoreInst *SI = dyn_cast<StoreInst>(Use))
- return SI->getPointerAddressSpace() == 0 && SI->getPointerOperand() == I;
+ if (!SI->isVolatile())
+ return SI->getPointerAddressSpace() == 0 && SI->getPointerOperand() == I;
}
return false;
}
diff --git a/test/Transforms/SimplifyCFG/volatile-phioper.ll b/test/Transforms/SimplifyCFG/volatile-phioper.ll
new file mode 100644
index 0000000..1648988
--- /dev/null
+++ b/test/Transforms/SimplifyCFG/volatile-phioper.ll
@@ -0,0 +1,48 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+;
+; rdar:13349374
+;
+; SimplifyCFG should not eliminate blocks with volatile stores.
+; Essentially, volatile needs to be backdoor that tells the optimizer
+; it can no longer use language standard as an excuse. The compiler
+; needs to expose the volatile access to the platform.
+;
+; CHECK: @test
+; CHECK: entry:
+; CHECK: @Trace
+; CHECK: while.body:
+; CHECK: store volatile
+; CHECK: end:
+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"
+
+define void @test(i8** nocapture %PeiServices) #0 {
+entry:
+ %call = tail call i32 (...)* @Trace() #2
+ %tobool = icmp eq i32 %call, 0
+ br i1 %tobool, label %while.body, label %if.then
+
+if.then: ; preds = %entry
+ %call1 = tail call i32 (...)* @Trace() #2
+ br label %while.body
+
+while.body: ; preds = %entry, %if.then, %while.body
+ %Addr.017 = phi i8* [ %incdec.ptr, %while.body ], [ null, %if.then ], [ null, %entry ]
+ %x.016 = phi i8 [ %inc, %while.body ], [ 0, %if.then ], [ 0, %entry ]
+ %inc = add i8 %x.016, 1
+ %incdec.ptr = getelementptr inbounds i8* %Addr.017, i64 1
+ store volatile i8 %x.016, i8* %Addr.017, align 1
+ %0 = ptrtoint i8* %incdec.ptr to i64
+ %1 = trunc i64 %0 to i32
+ %cmp = icmp ult i32 %1, 4096
+ br i1 %cmp, label %while.body, label %end
+
+end:
+ ret void
+}
+declare i32 @Trace(...) #1
+
+attributes #0 = { nounwind ssp uwtable "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "realign-stack" "relocation-model"="pic" "ssp-buffers-size"="8" }
+attributes #1 = { "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "realign-stack" "relocation-model"="pic" "ssp-buffers-size"="8" }
+attributes #2 = { nounwind }
+
+!0 = metadata !{i32 1039}