[IR] Reject inlining strictfp alwaysinline callee into non-strictfp caller (#210701)

Commit af0c933eda added a verifier check requiring every strictfp call
site to reside in a strictfp function.
It caused verify error `call site marked strictfp without caller
function marked strictfp` since AlwaysInliner force-inlines strictfp
callees into non-strictfp callers, bypassing checkStrictFP.

47b3b76825 explictly not implemented inlining strictfp function into
non-strictfp function. But the restriction was lost in 8eb6757564.
8eb6757564 was only NFC for the normal inliner pass. It regressed
AlwaysInliner path which bypasses checkStrictFP.

This PR restores the restriction.

---------

Co-authored-by: Jinsong Ji <jinsong.ji@intel.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Nikita Popov <github@npopov.com>
This commit is contained in:
Wenju He 2026-07-23 01:59:46 -07:00 committed by GitHub
parent 4138dc431a
commit a2b42b10a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 42 additions and 0 deletions

View file

@ -1393,6 +1393,11 @@ LLVM_ABI AttributeMask getUBImplyingAttributes();
LLVM_ABI bool areInlineCompatible(const Function &Caller,
const Function &Callee);
/// \returns Return false if callee is strictfp and caller is not. Return true
/// otherwise.
LLVM_ABI bool isStrictFPInlineCompatible(const Function &Caller,
const Function &Callee);
/// Checks if there are any incompatible function attributes between
/// \p A and \p B.
///

View file

@ -3210,6 +3210,9 @@ std::optional<InlineResult> llvm::getAttributeBasedInliningDecision(
if (Call.getAttributes().hasFnAttr(Attribute::NoInline))
return InlineResult::failure("noinline call site attribute");
if (!AttributeFuncs::isStrictFPInlineCompatible(*Caller, *Callee))
return InlineResult::failure("incompatible strictfp attributes");
auto IsViable = isInlineViable(*Callee);
if (IsViable.isSuccess())
return InlineResult::success();

View file

@ -2785,6 +2785,11 @@ bool AttributeFuncs::areInlineCompatible(const Function &Caller,
return hasCompatibleFnAttrs(Caller, Callee);
}
bool AttributeFuncs::isStrictFPInlineCompatible(const Function &Caller,
const Function &Callee) {
return checkStrictFP(Caller, Callee);
}
bool AttributeFuncs::areOutlineCompatible(const Function &A,
const Function &B) {
return hasCompatibleFnAttrs(A, B);

View file

@ -0,0 +1,29 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -passes=always-inline %s -S | FileCheck %s
; Check strictfp alwaysinline callee isn't inlined into non-strictfp caller.
declare void @foo()
define void @callee() alwaysinline strictfp {
; CHECK-LABEL: define void @callee(
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: call void @foo() #[[ATTR1:[0-9]+]]
; CHECK-NEXT: ret void
;
entry:
call void @foo() strictfp
ret void
}
define void @caller() {
; CHECK-LABEL: define void @caller() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: call void @callee()
; CHECK-NEXT: ret void
;
entry:
call void @callee()
ret void
}