/// Order of operands to transfer
// TODO: Will be extended when additional optimizations are added
enum OperandTransfer {
- OT_NA, ///< Not applicable
- OT_OperandsAll, ///< Transfer all operands
- 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
+ OT_NA, ///< Not applicable
+ OT_OperandsAll, ///< Transfer all operands
+ 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
+ OT_OperandsMovep, ///< Transfer operands for MOVEP
};
/// Reduction type
// returns true on success.
static bool ReduceSXtoSX16(ReduceEntryFunArgs *Arguments);
+ // Attempts to reduce two MOVE instructions into MOVEP instruction,
+ // returns true on success.
+ static bool ReduceMoveToMovep(ReduceEntryFunArgs *Arguments);
+
// Attempts to reduce arithmetic instructions, returns true on success.
static bool ReduceArithmeticInstructions(ReduceEntryFunArgs *Arguments);
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_TwoInstr, OpCodes(Mips::MOVE16_MM, Mips::MOVEP_MM), ReduceMoveToMovep,
+ OpInfo(OT_OperandsMovep), ImmField(0, 0, 0, -1)},
{RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16,
OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)},
{RT_OneInstr, OpCodes(Mips::SB_MM, Mips::SB16_MM), ReduceSXtoSX16,
return ReplaceInstruction(MI, Entry);
}
+// Returns true if Reg can be a source register
+// of MOVEP instruction
+static bool IsMovepSrcRegister(unsigned Reg) {
+
+ if (Reg == Mips::ZERO || Reg == Mips::V0 || Reg == Mips::V1 ||
+ Reg == Mips::S0 || Reg == Mips::S1 || Reg == Mips::S2 ||
+ Reg == Mips::S3 || Reg == Mips::S4)
+ return true;
+
+ return false;
+}
+
+// Returns true if Reg can be a destination register
+// of MOVEP instruction
+static bool IsMovepDestinationReg(unsigned Reg) {
+
+ if (Reg == Mips::A0 || Reg == Mips::A1 || Reg == Mips::A2 ||
+ Reg == Mips::A3 || Reg == Mips::S5 || Reg == Mips::S6)
+ return true;
+
+ return false;
+}
+
+// Returns true if the registers can be a pair of destination
+// registers in MOVEP instruction
+static bool IsMovepDestinationRegPair(unsigned R0, unsigned R1) {
+
+ if ((R0 == Mips::A0 && R1 == Mips::S5) ||
+ (R0 == Mips::A0 && R1 == Mips::S6) ||
+ (R0 == Mips::A0 && R1 == Mips::A1) ||
+ (R0 == Mips::A0 && R1 == Mips::A2) ||
+ (R0 == Mips::A0 && R1 == Mips::A3) ||
+ (R0 == Mips::A1 && R1 == Mips::A2) ||
+ (R0 == Mips::A1 && R1 == Mips::A3) ||
+ (R0 == Mips::A2 && R1 == Mips::A3))
+ return true;
+
+ return false;
+}
+
+bool MicroMipsSizeReduce::ReduceMoveToMovep(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;
+
+ unsigned RegDstMI1 = MI1->getOperand(0).getReg();
+ unsigned RegSrcMI1 = MI1->getOperand(1).getReg();
+
+ if (!IsMovepSrcRegister(RegSrcMI1))
+ return false;
+
+ if (!IsMovepDestinationReg(RegDstMI1))
+ return false;
+
+ if (MI2->getOpcode() != Entry.WideOpc())
+ return false;
+
+ unsigned RegDstMI2 = MI2->getOperand(0).getReg();
+ unsigned RegSrcMI2 = MI2->getOperand(1).getReg();
+
+ if (!IsMovepSrcRegister(RegSrcMI2))
+ return false;
+
+ bool ConsecutiveForward;
+ if (IsMovepDestinationRegPair(RegDstMI1, RegDstMI2)) {
+ ConsecutiveForward = true;
+ } else if (IsMovepDestinationRegPair(RegDstMI2, RegDstMI1)) {
+ ConsecutiveForward = false;
+ } else
+ return false;
+
+ NextMII = std::next(NextMII);
+ return ReplaceInstruction(MI1, Entry, MI2, ConsecutiveForward);
+}
+
bool MicroMipsSizeReduce::ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments) {
MachineInstr *MI = Arguments->MI;
}
break;
}
+ case OT_OperandsMovep:
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));
+ if (OpTransfer == OT_OperandsMovep)
+ MIB.add(MI2->getOperand(1));
+ else
+ 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));
+ if (OpTransfer == OT_OperandsMovep)
+ MIB.add(MI->getOperand(1));
+ else
+ MIB.add(MI2->getOperand(2));
}
LLVM_DEBUG(dbgs() << "and converting 32-bit: " << *MI2
--- /dev/null
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# 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 i64 @move1() { ret i64 0 }
+ define i64 @move2() { ret i64 0 }
+
+ declare i64 @f(i64 signext)
+ declare i64 @g()
+
+...
+---
+name: move1
+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: '' }
+constants:
+body: |
+ bb.0:
+ liveins: $ra
+
+ ; CHECK-LABEL: name: move1
+ ; CHECK: ADDIUSP_MM -24
+ ; CHECK: CFI_INSTRUCTION def_cfa_offset 24
+ ; CHECK: SWSP_MM killed $ra, $sp, 20 :: (store 4 into %stack.0)
+ ; CHECK: CFI_INSTRUCTION offset $ra_64, -4
+ ; CHECK: JAL_MM @g, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def $v0, implicit-def $v1
+ ; CHECK: $a0, $a1 = MOVEP_MM $v0, $v1
+ ; CHECK: JAL_MM @f, csr_o32, implicit-def dead $ra, implicit $a0, implicit $a1, implicit-def $sp, implicit-def $v0, implicit-def $v1
+ ; CHECK: $ra = LWSP_MM $sp, 20 :: (load 4 from %stack.0)
+ ; CHECK: ADDIUSP_MM 24
+ ; CHECK: PseudoReturn undef $ra, implicit $v0, implicit $v1
+ $sp = ADDiu $sp, -24
+ CFI_INSTRUCTION def_cfa_offset 24
+ SW killed $ra, $sp, 20 :: (store 4 into %stack.0)
+ CFI_INSTRUCTION offset $ra_64, -4
+ JAL_MM @g, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def $v0, implicit-def $v1
+ $a0 = MOVE16_MM $v0
+ $a1 = MOVE16_MM $v1
+ JAL_MM @f, csr_o32, implicit-def dead $ra, implicit $a0, implicit $a1, implicit-def $sp, implicit-def $v0, implicit-def $v1
+ $ra = LW $sp, 20 :: (load 4 from %stack.0)
+ $sp = ADDiu $sp, 24
+ PseudoReturn undef $ra, implicit $v0, implicit $v1
+
+...
+---
+name: move2
+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: '' }
+constants:
+body: |
+ bb.0:
+ liveins: $ra
+
+ ; CHECK-LABEL: name: move2
+ ; CHECK: ADDIUSP_MM -24
+ ; CHECK: CFI_INSTRUCTION def_cfa_offset 24
+ ; CHECK: SWSP_MM killed $ra, $sp, 20 :: (store 4 into %stack.0)
+ ; CHECK: CFI_INSTRUCTION offset $ra_64, -4
+ ; CHECK: JAL_MM @g, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def $v0, implicit-def $v1
+ ; CHECK: $a0, $a1 = MOVEP_MM $v0, $v1
+ ; CHECK: JAL_MM @f, csr_o32, implicit-def dead $ra, implicit $a0, implicit $a1, implicit-def $sp, implicit-def $v0, implicit-def $v1
+ ; CHECK: $ra = LWSP_MM $sp, 20 :: (load 4 from %stack.0)
+ ; CHECK: ADDIUSP_MM 24
+ ; CHECK: PseudoReturn undef $ra, implicit $v0, implicit $v1
+ $sp = ADDiu $sp, -24
+ CFI_INSTRUCTION def_cfa_offset 24
+ SW killed $ra, $sp, 20 :: (store 4 into %stack.0)
+ CFI_INSTRUCTION offset $ra_64, -4
+ JAL_MM @g, csr_o32, implicit-def dead $ra, implicit-def $sp, implicit-def $v0, implicit-def $v1
+ $a1 = MOVE16_MM $v1
+ $a0 = MOVE16_MM $v0
+ JAL_MM @f, csr_o32, implicit-def dead $ra, implicit $a0, implicit $a1, implicit-def $sp, implicit-def $v0, implicit-def $v1
+ $ra = LW $sp, 20 :: (load 4 from %stack.0)
+ $sp = ADDiu $sp, 24
+ PseudoReturn undef $ra, implicit $v0, implicit $v1
+
+...
+---
+
+