ARM: track globals promoted to coalesced const pool entries
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!
llvm-svn: 312692
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index 8e425dd..13335a8 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -865,11 +865,12 @@
// 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());
}
diff --git a/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp b/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp
index 9705c8b..88b3683 100644
--- a/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp
+++ b/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp
@@ -140,8 +140,9 @@
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 @@
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 @@
void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
ID.AddPointer(CVal);
+ for (const auto *GV : GVars)
+ ID.AddPointer(GV);
ARMConstantPoolValue::addSelectionDAGCSEId(ID);
}
diff --git a/llvm/lib/Target/ARM/ARMConstantPoolValue.h b/llvm/lib/Target/ARM/ARMConstantPoolValue.h
index 61c5215..30ce871 100644
--- a/llvm/lib/Target/ARM/ARMConstantPoolValue.h
+++ b/llvm/lib/Target/ARM/ARMConstantPoolValue.h
@@ -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 @@
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 @@
/// 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 @@
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 {