Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit ba54dc2

Browse files
author
James Molloy
committed
[ARM] Promote small global constants to constant pools
If a constant is unamed_addr and is only used within one function, we can save on the code size and runtime cost of an indirection by changing the global's storage to inside the constant pool. For example, instead of: ldr r0, .CPI0 bl printf bx lr .CPI0: &format_string format_string: .asciz "hello, world!\n" We can emit: adr r0, .CPI0 bl printf bx lr .CPI0: .asciz "hello, world!\n" This can cause significant code size savings when many small strings are used in one function (4 bytes per string). This recommit contains fixes for a nasty bug related to fast-isel fallback - because fast-isel doesn't know about this optimization, if it runs and emits references to a string that we inline (because fast-isel fell back to SDAG) we will end up with an inlined string and also an out-of-line string, and we won't emit the out-of-line string, causing backend failures. It also contains fixes for emitting .text relocations which made the sanitizer bots unhappy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282387 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 9209299 commit ba54dc2

11 files changed

+470
-9
lines changed

lib/CodeGen/MachineFunction.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -898,13 +898,20 @@ MachineConstantPoolEntry::getSectionKind(const DataLayout *DL) const {
898898
}
899899

900900
MachineConstantPool::~MachineConstantPool() {
901+
// A constant may be a member of both Constants and MachineCPVsSharingEntries,
902+
// so keep track of which we've deleted to avoid double deletions.
903+
DenseSet<MachineConstantPoolValue*> Deleted;
901904
for (unsigned i = 0, e = Constants.size(); i != e; ++i)
902-
if (Constants[i].isMachineConstantPoolEntry())
905+
if (Constants[i].isMachineConstantPoolEntry()) {
906+
Deleted.insert(Constants[i].Val.MachineCPVal);
903907
delete Constants[i].Val.MachineCPVal;
908+
}
904909
for (DenseSet<MachineConstantPoolValue*>::iterator I =
905910
MachineCPVsSharingEntries.begin(), E = MachineCPVsSharingEntries.end();
906-
I != E; ++I)
907-
delete *I;
911+
I != E; ++I) {
912+
if (Deleted.count(*I) == 0)
913+
delete *I;
914+
}
908915
}
909916

910917
/// Test whether the given two constants can be allocated the same constant pool

lib/Target/ARM/ARMAsmPrinter.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ void ARMAsmPrinter::EmitXXStructor(const DataLayout &DL, const Constant *CV) {
9797
OutStreamer->EmitValue(E, Size);
9898
}
9999

100+
void ARMAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
101+
if (PromotedGlobals.count(GV))
102+
// The global was promoted into a constant pool. It should not be emitted.
103+
return;
104+
AsmPrinter::EmitGlobalVariable(GV);
105+
}
106+
100107
/// runOnMachineFunction - This uses the EmitInstruction()
101108
/// method to print assembly for each instruction.
102109
///
@@ -109,6 +116,12 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
109116
const Function* F = MF.getFunction();
110117
const TargetMachine& TM = MF.getTarget();
111118

119+
// Collect all globals that had their storage promoted to a constant pool.
120+
// Functions are emitted before variables, so this accumulates promoted
121+
// globals from all functions in PromotedGlobals.
122+
for (auto *GV : AFI->getGlobalsPromotedToConstantPool())
123+
PromotedGlobals.insert(GV);
124+
112125
// Calculate this function's optimization goal.
113126
unsigned OptimizationGoal;
114127
if (F->hasFnAttribute(Attribute::OptimizeNone))
@@ -1002,6 +1015,26 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
10021015

10031016
ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
10041017

1018+
if (ACPV->isPromotedGlobal()) {
1019+
// This constant pool entry is actually a global whose storage has been
1020+
// promoted into the constant pool. This global may be referenced still
1021+
// by debug information, and due to the way AsmPrinter is set up, the debug
1022+
// info is immutable by the time we decide to promote globals to constant
1023+
// pools. Because of this, we need to ensure we emit a symbol for the global
1024+
// with private linkage (the default) so debug info can refer to it.
1025+
//
1026+
// However, if this global is promoted into several functions we must ensure
1027+
// we don't try and emit duplicate symbols!
1028+
auto *ACPC = cast<ARMConstantPoolConstant>(ACPV);
1029+
auto *GV = ACPC->getPromotedGlobal();
1030+
if (!EmittedPromotedGlobalLabels.count(GV)) {
1031+
MCSymbol *GVSym = getSymbol(GV);
1032+
OutStreamer->EmitLabel(GVSym);
1033+
EmittedPromotedGlobalLabels.insert(GV);
1034+
}
1035+
return EmitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
1036+
}
1037+
10051038
MCSymbol *MCSym;
10061039
if (ACPV->isLSDA()) {
10071040
MCSym = getCurExceptionSym();

lib/Target/ARM/ARMAsmPrinter.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter {
5656
/// -1 if uninitialized, 0 if conflicting goals
5757
int OptimizationGoals;
5858

59+
/// List of globals that have had their storage promoted to a constant
60+
/// pool. This lives between calls to runOnMachineFunction and collects
61+
/// data from every MachineFunction. It is used during doFinalization
62+
/// when all non-function globals are emitted.
63+
SmallPtrSet<const GlobalVariable*,2> PromotedGlobals;
64+
/// Set of globals in PromotedGlobals that we've emitted labels for.
65+
/// We need to emit labels even for promoted globals so that DWARF
66+
/// debug info can link properly.
67+
SmallPtrSet<const GlobalVariable*,2> EmittedPromotedGlobalLabels;
68+
5969
public:
6070
explicit ARMAsmPrinter(TargetMachine &TM,
6171
std::unique_ptr<MCStreamer> Streamer);
@@ -90,7 +100,8 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter {
90100
void EmitStartOfAsmFile(Module &M) override;
91101
void EmitEndOfAsmFile(Module &M) override;
92102
void EmitXXStructor(const DataLayout &DL, const Constant *CV) override;
93-
103+
void EmitGlobalVariable(const GlobalVariable *GV) override;
104+
94105
// lowerOperand - Convert a MachineOperand into the equivalent MCOperand.
95106
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
96107

lib/Target/ARM/ARMConstantIslandPass.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
767767
case ARM::LDRi12:
768768
case ARM::LDRcp:
769769
case ARM::t2LDRpci:
770+
case ARM::t2LDRHpci:
770771
Bits = 12; // +-offset_12
771772
NegOk = true;
772773
break;
@@ -782,6 +783,11 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
782783
Scale = 4; // +-(offset_8*4)
783784
NegOk = true;
784785
break;
786+
787+
case ARM::tLDRHi:
788+
Bits = 5;
789+
Scale = 2; // +(offset_5*2)
790+
break;
785791
}
786792

787793
// Remember that this is a user of a CP entry.

lib/Target/ARM/ARMConstantPoolValue.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,24 @@ ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C,
131131
AddCurrentAddress),
132132
CVal(C) {}
133133

134+
ARMConstantPoolConstant::ARMConstantPoolConstant(const GlobalVariable *GV,
135+
const Constant *C)
136+
: ARMConstantPoolValue((Type *)C->getType(), 0, ARMCP::CPPromotedGlobal, 0,
137+
ARMCP::no_modifier, false),
138+
CVal(C), GVar(GV) {}
139+
134140
ARMConstantPoolConstant *
135141
ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
136142
return new ARMConstantPoolConstant(C, ID, ARMCP::CPValue, 0,
137143
ARMCP::no_modifier, false);
138144
}
139145

