GlobalOpt: do not promote globals used atomically to constants.
authorTim Northover <tnorthover@apple.com>
Tue, 14 May 2019 11:03:13 +0000 (11:03 +0000)
committerTim Northover <tnorthover@apple.com>
Tue, 14 May 2019 11:03:13 +0000 (11:03 +0000)
Some atomic loads are implemented as cmpxchg (particularly if large or
floating), and that usually requires write access to the memory involved
or it will segfault.

We can still propagate the constant value to users we understand though.

llvm-svn: 360662

llvm/lib/Transforms/IPO/GlobalOpt.cpp
llvm/test/Transforms/GlobalOpt/atomic.ll

index 2a869444d6ef01ff7f6b8945c5bf4323075a7580..ca0e5807b5fbd160bd4ea0fc0159f9fc4717671a 100644 (file)
@@ -1980,7 +1980,12 @@ static bool processInternalGlobal(
   }
   if (GS.StoredType <= GlobalStatus::InitializerStored) {
     LLVM_DEBUG(dbgs() << "MARKING CONSTANT: " << *GV << "\n");
-    GV->setConstant(true);
+
+    // Don't actually mark a global constant if it's atomic because atomic loads
+    // are implemented by a trivial cmpxchg in some edge-cases and that usually
+    // requires write access to the variable even if it's not actually changed.
+    if (GS.Ordering == AtomicOrdering::NotAtomic)
+      GV->setConstant(true);
 
     // Clean up any obviously simplifiable users now.
     CleanupConstantGlobalUsers(GV, GV->getInitializer(), DL, TLI);
index 563c1fec7d27f9c20d56baba7b1c1583d66525ef..7597e0f03ba3eeb9d7a7b0ba351f2bf128f1a20f 100644 (file)
@@ -3,7 +3,7 @@
 @GV1 = internal global i64 1
 @GV2 = internal global i32 0
 
-; CHECK: @GV1 = internal unnamed_addr constant i64 1
+; CHECK: @GV1 = internal unnamed_addr global i64 1
 ; CHECK: @GV2 = internal unnamed_addr global i32 0
 
 define void @test1() {
@@ -23,3 +23,12 @@ entry:
   %atomic-load = load atomic i32, i32* @GV2 seq_cst, align 4
   ret i32 %atomic-load
 }
+
+
+define i64 @test3() {
+; CHECK-LABEL: @test3
+; CHECK: ret i64 1
+
+  %val = load atomic i64, i64* @GV1 acquire, align 8
+  ret i64 %val
+}