Skip to content

Commit 93019a1

Browse files
author
Yonghong Song
committed
[BPF] Remove 'may_goto 0' instructions
Emil Tsalapatis from Meta reported such a case where 'may_goto 0' insn is generated by clang compiler. But 'may_goto 0' insn is actually a no-op so it makes sense to remove that in llvm. The patch is also able to handle the following code pattern ... may_goto 2 may_goto 1 may_goto 0 ... where three may_goto insns can all be removed.
1 parent 2f39d13 commit 93019a1

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

llvm/lib/Target/BPF/BPFMIPeephole.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
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

326328
public:
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,65 @@ bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
682685
return Changed;
683686
}
684687

688+
bool BPFMIPreEmitPeephole::removeMayGotoZero() {
689+
bool Changed = false;
690+
MachineBasicBlock *Prev_MBB, *Curr_MBB = nullptr;
691+
MachineBasicBlock *ToErase = nullptr;
692+
693+
for (MachineBasicBlock &MBB : reverse(*MF)) {
694+
if (ToErase) {
695+
ToErase->eraseFromParent();
696+
ToErase = nullptr;
697+
}
698+
699+
Prev_MBB = Curr_MBB;
700+
Curr_MBB = &MBB;
701+
if (Prev_MBB == nullptr)
702+
continue;
703+
704+
MachineInstr &MI = MBB.back();
705+
if (!MI.isInlineAsm())
706+
continue;
707+
708+
const char *AsmStr = MI.getOperand(0).getSymbolName();
709+
SmallVector<StringRef, 4> AsmPieces;
710+
SplitString(AsmStr, AsmPieces, ";\n");
711+
712+
// Do not support multiple insns in one inline asm.
713+
if (AsmPieces.size() != 1)
714+
continue;
715+
716+
// The asm insn must be a may_goto insn.
717+
SmallVector<StringRef, 4> AsmOpPieces;
718+
SplitString(AsmPieces[0], AsmOpPieces, " ");
719+
if (AsmOpPieces[0] != "may_goto")
720+
continue;
721+
722+
// Get the may_goto branch target.
723+
MachineOperand &MO = MI.getOperand(InlineAsm::MIOp_FirstOperand + 1);
724+
if (MO.getMBB() != Prev_MBB)
725+
continue;
726+
727+
Changed = true;
728+
if (MBB.begin() == MI) {
729+
// Single 'may_goto' insn in the same basic block.
730+
ToErase = Curr_MBB;
731+
Curr_MBB->removeSuccessor(Prev_MBB);
732+
for (MachineBasicBlock *Pred : Curr_MBB->predecessors())
733+
Pred->replaceSuccessor(Curr_MBB, Prev_MBB);
734+
Curr_MBB = Prev_MBB;
735+
} else {
736+
// Remove 'may_goto' insn.
737+
MI.eraseFromParent();
738+
}
739+
}
740+
741+
if (ToErase)
742+
ToErase->eraseFromParent();
743+
744+
return Changed;
745+
}
746+
685747
} // end default namespace
686748

687749
INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",

llvm/test/CodeGen/BPF/may_goto.ll

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
; RUN: llc -mtriple=bpfel -mcpu=v3 -filetype=obj -o - %s | llvm-objdump --no-show-raw-insn -d - | FileCheck %s
2+
3+
@j = dso_local local_unnamed_addr global i32 0, align 4
4+
5+
define dso_local noundef i32 @foo() local_unnamed_addr {
6+
entry:
7+
callbr void asm sideeffect "may_goto ${0:l}", "!i"()
8+
to label %for.body [label %for.cond.cleanup]
9+
10+
for.cond.cleanup: ; preds = %for.body.2, %for.body.2, %for.body.1, %for.body, %entry
11+
ret i32 0
12+
13+
for.body: ; preds = %entry
14+
callbr void asm sideeffect "may_goto ${0:l}", "!i"()
15+
to label %for.body.1 [label %for.cond.cleanup]
16+
17+
for.body.1: ; preds = %for.body
18+
callbr void asm sideeffect "may_goto ${0:l}", "!i"()
19+
to label %for.body.2 [label %for.cond.cleanup]
20+
21+
for.body.2: ; preds = %for.body.1
22+
callbr void asm sideeffect "may_goto ${0:l}", "!i"()
23+
to label %for.cond.cleanup [label %for.cond.cleanup]
24+
}
25+
26+
; CHECK: 0: w0 = 0x0
27+
; CHECK-NEXT: 1: exit

0 commit comments

Comments
 (0)