-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[CodeGen] Avoid generating trap instructions after exception restore intrinsics #109560
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3125,6 +3125,14 @@ bool IRTranslator::translateUnreachable(const User &U, MachineIRBuilder &MIRBuil | |
// Do not emit an additional trap instruction. | ||
if (Call->isNonContinuableTrap()) | ||
return true; | ||
// Do not emit trap instructions after EH_RETURN intrinsics. | ||
// This can cause problems later down the line when other machine passes | ||
// attempt to use the last instruction in a BB to determine terminator behavior. | ||
if (const auto *II = dyn_cast<IntrinsicInst>(Call)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should these be handled in isNonContinuableTrap? |
||
const auto IID = II->getIntrinsicID(); | ||
if (IID == Intrinsic::eh_return_i32 || IID == Intrinsic::eh_return_i64) | ||
return true; | ||
} | ||
Comment on lines
+3131
to
+3135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These intrinsics are missing from the langref and I don't know what's expected of them. Should these really be terminators in the first place? Can the insert point just be adjusted?
This comment doesn't exactly make sense There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes and no, respectively. They're old exception-handling intrinsics that lower down to The problem becomes that these are not actually return instructions, they're intrinsics. When they're lowered, we visit an We therefore also get blocks where I'm not quite sure if this is a miscompile, but returning false in Looking at this again, I'm not sure these intrinsics are even supported in GlobalISel on any architecture, but it would be good to keep this consistent between instruction selection backends. |
||
} | ||
|
||
MIRBuilder.buildTrap(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
; RUN: llc < %s -mtriple=i386-unknown-unknown -trap-unreachable -no-trap-after-noreturn=false -verify-machineinstrs | FileCheck %s | ||
|
||
;; Ensure we restore caller-saved registers before EH_RETURN, even with trap-unreachable enabled. | ||
;; For now, we deliberately avoid generating traps altogether. | ||
|
||
; CHECK-LABEL: test32 | ||
; CHECK: pushl | ||
; CHECK: popl | ||
; CHECK: eh_return | ||
; CHECK-NOT: ud2 | ||
define void @test32(i32 %offset, ptr %handler) { | ||
call void @llvm.eh.unwind.init() | ||
call void @llvm.eh.return.i32(i32 %offset, ptr %handler) | ||
unreachable | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -trap-unreachable -no-trap-after-noreturn=false -verify-machineinstrs | FileCheck %s | ||
|
||
;; Ensure we restore caller-saved registers before EH_RETURN, even with trap-unreachable enabled. | ||
;; For now, we deliberately avoid generating traps altogether. | ||
|
||
; CHECK-LABEL: test64 | ||
; CHECK: pushq | ||
; CHECK: popq | ||
; CHECK: eh_return | ||
; CHECK-NOT: ud2 | ||
define void @test64(i64 %offset, ptr %handler) { | ||
call void @llvm.eh.unwind.init() | ||
call void @llvm.eh.return.i64(i64 %offset, ptr %handler) | ||
unreachable | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you still need to special case this in the code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused as to what you mean. The Clang intrinsic,
__builtin_eh_return
is marked asNoReturn
, everything essentially treats it asnoreturn
due tounreachable
being emitted immediately after them, and the verifier would complain if you emitted code after them (which is exactly what this PR is trying to fix).Marking these as
noreturn
accurately represents their behavior and makes it so that the patch can be a bit smaller since I don't need to reorganize logic in the instruction selectors.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IR intrinsic noreturn attribute is separate from the machine verifier issue you are seeing. You can do this as a pre-commit (which is independently observable in IR optimizations).
You're also not making use of this attribute below?