forked from OSchip/llvm-project
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
This commit is contained in:
parent
e2addb79b8
commit
5fba8ba9cc
|
@ -865,11 +865,12 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
|
||||||
// However, if this global is promoted into several functions we must ensure
|
// However, if this global is promoted into several functions we must ensure
|
||||||
// we don't try and emit duplicate symbols!
|
// we don't try and emit duplicate symbols!
|
||||||
auto *ACPC = cast<ARMConstantPoolConstant>(ACPV);
|
auto *ACPC = cast<ARMConstantPoolConstant>(ACPV);
|
||||||
auto *GV = ACPC->getPromotedGlobal();
|
for (const auto *GV : ACPC->promotedGlobals()) {
|
||||||
if (!EmittedPromotedGlobalLabels.count(GV)) {
|
if (!EmittedPromotedGlobalLabels.count(GV)) {
|
||||||
MCSymbol *GVSym = getSymbol(GV);
|
MCSymbol *GVSym = getSymbol(GV);
|
||||||
OutStreamer->EmitLabel(GVSym);
|
OutStreamer->EmitLabel(GVSym);
|
||||||
EmittedPromotedGlobalLabels.insert(GV);
|
EmittedPromotedGlobalLabels.insert(GV);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return EmitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
|
return EmitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,8 +140,9 @@ ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C,
|
||||||
ARMConstantPoolConstant::ARMConstantPoolConstant(const GlobalVariable *GV,
|
ARMConstantPoolConstant::ARMConstantPoolConstant(const GlobalVariable *GV,
|
||||||
const Constant *C)
|
const Constant *C)
|
||||||
: ARMConstantPoolValue((Type *)C->getType(), 0, ARMCP::CPPromotedGlobal, 0,
|
: ARMConstantPoolValue((Type *)C->getType(), 0, ARMCP::CPPromotedGlobal, 0,
|
||||||
ARMCP::no_modifier, false),
|
ARMCP::no_modifier, false), CVal(C) {
|
||||||
CVal(C), GVar(GV) {}
|
GVars.insert(GV);
|
||||||
|
}
|
||||||
|
|
||||||
ARMConstantPoolConstant *
|
ARMConstantPoolConstant *
|
||||||
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
|
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
|
||||||
|
@ -189,7 +190,15 @@ const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const {
|
||||||
|
|
||||||
int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
|
int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
|
||||||
unsigned Alignment) {
|
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) {
|
bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
|
||||||
|
@ -199,6 +208,8 @@ bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
|
||||||
|
|
||||||
void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
||||||
ID.AddPointer(CVal);
|
ID.AddPointer(CVal);
|
||||||
|
for (const auto *GV : GVars)
|
||||||
|
ID.AddPointer(GV);
|
||||||
ARMConstantPoolValue::addSelectionDAGCSEId(ID);
|
ARMConstantPoolValue::addSelectionDAGCSEId(ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#define LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
|
#define LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
|
||||||
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -80,8 +81,8 @@ protected:
|
||||||
for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
|
||||||
if (Constants[i].isMachineConstantPoolEntry() &&
|
if (Constants[i].isMachineConstantPoolEntry() &&
|
||||||
(Constants[i].getAlignment() & AlignMask) == 0) {
|
(Constants[i].getAlignment() & AlignMask) == 0) {
|
||||||
ARMConstantPoolValue *CPV =
|
auto *CPV =
|
||||||
(ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
|
static_cast<ARMConstantPoolValue*>(Constants[i].Val.MachineCPVal);
|
||||||
if (Derived *APC = dyn_cast<Derived>(CPV))
|
if (Derived *APC = dyn_cast<Derived>(CPV))
|
||||||
if (cast<Derived>(this)->equals(APC))
|
if (cast<Derived>(this)->equals(APC))
|
||||||
return i;
|
return i;
|
||||||
|
@ -139,7 +140,7 @@ inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) {
|
||||||
/// Functions, and BlockAddresses.
|
/// Functions, and BlockAddresses.
|
||||||
class ARMConstantPoolConstant : public ARMConstantPoolValue {
|
class ARMConstantPoolConstant : public ARMConstantPoolValue {
|
||||||
const Constant *CVal; // Constant being loaded.
|
const Constant *CVal; // Constant being loaded.
|
||||||
const GlobalVariable *GVar = nullptr;
|
SmallPtrSet<const GlobalVariable*, 1> GVars;
|
||||||
|
|
||||||
ARMConstantPoolConstant(const Constant *C,
|
ARMConstantPoolConstant(const Constant *C,
|
||||||
unsigned ID,
|
unsigned ID,
|
||||||
|
@ -173,8 +174,9 @@ public:
|
||||||
const GlobalValue *getGV() const;
|
const GlobalValue *getGV() const;
|
||||||
const BlockAddress *getBlockAddress() const;
|
const BlockAddress *getBlockAddress() const;
|
||||||
|
|
||||||
const GlobalVariable *getPromotedGlobal() const {
|
typedef SmallPtrSet<const GlobalVariable *, 1>::iterator promoted_iterator;
|
||||||
return dyn_cast_or_null<GlobalVariable>(GVar);
|
iterator_range<promoted_iterator> promotedGlobals() {
|
||||||
|
return iterator_range<promoted_iterator>(GVars.begin(), GVars.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
const Constant *getPromotedGlobalInit() const {
|
const Constant *getPromotedGlobalInit() const {
|
||||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue