[llvm] Inliner: Handle nofpclass return attributes (PR #179776)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 4 12:48:48 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Matt Arsenault (arsenm)
<details>
<summary>Changes</summary>
Follow along with how range is handled.
---
Full diff: https://github.com/llvm/llvm-project/pull/179776.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Utils/InlineFunction.cpp (+10)
- (added) llvm/test/Transforms/Inline/ret_attr_nofpclass.ll (+59)
``````````diff
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index aa902f687d8aa..3230b306f17d1 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1543,6 +1543,8 @@ static AttrBuilder IdentifyValidPoisonGeneratingAttributes(CallBase &CB) {
Valid.addAlignmentAttr(CB.getRetAlign());
if (std::optional<ConstantRange> Range = CB.getRange())
Valid.addRangeAttr(*Range);
+ if (CB.hasRetAttr(Attribute::NoFPClass))
+ Valid.addNoFPClassAttr(CB.getRetNoFPClass());
return Valid;
}
@@ -1648,6 +1650,14 @@ static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap,
CBRange.getRange().intersectWith(NewRange.getRange()));
}
}
+
+ Attribute CBNoFPClass = ValidPG.getAttribute(Attribute::NoFPClass);
+ if (CBNoFPClass.isValid() && AL.hasRetAttr(Attribute::NoFPClass)) {
+ ValidPG.addNoFPClassAttr(
+ CBNoFPClass.getNoFPClass() |
+ AL.getRetAttr(Attribute::NoFPClass).getNoFPClass());
+ }
+
// Three checks.
// If the callsite has `noundef`, then a poison due to violating the
// return attribute will create UB anyways so we can always propagate.
diff --git a/llvm/test/Transforms/Inline/ret_attr_nofpclass.ll b/llvm/test/Transforms/Inline/ret_attr_nofpclass.ll
new file mode 100644
index 0000000000000..08364f98f6a71
--- /dev/null
+++ b/llvm/test/Transforms/Inline/ret_attr_nofpclass.ll
@@ -0,0 +1,59 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=inline %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' %s | FileCheck %s
+; RUN: opt -S -passes='module-inline' %s | FileCheck %s
+
+declare float @val_f32()
+declare float @use.val(float) willreturn nounwind
+
+define float @callee() {
+; CHECK-LABEL: define float @callee() {
+; CHECK-NEXT: [[R:%.*]] = call float @val_f32()
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call float @val_f32()
+ ret float %r
+}
+
+define float @caller_okay_use_after_poison_anyways() {
+; CHECK-LABEL: define float @caller_okay_use_after_poison_anyways() {
+; CHECK-NEXT: [[R_I:%.*]] = call nofpclass(nan) float @val_f32()
+; CHECK-NEXT: call void @use.val(float [[R_I]])
+; CHECK-NEXT: ret float [[R_I]]
+;
+ %r = call nofpclass(nan) float @callee()
+ call void @use.val(float %r)
+ ret float %r
+}
+
+define float @callee_nofpclass_inf_nan() {
+; CHECK-LABEL: define float @callee_nofpclass_inf_nan() {
+; CHECK-NEXT: [[R:%.*]] = call nofpclass(nan inf) float @val_f32()
+; CHECK-NEXT: ret float [[R]]
+;
+ %r = call nofpclass(nan inf) float @val_f32()
+ ret float %r
+}
+
+define float @caller_okay_intersect_nofpclass() {
+; CHECK-LABEL: define float @caller_okay_intersect_nofpclass() {
+; CHECK-NEXT: [[R_I:%.*]] = call nofpclass(nan) float @val_f32()
+; CHECK-NEXT: call void @use.val(float [[R_I]])
+; CHECK-NEXT: ret float [[R_I]]
+;
+ %r = call nofpclass(nan) float @callee_nofpclass_inf_nan()
+ call void @use.val(float %r)
+ ret float %r
+}
+
+define float @caller_not_intersecting_nofpclass() {
+; CHECK-LABEL: define float @caller_not_intersecting_nofpclass() {
+; CHECK-NEXT: [[R_I:%.*]] = call nofpclass(zero) float @val_f32()
+; CHECK-NEXT: call void @use.val(float [[R_I]])
+; CHECK-NEXT: ret float [[R_I]]
+;
+ %r = call nofpclass(zero) float @callee_nofpclass_inf_nan()
+ call void @use.val(float %r)
+ ret float %r
+}
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/179776
More information about the llvm-commits
mailing list