-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BPF] Remove 'may_goto 0' instructions #123482
Conversation
wouldn't it be cleaner to do after inline asm was processed into proper insns ? Instead of string match? |
I agree with Alexei, this should be done at machine instruction level. |
On the other hand, after assembly instructions are compiled, there is no way to distinguish |
Also, I'm not sure there is a good hook to attach to. When using gdb to break and see where assembler is called to parse the inline assembly, it looks like parsed instruction is written directly to the output stream:
The parsing is done late in the pipeline and it's result is written directly either to object stream or to text output. So the only place seem to be |
matchAndEmitInstruction() handles one instruction only. So this is not a good place to do 'may_goto 0' elimination work. |
I checked other targets (X86, Arm) etc. They also parse and processes asm strings. For example, in ARM/ARMISelLowering.cpp,
So use one of backend passes might be the better choice. |
I get a compiler crash with the following test case: $ cat test.c
void bar() {
asm volatile goto ("may_goto %l[lbl];"::::lbl);
asm volatile("may_goto +0;");
lbl:
return;
}
$ clang -O2 --target=bpf -S test.c -o - 2>&1 | head -n20
clang: /home/eddy/work/llvm-project/llvm/include/llvm/CodeGen/MachineInstr.h:590: MachineOperand &llvm::MachineInstr::getOperand(unsigned int): Assertion `i < getNumOperands() && "getOperand() out of range!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0. Program arguments: clang -O2 --target=bpf -S test.c -o -
1. <eof> parser at end of file
2. Code generation
3. Running pass 'Function Pass Manager' on module 'test.c'.
4. Running pass 'BPF PreEmit Peephole Optimization' on function '@bar'
#0 0x00007fd5e35fe388 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/eddy/work/llvm-project/llvm/lib/Support/Unix/Signals.inc:794:13
#1 0x00007fd5e35fc260 llvm::sys::RunSignalHandlers() /home/eddy/work/llvm-project/llvm/lib/Support/Signals.cpp:106:18
#2 0x00007fd5e353e7d6 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) /home/eddy/work/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:73:5
#3 0x00007fd5e353e7d6 CrashRecoverySignalHandler(int) /home/eddy/work/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp:390:51
#4 0x00007fd5e2e26090 __restore_rt (/lib64/libc.so.6+0x1a090)
#5 0x00007fd5e2e7f0f4 __pthread_kill_implementation /usr/src/debug/glibc-2.40-17.fc41.x86_64/nptl/pthread_kill.c:44:76
#6 0x00007fd5e2e25fde gsignal /usr/src/debug/glibc-2.40-17.fc41.x86_64/signal/../sysdeps/posix/raise.c:27:6
#7 0x00007fd5e2e0d942 abort /usr/src/debug/glibc-2.40-17.fc41.x86_64/stdlib/abort.c:81:7
#8 0x00007fd5e2e0d85e _nl_load_domain.cold /usr/src/debug/glibc-2.40-17.fc41.x86_64/intl/loadmsgcat.c:1177:9
#9 0x00007fd5e2e1e107 (/lib64/libc.so.6+0x12107)
#10 0x00007fd5e9e2355a (anonymous namespace)::BPFMIPreEmitPeephole::runOnMachineFunction(llvm::MachineFunction&) /home/eddy/work/llvm-project/llvm/lib/Target/BPF/BPFMIPeephole.cpp:0:0
#11 0x00007fd5e75b31d7 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) /home/eddy/work/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:0:13 |
And the following example appears to be miscompiled: $ cat test.c
void bar() {
asm volatile goto ("may_goto %l[lbl];"::::lbl);
asm volatile goto ("may_goto %l[lbl];"::::lbl);
asm volatile goto ("may_goto %l[lbl];"::::lbl);
asm volatile goto ("r0 = 42;");
lbl:
return;
}
$ clang -O2 --target=bpf -S test.c -o - 2>&1 | head -n20
.file "test.c"
.text
.globl bar # -- Begin function bar
.p2align 3
.type bar,@function
bar: # @bar
# %bb.0: # %entry
#APP
may_goto LBB0_4
#NO_APP
# %bb.1: # %asm.fallthrough
#APP
may_goto LBB0_4
#NO_APP
# %bb.2: # %asm.fallthrough1
#APP
may_goto LBB0_4 (Note the disappearance of the |
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.
@eddyz87 Thanks for the error cases and suggestion to avoid ToErase variable. Will investigate all these issues. |
Fix an issue where INLINEASM_BR asm opcode should be checked instead of generic INLINEASM since later on retrieving target basic block needs INLINEASM_BR.
cb82108
to
af8076c
Compare
Check AsmOpPieces[1] to ensure may_goto asm format correct.
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
where three may_goto insns can all be removed.