This is an archive of the discontinued LLVM Phabricator instance.

[WinEHPrepare] Propagate funclet tokens when inlining into EH funclets
AbandonedPublic

Authored by sgraenitz on Jun 16 2022, 6:38 AM.

Details

Summary

WinEH requires funclet tokens for (nounwind) ObjC++ ARC intrinsics, because they are subject to pre-ISel lowering. That's because they appear as regular function calls for subsequent passes (like WinEHPrepare). Without funclet token they would be consider them implausible instrucitons and marked as unreachable. Affected EH funclets would get truncated silently, which causes unpredictable crashes at runtime.

Thus, when we target WinEH and generate calls to pre-ISel intrinsics from EH funclets, we emit funclet tokens explicitly. My previous patch D124762 implements that.

Now, the inliner has to propagate funclet tokens to such intrinsics, if they get inlined into EH funclets. That's what this patch implements.

Diff Detail

Event Timeline

sgraenitz created this revision.Jun 16 2022, 6:38 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 16 2022, 6:38 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
sgraenitz requested review of this revision.Jun 16 2022, 6:38 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 16 2022, 6:38 AM
sgraenitz updated this revision to Diff 437547.Jun 16 2022, 8:00 AM

Limit explicit propagation to actual pre-ISel intrinsics

This is the best solution I found so far. The funclet bundle operand (aka. token) of the inlinee function will be propagated to the set of intrinsics that is (as of today) subject to pre-ISel lowering. This only applies when targeting WinEH and only for functions inlined into EH funclets.

However, there is no check that makes sure the actual set of intrinsics is in sync with the condition I am using here. See my inline comment for a proposal.

llvm/lib/Transforms/Utils/InlineFunction.cpp
2313–2324

We could simplify the condition here by adding a new helper function in ObjCARCInstKind.h/.cpp:

bool llvm::objcarc::IsPreISelIntrinsic(Function *F) {
  ARCInstKind K = GetFunctionClass(F);
  return !IsUser(K) && K != ARCInstKind::None;
}

It could be used in D124762 CGCall.cpp as well as in PreISelIntrinsicLowering.cpp to assert the set of pre-ISel intrinsics is in sync with what we do here. This would also connect the three pieces of code explicitly, so it's easier for others to see their relation.

rnk added a comment.Jun 16 2022, 1:25 PM

Thanks, sorry for the delay.

llvm/lib/Transforms/Utils/InlineFunction.cpp
2313–2324

I think the generic predicate we are looking should be called something like IntrinsicInst::mayLowerToFunctionCall, and it would be true for these ObjC ARC intrinsics, statepoint, and anything else like that. Basically, we should apply funclet operand bundles to intrinsics that lower to function calls.

2317

The personality check should not be necessary. We check CallSiteEHPad above, and that's enough to imply that the current function uses funclet bundle operands. (Wasm, SEH, C++ EH)

Thanks for your feedback.

I think the generic predicate we are looking should be called something like IntrinsicInst::mayLowerToFunctionCall, and it would be true for these ObjC ARC intrinsics, statepoint, and anything else like that. Basically, we should apply funclet operand bundles to intrinsics that lower to function calls.

I was not aware it would be such a broad issue! So far, I was trying to narrow the condition to my ObjC ARC use-case as close as possible. D128190 aims to apply bundle operands correctly for intrinsics that lower to function calls and covers both cases, emit and inline, at once. If this is ok, I can close the two reviews here.

llvm/lib/Transforms/Utils/InlineFunction.cpp
2317

Alright, I assume then it's not necessary in clang/lib/CodeGen/CGCall.cpp either.

Close in favor of the D128190, which covers both cases at once: emit (was D124762) and inline (was D127962)