mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
2736a46c89
It's currently quite difficult to test passes like branch relaxation, which requires branches with large displacement to be generated. The .space assembler directive makes it easy to create arbitrarily large basic blocks, but getInlineAsmLength is not able to parse it and so the size of the block is not correctly estimated. Other backends (AArch64, AMDGPU) introduce options just for testing that artificially restrict the ranges of branch instructions (e.g. aarch64-tbz-offset-bits). Although parsing a single form of the .space directive feels inelegant, it does allow a more direct testing approach. This patch adapts the .space parsing code from Mips16InstrInfo::getInlineAsmLength and removes it now the extra functionality is provided by the base implementation. I want to move this functionality to the generic getInlineAsmLength as 1) I need the same for RISC-V, and 2) I feel other backends will benefit from more direct testing of large branch displacements. Differential Revision: https://reviews.llvm.org/D37798 llvm-svn: 314393
125 lines
5.0 KiB
C++
125 lines
5.0 KiB
C++
//===- Mips16InstrInfo.h - Mips16 Instruction Information -------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the Mips16 implementation of the TargetInstrInfo class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_MIPS_MIPS16INSTRINFO_H
|
|
#define LLVM_LIB_TARGET_MIPS_MIPS16INSTRINFO_H
|
|
|
|
#include "Mips16RegisterInfo.h"
|
|
#include "MipsInstrInfo.h"
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
#include "llvm/Support/MathExtras.h"
|
|
#include <cstdint>
|
|
|
|
namespace llvm {
|
|
|
|
class MCInstrDesc;
|
|
class MipsSubtarget;
|
|
|
|
class Mips16InstrInfo : public MipsInstrInfo {
|
|
const Mips16RegisterInfo RI;
|
|
|
|
public:
|
|
explicit Mips16InstrInfo(const MipsSubtarget &STI);
|
|
|
|
const MipsRegisterInfo &getRegisterInfo() const override;
|
|
|
|
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
|
/// load from a stack slot, return the virtual or physical register number of
|
|
/// the destination along with the FrameIndex of the loaded stack slot. If
|
|
/// not, return 0. This predicate must return 0 if the instruction has
|
|
/// any side effects other than loading from the stack slot.
|
|
unsigned isLoadFromStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const override;
|
|
|
|
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
|
/// store to a stack slot, return the virtual or physical register number of
|
|
/// the source reg along with the FrameIndex of the loaded stack slot. If
|
|
/// not, return 0. This predicate must return 0 if the instruction has
|
|
/// any side effects other than storing to the stack slot.
|
|
unsigned isStoreToStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const override;
|
|
|
|
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
|
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
|
|
bool KillSrc) const override;
|
|
|
|
void storeRegToStack(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI,
|
|
unsigned SrcReg, bool isKill, int FrameIndex,
|
|
const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI,
|
|
int64_t Offset) const override;
|
|
|
|
void loadRegFromStack(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI,
|
|
unsigned DestReg, int FrameIndex,
|
|
const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI,
|
|
int64_t Offset) const override;
|
|
|
|
bool expandPostRAPseudo(MachineInstr &MI) const override;
|
|
|
|
unsigned getOppositeBranchOpc(unsigned Opc) const override;
|
|
|
|
// Adjust SP by FrameSize bytes. Save RA, S0, S1
|
|
void makeFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I) const;
|
|
|
|
// Adjust SP by FrameSize bytes. Restore RA, S0, S1
|
|
void restoreFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I) const;
|
|
|
|
/// Adjust SP by Amount bytes.
|
|
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I) const override;
|
|
|
|
/// Emit a series of instructions to load an immediate.
|
|
// This is to adjust some FrameReg. We return the new register to be used
|
|
// in place of FrameReg and the adjusted immediate field (&NewImm)
|
|
unsigned loadImmediate(unsigned FrameReg, int64_t Imm, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator II, const DebugLoc &DL,
|
|
unsigned &NewImm) const;
|
|
|
|
static bool validImmediate(unsigned Opcode, unsigned Reg, int64_t Amount);
|
|
|
|
static bool validSpImm8(int offset) {
|
|
return ((offset & 7) == 0) && isInt<11>(offset);
|
|
}
|
|
|
|
// build the proper one based on the Imm field
|
|
|
|
const MCInstrDesc& AddiuSpImm(int64_t Imm) const;
|
|
|
|
void BuildAddiuSpImm
|
|
(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const;
|
|
private:
|
|
unsigned getAnalyzableBrOpc(unsigned Opc) const override;
|
|
|
|
void ExpandRetRA16(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
|
unsigned Opc) const;
|
|
|
|
// Adjust SP by Amount bytes where bytes can be up to 32bit number.
|
|
void adjustStackPtrBig(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I,
|
|
unsigned Reg1, unsigned Reg2) const;
|
|
|
|
// Adjust SP by Amount bytes where bytes can be up to 32bit number.
|
|
void adjustStackPtrBigUnrestricted(unsigned SP, int64_t Amount,
|
|
MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I) const;
|
|
};
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_LIB_TARGET_MIPS_MIPS16INSTRINFO_H
|