146+
ARMConstantPoolConstant *
147+
ARMConstantPoolConstant::Create(const GlobalVariable *GVar,
148+
const Constant *Initializer) {
149+
return new ARMConstantPoolConstant(GVar, Initializer);
150+
}
151+
140152
ARMConstantPoolConstant *
141153
ARMConstantPoolConstant::Create(const GlobalValue *GV,
142154
ARMCP::ARMCPModifier Modifier) {

lib/Target/ARM/ARMConstantPoolValue.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace llvm {
2424
class BlockAddress;
2525
class Constant;
2626
class GlobalValue;
27+
class GlobalVariable;
2728
class LLVMContext;
2829
class MachineBasicBlock;
2930

@@ -33,7 +34,8 @@ namespace ARMCP {
3334
CPExtSymbol,
3435
CPBlockAddress,
3536
CPLSDA,
36-
CPMachineBasicBlock
37+
CPMachineBasicBlock,
38+
CPPromotedGlobal
3739
};
3840

3941
enum ARMCPModifier {
@@ -103,7 +105,8 @@ class ARMConstantPoolValue : public MachineConstantPoolValue {
103105
bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; }
104106
bool isLSDA() const { return Kind == ARMCP::CPLSDA; }
105107
bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; }
106-
108+
bool isPromotedGlobal() const{ return Kind == ARMCP::CPPromotedGlobal; }
109+
107110
int getExistingMachineCPValue(MachineConstantPool *CP,
108111
unsigned Alignment) override;
109112

@@ -133,6 +136,7 @@ inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) {
133136
/// Functions, and BlockAddresses.
134137
class ARMConstantPoolConstant : public ARMConstantPoolValue {
135138
const Constant *CVal; // Constant being loaded.
139+
const GlobalVariable *GVar = nullptr;
136140

137141
ARMConstantPoolConstant(const Constant *C,
138142
unsigned ID,
@@ -146,11 +150,14 @@ class ARMConstantPoolConstant : public ARMConstantPoolValue {
146150
unsigned char PCAdj,
147151
ARMCP::ARMCPModifier Modifier,
148152
bool AddCurrentAddress);
153+
ARMConstantPoolConstant(const GlobalVariable *GV, const Constant *Init);
149154

150155
public:
151156
static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID);
152157
static ARMConstantPoolConstant *Create(const GlobalValue *GV,
153158
ARMCP::ARMCPModifier Modifier);
159+
static ARMConstantPoolConstant *Create(const GlobalVariable *GV,
160+
const Constant *Initializer);
154161
static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
155162
ARMCP::ARMCPKind Kind,
156163
unsigned char PCAdj);
@@ -162,6 +169,12 @@ class ARMConstantPoolConstant : public ARMConstantPoolValue {
162169

163170
const GlobalValue *getGV() const;
164171
const BlockAddress *getBlockAddress() const;
172+
const GlobalVariable *getPromotedGlobal() const {
173+
return dyn_cast_or_null<GlobalVariable>(GVar);
174+
}
175+
const Constant *getPromotedGlobalInit() const {
176+
return CVal;
177+
}
165178

166179
int getExistingMachineCPValue(MachineConstantPool *CP,
167180
unsigned Alignment) override;
@@ -174,7 +187,8 @@ class ARMConstantPoolConstant : public ARMConstantPoolValue {
174187

175188
void print(raw_ostream &O) const override;
176189
static bool classof(const ARMConstantPoolValue *APV) {
177-
return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA();
190+
return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA() ||
191+
APV->isPromotedGlobal();
178192
}
179193

180194
bool equals(const ARMConstantPoolConstant *A) const {

0 commit comments

Comments
 (0)