Skip to content

Commit

Permalink
[ARM] Allow rematerialization of ARM Thumb literal pool loads
Browse files Browse the repository at this point in the history
Constants are crucial for code size in the ARM Thumb-1 instruction
set. The 16 bit instruction size often does not offer enough space
for immediate arguments. This means that additional instructions are
frequently used to load constants into registers. Since constants are
hoisted, this can lead to significant register spillage if they are
used multiple times in a single function. This can be avoided by
rematerialization, i.e. recomputing a constant instead of reloading
it from the stack. This patch fixes the rematerialization of literal
pool loads in the ARM Thumb instruction set.

Patch by Philip Ginsbach

Differential Revision: https://reviews.llvm.org/D33936

llvm-svn: 308004
  • Loading branch information
sparker-arm committed Jul 14, 2017
1 parent 202a9f6 commit 2893448
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
20 changes: 17 additions & 3 deletions llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
Expand Up @@ -2682,9 +2682,12 @@ void ARMDAGToDAGISel::Select(SDNode *N) {

SDNode *ResNode;
if (Subtarget->isThumb()) {
SDValue Pred = getAL(CurDAG, dl);
SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() };
SDValue Ops[] = {
CPIdx,
getAL(CurDAG, dl),
CurDAG->getRegister(0, MVT::i32),
CurDAG->getEntryNode()
};
ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other,
Ops);
} else {
Expand All @@ -2698,6 +2701,17 @@ void ARMDAGToDAGISel::Select(SDNode *N) {
ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other,
Ops);
}
// Annotate the Node with memory operand information so that MachineInstr
// queries work properly. This e.g. gives the register allocation the
// required information for rematerialization.
MachineFunction& MF = CurDAG->getMachineFunction();
MachineSDNode::mmo_iterator MemOp = MF.allocateMemRefsArray(1);
MemOp[0] = MF.getMachineMemOperand(
MachinePointerInfo::getConstantPool(MF),
MachineMemOperand::MOLoad, 4, 4);

cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp+1);

ReplaceNode(N, ResNode);
return;
}
Expand Down
28 changes: 28 additions & 0 deletions llvm/test/CodeGen/Thumb/litpoolremat.ll
@@ -0,0 +1,28 @@
; RUN: llc < %s -mtriple=thumb-apple-darwin | FileCheck %s

declare void @consume_value(i32) #1

declare i32 @get_value(...) #1

declare void @consume_three_values(i32, i32, i32) #1

; Function Attrs: nounwind uwtable
define void @should_not_spill() #0 {
tail call void @consume_value(i32 1764) #2
%1 = tail call i32 (...) @get_value() #2
%2 = tail call i32 (...) @get_value() #2
%3 = tail call i32 (...) @get_value() #2
tail call void @consume_value(i32 %1) #2
tail call void @consume_value(i32 %2) #2
tail call void @consume_value(i32 %3) #2
tail call void @consume_value(i32 1764) #2
tail call void @consume_three_values(i32 %1, i32 %2, i32 %3) #2
ret void
}

; CHECK: ldr r0, LCPI0_0
; CHECK-NOT: str r0
; CHECK: bl
; CHECK: ldr r0, LCPI0_0
; CHECK-LABEL: LCPI0_0:
; CHECK-NEXT: .long 1764
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/Thumb/select.ll
Expand Up @@ -74,9 +74,9 @@ define double @f7(double %a, double %b) {
}
; CHECK-LABEL: f7:
; CHECK: blt
; CHECK: blt
; CHECK: {{blt|bge}}
; CHECK: __ltdf2
; CHECK-EABI-LABEL: f7:
; CHECK-EABI: __aeabi_dcmplt
; CHECK-EABI: bne
; CHECK-EABI: bne
; CHECK-EABI: {{bne|beq}}

0 comments on commit 2893448

Please sign in to comment.