2424#include " BPFInstrInfo.h"
2525#include " BPFTargetMachine.h"
2626#include " llvm/ADT/Statistic.h"
27+ #include " llvm/ADT/StringExtras.h"
2728#include " llvm/CodeGen/LivePhysRegs.h"
2829#include " llvm/CodeGen/MachineFrameInfo.h"
2930#include " llvm/CodeGen/MachineFunctionPass.h"
@@ -322,6 +323,7 @@ struct BPFMIPreEmitPeephole : public MachineFunctionPass {
322323 bool eliminateRedundantMov ();
323324 bool adjustBranch ();
324325 bool insertMissingCallerSavedSpills ();
326+ bool removeMayGotoZero ();
325327
326328public:
327329
@@ -337,6 +339,7 @@ struct BPFMIPreEmitPeephole : public MachineFunctionPass {
337339 if (SupportGotol)
338340 Changed = adjustBranch () || Changed;
339341 Changed |= insertMissingCallerSavedSpills ();
342+ Changed |= removeMayGotoZero ();
340343 return Changed;
341344 }
342345};
@@ -682,6 +685,59 @@ bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
682685 return Changed;
683686}
684687
688+ bool BPFMIPreEmitPeephole::removeMayGotoZero () {
689+ bool Changed = false ;
690+ MachineBasicBlock *Prev_MBB, *Curr_MBB = nullptr ;
691+
692+ for (MachineBasicBlock &MBB : make_early_inc_range (reverse (*MF))) {
693+ Prev_MBB = Curr_MBB;
694+ Curr_MBB = &MBB;
695+ if (Prev_MBB == nullptr || Curr_MBB->empty ())
696+ continue ;
697+
698+ MachineInstr &MI = Curr_MBB->back ();
699+ if (MI.getOpcode () != TargetOpcode::INLINEASM_BR)
700+ continue ;
701+
702+ const char *AsmStr = MI.getOperand (0 ).getSymbolName ();
703+ SmallVector<StringRef, 4 > AsmPieces;
704+ SplitString (AsmStr, AsmPieces, " ;\n " );
705+
706+ // Do not support multiple insns in one inline asm.
707+ if (AsmPieces.size () != 1 )
708+ continue ;
709+
710+ // The asm insn must be a may_goto insn.
711+ SmallVector<StringRef, 4 > AsmOpPieces;
712+ SplitString (AsmPieces[0 ], AsmOpPieces, " " );
713+ if (AsmOpPieces.size () != 2 || AsmOpPieces[0 ] != " may_goto" )
714+ continue ;
715+ // Enforce the format of 'may_goto <label>'.
716+ if (AsmOpPieces[1 ] != " ${0:l}" && AsmOpPieces[1 ] != " $0" )
717+ continue ;
718+
719+ // Get the may_goto branch target.
720+ MachineOperand &MO = MI.getOperand (InlineAsm::MIOp_FirstOperand + 1 );
721+ if (!MO.isMBB () || MO.getMBB () != Prev_MBB)
722+ continue ;
723+
724+ Changed = true ;
725+ if (Curr_MBB->begin () == MI) {
726+ // Single 'may_goto' insn in the same basic block.
727+ Curr_MBB->removeSuccessor (Prev_MBB);
728+ for (MachineBasicBlock *Pred : Curr_MBB->predecessors ())
729+ Pred->replaceSuccessor (Curr_MBB, Prev_MBB);
730+ Curr_MBB->eraseFromParent ();
731+ Curr_MBB = Prev_MBB;
732+ } else {
733+ // Remove 'may_goto' insn.
734+ MI.eraseFromParent ();
735+ }
736+ }
737+
738+ return Changed;
739+ }
740+
685741} // end default namespace
686742
687743INITIALIZE_PASS (BPFMIPreEmitPeephole, " bpf-mi-pemit-peephole" ,
0 commit comments