Skip to content

Commit 8aae191

Browse files
yonghong-songYonghong Song
andauthored
[BPF] Remove 'may_goto 0' instructions (llvm#123482)
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. --------- Co-authored-by: Yonghong Song <[email protected]>
1 parent e7f0224 commit 8aae191

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

llvm/lib/Target/BPF/BPFMIPeephole.cpp

Lines changed: 56 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,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

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

llvm/test/CodeGen/BPF/may_goto_1.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

llvm/test/CodeGen/BPF/may_goto_2.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", "!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", "!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", "!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", "!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)