| Issue |
185277
|
| Summary |
[ForceFunctionAttrs] Forcing optnone can produce invalid IR on optsize functions
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
cardigan1008
|
Here is a crash case when reviewing https://github.com/llvm/llvm-project/pull/180026:
```llvm
define void @hoo() #0 {
ret void
}
attributes #0 = { optsize }
```
Compiler Explorer: https://godbolt.org/z/Worb4cGc4
Crash:
```sh
Attribute 'optnone' requires 'noinline'!
ptr @hoo
LLVM ERROR: Broken module found, compilation aborted!
```
Backtrace:
```sh
Stack dump:
0. Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=forceattrs -force-attribute=optnone <source>
1. Running pass "verify" on module "<source>"
#0 0x0000000005c079b8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5c079b8)
#1 0x0000000005c047e4 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
#2 0x00007a855f242520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#3 0x00007a855f2969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
#4 0x00007a855f242476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
#5 0x00007a855f2287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
#6 0x00000000008324c1 llvm::json::operator==(llvm::json::Value const&, llvm::json::Value const&) (.cold) JSON.cpp:0:0
#7 0x0000000005b36d31 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5b36d31)
#8 0x00000000059b3018 (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x59b3018)
#9 0x000000000096ec4e llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x96ec4e)
#10 0x000000000596f831 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x596f831)
#11 0x0000000000978e3a llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x978e3a)
#12 0x000000000096ced5 optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x96ced5)
#13 0x00007a855f229d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#14 0x00007a855f229e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#15 0x0000000000963bb5 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x963bb5)
Program terminated with signal: SIGSEGV
```
> Note: This is a review assisted with a self-built agent. The reproducer was validated manually. Please let me know if anything is wrong.
**Bug Triggering Analysis:**
The provided test case defines a function `@hoo` with the `optsize` attribute. When `opt` is run with `-passes=forceattrs -force-attribute=optnone`, the `ForceFunctionAttrs` pass adds the `optnone` attribute to the function. However, the Verifier requires that `optnone` must be accompanied by `noinline`, and it is incompatible with `optsize`. Since the pass does not check for these incompatibilities (it only checks for `alwaysinline` vs `noinline`), it blindly adds `optnone`, resulting in a function with both `optsize` and `optnone` (and missing `noinline`). This causes the Verifier to fail and `opt` to crash.
**Fix Weakness Analysis:**
The fix introduced `hasConflictingFnAttr` to prevent adding `alwaysinline` to a function with `noinline` and vice versa. However, it failed to generalize this check to other mutually exclusive attributes defined in LLVM, such as `optnone` vs `optsize`/`minsize`/`optdebug`, or `writable` vs `readnone`. By only addressing the specific case of `alwaysinline` and `noinline`, the fix left the pass vulnerable to Verifier crashes when other conflicting attributes are forced.
**Reference (https://llvm.org/docs/LangRef.html):**
> optnone
>
> This function attribute indicates that most optimization passes will skip this function, with the exception of interprocedural optimization passes. Code generation defaults to the “fast” instruction selector. This attribute cannot be used together with the alwaysinline attribute; this attribute is also incompatible with the minsize, optsize, and optdebug attributes.
cc @justinfargnoli
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs