forked from OSchip/llvm-project
[mips][microMIPS] Extending size reduction pass with LWP and SWP
Author: milena.vujosevic.janicic Reviewers: sdardis The patch extends size reduction pass for MicroMIPS. It introduces reduction of two instructions into one instruction: Two SW instructions are transformed into one SWP instrucition. Two LW instructions are transformed into one LWP instrucition. Differential Revision: https://reviews.llvm.org/D39115 llvm-svn: 334595
This commit is contained in:
parent
36b816f814
commit
3a7654c15d
|
@ -10,7 +10,6 @@
|
|||
/// This pass is used to reduce the size of instructions where applicable.
|
||||
///
|
||||
/// TODO: Implement microMIPS64 support.
|
||||
/// TODO: Implement support for reducing into lwp/swp instruction.
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "Mips.h"
|
||||
#include "MipsInstrInfo.h"
|
||||
|
@ -22,8 +21,10 @@
|
|||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "micromips-reduce-size"
|
||||
#define MICROMIPS_SIZE_REDUCE_NAME "MicroMips instruction size reduce pass"
|
||||
|
||||
STATISTIC(NumReduced, "Number of 32-bit instructions reduced to 16-bit ones");
|
||||
STATISTIC(NumReduced, "Number of instructions reduced (32-bit to 16-bit ones, "
|
||||
"or two instructions into one");
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -35,12 +36,15 @@ enum OperandTransfer {
|
|||
OT_Operands02, ///< Transfer operands 0 and 2
|
||||
OT_Operand2, ///< Transfer just operand 2
|
||||
OT_OperandsXOR, ///< Transfer operands for XOR16
|
||||
OT_OperandsLwp, ///< Transfer operands for LWP
|
||||
OT_OperandsSwp, ///< Transfer operands for SWP
|
||||
};
|
||||
|
||||
/// Reduction type
|
||||
// TODO: Will be extended when additional optimizations are added
|
||||
enum ReduceType {
|
||||
RT_OneInstr ///< Reduce one instruction into a smaller instruction
|
||||
RT_TwoInstr, ///< Reduce two instructions into one instruction
|
||||
RT_OneInstr ///< Reduce one instruction into a smaller instruction
|
||||
};
|
||||
|
||||
// Information about immediate field restrictions
|
||||
|
@ -76,21 +80,22 @@ struct OpCodes {
|
|||
unsigned NarrowOpc; ///< Narrow opcode
|
||||
};
|
||||
|
||||
typedef struct ReduceEntryFunArgs ReduceEntryFunArgs;
|
||||
|
||||
/// ReduceTable - A static table with information on mapping from wide
|
||||
/// opcodes to narrow
|
||||
struct ReduceEntry {
|
||||
|
||||
enum ReduceType eRType; ///< Reduction type
|
||||
bool (*ReduceFunction)(
|
||||
MachineInstr *MI,
|
||||
const ReduceEntry &Entry); ///< Pointer to reduce function
|
||||
struct OpCodes Ops; ///< All relevant OpCodes
|
||||
struct OpInfo OpInf; ///< Characteristics of operands
|
||||
struct ImmField Imm; ///< Characteristics of immediate field
|
||||
ReduceEntryFunArgs *Arguments); ///< Pointer to reduce function
|
||||
struct OpCodes Ops; ///< All relevant OpCodes
|
||||
struct OpInfo OpInf; ///< Characteristics of operands
|
||||
struct ImmField Imm; ///< Characteristics of immediate field
|
||||
|
||||
ReduceEntry(enum ReduceType RType, struct OpCodes Op,
|
||||
bool (*F)(MachineInstr *MI, const ReduceEntry &Entry),
|
||||
struct OpInfo OpInf, struct ImmField Imm)
|
||||
bool (*F)(ReduceEntryFunArgs *Arguments), struct OpInfo OpInf,
|
||||
struct ImmField Imm)
|
||||
: eRType(RType), ReduceFunction(F), Ops(Op), OpInf(OpInf), Imm(Imm) {}
|
||||
|
||||
unsigned NarrowOpc() const { return Ops.NarrowOpc; }
|
||||
|
@ -113,6 +118,20 @@ struct ReduceEntry {
|
|||
}
|
||||
};
|
||||
|
||||
// Function arguments for ReduceFunction
|
||||
struct ReduceEntryFunArgs {
|
||||
MachineInstr *MI; // Instruction
|
||||
const ReduceEntry &Entry; // Entry field
|
||||
MachineBasicBlock::instr_iterator
|
||||
&NextMII; // Iterator to next instruction in block
|
||||
|
||||
ReduceEntryFunArgs(MachineInstr *argMI, const ReduceEntry &argEntry,
|
||||
MachineBasicBlock::instr_iterator &argNextMII)
|
||||
: MI(argMI), Entry(argEntry), NextMII(argNextMII) {}
|
||||
};
|
||||
|
||||
typedef llvm::SmallVector<ReduceEntry, 32> ReduceEntryVector;
|
||||
|
||||
class MicroMipsSizeReduce : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
@ -132,42 +151,50 @@ private:
|
|||
bool ReduceMBB(MachineBasicBlock &MBB);
|
||||
|
||||
/// Attempts to reduce MI, returns true on success.
|
||||
bool ReduceMI(const MachineBasicBlock::instr_iterator &MII);
|
||||
bool ReduceMI(const MachineBasicBlock::instr_iterator &MII,
|
||||
MachineBasicBlock::instr_iterator &NextMII);
|
||||
|
||||
// Attempts to reduce LW/SW instruction into LWSP/SWSP,
|
||||
// returns true on success.
|
||||
static bool ReduceXWtoXWSP(MachineInstr *MI, const ReduceEntry &Entry);
|
||||
static bool ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments);
|
||||
|
||||
// Attempts to reduce two LW/SW instructions into LWP/SWP instruction,
|
||||
// returns true on success.
|
||||
static bool ReduceXWtoXWP(ReduceEntryFunArgs *Arguments);
|
||||
|
||||
// Attempts to reduce LBU/LHU instruction into LBU16/LHU16,
|
||||
// returns true on success.
|
||||
static bool ReduceLXUtoLXU16(MachineInstr *MI, const ReduceEntry &Entry);
|
||||
static bool ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments);
|
||||
|
||||
// Attempts to reduce SB/SH instruction into SB16/SH16,
|
||||
// returns true on success.
|
||||
static bool ReduceSXtoSX16(MachineInstr *MI, const ReduceEntry &Entry);
|
||||
static bool ReduceSXtoSX16(ReduceEntryFunArgs *Arguments);
|
||||
|
||||
// Attempts to reduce arithmetic instructions, returns true on success.
|
||||
static bool ReduceArithmeticInstructions(MachineInstr *MI,
|
||||
const ReduceEntry &Entry);
|
||||
static bool ReduceArithmeticInstructions(ReduceEntryFunArgs *Arguments);
|
||||
|
||||
// Attempts to reduce ADDIU into ADDIUSP instruction,
|
||||
// returns true on success.
|
||||
static bool ReduceADDIUToADDIUSP(MachineInstr *MI, const ReduceEntry &Entry);
|
||||
static bool ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments);
|
||||
|
||||
// Attempts to reduce ADDIU into ADDIUR1SP instruction,
|
||||
// returns true on success.
|
||||
static bool ReduceADDIUToADDIUR1SP(MachineInstr *MI,
|
||||
const ReduceEntry &Entry);
|
||||
static bool ReduceADDIUToADDIUR1SP(ReduceEntryFunArgs *Arguments);
|
||||
|
||||
// Attempts to reduce XOR into XOR16 instruction,
|
||||
// returns true on success.
|
||||
static bool ReduceXORtoXOR16(MachineInstr *MI, const ReduceEntry &Entry);
|
||||
static bool ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments);
|
||||
|
||||
// Changes opcode of an instruction.
|
||||
static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry);
|
||||
// Changes opcode of an instruction, replaces an instruction with a
|
||||
// new one, or replaces two instructions with a new instruction
|
||||
// depending on their order i.e. if these are consecutive forward
|
||||
// or consecutive backward
|
||||
static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry,
|
||||
MachineInstr *MI2 = nullptr,
|
||||
bool ConsecutiveForward = true);
|
||||
|
||||
// Table with transformation rules for each instruction.
|
||||
static llvm::SmallVector<ReduceEntry, 16> ReduceTable;
|
||||
static ReduceEntryVector ReduceTable;
|
||||
};
|
||||
|
||||
char MicroMipsSizeReduce::ID = 0;
|
||||
|
@ -175,7 +202,7 @@ const MipsInstrInfo *MicroMipsSizeReduce::MipsII;
|
|||
|
||||
// This table must be sorted by WideOpc as a main criterion and
|
||||
// ReduceType as a sub-criterion (when wide opcodes are the same).
|
||||
llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {
|
||||
ReduceEntryVector MicroMipsSizeReduce::ReduceTable = {
|
||||
|
||||
// ReduceType, OpCodes, ReduceFunction,
|
||||
// OpInfo(TransferOperands),
|
||||
|
@ -206,8 +233,14 @@ llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {
|
|||
OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
|
||||
{RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16,
|
||||
OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
|
||||
{RT_TwoInstr, OpCodes(Mips::LW, Mips::LWP_MM), ReduceXWtoXWP,
|
||||
OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
|
||||
{RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP,
|
||||
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
||||
{RT_TwoInstr, OpCodes(Mips::LW16_MM, Mips::LWP_MM), ReduceXWtoXWP,
|
||||
OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
|
||||
{RT_TwoInstr, OpCodes(Mips::LW_MM, Mips::LWP_MM), ReduceXWtoXWP,
|
||||
OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)},
|
||||
{RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP,
|
||||
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
||||
{RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16,
|
||||
|
@ -224,15 +257,24 @@ llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {
|
|||
{RT_OneInstr, OpCodes(Mips::SUBu_MM, Mips::SUBU16_MM),
|
||||
ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
|
||||
ImmField(0, 0, 0, -1)},
|
||||
{RT_TwoInstr, OpCodes(Mips::SW, Mips::SWP_MM), ReduceXWtoXWP,
|
||||
OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
|
||||
{RT_OneInstr, OpCodes(Mips::SW, Mips::SWSP_MM), ReduceXWtoXWSP,
|
||||
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
||||
{RT_TwoInstr, OpCodes(Mips::SW16_MM, Mips::SWP_MM), ReduceXWtoXWP,
|
||||
OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
|
||||
{RT_TwoInstr, OpCodes(Mips::SW_MM, Mips::SWP_MM), ReduceXWtoXWP,
|
||||
OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)},
|
||||
{RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP,
|
||||
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
||||
{RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16,
|
||||
OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)},
|
||||
{RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16,
|
||||
OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}};
|
||||
} // namespace
|
||||
} // end anonymous namespace
|
||||
|
||||
INITIALIZE_PASS(MicroMipsSizeReduce, DEBUG_TYPE, MICROMIPS_SIZE_REDUCE_NAME,
|
||||
false, false)
|
||||
|
||||
// Returns true if the machine operand MO is register SP.
|
||||
static bool IsSP(const MachineOperand &MO) {
|
||||
|
@ -299,37 +341,100 @@ static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Returns true if MI can be reduced to lwp/swp instruction
|
||||
static bool CheckXWPInstr(MachineInstr *MI, bool ReduceToLwp,
|
||||
const ReduceEntry &Entry) {
|
||||
|
||||
if (ReduceToLwp &&
|
||||
!(MI->getOpcode() == Mips::LW || MI->getOpcode() == Mips::LW_MM ||
|
||||
MI->getOpcode() == Mips::LW16_MM))
|
||||
return false;
|
||||
|
||||
if (!ReduceToLwp &&
|
||||
!(MI->getOpcode() == Mips::SW || MI->getOpcode() == Mips::SW_MM ||
|
||||
MI->getOpcode() == Mips::SW16_MM))
|
||||
return false;
|
||||
|
||||
unsigned reg = MI->getOperand(0).getReg();
|
||||
if (reg == Mips::RA)
|
||||
return false;
|
||||
|
||||
if (!ImmInRange(MI, Entry))
|
||||
return false;
|
||||
|
||||
if (ReduceToLwp && (MI->getOperand(0).getReg() == MI->getOperand(1).getReg()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if the registers Reg1 and Reg2 are consecutive
|
||||
static bool ConsecutiveRegisters(unsigned Reg1, unsigned Reg2) {
|
||||
static SmallVector<unsigned, 31> Registers = {
|
||||
Mips::AT, Mips::V0, Mips::V1, Mips::A0, Mips::A1, Mips::A2, Mips::A3,
|
||||
Mips::T0, Mips::T1, Mips::T2, Mips::T3, Mips::T4, Mips::T5, Mips::T6,
|
||||
Mips::T7, Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5,
|
||||
Mips::S6, Mips::S7, Mips::T8, Mips::T9, Mips::K0, Mips::K1, Mips::GP,
|
||||
Mips::SP, Mips::FP, Mips::RA};
|
||||
|
||||
for (uint8_t i = 0; i < Registers.size() - 1; i++) {
|
||||
if (Registers[i] == Reg1) {
|
||||
if (Registers[i + 1] == Reg2)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if registers and offsets are consecutive
|
||||
static bool ConsecutiveInstr(MachineInstr *MI1, MachineInstr *MI2) {
|
||||
|
||||
int64_t Offset1, Offset2;
|
||||
if (!GetImm(MI1, 2, Offset1))
|
||||
return false;
|
||||
if (!GetImm(MI2, 2, Offset2))
|
||||
return false;
|
||||
|
||||
unsigned Reg1 = MI1->getOperand(0).getReg();
|
||||
unsigned Reg2 = MI2->getOperand(0).getReg();
|
||||
|
||||
return ((Offset1 == (Offset2 - 4)) && (ConsecutiveRegisters(Reg1, Reg2)));
|
||||
}
|
||||
|
||||
MicroMipsSizeReduce::MicroMipsSizeReduce() : MachineFunctionPass(ID) {}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceMI(
|
||||
const MachineBasicBlock::instr_iterator &MII) {
|
||||
bool MicroMipsSizeReduce::ReduceMI(const MachineBasicBlock::instr_iterator &MII,
|
||||
MachineBasicBlock::instr_iterator &NextMII) {
|
||||
|
||||
MachineInstr *MI = &*MII;
|
||||
unsigned Opcode = MI->getOpcode();
|
||||
|
||||
// Search the table.
|
||||
llvm::SmallVector<ReduceEntry, 16>::const_iterator Start =
|
||||
std::begin(ReduceTable);
|
||||
llvm::SmallVector<ReduceEntry, 16>::const_iterator End =
|
||||
std::end(ReduceTable);
|
||||
ReduceEntryVector::const_iterator Start = std::begin(ReduceTable);
|
||||
ReduceEntryVector::const_iterator End = std::end(ReduceTable);
|
||||
|
||||
std::pair<llvm::SmallVector<ReduceEntry, 16>::const_iterator,
|
||||
llvm::SmallVector<ReduceEntry, 16>::const_iterator>
|
||||
std::pair<ReduceEntryVector::const_iterator,
|
||||
ReduceEntryVector::const_iterator>
|
||||
Range = std::equal_range(Start, End, Opcode);
|
||||
|
||||
if (Range.first == Range.second)
|
||||
return false;
|
||||
|
||||
for (llvm::SmallVector<ReduceEntry, 16>::const_iterator Entry = Range.first;
|
||||
Entry != Range.second; ++Entry)
|
||||
if (((*Entry).ReduceFunction)(&(*MII), *Entry))
|
||||
for (ReduceEntryVector::const_iterator Entry = Range.first;
|
||||
Entry != Range.second; ++Entry) {
|
||||
ReduceEntryFunArgs Arguments(&(*MII), *Entry, NextMII);
|
||||
if (((*Entry).ReduceFunction)(&Arguments))
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceXWtoXWSP(MachineInstr *MI,
|
||||
const ReduceEntry &Entry) {
|
||||
bool MicroMipsSizeReduce::ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments) {
|
||||
|
||||
MachineInstr *MI = Arguments->MI;
|
||||
const ReduceEntry &Entry = Arguments->Entry;
|
||||
|
||||
if (!ImmInRange(MI, Entry))
|
||||
return false;
|
||||
|
@ -340,8 +445,51 @@ bool MicroMipsSizeReduce::ReduceXWtoXWSP(MachineInstr *MI,
|
|||
return ReplaceInstruction(MI, Entry);
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceXWtoXWP(ReduceEntryFunArgs *Arguments) {
|
||||
|
||||
const ReduceEntry &Entry = Arguments->Entry;
|
||||
MachineBasicBlock::instr_iterator &NextMII = Arguments->NextMII;
|
||||
const MachineBasicBlock::instr_iterator &E =
|
||||
Arguments->MI->getParent()->instr_end();
|
||||
|
||||
if (NextMII == E)
|
||||
return false;
|
||||
|
||||
MachineInstr *MI1 = Arguments->MI;
|
||||
MachineInstr *MI2 = &*NextMII;
|
||||
|
||||
// ReduceToLwp = true/false - reduce to LWP/SWP instruction
|
||||
bool ReduceToLwp = (MI1->getOpcode() == Mips::LW) ||
|
||||
(MI1->getOpcode() == Mips::LW_MM) ||
|
||||
(MI1->getOpcode() == Mips::LW16_MM);
|
||||
|
||||
if (!CheckXWPInstr(MI1, ReduceToLwp, Entry))
|
||||
return false;
|
||||
|
||||
if (!CheckXWPInstr(MI2, ReduceToLwp, Entry))
|
||||
return false;
|
||||
|
||||
unsigned Reg1 = MI1->getOperand(1).getReg();
|
||||
unsigned Reg2 = MI2->getOperand(1).getReg();
|
||||
|
||||
if (Reg1 != Reg2)
|
||||
return false;
|
||||
|
||||
bool ConsecutiveForward = ConsecutiveInstr(MI1, MI2);
|
||||
bool ConsecutiveBackward = ConsecutiveInstr(MI2, MI1);
|
||||
|
||||
if (!(ConsecutiveForward || ConsecutiveBackward))
|
||||
return false;
|
||||
|
||||
NextMII = std::next(NextMII);
|
||||
return ReplaceInstruction(MI1, Entry, MI2, ConsecutiveForward);
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceArithmeticInstructions(
|
||||
MachineInstr *MI, const ReduceEntry &Entry) {
|
||||
ReduceEntryFunArgs *Arguments) {
|
||||
|
||||
MachineInstr *MI = Arguments->MI;
|
||||
const ReduceEntry &Entry = Arguments->Entry;
|
||||
|
||||
if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
|
||||
!isMMThreeBitGPRegister(MI->getOperand(1)) ||
|
||||
|
@ -351,8 +499,11 @@ bool MicroMipsSizeReduce::ReduceArithmeticInstructions(
|
|||
return ReplaceInstruction(MI, Entry);
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(MachineInstr *MI,
|
||||
const ReduceEntry &Entry) {
|
||||
bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(
|
||||
ReduceEntryFunArgs *Arguments) {
|
||||
|
||||
MachineInstr *MI = Arguments->MI;
|
||||
const ReduceEntry &Entry = Arguments->Entry;
|
||||
|
||||
if (!ImmInRange(MI, Entry))
|
||||
return false;
|
||||
|
@ -363,8 +514,10 @@ bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(MachineInstr *MI,
|
|||
return ReplaceInstruction(MI, Entry);
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(MachineInstr *MI,
|
||||
const ReduceEntry &Entry) {
|
||||
bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments) {
|
||||
|
||||
MachineInstr *MI = Arguments->MI;
|
||||
const ReduceEntry &Entry = Arguments->Entry;
|
||||
|
||||
int64_t ImmValue;
|
||||
if (!GetImm(MI, Entry.ImmField(), ImmValue))
|
||||
|
@ -379,8 +532,10 @@ bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(MachineInstr *MI,
|
|||
return ReplaceInstruction(MI, Entry);
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI,
|
||||
const ReduceEntry &Entry) {
|
||||
bool MicroMipsSizeReduce::ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments) {
|
||||
|
||||
MachineInstr *MI = Arguments->MI;
|
||||
const ReduceEntry &Entry = Arguments->Entry;
|
||||
|
||||
if (!ImmInRange(MI, Entry))
|
||||
return false;
|
||||
|
@ -392,8 +547,10 @@ bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI,
|
|||
return ReplaceInstruction(MI, Entry);
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI,
|
||||
const ReduceEntry &Entry) {
|
||||
bool MicroMipsSizeReduce::ReduceSXtoSX16(ReduceEntryFunArgs *Arguments) {
|
||||
|
||||
MachineInstr *MI = Arguments->MI;
|
||||
const ReduceEntry &Entry = Arguments->Entry;
|
||||
|
||||
if (!ImmInRange(MI, Entry))
|
||||
return false;
|
||||
|
@ -405,8 +562,11 @@ bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI,
|
|||
return ReplaceInstruction(MI, Entry);
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReduceXORtoXOR16(MachineInstr *MI,
|
||||
const ReduceEntry &Entry) {
|
||||
bool MicroMipsSizeReduce::ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments) {
|
||||
|
||||
MachineInstr *MI = Arguments->MI;
|
||||
const ReduceEntry &Entry = Arguments->Entry;
|
||||
|
||||
if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
|
||||
!isMMThreeBitGPRegister(MI->getOperand(1)) ||
|
||||
!isMMThreeBitGPRegister(MI->getOperand(2)))
|
||||
|
@ -435,14 +595,16 @@ bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) {
|
|||
continue;
|
||||
|
||||
// Try to reduce 32-bit instruction into 16-bit instruction
|
||||
Modified |= ReduceMI(MII);
|
||||
Modified |= ReduceMI(MII, NextMII);
|
||||
}
|
||||
|
||||
return Modified;
|
||||
}
|
||||
|
||||
bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI,
|
||||
const ReduceEntry &Entry) {
|
||||
const ReduceEntry &Entry,
|
||||
MachineInstr *MI2,
|
||||
bool ConsecutiveForward) {
|
||||
|
||||
enum OperandTransfer OpTransfer = Entry.TransferOperands();
|
||||
|
||||
|
@ -479,6 +641,27 @@ bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case OT_OperandsLwp:
|
||||
case OT_OperandsSwp: {
|
||||
if (ConsecutiveForward) {
|
||||
MIB.add(MI->getOperand(0));
|
||||
MIB.add(MI2->getOperand(0));
|
||||
MIB.add(MI->getOperand(1));
|
||||
MIB.add(MI->getOperand(2));
|
||||
} else { // consecutive backward
|
||||
MIB.add(MI2->getOperand(0));
|
||||
MIB.add(MI->getOperand(0));
|
||||
MIB.add(MI2->getOperand(1));
|
||||
MIB.add(MI2->getOperand(2));
|
||||
}
|
||||
|
||||
LLVM_DEBUG(dbgs() << "and converting 32-bit: " << *MI2
|
||||
<< " to: " << *MIB);
|
||||
|
||||
MBB.erase_instr(MI);
|
||||
MBB.erase_instr(MI2);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
llvm_unreachable("Unknown operand transfer!");
|
||||
}
|
||||
|
@ -513,6 +696,6 @@ bool MicroMipsSizeReduce::runOnMachineFunction(MachineFunction &MF) {
|
|||
}
|
||||
|
||||
/// Returns an instance of the MicroMips size reduction pass.
|
||||
FunctionPass *llvm::createMicroMipsSizeReductionPass() {
|
||||
FunctionPass *llvm::createMicroMipsSizeReducePass() {
|
||||
return new MicroMipsSizeReduce();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace llvm {
|
|||
class MipsSubtarget;
|
||||
class MipsTargetMachine;
|
||||
class InstructionSelector;
|
||||
class PassRegistry;
|
||||
|
||||
ModulePass *createMipsOs16Pass();
|
||||
ModulePass *createMips16HardFloatPass();
|
||||
|
@ -35,7 +36,7 @@ namespace llvm {
|
|||
FunctionPass *createMipsDelaySlotFillerPass();
|
||||
FunctionPass *createMipsBranchExpansion();
|
||||
FunctionPass *createMipsConstantIslandPass();
|
||||
FunctionPass *createMicroMipsSizeReductionPass();
|
||||
FunctionPass *createMicroMipsSizeReducePass();
|
||||
|
||||
InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &,
|
||||
MipsSubtarget &,
|
||||
|
@ -43,6 +44,7 @@ namespace llvm {
|
|||
|
||||
void initializeMipsDelaySlotFillerPass(PassRegistry &);
|
||||
void initializeMipsBranchExpansionPass(PassRegistry &);
|
||||
void initializeMicroMipsSizeReducePass(PassRegistry &);
|
||||
} // end namespace llvm;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -728,6 +728,10 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin,
|
|||
(Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
|
||||
Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL))
|
||||
continue;
|
||||
// Instructions LWP/SWP should not be in a delay slot as that
|
||||
// results in unpredictable behaviour
|
||||
if (InMicroMipsMode && (Opcode == Mips::LWP_MM || Opcode == Mips::SWP_MM))
|
||||
continue;
|
||||
|
||||
Filler = CurrI;
|
||||
return true;
|
||||
|
|
|
@ -55,6 +55,7 @@ extern "C" void LLVMInitializeMipsTarget() {
|
|||
initializeGlobalISel(*PR);
|
||||
initializeMipsDelaySlotFillerPass(*PR);
|
||||
initializeMipsBranchExpansionPass(*PR);
|
||||
initializeMicroMipsSizeReducePass(*PR);
|
||||
}
|
||||
|
||||
static std::string computeDataLayout(const Triple &TT, StringRef CPU,
|
||||
|
@ -288,7 +289,7 @@ MipsTargetMachine::getTargetTransformInfo(const Function &F) {
|
|||
// machine code is emitted. return true if -print-machineinstrs should
|
||||
// print out the code after the passes.
|
||||
void MipsPassConfig::addPreEmitPass() {
|
||||
addPass(createMicroMipsSizeReductionPass());
|
||||
addPass(createMicroMipsSizeReducePass());
|
||||
|
||||
// The delay slot filler pass can potientially create forbidden slot hazards
|
||||
// for MIPSR6 and therefore it should go before MipsBranchExpansion pass.
|
||||
|
|
|
@ -335,8 +335,7 @@ define signext i128 @and_i128(i128 signext %a, i128 signext %b) {
|
|||
;
|
||||
; MM32R3-LABEL: and_i128:
|
||||
; MM32R3: # %bb.0: # %entry
|
||||
; MM32R3-NEXT: lw $3, 20($sp)
|
||||
; MM32R3-NEXT: lw $2, 16($sp)
|
||||
; MM32R3-NEXT: lwp $2, 16($sp)
|
||||
; MM32R3-NEXT: and16 $2, $4
|
||||
; MM32R3-NEXT: and16 $3, $5
|
||||
; MM32R3-NEXT: lw $4, 24($sp)
|
||||
|
|
|
@ -791,8 +791,7 @@ define signext i128 @ashr_i128(i128 signext %a, i128 signext %b) {
|
|||
; MMR3: # %bb.0: # %entry
|
||||
; MMR3-NEXT: addiusp -48
|
||||
; MMR3-NEXT: .cfi_def_cfa_offset 48
|
||||
; MMR3-NEXT: sw $17, 44($sp) # 4-byte Folded Spill
|
||||
; MMR3-NEXT: sw $16, 40($sp) # 4-byte Folded Spill
|
||||
; MMR3-NEXT: swp $16, 40($sp)
|
||||
; MMR3-NEXT: .cfi_offset 17, -4
|
||||
; MMR3-NEXT: .cfi_offset 16, -8
|
||||
; MMR3-NEXT: move $8, $7
|
||||
|
@ -870,8 +869,7 @@ define signext i128 @ashr_i128(i128 signext %a, i128 signext %b) {
|
|||
; MMR3-NEXT: movn $2, $11, $10
|
||||
; MMR3-NEXT: move $3, $8
|
||||
; MMR3-NEXT: move $4, $1
|
||||
; MMR3-NEXT: lw $16, 40($sp) # 4-byte Folded Reload
|
||||
; MMR3-NEXT: lw $17, 44($sp) # 4-byte Folded Reload
|
||||
; MMR3-NEXT: lwp $16, 40($sp)
|
||||
; MMR3-NEXT: addiusp 48
|
||||
; MMR3-NEXT: jrc $ra
|
||||
;
|
||||
|
|
|
@ -818,8 +818,7 @@ define signext i128 @lshr_i128(i128 signext %a, i128 signext %b) {
|
|||
; MMR3: # %bb.0: # %entry
|
||||
; MMR3-NEXT: addiusp -40
|
||||
; MMR3-NEXT: .cfi_def_cfa_offset 40
|
||||
; MMR3-NEXT: sw $17, 36($sp) # 4-byte Folded Spill
|
||||
; MMR3-NEXT: sw $16, 32($sp) # 4-byte Folded Spill
|
||||
; MMR3-NEXT: swp $16, 32($sp)
|
||||
; MMR3-NEXT: .cfi_offset 17, -4
|
||||
; MMR3-NEXT: .cfi_offset 16, -8
|
||||
; MMR3-NEXT: move $8, $7
|
||||
|
@ -896,8 +895,7 @@ define signext i128 @lshr_i128(i128 signext %a, i128 signext %b) {
|
|||
; MMR3-NEXT: li16 $4, 0
|
||||
; MMR3-NEXT: movz $2, $4, $10
|
||||
; MMR3-NEXT: move $4, $1
|
||||
; MMR3-NEXT: lw $16, 32($sp) # 4-byte Folded Reload
|
||||
; MMR3-NEXT: lw $17, 36($sp) # 4-byte Folded Reload
|
||||
; MMR3-NEXT: lwp $16, 32($sp)
|
||||
; MMR3-NEXT: addiusp 40
|
||||
; MMR3-NEXT: jrc $ra
|
||||
;
|
||||
|
|
|
@ -176,8 +176,7 @@ define signext i128 @or_i128(i128 signext %a, i128 signext %b) {
|
|||
;
|
||||
; MM32-LABEL: or_i128:
|
||||
; MM32: # %bb.0: # %entry
|
||||
; MM32-NEXT: lw $3, 20($sp)
|
||||
; MM32-NEXT: lw $2, 16($sp)
|
||||
; MM32-NEXT: lwp $2, 16($sp)
|
||||
; MM32-NEXT: or16 $2, $4
|
||||
; MM32-NEXT: or16 $3, $5
|
||||
; MM32-NEXT: lw $4, 24($sp)
|
||||
|
|
|
@ -847,8 +847,7 @@ define signext i128 @shl_i128(i128 signext %a, i128 signext %b) {
|
|||
; MMR3: # %bb.0: # %entry
|
||||
; MMR3-NEXT: addiusp -40
|
||||
; MMR3-NEXT: .cfi_def_cfa_offset 40
|
||||
; MMR3-NEXT: sw $17, 36($sp) # 4-byte Folded Spill
|
||||
; MMR3-NEXT: sw $16, 32($sp) # 4-byte Folded Spill
|
||||
; MMR3-NEXT: swp $16, 32($sp)
|
||||
; MMR3-NEXT: .cfi_offset 17, -4
|
||||
; MMR3-NEXT: .cfi_offset 16, -8
|
||||
; MMR3-NEXT: move $17, $7
|
||||
|
@ -926,8 +925,7 @@ define signext i128 @shl_i128(i128 signext %a, i128 signext %b) {
|
|||
; MMR3-NEXT: movz $6, $3, $10
|
||||
; MMR3-NEXT: move $3, $8
|
||||
; MMR3-NEXT: move $5, $6
|
||||
; MMR3-NEXT: lw $16, 32($sp) # 4-byte Folded Reload
|
||||
; MMR3-NEXT: lw $17, 36($sp) # 4-byte Folded Reload
|
||||
; MMR3-NEXT: lwp $16, 32($sp)
|
||||
; MMR3-NEXT: addiusp 40
|
||||
; MMR3-NEXT: jrc $ra
|
||||
;
|
||||
|
|
|
@ -333,8 +333,7 @@ define signext i128 @xor_i128(i128 signext %a, i128 signext %b) {
|
|||
;
|
||||
; MM32R3-LABEL: xor_i128:
|
||||
; MM32R3: # %bb.0: # %entry
|
||||
; MM32R3-NEXT: lw $3, 20($sp)
|
||||
; MM32R3-NEXT: lw $2, 16($sp)
|
||||
; MM32R3-NEXT: lwp $2, 16($sp)
|
||||
; MM32R3-NEXT: xor16 $2, $4
|
||||
; MM32R3-NEXT: xor16 $3, $5
|
||||
; MM32R3-NEXT: lw $4, 24($sp)
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=mipsel-unknown-linux-gnu -mattr=+micromips -mcpu=mips32r2 \
|
||||
; RUN: -verify-machineinstrs < %s | FileCheck %s
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @fun(i32* %adr, i32 %val) {
|
||||
; CHECK-LABEL: fun:
|
||||
; CHECK: # %bb.0: # %entry
|
||||
; CHECK-NEXT: addiusp -32
|
||||
; CHECK-NEXT: .cfi_def_cfa_offset 32
|
||||
; CHECK-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill
|
||||
; CHECK-NEXT: swp $16, 20($sp)
|
||||
; CHECK-NEXT: .cfi_offset 31, -4
|
||||
; CHECK-NEXT: .cfi_offset 17, -8
|
||||
; CHECK-NEXT: .cfi_offset 16, -12
|
||||
; CHECK-NEXT: move $17, $5
|
||||
; CHECK-NEXT: move $16, $4
|
||||
; CHECK-NEXT: jal fun1
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: sw16 $17, 0($16)
|
||||
; CHECK-NEXT: li16 $2, 0
|
||||
; CHECK-NEXT: lwp $16, 20($sp)
|
||||
; CHECK-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload
|
||||
; CHECK-NEXT: addiusp 32
|
||||
; CHECK-NEXT: jrc $ra
|
||||
entry:
|
||||
%call1 = call i32* @fun1()
|
||||
store i32 %val, i32* %adr, align 4
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
declare i32* @fun1()
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
# RUN: llc -mtriple=mipsel-unknown-linux-gnu -mattr=+micromips -mcpu=mips32r2 \
|
||||
# RUN: -verify-machineinstrs -run-pass micromips-reduce-size \
|
||||
# RUN: %s -o - | FileCheck %s
|
||||
|
||||
--- |
|
||||
define void @f1(i32* %adr, i32 %val) { ret void }
|
||||
define void @f2(i32* %adr, i32 %val) { ret void }
|
||||
define void @f3(i32* %adr, i32 %val) { ret void }
|
||||
define void @f4(i32* %adr, i32 %val) { ret void }
|
||||
|
||||
declare i32* @f()
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @llvm.stackprotector(i8*, i8**)
|
||||
|
||||
...
|
||||
---
|
||||
# CHECK-LABEL: name: f1
|
||||
# CHECK: SWP_MM
|
||||
# CHECK: LWP_MM
|
||||
name: f1
|
||||
alignment: 2
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
liveins:
|
||||
- { reg: '$a0', virtual-reg: '' }
|
||||
- { reg: '$a1', virtual-reg: '' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 32
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 4
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
stackProtector: ''
|
||||
maxCallFrameSize: 16
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
savePoint: ''
|
||||
restorePoint: ''
|
||||
fixedStack:
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$ra', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s1', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 2, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s0', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
constants:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $a0, $a1, $ra, $s1, $s0
|
||||
|
||||
$sp = ADDiu $sp, -32
|
||||
CFI_INSTRUCTION def_cfa_offset 32
|
||||
SW killed $ra, $sp, 28 :: (store 4 into %stack.0)
|
||||
SW killed $s1, $sp, 24 :: (store 4 into %stack.1)
|
||||
SW killed $s0, $sp, 20 :: (store 4 into %stack.2)
|
||||
CFI_INSTRUCTION offset $ra_64, -4
|
||||
CFI_INSTRUCTION offset $s1_64, -8
|
||||
CFI_INSTRUCTION offset $s0_64, -12
|
||||
$s1 = MOVE16_MM $a1
|
||||
$s0 = MOVE16_MM $a0
|
||||
JAL @f, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def dead $v0
|
||||
SW16_MM killed renamable $s1, killed renamable $s0, 0 :: (store 4 into %ir.adr)
|
||||
$v0 = LI16_MM 0
|
||||
$s0 = LW $sp, 20 :: (load 4 from %stack.2)
|
||||
$s1 = LW $sp, 24 :: (load 4 from %stack.1)
|
||||
$ra = LW $sp, 28 :: (load 4 from %stack.0)
|
||||
$sp = ADDiu $sp, 32
|
||||
PseudoReturn undef $ra, implicit killed $v0
|
||||
|
||||
...
|
||||
---
|
||||
# CHECK-LABEL: name: f2
|
||||
# CHECK: SWP_MM
|
||||
# CHECK: LWP_MM
|
||||
name: f2
|
||||
alignment: 2
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
liveins:
|
||||
- { reg: '$a0', virtual-reg: '' }
|
||||
- { reg: '$a1', virtual-reg: '' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 32
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 4
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
stackProtector: ''
|
||||
maxCallFrameSize: 16
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
savePoint: ''
|
||||
restorePoint: ''
|
||||
fixedStack:
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$ra', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s1', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 2, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s0', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
constants:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $a0, $a1, $ra, $s1, $s0
|
||||
|
||||
$sp = ADDiu $sp, -32
|
||||
CFI_INSTRUCTION def_cfa_offset 32
|
||||
SW killed $ra, $sp, 28 :: (store 4 into %stack.0)
|
||||
SW_MM killed $s1, $sp, 24 :: (store 4 into %stack.1)
|
||||
SW_MM killed $s0, $sp, 20 :: (store 4 into %stack.2)
|
||||
CFI_INSTRUCTION offset $ra_64, -4
|
||||
CFI_INSTRUCTION offset $s1_64, -8
|
||||
CFI_INSTRUCTION offset $s0_64, -12
|
||||
$s1 = MOVE16_MM $a1
|
||||
$s0 = MOVE16_MM $a0
|
||||
JAL @f, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def dead $v0
|
||||
SW16_MM killed renamable $s1, killed renamable $s0, 0 :: (store 4 into %ir.adr)
|
||||
$v0 = LI16_MM 0
|
||||
$s0 = LW_MM $sp, 20 :: (load 4 from %stack.2)
|
||||
$s1 = LW_MM $sp, 24 :: (load 4 from %stack.1)
|
||||
$ra = LW $sp, 28 :: (load 4 from %stack.0)
|
||||
$sp = ADDiu $sp, 32
|
||||
PseudoReturn undef $ra, implicit killed $v0
|
||||
|
||||
...
|
||||
---
|
||||
# CHECK-LABEL: name: f3
|
||||
# CHECK: SWP_MM
|
||||
# CHECK: LWP_MM
|
||||
name: f3
|
||||
alignment: 2
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
liveins:
|
||||
- { reg: '$a0', virtual-reg: '' }
|
||||
- { reg: '$a1', virtual-reg: '' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 32
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 4
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
stackProtector: ''
|
||||
maxCallFrameSize: 16
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
savePoint: ''
|
||||
restorePoint: ''
|
||||
fixedStack:
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$ra', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s1', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 2, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s0', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
constants:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $a0, $a1, $ra, $s1, $s0
|
||||
|
||||
$sp = ADDiu $sp, -32
|
||||
CFI_INSTRUCTION def_cfa_offset 32
|
||||
SW killed $ra, $sp, 28 :: (store 4 into %stack.0)
|
||||
SW_MM killed $s1, $sp, 24 :: (store 4 into %stack.1)
|
||||
SW killed $s0, $sp, 20 :: (store 4 into %stack.2)
|
||||
CFI_INSTRUCTION offset $ra_64, -4
|
||||
CFI_INSTRUCTION offset $s1_64, -8
|
||||
CFI_INSTRUCTION offset $s0_64, -12
|
||||
$s1 = MOVE16_MM $a1
|
||||
$s0 = MOVE16_MM $a0
|
||||
JAL @f, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def dead $v0
|
||||
SW16_MM killed renamable $s1, killed renamable $s0, 0 :: (store 4 into %ir.adr)
|
||||
$v0 = LI16_MM 0
|
||||
$s0 = LW_MM $sp, 20 :: (load 4 from %stack.2)
|
||||
$s1 = LW $sp, 24 :: (load 4 from %stack.1)
|
||||
$ra = LW $sp, 28 :: (load 4 from %stack.0)
|
||||
$sp = ADDiu $sp, 32
|
||||
PseudoReturn undef $ra, implicit killed $v0
|
||||
|
||||
...
|
||||
---
|
||||
# CHECK-LABEL: name: f4
|
||||
# CHECK: SWP_MM
|
||||
# CHECK: LWP_MM
|
||||
name: f4
|
||||
alignment: 2
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
liveins:
|
||||
- { reg: '$a0', virtual-reg: '' }
|
||||
- { reg: '$a1', virtual-reg: '' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 32
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 4
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
stackProtector: ''
|
||||
maxCallFrameSize: 16
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
savePoint: ''
|
||||
restorePoint: ''
|
||||
fixedStack:
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$ra', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s1', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 2, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s0', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
constants:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $a0, $a1, $ra, $s1, $s0
|
||||
|
||||
$sp = ADDiu $sp, -32
|
||||
CFI_INSTRUCTION def_cfa_offset 32
|
||||
SW killed $ra, $sp, 28 :: (store 4 into %stack.0)
|
||||
SW killed $s1, $sp, 24 :: (store 4 into %stack.1)
|
||||
SW_MM killed $s0, $sp, 20 :: (store 4 into %stack.2)
|
||||
CFI_INSTRUCTION offset $ra_64, -4
|
||||
CFI_INSTRUCTION offset $s1_64, -8
|
||||
CFI_INSTRUCTION offset $s0_64, -12
|
||||
$s1 = MOVE16_MM $a1
|
||||
$s0 = MOVE16_MM $a0
|
||||
JAL @f, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def dead $v0
|
||||
SW16_MM killed renamable $s1, killed renamable $s0, 0 :: (store 4 into %ir.adr)
|
||||
$v0 = LI16_MM 0
|
||||
$s0 = LW $sp, 20 :: (load 4 from %stack.2)
|
||||
$s1 = LW_MM $sp, 24 :: (load 4 from %stack.1)
|
||||
$ra = LW $sp, 28 :: (load 4 from %stack.0)
|
||||
$sp = ADDiu $sp, 32
|
||||
PseudoReturn undef $ra, implicit killed $v0
|
||||
|
||||
...
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
# RUN: llc -mtriple=mipsel-unknown-linux-gnu -mattr=+micromips -mcpu=mips32r2 \
|
||||
# RUN: -verify-machineinstrs -run-pass micromips-reduce-size \
|
||||
# RUN: %s -o - | FileCheck %s
|
||||
|
||||
--- |
|
||||
define void @f1(i32* %adr, i32 %val) { ret void }
|
||||
define void @f2(i32* %adr, i32 %val) { ret void }
|
||||
define void @f3(i32* %adr, i32 %val) { ret void }
|
||||
define void @f4(i32* %adr, i32 %val) { ret void }
|
||||
|
||||
declare i32* @f()
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @llvm.stackprotector(i8*, i8**)
|
||||
...
|
||||
---
|
||||
# CHECK-LABEL: name: f1
|
||||
# CHECK-NOT: SWP_MM
|
||||
# CHECK-NOT: LWP_MM
|
||||
name: f1
|
||||
alignment: 2
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
liveins:
|
||||
- { reg: '$a1', virtual-reg: '' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 24
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 4
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
stackProtector: ''
|
||||
maxCallFrameSize: 16
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
savePoint: ''
|
||||
restorePoint: ''
|
||||
fixedStack:
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$ra', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s0', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
constants:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $a1, $ra, $s0
|
||||
|
||||
$sp = ADDiu $sp, -24
|
||||
CFI_INSTRUCTION def_cfa_offset 24
|
||||
SW killed $ra, $sp, 20 :: (store 4 into %stack.0)
|
||||
SW killed $s0, $sp, 16 :: (store 4 into %stack.1)
|
||||
CFI_INSTRUCTION offset $ra_64, -4
|
||||
CFI_INSTRUCTION offset $s0_64, -8
|
||||
$s0 = MOVE16_MM $a1
|
||||
JAL @f, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def dead $v0
|
||||
$v0 = MOVE16_MM killed $s0
|
||||
$s0 = LW $sp, 16 :: (load 4 from %stack.1)
|
||||
$ra = LW $sp, 20 :: (load 4 from %stack.0)
|
||||
$sp = ADDiu $sp, 24
|
||||
PseudoReturn undef $ra, implicit killed $v0
|
||||
|
||||
...
|
||||
---
|
||||
# CHECK-LABEL: name: f2
|
||||
# CHECK-NOT: SWP_MM
|
||||
# CHECK-NOT: LWP_MM
|
||||
name: f2
|
||||
alignment: 2
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
liveins:
|
||||
- { reg: '$a1', virtual-reg: '' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 24
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 4
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
stackProtector: ''
|
||||
maxCallFrameSize: 16
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
savePoint: ''
|
||||
restorePoint: ''
|
||||
fixedStack:
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$ra', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s0', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
constants:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $a1, $ra, $s0
|
||||
|
||||
$sp = ADDiu $sp, -24
|
||||
CFI_INSTRUCTION def_cfa_offset 24
|
||||
SW_MM killed $ra, $sp, 20 :: (store 4 into %stack.0)
|
||||
SW_MM killed $s0, $sp, 16 :: (store 4 into %stack.1)
|
||||
CFI_INSTRUCTION offset $ra_64, -4
|
||||
CFI_INSTRUCTION offset $s0_64, -8
|
||||
$s0 = MOVE16_MM $a1
|
||||
JAL @f, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def dead $v0
|
||||
$v0 = MOVE16_MM killed $s0
|
||||
$s0 = LW_MM $sp, 16 :: (load 4 from %stack.1)
|
||||
$ra = LW_MM $sp, 20 :: (load 4 from %stack.0)
|
||||
$sp = ADDiu $sp, 24
|
||||
PseudoReturn undef $ra, implicit killed $v0
|
||||
|
||||
...
|
||||
---
|
||||
# CHECK-LABEL: name: f3
|
||||
# CHECK-NOT: SWP_MM
|
||||
# CHECK-NOT: LWP_MM
|
||||
name: f3
|
||||
alignment: 2
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
liveins:
|
||||
- { reg: '$a1', virtual-reg: '' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 24
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 4
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
stackProtector: ''
|
||||
maxCallFrameSize: 16
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
savePoint: ''
|
||||
restorePoint: ''
|
||||
fixedStack:
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$ra', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s0', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
constants:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $a1, $ra, $s0
|
||||
|
||||
$sp = ADDiu $sp, -24
|
||||
CFI_INSTRUCTION def_cfa_offset 24
|
||||
SW_MM killed $ra, $sp, 20 :: (store 4 into %stack.0)
|
||||
SW killed $s0, $sp, 16 :: (store 4 into %stack.1)
|
||||
CFI_INSTRUCTION offset $ra_64, -4
|
||||
CFI_INSTRUCTION offset $s0_64, -8
|
||||
$s0 = MOVE16_MM $a1
|
||||
JAL @f, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def dead $v0
|
||||
$v0 = MOVE16_MM killed $s0
|
||||
$s0 = LW_MM $sp, 16 :: (load 4 from %stack.1)
|
||||
$ra = LW $sp, 20 :: (load 4 from %stack.0)
|
||||
$sp = ADDiu $sp, 24
|
||||
PseudoReturn undef $ra, implicit killed $v0
|
||||
|
||||
...
|
||||
---
|
||||
# CHECK-LABEL: name: f4
|
||||
# CHECK-NOT: SWP_MM
|
||||
# CHECK-NOT: LWP_MM
|
||||
name: f4
|
||||
alignment: 2
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
liveins:
|
||||
- { reg: '$a1', virtual-reg: '' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 24
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 4
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
stackProtector: ''
|
||||
maxCallFrameSize: 16
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
savePoint: ''
|
||||
restorePoint: ''
|
||||
fixedStack:
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$ra', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
- { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
|
||||
stack-id: 0, callee-saved-register: '$s0', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
constants:
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $a1, $ra, $s0
|
||||
|
||||
$sp = ADDiu $sp, -24
|
||||
CFI_INSTRUCTION def_cfa_offset 24
|
||||
SW killed $ra, $sp, 20 :: (store 4 into %stack.0)
|
||||
SW_MM killed $s0, $sp, 16 :: (store 4 into %stack.1)
|
||||
CFI_INSTRUCTION offset $ra_64, -4
|
||||
CFI_INSTRUCTION offset $s0_64, -8
|
||||
$s0 = MOVE16_MM $a1
|
||||
JAL @f, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def dead $v0
|
||||
$v0 = MOVE16_MM killed $s0
|
||||
$s0 = LW $sp, 16 :: (load 4 from %stack.1)
|
||||
$ra = LW_MM $sp, 20 :: (load 4 from %stack.0)
|
||||
$sp = ADDiu $sp, 24
|
||||
PseudoReturn undef $ra, implicit killed $v0
|
||||
|
||||
...
|
||||
|
Loading…
Reference in New Issue