summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
diff options
context:
space:
mode:
authorJames Molloy <james.molloy@arm.com>2016-09-23 12:15:58 +0000
committerJames Molloy <james.molloy@arm.com>2016-09-23 12:15:58 +0000
commit1ce54d6be2bfba92c82372186a22aad6b0e09fbc (patch)
tree3d20a9876647763dba0b7e4fe3a86c8938864c3f /llvm/lib/Target/ARM/ARMAsmPrinter.cpp
parent63458c330f7814606af0fbaa9fd46baa866b4de0 (diff)
downloadbcm5719-llvm-1ce54d6be2bfba92c82372186a22aad6b0e09fbc.tar.gz
bcm5719-llvm-1ce54d6be2bfba92c82372186a22aad6b0e09fbc.zip
[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. llvm-svn: 282241
Diffstat (limited to 'llvm/lib/Target/ARM/ARMAsmPrinter.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMAsmPrinter.cpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index db6eefdb999..27d2c4b356d 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -97,6 +97,13 @@ void ARMAsmPrinter::EmitXXStructor(const DataLayout &DL, const Constant *CV) {
OutStreamer->EmitValue(E, Size);
}
+void ARMAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
+ if (PromotedGlobals.count(GV))
+ // The global was promoted into a constant pool. It should not be emitted.
+ return;
+ AsmPrinter::EmitGlobalVariable(GV);
+}
+
/// runOnMachineFunction - This uses the EmitInstruction()
/// method to print assembly for each instruction.
///
@@ -109,6 +116,12 @@ bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
const Function* F = MF.getFunction();
const TargetMachine& TM = MF.getTarget();
+ // Collect all globals that had their storage promoted to a constant pool.
+ // Functions are emitted before variables, so this accumulates promoted
+ // globals from all functions in PromotedGlobals.
+ for (auto *GV : AFI->getGlobalsPromotedToConstantPool())
+ PromotedGlobals.insert(GV);
+
// Calculate this function's optimization goal.
unsigned OptimizationGoal;
if (F->hasFnAttribute(Attribute::OptimizeNone))
@@ -1002,6 +1015,26 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
+ if (ACPV->isPromotedGlobal()) {
+ // This constant pool entry is actually a global whose storage has been
+ // promoted into the constant pool. This global may be referenced still
+ // by debug information, and due to the way AsmPrinter is set up, the debug
+ // info is immutable by the time we decide to promote globals to constant
+ // pools. Because of this, we need to ensure we emit a symbol for the global
+ // with private linkage (the default) so debug info can refer to it.
+ //
+ // 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);
+ }
+ return EmitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
+ }
+
MCSymbol *MCSym;
if (ACPV->isLSDA()) {
MCSym = getCurExceptionSym();
OpenPOWER on IntegriCloud