From 94026ce56df244ddad76fe5c28c41a3523f129b2 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Fri, 24 Feb 2023 10:57:39 -0400 Subject: [PATCH] Attributor: Start inferring nofpclass Some of this is boilerplate which doesn't do anything yet. --- llvm/include/llvm/Transforms/IPO/Attributor.h | 36 ++++++++ llvm/lib/Transforms/IPO/Attributor.cpp | 16 +++- llvm/lib/Transforms/IPO/AttributorAttributes.cpp | 100 +++++++++++++++++++++++ llvm/test/Transforms/Attributor/nofpclass.ll | 66 +++++++-------- 4 files changed, 183 insertions(+), 35 deletions(-) diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index 26859ff..e8159d2 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -2567,7 +2567,10 @@ template struct BitIntegerState : public IntegerStateBase { + using super = IntegerStateBase; using base_t = base_ty; + BitIntegerState() = default; + BitIntegerState(base_t Assumed) : super(Assumed) {} /// Return true if the bits set in \p BitsEncoding are "known bits". bool isKnown(base_t BitsEncoding) const { @@ -4840,6 +4843,39 @@ struct AANoUndef static const char ID; }; +struct AANoFPClass + : public IRAttribute< + Attribute::NoFPClass, + StateWrapper, + AbstractAttribute>> { + using Base = StateWrapper, + AbstractAttribute>; + + AANoFPClass(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {} + + /// Return true if we assume that the underlying value is nofpclass. + FPClassTest getAssumedNoFPClass() const { + return static_cast(getAssumed()); + } + + /// Create an abstract attribute view for the position \p IRP. + static AANoFPClass &createForPosition(const IRPosition &IRP, Attributor &A); + + /// See AbstractAttribute::getName() + const std::string getName() const override { return "AANoFPClass"; } + + /// See AbstractAttribute::getIdAddr() + const char *getIdAddr() const override { return &ID; } + + /// This function should return true if the type of the \p AA is AANoFPClass + static bool classof(const AbstractAttribute *AA) { + return (AA->getIdAddr() == &ID); + } + + /// Unique ID (due to the unique address) + static const char ID; +}; + struct AACallGraphNode; struct AACallEdges; diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 6cb74cd..46b2900 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -3240,6 +3240,8 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) { // Every function with pointer return type might be marked // dereferenceable. getOrCreateAAFor(RetPos); + } else if (AttributeFuncs::isNoFPClassCompatibleType(ReturnType)) { + getOrCreateAAFor(RetPos); } } @@ -3284,6 +3286,8 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) { // Every argument with pointer type might be privatizable (or promotable) getOrCreateAAFor(ArgPos); + } else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) { + getOrCreateAAFor(ArgPos); } } @@ -3312,11 +3316,13 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) { return true; if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) { - IRPosition CBRetPos = IRPosition::callsite_returned(CB); bool UsedAssumedInformation = false; getAssumedSimplified(CBRetPos, nullptr, UsedAssumedInformation, AA::Intraprocedural); + + if (AttributeFuncs::isNoFPClassCompatibleType(Callee->getReturnType())) + getOrCreateAAFor(CBInstPos); } for (int I = 0, E = CB.arg_size(); I < E; ++I) { @@ -3336,8 +3342,14 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) { // Every call site argument might be marked "noundef". getOrCreateAAFor(CBArgPos); - if (!CB.getArgOperand(I)->getType()->isPointerTy()) + Type *ArgTy = CB.getArgOperand(I)->getType(); + + if (!ArgTy->isPointerTy()) { + if (AttributeFuncs::isNoFPClassCompatibleType(ArgTy)) + getOrCreateAAFor(CBArgPos); + continue; + } // Call site argument attribute "non-null". getOrCreateAAFor(CBArgPos); diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index 100f43f..e2abf9b 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -177,6 +177,7 @@ PIPE_OPERATOR(AAUndefinedBehavior) PIPE_OPERATOR(AAPotentialConstantValues) PIPE_OPERATOR(AAPotentialValues) PIPE_OPERATOR(AANoUndef) +PIPE_OPERATOR(AANoFPClass) PIPE_OPERATOR(AACallEdges) PIPE_OPERATOR(AAInterFnReachability) PIPE_OPERATOR(AAPointerInfo) @@ -10205,6 +10206,103 @@ struct AANoUndefCallSiteReturned final void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) } }; +/// ------------------------ NoFPClass Attribute ------------------------------- + +struct AANoFPClassImpl : AANoFPClass { + AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {} + + void initialize(Attributor &A) override { + const IRPosition &IRP = getIRPosition(); + + Value &V = IRP.getAssociatedValue(); + if (isa(V)) { + indicateOptimisticFixpoint(); + return; + } + + SmallVector Attrs; + IRP.getAttrs({Attribute::NoFPClass}, Attrs, false, &A); + if (!Attrs.empty()) { + addKnownBits(Attrs[0].getNoFPClass()); + return; + } + + const DataLayout &DL = A.getDataLayout(); + if (getPositionKind() != IRPosition::IRP_RETURNED) { + KnownFPClass KnownFPClass = computeKnownFPClass(&V, DL); + addKnownBits(~KnownFPClass.KnownFPClasses); + } + } + + const std::string getAsStr() const override { + std::string Result = "nofpclass"; + raw_string_ostream OS(Result); + OS << getAssumedNoFPClass(); + return Result; + } + + void getDeducedAttributes(LLVMContext &Ctx, + SmallVectorImpl &Attrs) const override { + Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass())); + } +}; + +struct AANoFPClassFloating : public AANoFPClassImpl { + AANoFPClassFloating(const IRPosition &IRP, Attributor &A) + : AANoFPClassImpl(IRP, A) {} + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + return indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { + STATS_DECLTRACK_FNRET_ATTR(nofpclass) + } +}; + +struct AANoFPClassReturned final + : AAReturnedFromReturnedValues { + AANoFPClassReturned(const IRPosition &IRP, Attributor &A) + : AAReturnedFromReturnedValues(IRP, A) {} + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { + STATS_DECLTRACK_FNRET_ATTR(nofpclass) + } +}; + +struct AANoFPClassArgument final + : AAArgumentFromCallSiteArguments { + AANoFPClassArgument(const IRPosition &IRP, Attributor &A) + : AAArgumentFromCallSiteArguments(IRP, A) {} + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) } +}; + +struct AANoFPClassCallSiteArgument final : AANoFPClassFloating { + AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A) + : AANoFPClassFloating(IRP, A) {} + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { + STATS_DECLTRACK_CSARG_ATTR(nofpclass) + } +}; + +struct AANoFPClassCallSiteReturned final + : AACallSiteReturnedFromReturned { + AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A) + : AACallSiteReturnedFromReturned(IRP, A) {} + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { + STATS_DECLTRACK_CSRET_ATTR(nofpclass) + } +}; + struct AACallEdgesImpl : public AACallEdges { AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {} @@ -11629,6 +11727,7 @@ const char AAValueConstantRange::ID = 0; const char AAPotentialConstantValues::ID = 0; const char AAPotentialValues::ID = 0; const char AANoUndef::ID = 0; +const char AANoFPClass::ID = 0; const char AACallEdges::ID = 0; const char AAInterFnReachability::ID = 0; const char AAPointerInfo::ID = 0; @@ -11749,6 +11848,7 @@ CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueConstantRange) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialConstantValues) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialValues) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef) +CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFPClass) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo) CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify) diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll index a21f60a..fa44f3c 100644 --- a/llvm/test/Transforms/Attributor/nofpclass.ll +++ b/llvm/test/Transforms/Attributor/nofpclass.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --version 2 +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --version 2 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC @@ -14,7 +14,7 @@ declare void @extern.use.f16(half) declare i1 @llvm.is.fpclass.f32(float, i32 immarg) define float @returned_0() { -; CHECK-LABEL: define noundef float @returned_0() { +; CHECK-LABEL: define noundef nofpclass(nan inf nzero sub norm) float @returned_0() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -23,7 +23,7 @@ define float @returned_0() { } define float @returned_neg0() { -; CHECK-LABEL: define noundef float @returned_neg0() { +; CHECK-LABEL: define noundef nofpclass(nan inf pzero sub norm) float @returned_neg0() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float -0.000000e+00 ; @@ -32,7 +32,7 @@ define float @returned_neg0() { } define float @returned_undef() { -; CHECK-LABEL: define float @returned_undef() { +; CHECK-LABEL: define nofpclass(all) float @returned_undef() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float undef ; @@ -41,7 +41,7 @@ define float @returned_undef() { } define float @returned_poison() { -; CHECK-LABEL: define float @returned_poison() { +; CHECK-LABEL: define nofpclass(all) float @returned_poison() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float poison ; @@ -50,7 +50,7 @@ define float @returned_poison() { } define double @returned_snan() { -; CHECK-LABEL: define noundef double @returned_snan() { +; CHECK-LABEL: define noundef nofpclass(qnan inf zero sub norm) double @returned_snan() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret double 0x7FF0000000000001 ; @@ -59,7 +59,7 @@ define double @returned_snan() { } define double @returned_qnan() { -; CHECK-LABEL: define noundef double @returned_qnan() { +; CHECK-LABEL: define noundef nofpclass(snan inf zero sub norm) double @returned_qnan() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret double 0x7FF8000000000000 ; @@ -68,7 +68,7 @@ define double @returned_qnan() { } define <2 x double> @returned_zero_vector() { -; CHECK-LABEL: define noundef <2 x double> @returned_zero_vector() { +; CHECK-LABEL: define noundef nofpclass(nan inf nzero sub norm) <2 x double> @returned_zero_vector() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <2 x double> zeroinitializer ; @@ -77,7 +77,7 @@ define <2 x double> @returned_zero_vector() { } define <2 x double> @returned_negzero_vector() { -; CHECK-LABEL: define noundef <2 x double> @returned_negzero_vector() { +; CHECK-LABEL: define noundef nofpclass(nan inf pzero sub norm) <2 x double> @returned_negzero_vector() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <2 x double> ; @@ -96,8 +96,8 @@ define <2 x double> @returned_qnan_zero_vector() { ; Return a float trivially nofpclass(nan) (call return attribute) define float @return_nofpclass_nan_decl_return() { -; CHECK-LABEL: define float @return_nofpclass_nan_decl_return() { -; CHECK-NEXT: [[RET:%.*]] = call float @ret_nofpclass_nan() +; CHECK-LABEL: define nofpclass(nan) float @return_nofpclass_nan_decl_return() { +; CHECK-NEXT: [[RET:%.*]] = call nofpclass(nan) float @ret_nofpclass_nan() ; CHECK-NEXT: ret float [[RET]] ; %ret = call float @ret_nofpclass_nan() @@ -107,7 +107,7 @@ define float @return_nofpclass_nan_decl_return() { ; Return a float trivially nofpclass(nan) (argument attribute) define float @return_nofpclass_nan_arg(float returned nofpclass(nan) %p) { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @return_nofpclass_nan_arg +; CHECK-LABEL: define nofpclass(nan) float @return_nofpclass_nan_arg ; CHECK-SAME: (float returned nofpclass(nan) [[P:%.*]]) #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: ret float [[P]] ; @@ -115,7 +115,7 @@ define float @return_nofpclass_nan_arg(float returned nofpclass(nan) %p) { } define [2 x [3 x float]] @return_nofpclass_inf_ret_array() { -; CHECK-LABEL: define [2 x [3 x float]] @return_nofpclass_inf_ret_array() { +; CHECK-LABEL: define nofpclass(inf) [2 x [3 x float]] @return_nofpclass_inf_ret_array() { ; CHECK-NEXT: [[RET:%.*]] = call nofpclass(inf) [2 x [3 x float]] @ret_array() ; CHECK-NEXT: ret [2 x [3 x float]] [[RET]] ; @@ -125,7 +125,7 @@ define [2 x [3 x float]] @return_nofpclass_inf_ret_array() { define float @returned_nnan_fadd(float %arg0, float %arg1) { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CHECK-LABEL: define float @returned_nnan_fadd +; CHECK-LABEL: define nofpclass(nan) float @returned_nnan_fadd ; CHECK-SAME: (float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[FADD:%.*]] = fadd nnan float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[FADD]] @@ -135,7 +135,7 @@ define float @returned_nnan_fadd(float %arg0, float %arg1) { } define float @return_nofpclass_nan_callsite() { -; CHECK-LABEL: define float @return_nofpclass_nan_callsite() { +; CHECK-LABEL: define nofpclass(nan) float @return_nofpclass_nan_callsite() { ; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @extern() ; CHECK-NEXT: ret float [[CALL]] ; @@ -145,7 +145,7 @@ define float @return_nofpclass_nan_callsite() { ; Can union the return classes define nofpclass(inf) float @return_ninf_nofpclass_nan_callsite() { -; CHECK-LABEL: define nofpclass(inf) float @return_ninf_nofpclass_nan_callsite() { +; CHECK-LABEL: define nofpclass(nan inf) float @return_ninf_nofpclass_nan_callsite() { ; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @extern() ; CHECK-NEXT: ret float [[CALL]] ; @@ -177,7 +177,7 @@ define void @ninf_arg_used_by_nofpclass_nan_callsite(float nofpclass(inf) %arg) define void @ninf_arg_used_by_callsite_array([2 x [3 x float]] nofpclass(inf) %arg) { ; CHECK-LABEL: define void @ninf_arg_used_by_callsite_array ; CHECK-SAME: ([2 x [3 x float]] nofpclass(inf) [[ARG:%.*]]) { -; CHECK-NEXT: call void @extern.use.array([2 x [3 x float]] [[ARG]]) +; CHECK-NEXT: call void @extern.use.array([2 x [3 x float]] nofpclass(inf) [[ARG]]) ; CHECK-NEXT: ret void ; call void @extern.use.array([2 x [3 x float]] %arg) @@ -186,12 +186,12 @@ define void @ninf_arg_used_by_callsite_array([2 x [3 x float]] nofpclass(inf) %a define float @mutually_recursive0(float %arg) { ; TUNIT: Function Attrs: nofree nosync nounwind willreturn memory(none) -; TUNIT-LABEL: define float @mutually_recursive0 +; TUNIT-LABEL: define nofpclass(all) float @mutually_recursive0 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR3:[0-9]+]] { ; TUNIT-NEXT: ret float undef ; ; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CGSCC-LABEL: define float @mutually_recursive0 +; CGSCC-LABEL: define nofpclass(all) float @mutually_recursive0 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR2]] { ; CGSCC-NEXT: ret float undef ; @@ -201,12 +201,12 @@ define float @mutually_recursive0(float %arg) { define float @mutually_recursive1(float %arg) { ; TUNIT: Function Attrs: nofree nosync nounwind willreturn memory(none) -; TUNIT-LABEL: define float @mutually_recursive1 +; TUNIT-LABEL: define nofpclass(all) float @mutually_recursive1 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: ret float undef ; ; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; CGSCC-LABEL: define float @mutually_recursive1 +; CGSCC-LABEL: define nofpclass(all) float @mutually_recursive1 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR2]] { ; CGSCC-NEXT: ret float undef ; @@ -215,10 +215,10 @@ define float @mutually_recursive1(float %arg) { } define float @recursive_phi(ptr %ptr) { -; CHECK-LABEL: define float @recursive_phi +; CHECK-LABEL: define nofpclass(nan) float @recursive_phi ; CHECK-SAME: (ptr nofree [[PTR:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RET:%.*]] = call float @ret_nofpclass_nan() +; CHECK-NEXT: [[RET:%.*]] = call nofpclass(nan) float @ret_nofpclass_nan() ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[PHI:%.*]] = phi float [ [[RET]], [[ENTRY:%.*]] ], [ [[RET]], [[LOOP]] ] @@ -310,7 +310,7 @@ entry: } define internal float @returned_dead() { -; CHECK-LABEL: define internal float @returned_dead() { +; CHECK-LABEL: define internal nofpclass(nan inf nzero sub norm) float @returned_dead() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float undef ; @@ -330,7 +330,7 @@ define void @returned_dead_caller() { define internal float @only_nofpclass_inf_callers(float %arg) { ; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define internal float @only_nofpclass_inf_callers -; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR2]] { +; CHECK-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] ; @@ -342,13 +342,13 @@ define float @call_noinf_0(float nofpclass(inf) %arg) { ; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define float @call_noinf_0 ; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR2]] { -; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float [[ARG]]) #[[ATTR5:[0-9]+]] +; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR5:[0-9]+]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @call_noinf_0 ; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3:[0-9]+]] { -; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float [[ARG]]) #[[ATTR4]] +; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR4]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call float @only_nofpclass_inf_callers(float %arg) @@ -386,13 +386,13 @@ define internal float @only_nofpclass_inf_return_users(float %arg) { define float @call_noinf_return_0(float %arg) { ; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; TUNIT-LABEL: define float @call_noinf_return_0 +; TUNIT-LABEL: define nofpclass(inf) float @call_noinf_return_0 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR2]] { ; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR5]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none) -; CGSCC-LABEL: define float @call_noinf_return_0 +; CGSCC-LABEL: define nofpclass(inf) float @call_noinf_return_0 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR4]] ; CGSCC-NEXT: ret float [[RESULT]] @@ -403,13 +403,13 @@ define float @call_noinf_return_0(float %arg) { define float @call_noinf_return_1(float %arg) { ; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) -; TUNIT-LABEL: define float @call_noinf_return_1 +; TUNIT-LABEL: define nofpclass(inf) float @call_noinf_return_1 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR2]] { ; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR5]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none) -; CGSCC-LABEL: define float @call_noinf_return_1 +; CGSCC-LABEL: define nofpclass(inf) float @call_noinf_return_1 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR4]] ; CGSCC-NEXT: ret float [[RESULT]] @@ -594,11 +594,11 @@ define float @assume_bundles(i1 %c, float %ret) { ; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] ; CHECK: A: ; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR4]] [ "nofpclass"(float [[RET]], i32 3) ] -; CHECK-NEXT: call void @extern.use(float [[RET]]) +; CHECK-NEXT: call void @extern.use(float nofpclass(nan) [[RET]]) ; CHECK-NEXT: ret float [[RET]] ; CHECK: B: ; CHECK-NEXT: call void @llvm.assume(i1 noundef true) [ "nofpclass"(float [[RET]], i32 12) ] -; CHECK-NEXT: call void @extern.use(float [[RET]]) +; CHECK-NEXT: call void @extern.use(float nofpclass(ninf nnorm) [[RET]]) ; CHECK-NEXT: ret float [[RET]] ; entry: -- 2.7.4