]> granicus.if.org Git - llvm/commitdiff
ARM: track globals promoted to coalesced const pool entries
authorSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 7 Sep 2017 04:00:13 +0000 (04:00 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Thu, 7 Sep 2017 04:00:13 +0000 (04:00 +0000)
Globals that are promoted to an ARM constant pool may alias with another
existing constant pool entry. We need to keep a reference to all globals
that were promoted to each constant pool value so that we can emit a
distinct label for each promoted global. These labels are necessary so
that debug info can refer to the promoted global without an undefined
reference during linking.

Patch by Stephen Crane!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312692 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMAsmPrinter.cpp
lib/Target/ARM/ARMConstantPoolValue.cpp
lib/Target/ARM/ARMConstantPoolValue.h
test/CodeGen/ARM/constantpool-promote-duplicate.ll [new file with mode: 0644]

index 8e425ddcdada82854305ad0882f350d491a1f56a..13335a84f6d9bec07659b5e1c9a2132e1adada00 100644 (file)
@@ -865,11 +865,12 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
     // However, if this global is promoted into several functions we must ensure
     // we don't try and emit duplicate symbols!
     auto *ACPC = cast<ARMConstantPoolConstant>(ACPV);
-    auto *GV = ACPC->getPromotedGlobal();
-    if (!EmittedPromotedGlobalLabels.count(GV)) {
-      MCSymbol *GVSym = getSymbol(GV);
-      OutStreamer->EmitLabel(GVSym);
-      EmittedPromotedGlobalLabels.insert(GV);
+    for (const auto *GV : ACPC->promotedGlobals()) {
+      if (!EmittedPromotedGlobalLabels.count(GV)) {
+        MCSymbol *GVSym = getSymbol(GV);
+        OutStreamer->EmitLabel(GVSym);
+        EmittedPromotedGlobalLabels.insert(GV);
+      }
     }
     return EmitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
   }
index 9705c8b718b70f0c964d927dfa6d94662dc6b0ee..88b3683bd75b203adaa82140d1bf16aff3326d37 100644 (file)
@@ -140,8 +140,9 @@ ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C,
 ARMConstantPoolConstant::ARMConstantPoolConstant(const GlobalVariable *GV,
                                                  const Constant *C)
     : ARMConstantPoolValue((Type *)C->getType(), 0, ARMCP::CPPromotedGlobal, 0,
-                           ARMCP::no_modifier, false),
-      CVal(C), GVar(GV) {}
+                           ARMCP::no_modifier, false), CVal(C) {
+  GVars.insert(GV);
+}
 
 ARMConstantPoolConstant *
 ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
@@ -189,7 +190,15 @@ const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const {
 
 int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
                                                        unsigned Alignment) {
-  return getExistingMachineCPValueImpl<ARMConstantPoolConstant>(CP, Alignment);
+  int index =
+    getExistingMachineCPValueImpl<ARMConstantPoolConstant>(CP, Alignment);
+  if (index != -1) {
+    auto *CPV = static_cast<ARMConstantPoolValue*>(
+        CP->getConstants()[index].Val.MachineCPVal);
+    auto *Constant = cast<ARMConstantPoolConstant>(CPV);
+    Constant->GVars.insert(GVars.begin(), GVars.end());
+  }
+  return index;
 }
 
 bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
@@ -199,6 +208,8 @@ bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
 
 void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
   ID.AddPointer(CVal);
+  for (const auto *GV : GVars)
+    ID.AddPointer(GV);
   ARMConstantPoolValue::addSelectionDAGCSEId(ID);
 }
 
index 61c521581f79565523ed3c050edc78523b6f95c5..30ce8716c5cb70af489ec915f2690a89253d41f0 100644 (file)
@@ -15,6 +15,7 @@
 #define LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/Support/Casting.h"
 #include <string>
@@ -80,8 +81,8 @@ protected:
     for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
       if (Constants[i].isMachineConstantPoolEntry() &&
           (Constants[i].getAlignment() & AlignMask) == 0) {
-        ARMConstantPoolValue *CPV =
-            (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
+        auto *CPV =
+          static_cast<ARMConstantPoolValue*>(Constants[i].Val.MachineCPVal);
         if (Derived *APC = dyn_cast<Derived>(CPV))
           if (cast<Derived>(this)->equals(APC))
             return i;
@@ -139,7 +140,7 @@ inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) {
 /// Functions, and BlockAddresses.
 class ARMConstantPoolConstant : public ARMConstantPoolValue {
   const Constant *CVal;         // Constant being loaded.
-  const GlobalVariable *GVar = nullptr;
+  SmallPtrSet<const GlobalVariable*, 1> GVars;
 
   ARMConstantPoolConstant(const Constant *C,
                           unsigned ID,
@@ -173,8 +174,9 @@ public:
   const GlobalValue *getGV() const;
   const BlockAddress *getBlockAddress() const;
 
-  const GlobalVariable *getPromotedGlobal() const {
-    return dyn_cast_or_null<GlobalVariable>(GVar);
+  typedef SmallPtrSet<const GlobalVariable *, 1>::iterator promoted_iterator;
+  iterator_range<promoted_iterator> promotedGlobals() {
+    return iterator_range<promoted_iterator>(GVars.begin(), GVars.end());
   }
 
   const Constant *getPromotedGlobalInit() const {
diff --git a/test/CodeGen/ARM/constantpool-promote-duplicate.ll b/test/CodeGen/ARM/constantpool-promote-duplicate.ll
new file mode 100644 (file)
index 0000000..70c4807
--- /dev/null
@@ -0,0 +1,21 @@
+; RUN: llc -mtriple=arm-eabi -relocation-model=static -arm-promote-constant < %s | FileCheck %s
+
+@const1 = private unnamed_addr constant i32 0, align 4
+@const2 = private unnamed_addr constant i32 0, align 4
+
+; const1 and const2 both need labels for debug info, but will be coalesced into
+; a single constpool entry
+
+; CHECK-LABEL: @test1
+; CHECK-DAG: const1:
+; CHECK-DAG: const2:
+; CHECK: .fnend
+define void @test1() {
+  %1 = load i32, i32* @const1, align 4
+  call void @a(i32 %1)
+  %2 = load i32, i32* @const2, align 4
+  call void @a(i32 %2)
+  ret void
+}
+
+declare void @a(i32)