When inline assembly requests more registers than available, the MachineInstr::emitError function in the RegAllocFast pass emits an error but doesn't stop the pass. Then the compiler crashes at an assertion error. This commit, mimicking the RegAllocGreedy pass, assigns a random physical register, and therefore avoids the crash. This error has been found for both rust and clang, while it doesn't occur in gcc.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/lib/CodeGen/RegAllocFast.cpp | ||
---|---|---|
838 | MachineInstr::emitError falls back to calling report_fatal_error if it cannot find a MCContext. Making an additional call to report_fatal_error here doesn't feel right. Why isn't MI.emitError able to stop the compiler before it crashes? |
llvm/lib/CodeGen/RegAllocFast.cpp | ||
---|---|---|
838 |
I meant LLVMContext, not MCContext. |
llvm/lib/CodeGen/RegAllocFast.cpp | ||
---|---|---|
838 | emitError is designed to return and does not stop the pass. In fact, given the same test case, RegAllocGreedy also reports the error but ends up generating bogus assembly, without crashing. I have updated the patch to mimic that behaviour, by copying some existing logic from useVirtReg. |
llvm/lib/CodeGen/RegAllocFast.cpp | ||
---|---|---|
941 | Why doesn't this return the result of setPhysReg? You should also add a comment to explain that since there was an error finding a suitable register for LRI, we just pick a register at random and bail out of the function immediately. |
llvm/test/CodeGen/X86/inline-asm-assertion.ll | ||
---|---|---|
3 | Suggestions:
|
llvm/test/CodeGen/X86/inline-asm-assertion.ll | ||
---|---|---|
3 | That's a good point. However, adding MachineVerifier reports a fatal error for llc -O2: "Bad machine code: Using an undefined physical register". |
llvm/test/CodeGen/X86/inline-asm-assertion.ll | ||
---|---|---|
3 | Which is another bug which needs to be fixed |
llvm/test/CodeGen/X86/inline-asm-assertion.ll | ||
---|---|---|
2 | Don't need the REQUIRES, it's implied by the x86 directory |
llvm/test/CodeGen/X86/inline-asm-assertion.ll | ||
---|---|---|
3 | If it's failing the verifier after this, you should check the verification message. You'll need to handle that to not break EXPENSIVE_CHECKS testing. You can fix the additional verifier error separately though |
llvm/test/CodeGen/X86/inline-asm-assertion.ll | ||
---|---|---|
3 | I don't know how to fix the verifier error at this point, but I agree that it should be handled as a separate issue. |
llvm/lib/CodeGen/RegAllocFast.cpp | ||
---|---|---|
941 | Should also guard against AllocationOrder being empty which can happen if all the registers become reserved, I guess you just have to use noreg at that point |
llvm/lib/CodeGen/RegAllocFast.cpp | ||
---|---|---|
941 | @arsenm This pass uses emitError to indicate that the IR is no longer valid, but is still required to continue and complete register allocation. If we enter this code path, we don't expect to generate correct code anyway, so I think it should be okay to skip the check, both here and in useVirtReg. |
llvm/lib/CodeGen/RegAllocFast.cpp | ||
---|---|---|
941 | If AllocationOrder is empty the compiler will just immediately crash which is not helpful |
llvm/lib/CodeGen/RegAllocFast.cpp | ||
---|---|---|
941 | I see, I had misread your comment. Thanks. |
MachineInstr::emitError falls back to calling report_fatal_error if it cannot find a MCContext. Making an additional call to report_fatal_error here doesn't feel right. Why isn't MI.emitError able to stop the compiler before it crashes?