summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorTilmann Scheller <tilmann.scheller@googlemail.com>2013-09-05 11:10:31 +0000
committerTilmann Scheller <tilmann.scheller@googlemail.com>2013-09-05 11:10:31 +0000
commita1787a58350d45c61e4586cbe1cb8271572f0496 (patch)
tree96a937da380e40b12dd409bd35ae82e62725da82 /llvm/lib/Target
parentf3a5d004915bf70a32359d45d043a4197dc4c20d (diff)
downloadbcm5719-llvm-a1787a58350d45c61e4586cbe1cb8271572f0496.tar.gz
bcm5719-llvm-a1787a58350d45c61e4586cbe1cb8271572f0496.zip
ARM: Add GPR register class excluding LR for use with the ADR instruction.
This improves code generation for jump tables by avoiding the emission of "mov pc, lr" which could fool the processor into believing this is a return from a function causing mispredicts. The code generation logic for jump tables uses ADR to materialize the address of the jump target. Patch by Daniel Stewart! llvm-svn: 190043
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMInstrThumb2.td2
-rw-r--r--llvm/lib/Target/ARM/ARMRegisterInfo.td8
-rw-r--r--llvm/lib/Target/ARM/Thumb2InstrInfo.cpp16
3 files changed, 23 insertions, 3 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index 5d0c48443ac..2f3fa63a41a 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -1233,7 +1233,7 @@ let neverHasSideEffects = 1, isReMaterializable = 1 in
def t2LEApcrel : t2PseudoInst<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p),
4, IIC_iALUi, []>, Sched<[WriteALU, ReadALU]>;
let hasSideEffects = 1 in
-def t2LEApcrelJT : t2PseudoInst<(outs rGPR:$Rd),
+def t2LEApcrelJT : t2PseudoInst<(outs jtGPR:$Rd),
(ins i32imm:$label, nohash_imm:$id, pred:$p),
4, IIC_iALUi,
[]>, Sched<[WriteALU, ReadALU]>;
diff --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td
index 90c6a965acf..51ecaf7c465 100644
--- a/llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -240,6 +240,14 @@ def rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> {
}];
}
+// jtGPR - Jump Table General Purpose Registers.
+// Used by the Thumb2 instructions to prevent Thumb2 jump tables
+// from using the LR. The implementation of the jump table uses a mov pc, rA
+// type instruction to jump into the table. Use of the LR register (as in
+// mov pc, lr) can cause the ARM branch predictor to think it is returning
+// from a function instead. This causes a mispredict and a pipe flush.
+def jtGPR : RegisterClass<"ARM", [i32], 32, (sub rGPR, LR)>;
+
// Thumb registers are R0-R7 normally. Some instructions can still use
// the general GPR register class above (MOV, e.g.)
def tGPR : RegisterClass<"ARM", [i32], 32, (trunc GPR, 8)>;
diff --git a/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp b/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
index 286eaa0946d..7c51c70f679 100644
--- a/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
+++ b/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
@@ -152,7 +152,13 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
// gsub_0, but needs an extra constraint for gsub_1 (which could be sp
// otherwise).
MachineRegisterInfo *MRI = &MF.getRegInfo();
- MRI->constrainRegClass(SrcReg, &ARM::GPRPair_with_gsub_1_in_rGPRRegClass);
+ const TargetRegisterClass* TargetClass = TRI->getMatchingSuperRegClass(RC,
+ &ARM::rGPRRegClass,
+ ARM::gsub_1);
+ assert(TargetClass && "No Matching GPRPair with gsub_1 in rGPRRegClass");
+ const TargetRegisterClass* ConstrainedClass =
+ MRI->constrainRegClass(SrcReg, TargetClass);
+ assert(ConstrainedClass && "Couldn't constrain the register class");
MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2STRDi8));
AddDReg(MIB, SrcReg, ARM::gsub_0, getKillRegState(isKill), TRI);
@@ -193,7 +199,13 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
// gsub_0, but needs an extra constraint for gsub_1 (which could be sp
// otherwise).
MachineRegisterInfo *MRI = &MF.getRegInfo();
- MRI->constrainRegClass(DestReg, &ARM::GPRPair_with_gsub_1_in_rGPRRegClass);
+ const TargetRegisterClass* TargetClass = TRI->getMatchingSuperRegClass(RC,
+ &ARM::rGPRRegClass,
+ ARM::gsub_1);
+ assert(TargetClass && "No Matching GPRPair with gsub_1 in rGPRRegClass");
+ const TargetRegisterClass* ConstrainedClass =
+ MRI->constrainRegClass(DestReg, TargetClass);
+ assert(ConstrainedClass && "Couldn't constrain the register class");
MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2LDRDi8));
AddDReg(MIB, DestReg, ARM::gsub_0, RegState::DefineNoRead, TRI);
OpenPOWER on IntegriCloud