@@ -146,6 +146,19 @@ class MipsAsmParser : public MCTargetAsmParser {
146146 // nullptr, which indicates that no function is currently
147147 // selected. This usually happens after an '.end func'
148148 // directive.
149+ // Because we want do `sw $4, 0($2)
150+ // addiu $2, $2, 4
151+ // bne $2, $3, $BB0_1`
152+ // to
153+ // `addiu $2, $2, 4
154+ // sw $4, -4($2)
155+ // bne $2, $3, $BB0_1`,
156+ // so that the sw can be placed into delay slot.
157+ // If true, reprents inst `addiu` following inst `sw`, and save inst
158+ // `sw`. Later we will check if inst 'bne' following inst `addiu`.
159+ bool saveCurInst;
160+ MCInst CurInst;
161+
149162 bool IsLittleEndian;
150163 bool IsPicEnabled;
151164 bool IsCpRestoreSet;
@@ -351,6 +364,9 @@ class MipsAsmParser : public MCTargetAsmParser {
351364 bool expandSaaAddr (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
352365 const MCSubtargetInfo *STI);
353366
367+ MipsAsmParser::MacroExpanderResultTy expandSW (MCInst &Inst, SMLoc IDLoc,
368+ MCStreamer &Out,
369+ const MCSubtargetInfo *STI);
354370 bool reportParseError (const Twine &ErrorMsg);
355371 bool reportParseError (SMLoc Loc, const Twine &ErrorMsg);
356372
@@ -550,6 +566,7 @@ class MipsAsmParser : public MCTargetAsmParser {
550566 report_fatal_error (" -mno-odd-spreg requires the O32 ABI" );
551567
552568 CurrentFn = nullptr ;
569+ saveCurInst = false ;
553570
554571 CurForbiddenSlotAttr = false ;
555572 IsPicEnabled = getContext ().getObjectFileInfo ()->isPositionIndependent ();
@@ -2572,8 +2589,82 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
25722589 if ((Inst.getNumOperands () == 3 ) && Inst.getOperand (0 ).isReg () &&
25732590 Inst.getOperand (1 ).isReg () && Inst.getOperand (2 ).isImm ()) {
25742591 int64_t ImmValue = Inst.getOperand (2 ).getImm ();
2575- if (isInt<16 >(ImmValue))
2576- return MER_NotAMacro;
2592+ if (isInt<16 >(ImmValue)) {
2593+ if (saveCurInst == true ) {
2594+ AsmToken ID = getTok ();
2595+ saveCurInst = false ;
2596+ bool doLex = false ;
2597+
2598+ // If this is a line comment we can drop it safely.
2599+ while (getLexer ().is (AsmToken::EndOfStatement)) {
2600+ doLex = true ;
2601+ getLexer ().Lex ();
2602+ }
2603+
2604+ // Get last inst `sw` register info and offset value.
2605+ MipsTargetStreamer &TOut = getTargetStreamer ();
2606+ MCRegister FirstReg = CurInst.getOperand (0 ).getReg ();
2607+ MCRegister BaseReg = CurInst.getOperand (1 ).getReg ();
2608+ MCOperand &OffsetImmOp = CurInst.getOperand (2 );
2609+ unsigned OffsetValue = OffsetImmOp.getImm ();
2610+
2611+ // Optimize `sw $4, 0($2)
2612+ // addiu $2, $2, 4
2613+ // bne $2, $3, $BB0_1`
2614+ // to
2615+ // `addiu $2, $2, 4
2616+ // sw $4, -4($2)
2617+ // bne $2, $3, $BB0_1`.
2618+ // If match sw+addiu+bne, then emit addiu+sw.
2619+ if (getTok ().getString () == " bne" ) {
2620+ if (OffsetValue != 0 ) {
2621+ // Back to initial location before return.
2622+ if (doLex == true )
2623+ getLexer ().UnLex (ID);
2624+ // If not match, we need to emit the last reserved instruction
2625+ // `sw`.
2626+ TOut.emitRRI (CurInst.getOpcode (), FirstReg, BaseReg, OffsetValue,
2627+ IDLoc, STI);
2628+ return MER_NotAMacro;
2629+ }
2630+
2631+ // Get inst `addiu` register info and imm value.
2632+ MCRegister destReg = Inst.getOperand (0 ).getReg ();
2633+ MCRegister srcReg = Inst.getOperand (1 ).getReg ();
2634+ unsigned addImm = Inst.getOperand (2 ).getImm ();
2635+
2636+ if (destReg == srcReg && BaseReg == destReg && addImm == 4 ) {
2637+ // Emit addiu+sw.
2638+ TOut.emitRRI (Inst.getOpcode (), destReg, srcReg, addImm, IDLoc,
2639+ STI);
2640+ TOut.emitRRI (CurInst.getOpcode (), FirstReg, BaseReg,
2641+ OffsetValue - addImm, IDLoc, STI);
2642+ // Back to initial location before return.
2643+ if (doLex == true )
2644+ getLexer ().UnLex (ID);
2645+ return MER_Success;
2646+ } else {
2647+ // Back to initial location before return.
2648+ if (doLex == true )
2649+ getLexer ().UnLex (ID);
2650+ // If not match, we need to emit the last reserved instruction
2651+ // `sw`.
2652+ TOut.emitRRI (CurInst.getOpcode (), FirstReg, BaseReg, OffsetValue,
2653+ IDLoc, STI);
2654+ return MER_NotAMacro;
2655+ }
2656+ } else {
2657+ // Back to initial location before return.
2658+ if (doLex == true )
2659+ getLexer ().UnLex (ID);
2660+ // If not match, we need to emit the last reserved instruction `sw`.
2661+ TOut.emitRRI (CurInst.getOpcode (), FirstReg, BaseReg, OffsetValue,
2662+ IDLoc, STI);
2663+ return MER_NotAMacro;
2664+ }
2665+ } else
2666+ return MER_NotAMacro;
2667+ }
25772668 return expandAliasImmediate (Inst, IDLoc, Out, STI) ? MER_Fail
25782669 : MER_Success;
25792670 }
@@ -2646,6 +2737,8 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
26462737 case Mips::SaaAddr:
26472738 case Mips::SaadAddr:
26482739 return expandSaaAddr (Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2740+ case Mips::SW:
2741+ return expandSW (Inst, IDLoc, Out, STI);
26492742 }
26502743}
26512744
@@ -5280,6 +5373,33 @@ bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
52805373 return false ;
52815374}
52825375
5376+ // Check if match sw+addiu.
5377+ MipsAsmParser::MacroExpanderResultTy
5378+ MipsAsmParser::expandSW (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
5379+ const MCSubtargetInfo *STI) {
5380+ AsmToken ID = getTok ();
5381+ bool doLex = false ;
5382+
5383+ // If this is a line comment we can drop it safely.
5384+ while (getLexer ().is (AsmToken::EndOfStatement)) {
5385+ getLexer ().Lex ();
5386+ doLex = true ;
5387+ }
5388+ // If match sw+addiu, then save current Inst,
5389+ // and back to initial location before return.
5390+ if (getTok ().getString () == " addiu" ) {
5391+ if (doLex == true )
5392+ getLexer ().UnLex (ID);
5393+ CurInst = Inst;
5394+ saveCurInst = true ;
5395+ return MER_Success;
5396+ } else {
5397+ if (doLex == true )
5398+ getLexer ().UnLex (ID);
5399+ return MER_NotAMacro;
5400+ }
5401+ }
5402+
52835403// Expand 'ld $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
52845404// lw $<reg+1>>, offset+4($reg2)'
52855405// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, offset($reg2);
0 commit comments