aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2009-08-14 00:32:16 +0000
committerEvan Cheng <evan.cheng@apple.com>2009-08-14 00:32:16 +0000
commita1efbbdbf3217598f334a6f39dab84ca06f5de41 (patch)
treef795d4be2592c6e8899a3fed7c340b1e4ea2c468 /lib/Target/ARM
parent0668dc7955644dcf5003b5356dabf9edb847932f (diff)
downloadexternal_llvm-a1efbbdbf3217598f334a6f39dab84ca06f5de41.zip
external_llvm-a1efbbdbf3217598f334a6f39dab84ca06f5de41.tar.gz
external_llvm-a1efbbdbf3217598f334a6f39dab84ca06f5de41.tar.bz2
Shrink ADR and LDR from constantpool late during constantpool island pass.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78970 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r--lib/Target/ARM/ARMConstantIslandPass.cpp83
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td9
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td1
-rw-r--r--lib/Target/ARM/Thumb2SizeReduction.cpp2
4 files changed, 79 insertions, 16 deletions
diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp
index d60799e..ea64bab 100644
--- a/lib/Target/ARM/ARMConstantIslandPass.cpp
+++ b/lib/Target/ARM/ARMConstantIslandPass.cpp
@@ -32,11 +32,12 @@
#include "llvm/ADT/Statistic.h"
using namespace llvm;
-STATISTIC(NumCPEs, "Number of constpool entries");
-STATISTIC(NumSplit, "Number of uncond branches inserted");
-STATISTIC(NumCBrFixed, "Number of cond branches fixed");
-STATISTIC(NumUBrFixed, "Number of uncond branches fixed");
-STATISTIC(NumTBs, "Number of table branches generated");
+STATISTIC(NumCPEs, "Number of constpool entries");
+STATISTIC(NumSplit, "Number of uncond branches inserted");
+STATISTIC(NumCBrFixed, "Number of cond branches fixed");
+STATISTIC(NumUBrFixed, "Number of uncond branches fixed");
+STATISTIC(NumTBs, "Number of table branches generated");
+STATISTIC(NumT2CPShrunk, "Number of Thumb2 constantpool instructions shrunk");
namespace {
/// ARMConstantIslands - Due to limited PC-relative displacements, ARM
@@ -179,6 +180,8 @@ namespace {
bool FixUpConditionalBr(MachineFunction &MF, ImmBranch &Br);
bool FixUpUnconditionalBr(MachineFunction &MF, ImmBranch &Br);
bool UndoLRSpillRestore();
+ bool OptimizeThumb2Instructions(MachineFunction &MF);
+ bool OptimizeThumb2Branches(MachineFunction &MF);
bool OptimizeThumb2JumpTables(MachineFunction &MF);
unsigned GetOffsetOf(MachineInstr *MI) const;
@@ -292,8 +295,9 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &MF) {
MadeChange = true;
}
- // Let's see if we can use tbb / tbh to do jump tables.
- MadeChange |= OptimizeThumb2JumpTables(MF);
+ // Shrink 32-bit Thumb2 branch, load, and store instructions.
+ if (isThumb2)
+ MadeChange |= OptimizeThumb2Instructions(MF);
// After a while, this might be made debug-only, but it is not expensive.
verify(MF);
@@ -1077,7 +1081,7 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &MF,
unsigned Size = CPEMI->getOperand(2).getImm();
MachineBasicBlock *NewMBB;
// Compute this only once, it's expensive. The 4 or 8 is the value the
- // hardware keeps in the PC (2 insns ahead of the reference).
+ // hardware keeps in the PC.
unsigned UserOffset = GetOffsetOf(UserMI) + (isThumb ? 4 : 8);
// See if the current entry is within range, or there is a clone of it
@@ -1350,6 +1354,62 @@ bool ARMConstantIslands::UndoLRSpillRestore() {
return MadeChange;
}
+bool ARMConstantIslands::OptimizeThumb2Instructions(MachineFunction &MF) {
+ bool MadeChange = false;
+
+ // Shrink ADR and LDR from constantpool.
+ for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) {
+ CPUser &U = CPUsers[i];
+ unsigned Opcode = U.MI->getOpcode();
+ unsigned NewOpc = 0;
+ unsigned Scale = 1;
+ unsigned Bits = 0;
+ switch (Opcode) {
+ default: break;
+ case ARM::t2LEApcrel:
+ if (isARMLowRegister(U.MI->getOperand(0).getReg())) {
+ NewOpc = ARM::tLEApcrel;
+ Bits = 8;
+ Scale = 4;
+ }
+ break;
+ case ARM::t2LDRpci:
+ if (isARMLowRegister(U.MI->getOperand(0).getReg())) {
+ NewOpc = ARM::tLDRpci;
+ Bits = 8;
+ Scale = 4;
+ }
+ break;
+ }
+
+ if (!NewOpc)
+ continue;
+
+ unsigned UserOffset = GetOffsetOf(U.MI) + 4;
+ unsigned MaxOffs = ((1 << Bits) - 1) * Scale;
+ // FIXME: Check if offset is multiple of scale if scale is not 4.
+ if (CPEIsInRange(U.MI, UserOffset, U.CPEMI, MaxOffs, false, true)) {
+ U.MI->setDesc(TII->get(NewOpc));
+ MachineBasicBlock *MBB = U.MI->getParent();
+ BBSizes[MBB->getNumber()] -= 2;
+ AdjustBBOffsetsAfter(MBB, -2);
+ ++NumT2CPShrunk;
+ MadeChange = true;
+ }
+ }
+
+ MadeChange |= OptimizeThumb2JumpTables(MF);
+ MadeChange |= OptimizeThumb2Branches(MF);
+ return MadeChange;
+}
+
+bool ARMConstantIslands::OptimizeThumb2Branches(MachineFunction &MF) {
+ return false;
+}
+
+
+/// OptimizeThumb2JumpTables - Use tbb / tbh instructions to generate smaller
+/// jumptables when it's possible.
bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) {
bool MadeChange = false;
@@ -1417,10 +1477,11 @@ bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) {
if (!OptOk)
continue;
- // The previous instruction should be a t2LEApcrelJT, we want to delete
- // it as well.
+ // The previous instruction should be a tLEApcrel or t2LEApcrelJT, we want
+ // to delete it as well.
MachineInstr *LeaMI = --PrevI;
- if (LeaMI->getOpcode() != ARM::t2LEApcrelJT ||
+ if ((LeaMI->getOpcode() != ARM::tLEApcrelJT &&
+ LeaMI->getOpcode() != ARM::t2LEApcrelJT) ||
LeaMI->getOperand(0).getReg() != BaseReg)
OptOk = false;
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 212c32b..3e4725f 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -627,11 +627,12 @@ def tMOVCCi : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iALU,
// tLEApcrel - Load a pc-relative address into a register without offending the
// assembler.
-def tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label), IIC_iALU,
- "adr $dst, #$label", []>;
+def tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALU,
+ "adr$p.n $dst, #$label", []>;
-def tLEApcrelJT : T1I<(outs tGPR:$dst), (ins i32imm:$label, lane_cst:$id),
- IIC_iALU, "adr $dst, #${label}_${id}", []>;
+def tLEApcrelJT : T1I<(outs tGPR:$dst),
+ (ins i32imm:$label, lane_cst:$id, pred:$p),
+ IIC_iALU, "adr$p $dst, #${label}_${id}", []>;
//===----------------------------------------------------------------------===//
// TLS Instructions
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index c4e79a7..840a6bb 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -434,7 +434,6 @@ def t2LEApcrelJT : T2XI<(outs GPR:$dst),
(ins i32imm:$label, lane_cst:$id, pred:$p), IIC_iALU,
"adr$p.w $dst, #${label}_${id}", []>;
-
// ADD r, sp, {so_imm|i12}
def t2ADDrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), IIC_iALU,
"add", ".w $dst, $sp, $imm", []>;
diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp
index fd6bcf0..0a86a75 100644
--- a/lib/Target/ARM/Thumb2SizeReduction.cpp
+++ b/lib/Target/ARM/Thumb2SizeReduction.cpp
@@ -71,6 +71,8 @@ namespace {
{ ARM::t2CMPzri,ARM::tCMPzi8, 0, 8, 0, 1, 0, 2,0, 0 },
{ ARM::t2CMPzrr,ARM::tCMPzhir,0, 0, 0, 0, 0, 2,0, 0 },
{ ARM::t2EORrr, 0, ARM::tEOR, 0, 0, 0, 1, 0,0, 0 },
+ // FIXME: adr.n immediate offset must be multiple of 4.
+ //{ ARM::t2LEApcrelJT,ARM::tLEApcrelJT, 0, 0, 0, 1, 0, 1,0, 0 },
{ ARM::t2LSLri, ARM::tLSLri, 0, 5, 0, 1, 0, 0,0, 0 },
{ ARM::t2LSLrr, 0, ARM::tLSLrr, 0, 0, 0, 1, 0,0, 0 },
{ ARM::t2LSRri, ARM::tLSRri, 0, 5, 0, 1, 0, 0,0, 0 },