; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -S -passes=function-attrs %s | FileCheck --check-prefixes=COMMON,FNATTRS %s ; RUN: opt -S -passes=attributor-light %s | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s ; Test propagation of nofpclass callsite args back to caller. declare void @use1_nofpclass(float nofpclass(nan) noundef %x) declare void @use1_nofpclass_without_noundef(float nofpclass(nan) %x) ; Extend nofpclass to parent for all arguments. declare void @use3(float %x, float %y, float %z) declare void @use3_nofpclass(float nofpclass(nan) noundef %x, float nofpclass(nan) noundef %y, float nofpclass(nan) noundef %z) ; Without noundef, nofpclass cannot be propagated to the parent define void @parent_poison(float %a) { ; FNATTRS-LABEL: define void @parent_poison( ; FNATTRS-SAME: float [[A:%.*]]) { ; FNATTRS-NEXT: call void @use1_nofpclass_without_noundef(float [[A]]) ; FNATTRS-NEXT: call void @use1_nofpclass_without_noundef(float [[A]]) ; FNATTRS-NEXT: ret void ; ; ATTRIBUTOR-LABEL: define void @parent_poison( ; ATTRIBUTOR-SAME: float nofpclass(nan) [[A:%.*]]) { ; ATTRIBUTOR-NEXT: call void @use1_nofpclass_without_noundef(float nofpclass(nan) [[A]]) ; ATTRIBUTOR-NEXT: call void @use1_nofpclass_without_noundef(float [[A]]) ; ATTRIBUTOR-NEXT: ret void ; call void @use1_nofpclass_without_noundef(float %a) call void @use1_nofpclass_without_noundef(float %a) ret void } ; Can't extend nofpclass to parent for any argument because the 2nd call is not guaranteed to execute. define void @parent1(float %a, float %b, float %c) { ; COMMON-LABEL: define void @parent1( ; COMMON-SAME: float [[A:%.*]], float [[B:%.*]], float [[C:%.*]]) { ; COMMON-NEXT: call void @use3(float [[C]], float [[A]], float [[B]]) ; COMMON-NEXT: call void @use3_nofpclass(float [[B]], float [[C]], float [[A]]) ; COMMON-NEXT: ret void ; call void @use3(float %c, float %a, float %b) call void @use3_nofpclass(float %b, float %c, float %a) ret void } define void @parent2(float %a, float %b, float %c) { ; FNATTRS-LABEL: define void @parent2( ; FNATTRS-SAME: float nofpclass(nan nzero) [[A:%.*]], float nofpclass(nan) [[B:%.*]], float nofpclass(nan inf) [[C:%.*]]) { ; FNATTRS-NEXT: call void @use3_nofpclass(float [[B]], float nofpclass(inf) [[C]], float nofpclass(nzero) [[A]]) ; FNATTRS-NEXT: call void @use3(float [[C]], float [[A]], float [[B]]) ; FNATTRS-NEXT: ret void ; ; ATTRIBUTOR-LABEL: define void @parent2( ; ATTRIBUTOR-SAME: float nofpclass(nan nzero) [[A:%.*]], float nofpclass(nan) [[B:%.*]], float nofpclass(nan inf) [[C:%.*]]) { ; ATTRIBUTOR-NEXT: call void @use3_nofpclass(float nofpclass(nan) [[B]], float nofpclass(nan inf) [[C]], float nofpclass(nan nzero) [[A]]) ; ATTRIBUTOR-NEXT: call void @use3(float [[C]], float [[A]], float [[B]]) ; ATTRIBUTOR-NEXT: ret void ; call void @use3_nofpclass(float %b, float nofpclass(inf) %c, float nofpclass(nzero) %a) call void @use3(float %c, float %a, float %b) ret void } define void @parent3(ptr %a, i1 %a_is_not_nan) { ; COMMON-LABEL: define void @parent3( ; COMMON-SAME: ptr [[A:%.*]], i1 [[A_IS_NOT_NAN:%.*]]) { ; COMMON-NEXT: br i1 [[A_IS_NOT_NAN]], label %[[T:.*]], label %[[F:.*]] ; COMMON: [[T]]: ; COMMON-NEXT: call void @use1_nofpclass(ptr [[A]]) ; COMMON-NEXT: ret void ; COMMON: [[F]]: ; COMMON-NEXT: ret void ; br i1 %a_is_not_nan, label %t, label %f t: call void @use1_nofpclass(ptr %a) ret void f: ret void }