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.
|
/// This pass is used to reduce the size of instructions where applicable.
|
||||||
///
|
///
|
||||||
/// TODO: Implement microMIPS64 support.
|
/// TODO: Implement microMIPS64 support.
|
||||||
/// TODO: Implement support for reducing into lwp/swp instruction.
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
#include "Mips.h"
|
#include "Mips.h"
|
||||||
#include "MipsInstrInfo.h"
|
#include "MipsInstrInfo.h"
|
||||||
|
@ -22,8 +21,10 @@
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "micromips-reduce-size"
|
#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 {
|
namespace {
|
||||||
|
|
||||||
|
@ -35,11 +36,14 @@ enum OperandTransfer {
|
||||||
OT_Operands02, ///< Transfer operands 0 and 2
|
OT_Operands02, ///< Transfer operands 0 and 2
|
||||||
OT_Operand2, ///< Transfer just operand 2
|
OT_Operand2, ///< Transfer just operand 2
|
||||||
OT_OperandsXOR, ///< Transfer operands for XOR16
|
OT_OperandsXOR, ///< Transfer operands for XOR16
|
||||||
|
OT_OperandsLwp, ///< Transfer operands for LWP
|
||||||
|
OT_OperandsSwp, ///< Transfer operands for SWP
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reduction type
|
/// Reduction type
|
||||||
// TODO: Will be extended when additional optimizations are added
|
// TODO: Will be extended when additional optimizations are added
|
||||||
enum ReduceType {
|
enum ReduceType {
|
||||||
|
RT_TwoInstr, ///< Reduce two instructions into one instruction
|
||||||
RT_OneInstr ///< Reduce one instruction into a smaller instruction
|
RT_OneInstr ///< Reduce one instruction into a smaller instruction
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,21 +80,22 @@ struct OpCodes {
|
||||||
unsigned NarrowOpc; ///< Narrow opcode
|
unsigned NarrowOpc; ///< Narrow opcode
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct ReduceEntryFunArgs ReduceEntryFunArgs;
|
||||||
|
|
||||||
/// ReduceTable - A static table with information on mapping from wide
|
/// ReduceTable - A static table with information on mapping from wide
|
||||||
/// opcodes to narrow
|
/// opcodes to narrow
|
||||||
struct ReduceEntry {
|
struct ReduceEntry {
|
||||||
|
|
||||||
enum ReduceType eRType; ///< Reduction type
|
enum ReduceType eRType; ///< Reduction type
|
||||||
bool (*ReduceFunction)(
|
bool (*ReduceFunction)(
|
||||||
MachineInstr *MI,
|
ReduceEntryFunArgs *Arguments); ///< Pointer to reduce function
|
||||||
const ReduceEntry &Entry); ///< Pointer to reduce function
|
|
||||||
struct OpCodes Ops; ///< All relevant OpCodes
|
struct OpCodes Ops; ///< All relevant OpCodes
|
||||||
struct OpInfo OpInf; ///< Characteristics of operands
|
struct OpInfo OpInf; ///< Characteristics of operands
|
||||||
struct ImmField Imm; ///< Characteristics of immediate field
|
struct ImmField Imm; ///< Characteristics of immediate field
|
||||||
|
|
||||||
ReduceEntry(enum ReduceType RType, struct OpCodes Op,
|
ReduceEntry(enum ReduceType RType, struct OpCodes Op,
|
||||||
bool (*F)(MachineInstr *MI, const ReduceEntry &Entry),
|
bool (*F)(ReduceEntryFunArgs *Arguments), struct OpInfo OpInf,
|
||||||
struct OpInfo OpInf, struct ImmField Imm)
|
struct ImmField Imm)
|
||||||
: eRType(RType), ReduceFunction(F), Ops(Op), OpInf(OpInf), Imm(Imm) {}
|
: eRType(RType), ReduceFunction(F), Ops(Op), OpInf(OpInf), Imm(Imm) {}
|
||||||
|
|
||||||
unsigned NarrowOpc() const { return Ops.NarrowOpc; }
|
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 {
|
class MicroMipsSizeReduce : public MachineFunctionPass {
|
||||||
public:
|
public:
|
||||||
static char ID;
|
static char ID;
|
||||||
|
@ -132,42 +151,50 @@ private:
|
||||||
bool ReduceMBB(MachineBasicBlock &MBB);
|
bool ReduceMBB(MachineBasicBlock &MBB);
|
||||||
|
|
||||||
/// Attempts to reduce MI, returns true on success.
|
/// 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,
|
// Attempts to reduce LW/SW instruction into LWSP/SWSP,
|
||||||
// returns true on success.
|
// 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,
|
// Attempts to reduce LBU/LHU instruction into LBU16/LHU16,
|
||||||
// returns true on success.
|
// 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,
|
// Attempts to reduce SB/SH instruction into SB16/SH16,
|
||||||
// returns true on success.
|
// 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.
|
// Attempts to reduce arithmetic instructions, returns true on success.
|
||||||
static bool ReduceArithmeticInstructions(MachineInstr *MI,
|
static bool ReduceArithmeticInstructions(ReduceEntryFunArgs *Arguments);
|
||||||
const ReduceEntry &Entry);
|
|
||||||
|
|
||||||
// Attempts to reduce ADDIU into ADDIUSP instruction,
|
// Attempts to reduce ADDIU into ADDIUSP instruction,
|
||||||
// returns true on success.
|
// returns true on success.
|
||||||
static bool ReduceADDIUToADDIUSP(MachineInstr *MI, const ReduceEntry &Entry);
|
static bool ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments);
|
||||||
|
|
||||||
// Attempts to reduce ADDIU into ADDIUR1SP instruction,
|
// Attempts to reduce ADDIU into ADDIUR1SP instruction,
|
||||||
// returns true on success.
|
// returns true on success.
|
||||||
static bool ReduceADDIUToADDIUR1SP(MachineInstr *MI,
|
static bool ReduceADDIUToADDIUR1SP(ReduceEntryFunArgs *Arguments);
|
||||||
const ReduceEntry &Entry);
|
|
||||||
|
|
||||||
// Attempts to reduce XOR into XOR16 instruction,
|
// Attempts to reduce XOR into XOR16 instruction,
|
||||||
// returns true on success.
|
// returns true on success.
|
||||||
static bool ReduceXORtoXOR16(MachineInstr *MI, const ReduceEntry &Entry);
|
static bool ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments);
|
||||||
|
|
||||||
// Changes opcode of an instruction.
|
// Changes opcode of an instruction, replaces an instruction with a
|
||||||
static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry);
|
// 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.
|
// Table with transformation rules for each instruction.
|
||||||
static llvm::SmallVector<ReduceEntry, 16> ReduceTable;
|
static ReduceEntryVector ReduceTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
char MicroMipsSizeReduce::ID = 0;
|
char MicroMipsSizeReduce::ID = 0;
|
||||||
|
@ -175,7 +202,7 @@ const MipsInstrInfo *MicroMipsSizeReduce::MipsII;
|
||||||
|
|
||||||
// This table must be sorted by WideOpc as a main criterion and
|
// This table must be sorted by WideOpc as a main criterion and
|
||||||
// ReduceType as a sub-criterion (when wide opcodes are the same).
|
// ReduceType as a sub-criterion (when wide opcodes are the same).
|
||||||
llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {
|
ReduceEntryVector MicroMipsSizeReduce::ReduceTable = {
|
||||||
|
|
||||||
// ReduceType, OpCodes, ReduceFunction,
|
// ReduceType, OpCodes, ReduceFunction,
|
||||||
// OpInfo(TransferOperands),
|
// OpInfo(TransferOperands),
|
||||||
|
@ -206,8 +233,14 @@ llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = {
|
||||||
OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
|
OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
|
||||||
{RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16,
|
{RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16,
|
||||||
OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)},
|
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,
|
{RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP,
|
||||||
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
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,
|
{RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP,
|
||||||
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
||||||
{RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16,
|
{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),
|
{RT_OneInstr, OpCodes(Mips::SUBu_MM, Mips::SUBU16_MM),
|
||||||
ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
|
ReduceArithmeticInstructions, OpInfo(OT_OperandsAll),
|
||||||
ImmField(0, 0, 0, -1)},
|
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,
|
{RT_OneInstr, OpCodes(Mips::SW, Mips::SWSP_MM), ReduceXWtoXWSP,
|
||||||
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
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,
|
{RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP,
|
||||||
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)},
|
||||||
{RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16,
|
{RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16,
|
||||||
OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)},
|
OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)},
|
||||||
{RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16,
|
{RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16,
|
||||||
OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}};
|
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.
|
// Returns true if the machine operand MO is register SP.
|
||||||
static bool IsSP(const MachineOperand &MO) {
|
static bool IsSP(const MachineOperand &MO) {
|
||||||
|
@ -299,37 +341,100 @@ static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry) {
|
||||||
return true;
|
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) {}
|
MicroMipsSizeReduce::MicroMipsSizeReduce() : MachineFunctionPass(ID) {}
|
||||||
|
|
||||||
bool MicroMipsSizeReduce::ReduceMI(
|
bool MicroMipsSizeReduce::ReduceMI(const MachineBasicBlock::instr_iterator &MII,
|
||||||
const MachineBasicBlock::instr_iterator &MII) {
|
MachineBasicBlock::instr_iterator &NextMII) {
|
||||||
|
|
||||||
MachineInstr *MI = &*MII;
|
MachineInstr *MI = &*MII;
|
||||||
unsigned Opcode = MI->getOpcode();
|
unsigned Opcode = MI->getOpcode();
|
||||||
|
|
||||||
// Search the table.
|
// Search the table.
|
||||||
llvm::SmallVector<ReduceEntry, 16>::const_iterator Start =
|
ReduceEntryVector::const_iterator Start = std::begin(ReduceTable);
|
||||||
std::begin(ReduceTable);
|
ReduceEntryVector::const_iterator End = std::end(ReduceTable);
|
||||||
llvm::SmallVector<ReduceEntry, 16>::const_iterator End =
|
|
||||||
std::end(ReduceTable);
|
|
||||||
|
|
||||||
std::pair<llvm::SmallVector<ReduceEntry, 16>::const_iterator,
|
std::pair<ReduceEntryVector::const_iterator,
|
||||||
llvm::SmallVector<ReduceEntry, 16>::const_iterator>
|
ReduceEntryVector::const_iterator>
|
||||||
Range = std::equal_range(Start, End, Opcode);
|
Range = std::equal_range(Start, End, Opcode);
|
||||||
|
|
||||||
if (Range.first == Range.second)
|
if (Range.first == Range.second)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (llvm::SmallVector<ReduceEntry, 16>::const_iterator Entry = Range.first;
|
for (ReduceEntryVector::const_iterator Entry = Range.first;
|
||||||
Entry != Range.second; ++Entry)
|
Entry != Range.second; ++Entry) {
|
||||||
if (((*Entry).ReduceFunction)(&(*MII), *Entry))
|
ReduceEntryFunArgs Arguments(&(*MII), *Entry, NextMII);
|
||||||
|
if (((*Entry).ReduceFunction)(&Arguments))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroMipsSizeReduce::ReduceXWtoXWSP(MachineInstr *MI,
|
bool MicroMipsSizeReduce::ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments) {
|
||||||
const ReduceEntry &Entry) {
|
|
||||||
|
MachineInstr *MI = Arguments->MI;
|
||||||
|
const ReduceEntry &Entry = Arguments->Entry;
|
||||||
|
|
||||||
if (!ImmInRange(MI, Entry))
|
if (!ImmInRange(MI, Entry))
|
||||||
return false;
|
return false;
|
||||||
|
@ -340,8 +445,51 @@ bool MicroMipsSizeReduce::ReduceXWtoXWSP(MachineInstr *MI,
|
||||||
return ReplaceInstruction(MI, Entry);
|
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(
|
bool MicroMipsSizeReduce::ReduceArithmeticInstructions(
|
||||||
MachineInstr *MI, const ReduceEntry &Entry) {
|
ReduceEntryFunArgs *Arguments) {
|
||||||
|
|
||||||
|
MachineInstr *MI = Arguments->MI;
|
||||||
|
const ReduceEntry &Entry = Arguments->Entry;
|
||||||
|
|
||||||
if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
|
if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
|
||||||
!isMMThreeBitGPRegister(MI->getOperand(1)) ||
|
!isMMThreeBitGPRegister(MI->getOperand(1)) ||
|
||||||
|
@ -351,8 +499,11 @@ bool MicroMipsSizeReduce::ReduceArithmeticInstructions(
|
||||||
return ReplaceInstruction(MI, Entry);
|
return ReplaceInstruction(MI, Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(MachineInstr *MI,
|
bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(
|
||||||
const ReduceEntry &Entry) {
|
ReduceEntryFunArgs *Arguments) {
|
||||||
|
|
||||||
|
MachineInstr *MI = Arguments->MI;
|
||||||
|
const ReduceEntry &Entry = Arguments->Entry;
|
||||||
|
|
||||||
if (!ImmInRange(MI, Entry))
|
if (!ImmInRange(MI, Entry))
|
||||||
return false;
|
return false;
|
||||||
|
@ -363,8 +514,10 @@ bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(MachineInstr *MI,
|
||||||
return ReplaceInstruction(MI, Entry);
|
return ReplaceInstruction(MI, Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(MachineInstr *MI,
|
bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments) {
|
||||||
const ReduceEntry &Entry) {
|
|
||||||
|
MachineInstr *MI = Arguments->MI;
|
||||||
|
const ReduceEntry &Entry = Arguments->Entry;
|
||||||
|
|
||||||
int64_t ImmValue;
|
int64_t ImmValue;
|
||||||
if (!GetImm(MI, Entry.ImmField(), ImmValue))
|
if (!GetImm(MI, Entry.ImmField(), ImmValue))
|
||||||
|
@ -379,8 +532,10 @@ bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(MachineInstr *MI,
|
||||||
return ReplaceInstruction(MI, Entry);
|
return ReplaceInstruction(MI, Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI,
|
bool MicroMipsSizeReduce::ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments) {
|
||||||
const ReduceEntry &Entry) {
|
|
||||||
|
MachineInstr *MI = Arguments->MI;
|
||||||
|
const ReduceEntry &Entry = Arguments->Entry;
|
||||||
|
|
||||||
if (!ImmInRange(MI, Entry))
|
if (!ImmInRange(MI, Entry))
|
||||||
return false;
|
return false;
|
||||||
|
@ -392,8 +547,10 @@ bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI,
|
||||||
return ReplaceInstruction(MI, Entry);
|
return ReplaceInstruction(MI, Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI,
|
bool MicroMipsSizeReduce::ReduceSXtoSX16(ReduceEntryFunArgs *Arguments) {
|
||||||
const ReduceEntry &Entry) {
|
|
||||||
|
MachineInstr *MI = Arguments->MI;
|
||||||
|
const ReduceEntry &Entry = Arguments->Entry;
|
||||||
|
|
||||||
if (!ImmInRange(MI, Entry))
|
if (!ImmInRange(MI, Entry))
|
||||||
return false;
|
return false;
|
||||||
|
@ -405,8 +562,11 @@ bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI,
|
||||||
return ReplaceInstruction(MI, Entry);
|
return ReplaceInstruction(MI, Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroMipsSizeReduce::ReduceXORtoXOR16(MachineInstr *MI,
|
bool MicroMipsSizeReduce::ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments) {
|
||||||
const ReduceEntry &Entry) {
|
|
||||||
|
MachineInstr *MI = Arguments->MI;
|
||||||
|
const ReduceEntry &Entry = Arguments->Entry;
|
||||||
|
|
||||||
if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
|
if (!isMMThreeBitGPRegister(MI->getOperand(0)) ||
|
||||||
!isMMThreeBitGPRegister(MI->getOperand(1)) ||
|
!isMMThreeBitGPRegister(MI->getOperand(1)) ||
|
||||||
!isMMThreeBitGPRegister(MI->getOperand(2)))
|
!isMMThreeBitGPRegister(MI->getOperand(2)))
|
||||||
|
@ -435,14 +595,16 @@ bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Try to reduce 32-bit instruction into 16-bit instruction
|
// Try to reduce 32-bit instruction into 16-bit instruction
|
||||||
Modified |= ReduceMI(MII);
|
Modified |= ReduceMI(MII, NextMII);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Modified;
|
return Modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI,
|
bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI,
|
||||||
const ReduceEntry &Entry) {
|
const ReduceEntry &Entry,
|
||||||
|
MachineInstr *MI2,
|
||||||
|
bool ConsecutiveForward) {
|
||||||
|
|
||||||
enum OperandTransfer OpTransfer = Entry.TransferOperands();
|
enum OperandTransfer OpTransfer = Entry.TransferOperands();
|
||||||
|
|
||||||
|
@ -479,6 +641,27 @@ bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI,
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
llvm_unreachable("Unknown operand transfer!");
|
llvm_unreachable("Unknown operand transfer!");
|
||||||
}
|
}
|
||||||
|
@ -513,6 +696,6 @@ bool MicroMipsSizeReduce::runOnMachineFunction(MachineFunction &MF) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an instance of the MicroMips size reduction pass.
|
/// Returns an instance of the MicroMips size reduction pass.
|
||||||
FunctionPass *llvm::createMicroMipsSizeReductionPass() {
|
FunctionPass *llvm::createMicroMipsSizeReducePass() {
|
||||||
return new MicroMipsSizeReduce();
|
return new MicroMipsSizeReduce();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace llvm {
|
||||||
class MipsSubtarget;
|
class MipsSubtarget;
|
||||||
class MipsTargetMachine;
|
class MipsTargetMachine;
|
||||||
class InstructionSelector;
|
class InstructionSelector;
|
||||||
|
class PassRegistry;
|
||||||
|
|
||||||
ModulePass *createMipsOs16Pass();
|
ModulePass *createMipsOs16Pass();
|
||||||
ModulePass *createMips16HardFloatPass();
|
ModulePass *createMips16HardFloatPass();
|
||||||
|
@ -35,7 +36,7 @@ namespace llvm {
|
||||||
FunctionPass *createMipsDelaySlotFillerPass();
|
FunctionPass *createMipsDelaySlotFillerPass();
|
||||||
FunctionPass *createMipsBranchExpansion();
|
FunctionPass *createMipsBranchExpansion();
|
||||||
FunctionPass *createMipsConstantIslandPass();
|
FunctionPass *createMipsConstantIslandPass();
|
||||||
FunctionPass *createMicroMipsSizeReductionPass();
|
FunctionPass *createMicroMipsSizeReducePass();
|
||||||
|
|
||||||
InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &,
|
InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &,
|
||||||
MipsSubtarget &,
|
MipsSubtarget &,
|
||||||
|
@ -43,6 +44,7 @@ namespace llvm {
|
||||||
|
|
||||||
void initializeMipsDelaySlotFillerPass(PassRegistry &);
|
void initializeMipsDelaySlotFillerPass(PassRegistry &);
|
||||||
void initializeMipsBranchExpansionPass(PassRegistry &);
|
void initializeMipsBranchExpansionPass(PassRegistry &);
|
||||||
|
void initializeMicroMipsSizeReducePass(PassRegistry &);
|
||||||
} // end namespace llvm;
|
} // end namespace llvm;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -728,6 +728,10 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin,
|
||||||
(Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
|
(Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
|
||||||
Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL))
|
Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL))
|
||||||
continue;
|
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;
|
Filler = CurrI;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -55,6 +55,7 @@ extern "C" void LLVMInitializeMipsTarget() {
|
||||||
initializeGlobalISel(*PR);
|
initializeGlobalISel(*PR);
|
||||||
initializeMipsDelaySlotFillerPass(*PR);
|
initializeMipsDelaySlotFillerPass(*PR);
|
||||||
initializeMipsBranchExpansionPass(*PR);
|
initializeMipsBranchExpansionPass(*PR);
|
||||||
|
initializeMicroMipsSizeReducePass(*PR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string computeDataLayout(const Triple &TT, StringRef CPU,
|
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
|
// machine code is emitted. return true if -print-machineinstrs should
|
||||||
// print out the code after the passes.
|
// print out the code after the passes.
|
||||||
void MipsPassConfig::addPreEmitPass() {
|
void MipsPassConfig::addPreEmitPass() {
|
||||||
addPass(createMicroMipsSizeReductionPass());
|
addPass(createMicroMipsSizeReducePass());
|
||||||
|
|
||||||
// The delay slot filler pass can potientially create forbidden slot hazards
|
// The delay slot filler pass can potientially create forbidden slot hazards
|
||||||
// for MIPSR6 and therefore it should go before MipsBranchExpansion pass.
|
// 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-LABEL: and_i128:
|
||||||
; MM32R3: # %bb.0: # %entry
|
; MM32R3: # %bb.0: # %entry
|
||||||
; MM32R3-NEXT: lw $3, 20($sp)
|
; MM32R3-NEXT: lwp $2, 16($sp)
|
||||||
; MM32R3-NEXT: lw $2, 16($sp)
|
|
||||||
; MM32R3-NEXT: and16 $2, $4
|
; MM32R3-NEXT: and16 $2, $4
|
||||||
; MM32R3-NEXT: and16 $3, $5
|
; MM32R3-NEXT: and16 $3, $5
|
||||||
; MM32R3-NEXT: lw $4, 24($sp)
|
; 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: # %bb.0: # %entry
|
||||||
; MMR3-NEXT: addiusp -48
|
; MMR3-NEXT: addiusp -48
|
||||||
; MMR3-NEXT: .cfi_def_cfa_offset 48
|
; MMR3-NEXT: .cfi_def_cfa_offset 48
|
||||||
; MMR3-NEXT: sw $17, 44($sp) # 4-byte Folded Spill
|
; MMR3-NEXT: swp $16, 40($sp)
|
||||||
; MMR3-NEXT: sw $16, 40($sp) # 4-byte Folded Spill
|
|
||||||
; MMR3-NEXT: .cfi_offset 17, -4
|
; MMR3-NEXT: .cfi_offset 17, -4
|
||||||
; MMR3-NEXT: .cfi_offset 16, -8
|
; MMR3-NEXT: .cfi_offset 16, -8
|
||||||
; MMR3-NEXT: move $8, $7
|
; 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: movn $2, $11, $10
|
||||||
; MMR3-NEXT: move $3, $8
|
; MMR3-NEXT: move $3, $8
|
||||||
; MMR3-NEXT: move $4, $1
|
; MMR3-NEXT: move $4, $1
|
||||||
; MMR3-NEXT: lw $16, 40($sp) # 4-byte Folded Reload
|
; MMR3-NEXT: lwp $16, 40($sp)
|
||||||
; MMR3-NEXT: lw $17, 44($sp) # 4-byte Folded Reload
|
|
||||||
; MMR3-NEXT: addiusp 48
|
; MMR3-NEXT: addiusp 48
|
||||||
; MMR3-NEXT: jrc $ra
|
; MMR3-NEXT: jrc $ra
|
||||||
;
|
;
|
||||||
|
|
|
@ -818,8 +818,7 @@ define signext i128 @lshr_i128(i128 signext %a, i128 signext %b) {
|
||||||
; MMR3: # %bb.0: # %entry
|
; MMR3: # %bb.0: # %entry
|
||||||
; MMR3-NEXT: addiusp -40
|
; MMR3-NEXT: addiusp -40
|
||||||
; MMR3-NEXT: .cfi_def_cfa_offset 40
|
; MMR3-NEXT: .cfi_def_cfa_offset 40
|
||||||
; MMR3-NEXT: sw $17, 36($sp) # 4-byte Folded Spill
|
; MMR3-NEXT: swp $16, 32($sp)
|
||||||
; MMR3-NEXT: sw $16, 32($sp) # 4-byte Folded Spill
|
|
||||||
; MMR3-NEXT: .cfi_offset 17, -4
|
; MMR3-NEXT: .cfi_offset 17, -4
|
||||||
; MMR3-NEXT: .cfi_offset 16, -8
|
; MMR3-NEXT: .cfi_offset 16, -8
|
||||||
; MMR3-NEXT: move $8, $7
|
; 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: li16 $4, 0
|
||||||
; MMR3-NEXT: movz $2, $4, $10
|
; MMR3-NEXT: movz $2, $4, $10
|
||||||
; MMR3-NEXT: move $4, $1
|
; MMR3-NEXT: move $4, $1
|
||||||
; MMR3-NEXT: lw $16, 32($sp) # 4-byte Folded Reload
|
; MMR3-NEXT: lwp $16, 32($sp)
|
||||||
; MMR3-NEXT: lw $17, 36($sp) # 4-byte Folded Reload
|
|
||||||
; MMR3-NEXT: addiusp 40
|
; MMR3-NEXT: addiusp 40
|
||||||
; MMR3-NEXT: jrc $ra
|
; MMR3-NEXT: jrc $ra
|
||||||
;
|
;
|
||||||
|
|
|
@ -176,8 +176,7 @@ define signext i128 @or_i128(i128 signext %a, i128 signext %b) {
|
||||||
;
|
;
|
||||||
; MM32-LABEL: or_i128:
|
; MM32-LABEL: or_i128:
|
||||||
; MM32: # %bb.0: # %entry
|
; MM32: # %bb.0: # %entry
|
||||||
; MM32-NEXT: lw $3, 20($sp)
|
; MM32-NEXT: lwp $2, 16($sp)
|
||||||
; MM32-NEXT: lw $2, 16($sp)
|
|
||||||
; MM32-NEXT: or16 $2, $4
|
; MM32-NEXT: or16 $2, $4
|
||||||
; MM32-NEXT: or16 $3, $5
|
; MM32-NEXT: or16 $3, $5
|
||||||
; MM32-NEXT: lw $4, 24($sp)
|
; 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: # %bb.0: # %entry
|
||||||
; MMR3-NEXT: addiusp -40
|
; MMR3-NEXT: addiusp -40
|
||||||
; MMR3-NEXT: .cfi_def_cfa_offset 40
|
; MMR3-NEXT: .cfi_def_cfa_offset 40
|
||||||
; MMR3-NEXT: sw $17, 36($sp) # 4-byte Folded Spill
|
; MMR3-NEXT: swp $16, 32($sp)
|
||||||
; MMR3-NEXT: sw $16, 32($sp) # 4-byte Folded Spill
|
|
||||||
; MMR3-NEXT: .cfi_offset 17, -4
|
; MMR3-NEXT: .cfi_offset 17, -4
|
||||||
; MMR3-NEXT: .cfi_offset 16, -8
|
; MMR3-NEXT: .cfi_offset 16, -8
|
||||||
; MMR3-NEXT: move $17, $7
|
; 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: movz $6, $3, $10
|
||||||
; MMR3-NEXT: move $3, $8
|
; MMR3-NEXT: move $3, $8
|
||||||
; MMR3-NEXT: move $5, $6
|
; MMR3-NEXT: move $5, $6
|
||||||
; MMR3-NEXT: lw $16, 32($sp) # 4-byte Folded Reload
|
; MMR3-NEXT: lwp $16, 32($sp)
|
||||||
; MMR3-NEXT: lw $17, 36($sp) # 4-byte Folded Reload
|
|
||||||
; MMR3-NEXT: addiusp 40
|
; MMR3-NEXT: addiusp 40
|
||||||
; MMR3-NEXT: jrc $ra
|
; MMR3-NEXT: jrc $ra
|
||||||
;
|
;
|
||||||
|
|
|
@ -333,8 +333,7 @@ define signext i128 @xor_i128(i128 signext %a, i128 signext %b) {
|
||||||
;
|
;
|
||||||
; MM32R3-LABEL: xor_i128:
|
; MM32R3-LABEL: xor_i128:
|
||||||
; MM32R3: # %bb.0: # %entry
|
; MM32R3: # %bb.0: # %entry
|
||||||
; MM32R3-NEXT: lw $3, 20($sp)
|
; MM32R3-NEXT: lwp $2, 16($sp)
|
||||||
; MM32R3-NEXT: lw $2, 16($sp)
|
|
||||||
; MM32R3-NEXT: xor16 $2, $4
|
; MM32R3-NEXT: xor16 $2, $4
|
||||||
; MM32R3-NEXT: xor16 $3, $5
|
; MM32R3-NEXT: xor16 $3, $5
|
||||||
; MM32R3-NEXT: lw $4, 24($sp)
|
; 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