aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp124
1 files changed, 112 insertions, 12 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
index 5ece577e8285..6e55bc6b5c2c 100644
--- a/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonRegisterInfo.cpp
@@ -17,8 +17,10 @@
#include "HexagonSubtarget.h"
#include "HexagonTargetMachine.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -30,6 +32,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -41,6 +44,15 @@
using namespace llvm;
+static cl::opt<unsigned> FrameIndexSearchRange(
+ "hexagon-frame-index-search-range", cl::init(32), cl::Hidden,
+ cl::desc("Limit on instruction search range in frame index elimination"));
+
+static cl::opt<unsigned> FrameIndexReuseLimit(
+ "hexagon-frame-index-reuse-limit", cl::init(~0), cl::Hidden,
+ cl::desc("Limit on the number of reused registers in frame index "
+ "elimination"));
+
HexagonRegisterInfo::HexagonRegisterInfo(unsigned HwMode)
: HexagonGenRegisterInfo(Hexagon::R31, 0/*DwarfFlavor*/, 0/*EHFlavor*/,
0/*PC*/, HwMode) {}
@@ -133,7 +145,7 @@ const uint32_t *HexagonRegisterInfo::getCallPreservedMask(
BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
- const {
+ const {
BitVector Reserved(getNumRegs());
Reserved.set(Hexagon::R29);
Reserved.set(Hexagon::R30);
@@ -188,10 +200,10 @@ BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
return Reserved;
}
-
void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOp,
RegScavenger *RS) const {
+ static unsigned ReuseCount = 0;
//
// Hexagon_TODO: Do we need to enforce this for Hexagon?
assert(SPAdj == 0 && "Unexpected");
@@ -210,7 +222,6 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int Offset = HFI.getFrameIndexReference(MF, FI, BP).getFixed();
// Add the offset from the instruction.
int RealOffset = Offset + MI.getOperand(FIOp+1).getImm();
- bool IsKill = false;
unsigned Opc = MI.getOpcode();
switch (Opc) {
@@ -228,18 +239,107 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
if (!HII.isValidOffset(Opc, RealOffset, this)) {
// If the offset is not valid, calculate the address in a temporary
// register and use it with offset 0.
+ int InstOffset = 0;
+ // The actual base register (BP) is typically shared between many
+ // instructions where frame indices are being replaced. In scalar
+ // instructions the offset range is large, and the need for an extra
+ // add instruction is infrequent. Vector loads/stores, however, have
+ // a much smaller offset range: [-8, 7), or #s4. In those cases it
+ // makes sense to "standardize" the immediate in the "addi" instruction
+ // so that multiple loads/stores could be based on it.
+ bool IsPair = false;
+ switch (MI.getOpcode()) {
+ // All of these instructions have the same format: base+#s4.
+ case Hexagon::PS_vloadrw_ai:
+ case Hexagon::PS_vloadrw_nt_ai:
+ case Hexagon::PS_vstorerw_ai:
+ case Hexagon::PS_vstorerw_nt_ai:
+ IsPair = true;
+ LLVM_FALLTHROUGH;
+ case Hexagon::PS_vloadrv_ai:
+ case Hexagon::PS_vloadrv_nt_ai:
+ case Hexagon::PS_vstorerv_ai:
+ case Hexagon::PS_vstorerv_nt_ai:
+ case Hexagon::V6_vL32b_ai:
+ case Hexagon::V6_vS32b_ai: {
+ unsigned HwLen = HST.getVectorLength();
+ if (RealOffset % HwLen == 0) {
+ int VecOffset = RealOffset / HwLen;
+ // Rewrite the offset as "base + [-8, 7)".
+ VecOffset += 8;
+ // Pairs are expanded into two instructions: make sure that both
+ // can use the same base (i.e. VecOffset+1 is not a different
+ // multiple of 16 than VecOffset).
+ if (!IsPair || (VecOffset + 1) % 16 != 0) {
+ RealOffset = (VecOffset & -16) * HwLen;
+ InstOffset = (VecOffset % 16 - 8) * HwLen;
+ }
+ }
+ }
+ }
+
+ // Search backwards in the block for "Reg = A2_addi BP, RealOffset".
+ // This will give us a chance to avoid creating a new register.
+ Register ReuseBP;
+
+ if (ReuseCount < FrameIndexReuseLimit) {
+ unsigned SearchCount = 0, SearchRange = FrameIndexSearchRange;
+ SmallSet<Register,2> SeenVRegs;
+ bool PassedCall = false;
+ LiveRegUnits Defs(*this), Uses(*this);
+
+ for (auto I = std::next(II.getReverse()), E = MB.rend(); I != E; ++I) {
+ if (SearchCount == SearchRange)
+ break;
+ ++SearchCount;
+ const MachineInstr &BI = *I;
+ LiveRegUnits::accumulateUsedDefed(BI, Defs, Uses, this);
+ PassedCall |= BI.isCall();
+ for (const MachineOperand &Op : BI.operands()) {
+ if (SeenVRegs.size() > 1)
+ break;
+ if (Op.isReg() && Op.getReg().isVirtual())
+ SeenVRegs.insert(Op.getReg());
+ }
+ if (BI.getOpcode() != Hexagon::A2_addi)
+ continue;
+ if (BI.getOperand(1).getReg() != BP)
+ continue;
+ const auto &Op2 = BI.getOperand(2);
+ if (!Op2.isImm() || Op2.getImm() != RealOffset)
+ continue;
+
+ Register R = BI.getOperand(0).getReg();
+ if (R.isPhysical()) {
+ if (Defs.available(R))
+ ReuseBP = R;
+ } else if (R.isVirtual()) {
+ // Extending a range of a virtual register can be dangerous,
+ // since the scavenger will need to find a physical register
+ // for it. Avoid extending the range past a function call,
+ // and avoid overlapping it with another virtual register.
+ if (!PassedCall && SeenVRegs.size() <= 1)
+ ReuseBP = R;
+ }
+ break;
+ }
+ if (ReuseBP)
+ ++ReuseCount;
+ }
+
auto &MRI = MF.getRegInfo();
- Register TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
- const DebugLoc &DL = MI.getDebugLoc();
- BuildMI(MB, II, DL, HII.get(Hexagon::A2_addi), TmpR)
- .addReg(BP)
- .addImm(RealOffset);
- BP = TmpR;
- RealOffset = 0;
- IsKill = true;
+ if (!ReuseBP) {
+ ReuseBP = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
+ const DebugLoc &DL = MI.getDebugLoc();
+ BuildMI(MB, II, DL, HII.get(Hexagon::A2_addi), ReuseBP)
+ .addReg(BP)
+ .addImm(RealOffset);
+ }
+ BP = ReuseBP;
+ RealOffset = InstOffset;
}
- MI.getOperand(FIOp).ChangeToRegister(BP, false, false, IsKill);
+ MI.getOperand(FIOp).ChangeToRegister(BP, false, false, false);
MI.getOperand(FIOp+1).ChangeToImmediate(RealOffset);
}