When we encounter a bitcast from an integer type we can use the information from `KnownBits` to glean some information about the fpclass: - If the sign bit is known, we can transfer this information over. - If the float is IEEE format and enough of the bits are known, we may be able to prove or rule out some fpclasses such as NaN, Zero, or Inf.
2981 lines
138 KiB
LLVM
2981 lines
138 KiB
LLVM
; 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-annotate-decl-cs -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
|
|
|
|
declare nofpclass(nan) float @ret_nofpclass_nan()
|
|
declare [2 x [3 x float]] @ret_array()
|
|
declare float @extern()
|
|
declare float @extern.f32(float)
|
|
declare void @extern.use(float)
|
|
declare void @extern.use.array([2 x [3 x float]])
|
|
declare void @llvm.assume(i1 noundef)
|
|
declare void @unknown()
|
|
declare half @llvm.fabs.f16(half)
|
|
declare float @llvm.fabs.f32(float)
|
|
declare void @extern.use.f16(half)
|
|
declare i1 @llvm.is.fpclass.f32(float, i32 immarg)
|
|
declare float @llvm.experimental.constrained.sitofp.f32.i32(i32, metadata, metadata)
|
|
declare float @llvm.experimental.constrained.uitofp.f32.i32(i32, metadata, metadata)
|
|
declare float @llvm.arithmetic.fence.f32(float)
|
|
|
|
define 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
|
|
;
|
|
call void @unknown()
|
|
ret float 0.0
|
|
}
|
|
|
|
define 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
|
|
;
|
|
call void @unknown()
|
|
ret float -0.0
|
|
}
|
|
|
|
define float @returned_undef() {
|
|
; CHECK-LABEL: define nofpclass(all) float @returned_undef() {
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: ret float undef
|
|
;
|
|
call void @unknown()
|
|
ret float undef
|
|
}
|
|
|
|
define float @returned_poison() {
|
|
; CHECK-LABEL: define nofpclass(all) float @returned_poison() {
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: ret float poison
|
|
;
|
|
call void @unknown()
|
|
ret float poison
|
|
}
|
|
|
|
; Know nothing
|
|
define float @returned_freeze_poison() {
|
|
; CHECK-LABEL: define noundef float @returned_freeze_poison() {
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: [[FREEZE_POISON:%.*]] = freeze float poison
|
|
; CHECK-NEXT: ret float [[FREEZE_POISON]]
|
|
;
|
|
call void @unknown()
|
|
%freeze.poison = freeze float poison
|
|
ret float %freeze.poison
|
|
}
|
|
|
|
define 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
|
|
;
|
|
call void @unknown()
|
|
ret double 0x7FF0000000000001
|
|
}
|
|
|
|
define 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
|
|
;
|
|
call void @unknown()
|
|
ret double 0x7FF8000000000000
|
|
}
|
|
|
|
define <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
|
|
;
|
|
call void @unknown()
|
|
ret <2 x double> zeroinitializer
|
|
}
|
|
|
|
define <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> <double -0.000000e+00, double -0.000000e+00>
|
|
;
|
|
call void @unknown()
|
|
ret <2 x double> <double -0.0, double -0.0>
|
|
}
|
|
|
|
; Test a vector element that's a constant but not ConstantFP.
|
|
define <2 x double> @returned_strange_constant_vector_elt() {
|
|
; CHECK-LABEL: define <2 x double> @returned_strange_constant_vector_elt() {
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: ret <2 x double> <double -0.000000e+00, double bitcast (i64 ptrtoint (ptr @unknown to i64) to double)>
|
|
;
|
|
call void @unknown()
|
|
ret <2 x double> <double -0.0, double bitcast (i64 ptrtoint (ptr @unknown to i64) to double)>
|
|
}
|
|
|
|
; Test a vector element that's undef
|
|
define <3 x double> @returned_undef_constant_vector_elt() {
|
|
; CHECK-LABEL: define <3 x double> @returned_undef_constant_vector_elt() {
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: ret <3 x double> <double -0.000000e+00, double 0.000000e+00, double undef>
|
|
;
|
|
call void @unknown()
|
|
ret <3 x double> <double -0.0, double 0.0, double undef>
|
|
}
|
|
|
|
; Test a vector element that's poison
|
|
define <3 x double> @returned_poison_constant_vector_elt() {
|
|
; CHECK-LABEL: define nofpclass(nan inf sub norm) <3 x double> @returned_poison_constant_vector_elt() {
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: ret <3 x double> <double -0.000000e+00, double 0.000000e+00, double poison>
|
|
;
|
|
call void @unknown()
|
|
ret <3 x double> <double -0.0, double 0.0, double poison>
|
|
}
|
|
|
|
define <2 x double> @returned_qnan_zero_vector() {
|
|
; CHECK-LABEL: define noundef nofpclass(snan inf nzero sub norm) <2 x double> @returned_qnan_zero_vector() {
|
|
; CHECK-NEXT: call void @unknown()
|
|
; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double 0.000000e+00>
|
|
;
|
|
call void @unknown()
|
|
ret <2 x double> <double 0x7FF8000000000000, double 0.0>
|
|
}
|
|
|
|
; Return a float trivially nofpclass(nan) (call return attribute)
|
|
define float @return_nofpclass_nan_decl_return() {
|
|
; 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()
|
|
ret float %ret
|
|
}
|
|
|
|
; Return a float trivially nofpclass(nan) (argument attribute)
|
|
define float @return_nofpclass_nan_arg(float returned nofpclass(nan) %p) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan) float @return_nofpclass_nan_arg
|
|
; CHECK-SAME: (float returned nofpclass(nan) [[P:%.*]]) #[[ATTR3:[0-9]+]] {
|
|
; CHECK-NEXT: ret float [[P]]
|
|
;
|
|
ret float %p
|
|
}
|
|
|
|
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]]
|
|
;
|
|
%ret = call nofpclass(inf) [2 x [3 x float]] @ret_array()
|
|
ret [2 x [3 x float]] %ret
|
|
}
|
|
|
|
define float @returned_nnan_fadd(float %arg0, float %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan) float @returned_nnan_fadd
|
|
; CHECK-SAME: (float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FADD:%.*]] = fadd nnan float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[FADD]]
|
|
;
|
|
%fadd = fadd nnan float %arg0, %arg1
|
|
ret float %fadd
|
|
}
|
|
|
|
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]]
|
|
;
|
|
%call = call nofpclass(nan) float @extern()
|
|
ret float %call
|
|
}
|
|
|
|
; Can union the return classes
|
|
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]]
|
|
;
|
|
%call = call nofpclass(nan) float @extern()
|
|
ret float %call
|
|
}
|
|
|
|
define void @arg_used_by_nofpclass_nan_callsite(float %arg) {
|
|
; CHECK-LABEL: define void @arg_used_by_nofpclass_nan_callsite
|
|
; CHECK-SAME: (float nofpclass(nan) [[ARG:%.*]]) {
|
|
; CHECK-NEXT: call void @extern.use(float nofpclass(nan) [[ARG]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void @extern.use(float nofpclass(nan) %arg)
|
|
ret void
|
|
}
|
|
|
|
; Callsite can union the incoming and outgoing
|
|
define void @ninf_arg_used_by_nofpclass_nan_callsite(float nofpclass(inf) %arg) {
|
|
; CHECK-LABEL: define void @ninf_arg_used_by_nofpclass_nan_callsite
|
|
; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) {
|
|
; CHECK-NEXT: call void @extern.use(float nofpclass(nan inf) [[ARG]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void @extern.use(float nofpclass(nan) %arg)
|
|
ret void
|
|
}
|
|
|
|
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]] nofpclass(inf) [[ARG]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void @extern.use.array([2 x [3 x float]] %arg)
|
|
ret void
|
|
}
|
|
|
|
define void @nofpclass_call_use_after_unannotated_use(float %arg) {
|
|
; CHECK-LABEL: define void @nofpclass_call_use_after_unannotated_use
|
|
; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) {
|
|
; CHECK-NEXT: call void @extern(float nofpclass(nan inf) [[ARG]]) #[[ATTR17:[0-9]+]]
|
|
; CHECK-NEXT: call void @extern(float nofpclass(nan inf) [[ARG]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call void @extern(float %arg) willreturn nounwind ; < annotate this use
|
|
call void @extern(float nofpclass(nan inf) %arg)
|
|
ret void
|
|
}
|
|
|
|
define float @mutually_recursive0(float %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(all) float @mutually_recursive0
|
|
; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
|
|
; TUNIT-NEXT: ret float undef
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(all) float @mutually_recursive0
|
|
; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: ret float undef
|
|
;
|
|
%call = call float @mutually_recursive1(float %arg)
|
|
ret float %call
|
|
}
|
|
|
|
define float @mutually_recursive1(float %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(all) float @mutually_recursive1
|
|
; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR4]] {
|
|
; TUNIT-NEXT: ret float undef
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(all) float @mutually_recursive1
|
|
; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: ret float undef
|
|
;
|
|
%call = call float @mutually_recursive0(float %arg)
|
|
ret float %call
|
|
}
|
|
|
|
define float @recursive_phi(ptr %ptr) {
|
|
; CHECK-LABEL: define nofpclass(nan) float @recursive_phi
|
|
; CHECK-SAME: (ptr nofree [[PTR:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; 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]] ]
|
|
; CHECK-NEXT: [[COND:%.*]] = load volatile i1, ptr [[PTR]], align 1
|
|
; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret float [[RET]]
|
|
;
|
|
entry:
|
|
%ret = call float @ret_nofpclass_nan()
|
|
br label %loop
|
|
|
|
loop:
|
|
%phi = phi float [%ret, %entry], [%phi, %loop]
|
|
%cond = load volatile i1, ptr %ptr
|
|
br i1 %cond, label %loop, label %exit
|
|
|
|
exit:
|
|
ret float %phi
|
|
}
|
|
|
|
; Should be able to infer nofpclass(nan) return
|
|
define float @fcmp_uno_check(float %arg) local_unnamed_addr {
|
|
; CHECK-LABEL: define float @fcmp_uno_check
|
|
; CHECK-SAME: (float [[ARG:%.*]]) local_unnamed_addr {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ISNAN:%.*]] = fcmp uno float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: br i1 [[ISNAN]], label [[BB0:%.*]], label [[BB1:%.*]]
|
|
; CHECK: bb0:
|
|
; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @ret_nofpclass_nan()
|
|
; CHECK-NEXT: br label [[BB1]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi float [ [[CALL]], [[BB0]] ], [ [[ARG]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: ret float [[PHI]]
|
|
;
|
|
entry:
|
|
%isnan = fcmp uno float %arg, 0.0
|
|
br i1 %isnan, label %bb0, label %bb1
|
|
|
|
bb0:
|
|
%call = call float @ret_nofpclass_nan()
|
|
br label %bb1
|
|
|
|
bb1:
|
|
%phi = phi float [ %call, %bb0 ], [ %arg, %entry ]
|
|
ret float %phi
|
|
}
|
|
|
|
; Should be able to infer nofpclass(nan) on %arg use
|
|
define void @fcmp_ord_guard_callsite_arg(float %arg) {
|
|
; CHECK-LABEL: define void @fcmp_ord_guard_callsite_arg
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[IS_NOT_NAN:%.*]] = fcmp ord float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: br i1 [[IS_NOT_NAN]], label [[BB0:%.*]], label [[BB1:%.*]]
|
|
; CHECK: bb0:
|
|
; CHECK-NEXT: call void @extern.use(float [[ARG]])
|
|
; CHECK-NEXT: br label [[BB1]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%is.not.nan = fcmp ord float %arg, 0.0
|
|
br i1 %is.not.nan, label %bb0, label %bb1
|
|
|
|
bb0:
|
|
call void @extern.use(float %arg)
|
|
br label %bb1
|
|
|
|
bb1:
|
|
ret void
|
|
}
|
|
|
|
; Should be able to infer nofpclass on both %arg uses
|
|
define float @fcmp_ord_assume_callsite_arg_return(float %arg) {
|
|
; CHECK-LABEL: define float @fcmp_ord_assume_callsite_arg_return
|
|
; CHECK-SAME: (float returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[IS_NOT_NAN:%.*]] = fcmp ord float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_NAN]]) #[[ATTR18:[0-9]+]]
|
|
; CHECK-NEXT: call void @extern.use(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[ARG]]
|
|
;
|
|
entry:
|
|
%is.not.nan = fcmp ord float %arg, 0.0
|
|
call void @llvm.assume(i1 %is.not.nan)
|
|
call void @extern.use(float %arg)
|
|
ret float %arg
|
|
}
|
|
|
|
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
|
|
;
|
|
call void @unknown()
|
|
ret float 0.0
|
|
}
|
|
|
|
define void @returned_dead_caller() {
|
|
; CHECK-LABEL: define void @returned_dead_caller() {
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call float @returned_dead()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
call float @returned_dead()
|
|
ret void
|
|
}
|
|
|
|
define internal float @only_nofpclass_inf_callers(float %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define internal float @only_nofpclass_inf_callers
|
|
; CHECK-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg, %arg
|
|
ret float %add
|
|
}
|
|
|
|
define float @call_noinf_0(float nofpclass(inf) %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define float @call_noinf_0
|
|
; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR19:[0-9]+]]
|
|
; TUNIT-NEXT: ret float [[RESULT]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define float @call_noinf_0
|
|
; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
|
|
; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR19:[0-9]+]]
|
|
; CGSCC-NEXT: ret float [[RESULT]]
|
|
;
|
|
%result = call float @only_nofpclass_inf_callers(float %arg)
|
|
ret float %result
|
|
}
|
|
|
|
define float @call_noinf_1(float %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define float @call_noinf_1
|
|
; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR19]]
|
|
; TUNIT-NEXT: ret float [[RESULT]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define float @call_noinf_1
|
|
; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[RESULT]]
|
|
;
|
|
%result = call float @only_nofpclass_inf_callers(float nofpclass(inf) %arg)
|
|
ret float %result
|
|
}
|
|
|
|
; TODO: Should be able to infer nofpclass(inf) on return
|
|
define internal float @only_nofpclass_inf_return_users(float %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define internal float @only_nofpclass_inf_return_users
|
|
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg, %arg
|
|
ret float %add
|
|
}
|
|
|
|
define float @call_noinf_return_0(float %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(inf) float @call_noinf_return_0
|
|
; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR19]]
|
|
; TUNIT-NEXT: ret float [[RESULT]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(inf) float @call_noinf_return_0
|
|
; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[RESULT]]
|
|
;
|
|
%result = call nofpclass(inf) float @only_nofpclass_inf_return_users(float %arg)
|
|
ret float %result
|
|
}
|
|
|
|
define float @call_noinf_return_1(float %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(inf) float @call_noinf_return_1
|
|
; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR19]]
|
|
; TUNIT-NEXT: ret float [[RESULT]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(inf) float @call_noinf_return_1
|
|
; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[RESULT]]
|
|
;
|
|
%result = call nofpclass(inf) float @only_nofpclass_inf_return_users(float %arg)
|
|
ret float %result
|
|
}
|
|
|
|
define float @fcmp_olt_assume_one_0_callsite_arg_return(float %arg) {
|
|
; CHECK-LABEL: define float @fcmp_olt_assume_one_0_callsite_arg_return
|
|
; CHECK-SAME: (float returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[IS_NOT_ZERO_OR_NAN:%.*]] = fcmp one float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[ARG]]
|
|
;
|
|
entry:
|
|
%is.not.zero.or.nan = fcmp one float %arg, 0.0
|
|
call void @llvm.assume(i1 %is.not.zero.or.nan)
|
|
call void @extern.use(float %arg)
|
|
ret float %arg
|
|
}
|
|
|
|
define float @fcmp_olt_assume_une_0_callsite_arg_return(float %arg) {
|
|
; CHECK-LABEL: define float @fcmp_olt_assume_une_0_callsite_arg_return
|
|
; CHECK-SAME: (float returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[IS_NOT_ZERO_OR_NAN:%.*]] = fcmp une float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[ARG]]
|
|
;
|
|
entry:
|
|
%is.not.zero.or.nan = fcmp une float %arg, 0.0
|
|
call void @llvm.assume(i1 %is.not.zero.or.nan)
|
|
call void @extern.use(float %arg)
|
|
ret float %arg
|
|
}
|
|
|
|
define half @fcmp_assume_issubnormal_callsite_arg_return(half %arg) {
|
|
; CHECK-LABEL: define half @fcmp_assume_issubnormal_callsite_arg_return
|
|
; CHECK-SAME: (half returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fabs.f16(half [[ARG]]) #[[ATTR20:[0-9]+]]
|
|
; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use.f16(half [[ARG]])
|
|
; CHECK-NEXT: ret half [[ARG]]
|
|
;
|
|
entry:
|
|
%fabs = call half @llvm.fabs.f16(half %arg)
|
|
%is.subnormal = fcmp olt half %fabs, 0xH0400
|
|
call void @llvm.assume(i1 %is.subnormal)
|
|
call void @extern.use.f16(half %arg)
|
|
ret half %arg
|
|
}
|
|
|
|
; Assume is after the call, shouldn't mark callsite.
|
|
define half @fcmp_assume_not_inf_after_call(half %arg) {
|
|
; CHECK-LABEL: define half @fcmp_assume_not_inf_after_call
|
|
; CHECK-SAME: (half returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: call void @extern.use.f16(half [[ARG]])
|
|
; CHECK-NEXT: [[NOT_INF:%.*]] = fcmp oeq half [[ARG]], 0xH7C00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_INF]])
|
|
; CHECK-NEXT: ret half [[ARG]]
|
|
;
|
|
entry:
|
|
call void @extern.use.f16(half %arg)
|
|
%not.inf = fcmp oeq half %arg, 0xH7C00
|
|
call void @llvm.assume(i1 %not.inf)
|
|
ret half %arg
|
|
}
|
|
|
|
; Assume not subnormal or zero, and not infinity
|
|
define half @fcmp_assume2_callsite_arg_return(half %arg) {
|
|
; CHECK-LABEL: define half @fcmp_assume2_callsite_arg_return
|
|
; CHECK-SAME: (half returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fabs.f16(half [[ARG]]) #[[ATTR20]]
|
|
; CHECK-NEXT: [[NOT_SUBNORMAL_OR_ZERO:%.*]] = fcmp oge half [[FABS]], 0xH0400
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_SUBNORMAL_OR_ZERO]]) #[[ATTR18]]
|
|
; CHECK-NEXT: [[NOT_INF:%.*]] = fcmp one half [[ARG]], 0xH7C00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_INF]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use.f16(half [[ARG]])
|
|
; CHECK-NEXT: ret half [[ARG]]
|
|
;
|
|
entry:
|
|
%fabs = call half @llvm.fabs.f16(half %arg)
|
|
%not.subnormal.or.zero = fcmp oge half %fabs, 0xH0400
|
|
call void @llvm.assume(i1 %not.subnormal.or.zero)
|
|
|
|
%not.inf = fcmp one half %arg, 0xH7C00
|
|
call void @llvm.assume(i1 %not.inf)
|
|
|
|
call void @extern.use.f16(half %arg)
|
|
ret half %arg
|
|
}
|
|
|
|
define float @is_fpclass_assume_arg_return(float %arg) {
|
|
; CHECK-LABEL: define float @is_fpclass_assume_arg_return
|
|
; CHECK-SAME: (float returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CLASS_TEST:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 292) #[[ATTR20]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CLASS_TEST]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[ARG]]
|
|
;
|
|
entry:
|
|
%class.test = call i1 @llvm.is.fpclass.f32(float %arg, i32 292)
|
|
call void @llvm.assume(i1 %class.test)
|
|
call void @extern.use(float %arg)
|
|
ret float %arg
|
|
}
|
|
|
|
; Make sure we don't get confused by looking at an unrelated assume
|
|
; based on the fabs of the value.
|
|
define half @assume_fcmp_fabs_with_other_fabs_assume(half %arg) {
|
|
; CHECK-LABEL: define half @assume_fcmp_fabs_with_other_fabs_assume
|
|
; CHECK-SAME: (half returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fabs.f16(half [[ARG]]) #[[ATTR20]]
|
|
; CHECK-NEXT: [[UNRELATED_FABS:%.*]] = fcmp one half [[FABS]], 0xH0000
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR18]]
|
|
; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use.f16(half [[ARG]])
|
|
; CHECK-NEXT: call void @extern.use.f16(half nofpclass(ninf nzero nsub nnorm) [[FABS]])
|
|
; CHECK-NEXT: ret half [[ARG]]
|
|
;
|
|
entry:
|
|
|
|
%fabs = call half @llvm.fabs.f16(half %arg)
|
|
%unrelated.fabs = fcmp one half %fabs, 0.0
|
|
call void @llvm.assume(i1 %unrelated.fabs)
|
|
%is.subnormal = fcmp olt half %fabs, 0xH0400
|
|
call void @llvm.assume(i1 %is.subnormal)
|
|
call void @extern.use.f16(half %arg)
|
|
call void @extern.use.f16(half %fabs)
|
|
ret half %arg
|
|
}
|
|
|
|
; Make sure if looking through the fabs finds a different source
|
|
; value, we still identify a test mask by ignoring the fabs
|
|
define half @assume_fcmp_fabs_with_other_fabs_assume_fallback(half %arg) {
|
|
; CHECK-LABEL: define half @assume_fcmp_fabs_with_other_fabs_assume_fallback
|
|
; CHECK-SAME: (half returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fabs.f16(half [[ARG]]) #[[ATTR20]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR18]]
|
|
; CHECK-NEXT: [[UNRELATED_FABS:%.*]] = fcmp oeq half [[FABS]], 0xH0000
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use.f16(half [[ARG]])
|
|
; CHECK-NEXT: call void @extern.use.f16(half nofpclass(ninf nzero nsub nnorm) [[FABS]])
|
|
; CHECK-NEXT: ret half [[ARG]]
|
|
;
|
|
entry:
|
|
|
|
%fabs = call half @llvm.fabs.f16(half %arg)
|
|
|
|
%one.inf = fcmp one half %arg, 0xH7C00
|
|
call void @llvm.assume(i1 %one.inf)
|
|
|
|
%unrelated.fabs = fcmp oeq half %fabs, 0.0
|
|
call void @llvm.assume(i1 %unrelated.fabs)
|
|
|
|
%is.subnormal = fcmp olt half %fabs, 0xH0400
|
|
call void @llvm.assume(i1 %is.subnormal)
|
|
call void @extern.use.f16(half %arg)
|
|
call void @extern.use.f16(half %fabs)
|
|
ret half %arg
|
|
}
|
|
|
|
define float @assume_bundles(i1 %c, float %ret) {
|
|
; CHECK-LABEL: define float @assume_bundles
|
|
; CHECK-SAME: (i1 noundef [[C:%.*]], float returned [[RET:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]]
|
|
; CHECK: A:
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR18]] [ "nofpclass"(float [[RET]], i32 3) ]
|
|
; 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 nofpclass(ninf nnorm) [[RET]])
|
|
; CHECK-NEXT: ret float [[RET]]
|
|
;
|
|
entry:
|
|
br i1 %c, label %A, label %B
|
|
|
|
A:
|
|
call void @llvm.assume(i1 true) [ "nofpclass"(float %ret, i32 3) ]
|
|
call void @extern.use(float %ret)
|
|
ret float %ret
|
|
|
|
B:
|
|
call void @llvm.assume(i1 true) [ "nofpclass"(float %ret, i32 12) ]
|
|
call void @extern.use(float %ret)
|
|
ret float %ret
|
|
}
|
|
|
|
define float @returned_load(ptr %ptr) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
|
|
; CHECK-LABEL: define float @returned_load
|
|
; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[PTR:%.*]]) #[[ATTR5:[0-9]+]] {
|
|
; CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[LOAD]]
|
|
;
|
|
%load = load float, ptr %ptr
|
|
ret float %load
|
|
}
|
|
|
|
define float @pass_nofpclass_inf_through_memory(float nofpclass(inf) %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define float @pass_nofpclass_inf_through_memory
|
|
; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4
|
|
; TUNIT-NEXT: store float [[ARG]], ptr [[ALLOCA]], align 4
|
|
; TUNIT-NEXT: [[RET:%.*]] = call float @returned_load(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ALLOCA]]) #[[ATTR21:[0-9]+]]
|
|
; TUNIT-NEXT: ret float [[RET]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define float @pass_nofpclass_inf_through_memory
|
|
; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4
|
|
; CGSCC-NEXT: store float [[ARG]], ptr [[ALLOCA]], align 4
|
|
; CGSCC-NEXT: [[RET:%.*]] = call float @returned_load(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ALLOCA]]) #[[ATTR21:[0-9]+]]
|
|
; CGSCC-NEXT: ret float [[RET]]
|
|
;
|
|
%alloca = alloca float
|
|
store float %arg, ptr %alloca
|
|
%ret = call float @returned_load(ptr %alloca)
|
|
ret float %ret
|
|
}
|
|
|
|
define float @returned_fabs(float %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs
|
|
; TUNIT-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float [[X]]) #[[ATTR22:[0-9]+]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs
|
|
; CGSCC-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nosnan(float nofpclass(snan) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(snan ninf nzero nsub nnorm) float @returned_fabs_nosnan
|
|
; TUNIT-SAME: (float nofpclass(snan) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(snan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(snan) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(snan ninf nzero nsub nnorm) float @returned_fabs_nosnan
|
|
; CGSCC-SAME: (float nofpclass(snan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(snan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(snan) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_noqnan(float nofpclass(qnan) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(qnan ninf nzero nsub nnorm) float @returned_fabs_noqnan
|
|
; TUNIT-SAME: (float nofpclass(qnan) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(qnan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(qnan) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(qnan ninf nzero nsub nnorm) float @returned_fabs_noqnan
|
|
; CGSCC-SAME: (float nofpclass(qnan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(qnan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(qnan) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nonan(float nofpclass(nan) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_nonan
|
|
; TUNIT-SAME: (float nofpclass(nan) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_nonan
|
|
; CGSCC-SAME: (float nofpclass(nan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_noinf(float nofpclass(inf) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(inf nzero nsub nnorm) float @returned_fabs_noinf
|
|
; TUNIT-SAME: (float nofpclass(inf) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(inf nzero nsub nnorm) float @returned_fabs_noinf
|
|
; CGSCC-SAME: (float nofpclass(inf) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nopos(float nofpclass(psub pnorm pinf) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopos
|
|
; TUNIT-SAME: (float nofpclass(pinf psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pinf psub pnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopos
|
|
; CGSCC-SAME: (float nofpclass(pinf psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pinf psub pnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nopos_nopzero(float nofpclass(psub pnorm pinf pzero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopos_nopzero
|
|
; TUNIT-SAME: (float nofpclass(pinf pzero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pinf pzero psub pnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopos_nopzero
|
|
; CGSCC-SAME: (float nofpclass(pinf pzero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pinf pzero psub pnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nopos_nozero(float nofpclass(psub pnorm pinf zero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf zero nsub nnorm) float @returned_fabs_nopos_nozero
|
|
; TUNIT-SAME: (float nofpclass(pinf zero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pinf zero psub pnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf zero nsub nnorm) float @returned_fabs_nopos_nozero
|
|
; CGSCC-SAME: (float nofpclass(pinf zero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pinf zero psub pnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nopos_nonan(float nofpclass(psub pnorm pinf nan) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_nopos_nonan
|
|
; TUNIT-SAME: (float nofpclass(nan pinf psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan pinf psub pnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_nopos_nonan
|
|
; CGSCC-SAME: (float nofpclass(nan pinf psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan pinf psub pnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_noneg(float nofpclass(nsub nnorm ninf) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_noneg
|
|
; TUNIT-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nsub nnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_noneg
|
|
; CGSCC-SAME: (float nofpclass(ninf nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nsub nnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_noneg_nonzero(float nofpclass(nsub nnorm ninf nzero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_noneg_nonzero
|
|
; TUNIT-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_noneg_nonzero
|
|
; CGSCC-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_noneg_nozero(float nofpclass(nsub nnorm ninf zero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf zero nsub nnorm) float @returned_fabs_noneg_nozero
|
|
; TUNIT-SAME: (float nofpclass(ninf zero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf zero nsub nnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf zero nsub nnorm) float @returned_fabs_noneg_nozero
|
|
; CGSCC-SAME: (float nofpclass(ninf zero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf zero nsub nnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_noneg_nonan(float nofpclass(nsub nnorm ninf nan) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_noneg_nonan
|
|
; TUNIT-SAME: (float nofpclass(nan ninf nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan ninf nsub nnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_noneg_nonan
|
|
; CGSCC-SAME: (float nofpclass(nan ninf nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan ninf nsub nnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nonsub_nopnorm_nonzero(float nofpclass(nsub pnorm nzero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nonsub_nopnorm_nonzero
|
|
; TUNIT-SAME: (float nofpclass(nzero nsub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nzero nsub pnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nonsub_nopnorm_nonzero
|
|
; CGSCC-SAME: (float nofpclass(nzero nsub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nzero nsub pnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nopsub_nonnorm_nopzero(float nofpclass(psub nnorm pzero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopsub_nonnorm_nopzero
|
|
; TUNIT-SAME: (float nofpclass(pzero psub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pzero psub nnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopsub_nonnorm_nopzero
|
|
; CGSCC-SAME: (float nofpclass(pzero psub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pzero psub nnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fabs_nonnorm_nozero(float nofpclass(nnorm nzero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nonnorm_nozero
|
|
; TUNIT-SAME: (float nofpclass(nzero nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nzero nnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nonnorm_nozero
|
|
; CGSCC-SAME: (float nofpclass(nzero nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nzero nnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
ret float %fabs
|
|
}
|
|
|
|
define float @returned_fneg(float %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @returned_fneg
|
|
; CHECK-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_nosnan(float nofpclass(snan) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(snan) float @returned_fneg_nosnan
|
|
; CHECK-SAME: (float nofpclass(snan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_noqnan(float nofpclass(qnan) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(qnan) float @returned_fneg_noqnan
|
|
; CHECK-SAME: (float nofpclass(qnan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_nosnan_ninf_flag(float nofpclass(snan) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(snan inf) float @returned_fneg_nosnan_ninf_flag
|
|
; CHECK-SAME: (float nofpclass(snan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg ninf float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg ninf float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_nonan(float nofpclass(nan) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan) float @returned_fneg_nonan
|
|
; CHECK-SAME: (float nofpclass(nan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_noinf(float nofpclass(inf) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(inf) float @returned_fneg_noinf
|
|
; CHECK-SAME: (float nofpclass(inf) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_noneg(float nofpclass(ninf nsub nnorm nzero) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_noneg
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_noneg_nnan_flag(float nofpclass(ninf nsub nnorm nzero) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @returned_fneg_noneg_nnan_flag
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg nnan float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg nnan float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_nonsubnnorm(float nofpclass(nsub nnorm) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(psub pnorm) float @returned_fneg_nonsubnnorm
|
|
; CHECK-SAME: (float nofpclass(nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_nopos(float nofpclass(pinf psub pnorm pzero) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fneg_nopos
|
|
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_nopnormpsub(float nofpclass(psub pnorm) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nsub nnorm) float @returned_fneg_nopnormpsub
|
|
; CHECK-SAME: (float nofpclass(psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_mixed(float nofpclass(psub nnorm nzero qnan ninf) %x) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(qnan pinf pzero nsub pnorm) float @returned_fneg_mixed
|
|
; CHECK-SAME: (float nofpclass(qnan ninf nzero psub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]]
|
|
; CHECK-NEXT: ret float [[FNEG]]
|
|
;
|
|
%fneg = fneg float %x
|
|
ret float %fneg
|
|
}
|
|
|
|
define float @returned_fneg_fabs(float %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs
|
|
; TUNIT-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs
|
|
; CGSCC-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @returned_fneg_fabs_nosnan(float nofpclass(snan) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(snan pinf pzero psub pnorm) float @returned_fneg_fabs_nosnan
|
|
; TUNIT-SAME: (float nofpclass(snan) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(snan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(snan) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(snan pinf pzero psub pnorm) float @returned_fneg_fabs_nosnan
|
|
; CGSCC-SAME: (float nofpclass(snan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(snan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(snan) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @returned_fneg_fabs_noqnan(float nofpclass(qnan) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(qnan pinf pzero psub pnorm) float @returned_fneg_fabs_noqnan
|
|
; TUNIT-SAME: (float nofpclass(qnan) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(qnan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(qnan) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(qnan pinf pzero psub pnorm) float @returned_fneg_fabs_noqnan
|
|
; CGSCC-SAME: (float nofpclass(qnan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(qnan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(qnan) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @returned_fneg_fabs_nonan(float nofpclass(nan) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @returned_fneg_fabs_nonan
|
|
; TUNIT-SAME: (float nofpclass(nan) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @returned_fneg_fabs_nonan
|
|
; CGSCC-SAME: (float nofpclass(nan) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @returned_fneg_fabs_noneg(float nofpclass(ninf nsub nnorm nzero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs_noneg
|
|
; TUNIT-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs_noneg
|
|
; CGSCC-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @returned_fneg_fabs_nopos(float nofpclass(pinf psub pnorm pzero) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs_nopos
|
|
; TUNIT-SAME: (float nofpclass(pinf pzero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pinf pzero psub pnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs_nopos
|
|
; CGSCC-SAME: (float nofpclass(pinf pzero psub pnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(pinf pzero psub pnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @returned_fneg_fabs_mixed(float nofpclass(psub nnorm nzero qnan ninf) %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(qnan pinf pzero psub pnorm) float @returned_fneg_fabs_mixed
|
|
; TUNIT-SAME: (float nofpclass(qnan ninf nzero psub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(qnan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(qnan ninf nzero psub nnorm) [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(qnan pinf pzero psub pnorm) float @returned_fneg_fabs_mixed
|
|
; CGSCC-SAME: (float nofpclass(qnan ninf nzero psub nnorm) [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(qnan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(qnan ninf nzero psub nnorm) [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @returned_fneg_fabs_ninf_flag_fabs(float %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(inf pzero psub pnorm) float @returned_fneg_fabs_ninf_flag_fabs
|
|
; TUNIT-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call ninf nofpclass(inf nzero nsub nnorm) float @llvm.fabs.f32(float [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(inf pzero psub pnorm) float @returned_fneg_fabs_ninf_flag_fabs
|
|
; CGSCC-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call ninf nofpclass(inf nzero nsub nnorm) float @llvm.fabs.f32(float [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call ninf float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @returned_fneg_fabs_ninf_flag_fneg(float %x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(inf pzero psub pnorm) float @returned_fneg_fabs_ninf_flag_fneg
|
|
; TUNIT-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float [[X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg ninf float [[FABS]]
|
|
; TUNIT-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define nofpclass(inf pzero psub pnorm) float @returned_fneg_fabs_ninf_flag_fneg
|
|
; CGSCC-SAME: (float [[X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float [[X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg ninf float [[FABS]]
|
|
; CGSCC-NEXT: ret float [[FNEG_FABS]]
|
|
;
|
|
%fabs = call float @llvm.fabs.f32(float %x)
|
|
%fneg.fabs = fneg ninf float %fabs
|
|
ret float %fneg.fabs
|
|
}
|
|
|
|
define float @uitofp_i32_to_f32(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero sub nnorm) float @uitofp_i32_to_f32
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CVT:%.*]] = uitofp i32 [[ARG]] to float
|
|
; CHECK-NEXT: ret float [[CVT]]
|
|
;
|
|
%cvt = uitofp i32 %arg to float
|
|
ret float %cvt
|
|
}
|
|
|
|
define float @sitofp_i32_to_f32(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero sub) float @sitofp_i32_to_f32
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CVT:%.*]] = sitofp i32 [[ARG]] to float
|
|
; CHECK-NEXT: ret float [[CVT]]
|
|
;
|
|
%cvt = sitofp i32 %arg to float
|
|
ret float %cvt
|
|
}
|
|
|
|
define <2 x float> @uitofp_v2i32_to_v2f32(<2 x i32> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero sub nnorm) <2 x float> @uitofp_v2i32_to_v2f32
|
|
; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CVT:%.*]] = uitofp <2 x i32> [[ARG]] to <2 x float>
|
|
; CHECK-NEXT: ret <2 x float> [[CVT]]
|
|
;
|
|
%cvt = uitofp <2 x i32> %arg to <2 x float>
|
|
ret <2 x float> %cvt
|
|
}
|
|
|
|
define <2 x float> @sitofp_v2i32_to_v2i32(<2 x i32> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero sub) <2 x float> @sitofp_v2i32_to_v2i32
|
|
; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CVT:%.*]] = sitofp <2 x i32> [[ARG]] to <2 x float>
|
|
; CHECK-NEXT: ret <2 x float> [[CVT]]
|
|
;
|
|
%cvt = sitofp <2 x i32> %arg to <2 x float>
|
|
ret <2 x float> %cvt
|
|
}
|
|
|
|
define half @uitofp_i17_to_f16(i17 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) half @uitofp_i17_to_f16
|
|
; CHECK-SAME: (i17 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CVT:%.*]] = uitofp i17 [[ARG]] to half
|
|
; CHECK-NEXT: ret half [[CVT]]
|
|
;
|
|
%cvt = uitofp i17 %arg to half
|
|
ret half %cvt
|
|
}
|
|
|
|
define half @sitofp_i17_to_f16(i17 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan nzero sub) half @sitofp_i17_to_f16
|
|
; CHECK-SAME: (i17 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CVT:%.*]] = sitofp i17 [[ARG]] to half
|
|
; CHECK-NEXT: ret half [[CVT]]
|
|
;
|
|
%cvt = sitofp i17 %arg to half
|
|
ret half %cvt
|
|
}
|
|
|
|
define <2 x half> @uitofp_v2i17_to_v2f16(<2 x i17> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) <2 x half> @uitofp_v2i17_to_v2f16
|
|
; CHECK-SAME: (<2 x i17> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CVT:%.*]] = uitofp <2 x i17> [[ARG]] to <2 x half>
|
|
; CHECK-NEXT: ret <2 x half> [[CVT]]
|
|
;
|
|
%cvt = uitofp <2 x i17> %arg to <2 x half>
|
|
ret <2 x half> %cvt
|
|
}
|
|
|
|
define <2 x half> @sitofp_v2i17_to_v2i17(<2 x i17> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan nzero sub) <2 x half> @sitofp_v2i17_to_v2i17
|
|
; CHECK-SAME: (<2 x i17> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CVT:%.*]] = sitofp <2 x i17> [[ARG]] to <2 x half>
|
|
; CHECK-NEXT: ret <2 x half> [[CVT]]
|
|
;
|
|
%cvt = sitofp <2 x i17> %arg to <2 x half>
|
|
ret <2 x half> %cvt
|
|
}
|
|
|
|
define float @assume_intersection_not_zero_and_not_nan(float %arg) {
|
|
; CHECK-LABEL: define float @assume_intersection_not_zero_and_not_nan
|
|
; CHECK-SAME: (float returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[IS_NOT_ZERO_OR_NAN:%.*]] = fcmp une float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR18]]
|
|
; CHECK-NEXT: [[IS_ORD:%.*]] = fcmp ord float [[ARG]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_ORD]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[ARG]]
|
|
;
|
|
entry:
|
|
%is.not.zero.or.nan = fcmp une float %arg, 0.0
|
|
call void @llvm.assume(i1 %is.not.zero.or.nan)
|
|
%is.ord = fcmp ord float %arg, 0.0
|
|
call void @llvm.assume(i1 %is.ord)
|
|
call void @extern.use(float %arg)
|
|
ret float %arg
|
|
}
|
|
|
|
define float @assume_intersection_class(float %arg) {
|
|
; CHECK-LABEL: define float @assume_intersection_class
|
|
; CHECK-SAME: (float returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[POS_NORMAL_OR_POS_SUBNORMAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 384) #[[ATTR20]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[POS_NORMAL_OR_POS_SUBNORMAL]]) #[[ATTR18]]
|
|
; CHECK-NEXT: [[IS_NORMAL:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 264) #[[ATTR20]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NORMAL]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[ARG]]
|
|
;
|
|
entry:
|
|
%pos.normal.or.pos.subnormal = call i1 @llvm.is.fpclass.f32(float %arg, i32 384)
|
|
call void @llvm.assume(i1 %pos.normal.or.pos.subnormal)
|
|
%is.normal = call i1 @llvm.is.fpclass.f32(float %arg, i32 264)
|
|
call void @llvm.assume(i1 %is.normal)
|
|
|
|
call void @extern.use(float %arg)
|
|
ret float %arg
|
|
}
|
|
|
|
define float @assume_intersection_none(float %arg) {
|
|
; CHECK-LABEL: define float @assume_intersection_none
|
|
; CHECK-SAME: (float returned [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CLASS1:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 682) #[[ATTR20]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CLASS1]]) #[[ATTR18]]
|
|
; CHECK-NEXT: [[CLASS2:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 341) #[[ATTR20]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CLASS2]]) #[[ATTR18]]
|
|
; CHECK-NEXT: call void @extern.use(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[ARG]]
|
|
;
|
|
entry:
|
|
%class1 = call i1 @llvm.is.fpclass.f32(float %arg, i32 682)
|
|
call void @llvm.assume(i1 %class1)
|
|
%class2 = call i1 @llvm.is.fpclass.f32(float %arg, i32 341)
|
|
call void @llvm.assume(i1 %class2)
|
|
call void @extern.use(float %arg)
|
|
ret float %arg
|
|
}
|
|
|
|
define float @returned_extractelement_dynamic_index(<4 x float> nofpclass(nan) %vec, i32 %idx) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan) float @returned_extractelement_dynamic_index
|
|
; CHECK-SAME: (<4 x float> nofpclass(nan) [[VEC:%.*]], i32 [[IDX:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[VEC]], i32 [[IDX]]
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%extract = extractelement <4 x float> %vec, i32 %idx
|
|
ret float %extract
|
|
}
|
|
|
|
define float @returned_extractelement_index0(<4 x float> nofpclass(nan) %vec) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan) float @returned_extractelement_index0
|
|
; CHECK-SAME: (<4 x float> nofpclass(nan) [[VEC:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[VEC]], i32 0
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%extract = extractelement <4 x float> %vec, i32 0
|
|
ret float %extract
|
|
}
|
|
|
|
define float @returned_extractelement_index_oob(<4 x float> nofpclass(nan) %vec) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan) float @returned_extractelement_index_oob
|
|
; CHECK-SAME: (<4 x float> nofpclass(nan) [[VEC:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[VEC]], i32 5
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%extract = extractelement <4 x float> %vec, i32 5
|
|
ret float %extract
|
|
}
|
|
|
|
define float @returned_extractelement_scalable(<vscale x 4 x float> nofpclass(nan) %vec) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @returned_extractelement_scalable
|
|
; CHECK-SAME: (<vscale x 4 x float> nofpclass(nan) [[VEC:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <vscale x 4 x float> [[VEC]], i32 0
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%extract = extractelement <vscale x 4 x float> %vec, i32 0
|
|
ret float %extract
|
|
}
|
|
|
|
define float @returned_extractvalue([4 x float] nofpclass(nan) %array) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan) float @returned_extractvalue
|
|
; CHECK-SAME: ([4 x float] nofpclass(nan) [[ARRAY:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractvalue [4 x float] [[ARRAY]], 0
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%extract = extractvalue [4 x float] %array, 0
|
|
ret float %extract
|
|
}
|
|
|
|
define float @return_nofpclass_freeze_nan_arg(float nofpclass(nan) %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define noundef float @return_nofpclass_freeze_nan_arg
|
|
; CHECK-SAME: (float nofpclass(nan) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FREEZE:%.*]] = freeze float [[ARG]]
|
|
; CHECK-NEXT: ret float [[FREEZE]]
|
|
;
|
|
%freeze = freeze float %arg
|
|
ret float %freeze
|
|
}
|
|
|
|
define float @return_nofpclass_extractelement_freeze_pinf_arg(<2 x float> nofpclass(pinf) %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define noundef float @return_nofpclass_extractelement_freeze_pinf_arg
|
|
; CHECK-SAME: (<2 x float> nofpclass(pinf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FREEZE:%.*]] = freeze <2 x float> [[ARG]]
|
|
; CHECK-NEXT: [[ELT:%.*]] = extractelement <2 x float> [[FREEZE]], i32 0
|
|
; CHECK-NEXT: ret float [[ELT]]
|
|
;
|
|
%freeze = freeze <2 x float> %arg
|
|
%elt = extractelement <2 x float> %freeze, i32 0
|
|
ret float %elt
|
|
}
|
|
|
|
define <4 x float> @insertelement_constant_chain() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero sub) <4 x float> @insertelement_constant_chain
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INS_0:%.*]] = insertelement <4 x float> poison, float 1.000000e+00, i32 0
|
|
; CHECK-NEXT: [[INS_1:%.*]] = insertelement <4 x float> [[INS_0]], float 0.000000e+00, i32 1
|
|
; CHECK-NEXT: [[INS_2:%.*]] = insertelement <4 x float> [[INS_1]], float -9.000000e+00, i32 2
|
|
; CHECK-NEXT: [[INS_3:%.*]] = insertelement <4 x float> [[INS_2]], float 0x7FF0000000000000, i32 3
|
|
; CHECK-NEXT: ret <4 x float> [[INS_3]]
|
|
;
|
|
%ins.0 = insertelement <4 x float> poison, float 1.0, i32 0
|
|
%ins.1 = insertelement <4 x float> %ins.0, float 0.0, i32 1
|
|
%ins.2 = insertelement <4 x float> %ins.1, float -9.0, i32 2
|
|
%ins.3 = insertelement <4 x float> %ins.2, float 0x7FF0000000000000, i32 3
|
|
ret <4 x float> %ins.3
|
|
}
|
|
|
|
define <4 x float> @insertelement_non_constant_chain(i32 %idx) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero sub) <4 x float> @insertelement_non_constant_chain
|
|
; CHECK-SAME: (i32 [[IDX:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INS_0:%.*]] = insertelement <4 x float> poison, float 1.000000e+00, i32 0
|
|
; CHECK-NEXT: [[INS_1:%.*]] = insertelement <4 x float> [[INS_0]], float 0.000000e+00, i32 1
|
|
; CHECK-NEXT: [[INS_2:%.*]] = insertelement <4 x float> [[INS_1]], float -9.000000e+00, i32 2
|
|
; CHECK-NEXT: [[INS_3:%.*]] = insertelement <4 x float> [[INS_2]], float 3.000000e+00, i32 3
|
|
; CHECK-NEXT: [[INS_4:%.*]] = insertelement <4 x float> [[INS_2]], float 4.000000e+00, i32 [[IDX]]
|
|
; CHECK-NEXT: ret <4 x float> [[INS_4]]
|
|
;
|
|
%ins.0 = insertelement <4 x float> poison, float 1.0, i32 0
|
|
%ins.1 = insertelement <4 x float> %ins.0, float 0.0, i32 1
|
|
%ins.2 = insertelement <4 x float> %ins.1, float -9.0, i32 2
|
|
%ins.3 = insertelement <4 x float> %ins.2, float 3.0, i32 3
|
|
%ins.4 = insertelement <4 x float> %ins.2, float 4.0, i32 %idx
|
|
ret <4 x float> %ins.4
|
|
}
|
|
|
|
define <vscale x 4 x float> @insertelement_scalable_constant_chain() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <vscale x 4 x float> @insertelement_scalable_constant_chain
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INS_0:%.*]] = insertelement <vscale x 4 x float> poison, float 1.000000e+00, i32 0
|
|
; CHECK-NEXT: [[INS_1:%.*]] = insertelement <vscale x 4 x float> [[INS_0]], float 0.000000e+00, i32 1
|
|
; CHECK-NEXT: [[INS_2:%.*]] = insertelement <vscale x 4 x float> [[INS_1]], float -9.000000e+00, i32 2
|
|
; CHECK-NEXT: [[INS_3:%.*]] = insertelement <vscale x 4 x float> [[INS_2]], float 0x7FF0000000000000, i32 3
|
|
; CHECK-NEXT: ret <vscale x 4 x float> [[INS_3]]
|
|
;
|
|
%ins.0 = insertelement <vscale x 4 x float> poison, float 1.0, i32 0
|
|
%ins.1 = insertelement <vscale x 4 x float> %ins.0, float 0.0, i32 1
|
|
%ins.2 = insertelement <vscale x 4 x float> %ins.1, float -9.0, i32 2
|
|
%ins.3 = insertelement <vscale x 4 x float> %ins.2, float 0x7FF0000000000000, i32 3
|
|
ret <vscale x 4 x float> %ins.3
|
|
}
|
|
|
|
define <4 x float> @insertelement_unknown_base(<4 x float> %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <4 x float> @insertelement_unknown_base
|
|
; CHECK-SAME: (<4 x float> [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
|
|
; CHECK-NEXT: ret <4 x float> [[INSERT]]
|
|
;
|
|
%insert = insertelement <4 x float> %arg0, float 0.0, i32 1
|
|
ret <4 x float> %insert
|
|
}
|
|
|
|
define float @insertelement_extractelement_same(<4 x float> %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) float @insertelement_extractelement_same
|
|
; CHECK-SAME: (<4 x float> [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 1
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%insert = insertelement <4 x float> %arg0, float 0.0, i32 1
|
|
%extract = extractelement <4 x float> %insert, i32 1
|
|
ret float %extract
|
|
}
|
|
|
|
define float @insertelement_extractelement_different(<4 x float> nofpclass(zero) %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(zero) float @insertelement_extractelement_different
|
|
; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 2
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%insert = insertelement <4 x float> %arg0, float 0.0, i32 1
|
|
%extract = extractelement <4 x float> %insert, i32 2
|
|
ret float %extract
|
|
}
|
|
|
|
define float @insertelement_extractelement_unknown(<4 x float> nofpclass(zero) %arg0, i32 %idx) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @insertelement_extractelement_unknown
|
|
; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]], i32 [[IDX:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 [[IDX]]
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%insert = insertelement <4 x float> %arg0, float 0.0, i32 1
|
|
%extract = extractelement <4 x float> %insert, i32 %idx
|
|
ret float %extract
|
|
}
|
|
|
|
define <4 x float> @insertelement_index_oob_chain() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero sub norm) <4 x float> @insertelement_index_oob_chain
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> zeroinitializer, float 0x7FF0000000000000, i32 4
|
|
; CHECK-NEXT: ret <4 x float> [[INSERT]]
|
|
;
|
|
%insert = insertelement <4 x float> zeroinitializer, float 0x7FF0000000000000, i32 4
|
|
ret <4 x float> %insert
|
|
}
|
|
|
|
define <2 x float> @multiple_extractelement(<4 x float> nofpclass(zero) %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(zero) <2 x float> @multiple_extractelement
|
|
; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1
|
|
; CHECK-NEXT: [[EXTRACT2:%.*]] = extractelement <4 x float> [[INSERT]], i32 2
|
|
; CHECK-NEXT: [[EXTRACT3:%.*]] = extractelement <4 x float> [[INSERT]], i32 3
|
|
; CHECK-NEXT: [[INS_0:%.*]] = insertelement <2 x float> poison, float [[EXTRACT3]], i32 0
|
|
; CHECK-NEXT: [[INS_1:%.*]] = insertelement <2 x float> [[INS_0]], float [[EXTRACT2]], i32 1
|
|
; CHECK-NEXT: ret <2 x float> [[INS_1]]
|
|
;
|
|
%insert = insertelement <4 x float> %arg0, float 0.0, i32 1
|
|
%extract2 = extractelement <4 x float> %insert, i32 2
|
|
%extract3 = extractelement <4 x float> %insert, i32 3
|
|
%ins.0 = insertelement <2 x float> poison, float %extract3, i32 0
|
|
%ins.1 = insertelement <2 x float> %ins.0, float %extract2, i32 1
|
|
ret <2 x float> %ins.1
|
|
}
|
|
|
|
; FIXME: Doesn't actually reach computeKnownFPClass
|
|
define <4 x float> @shufflevector_constexpr() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <4 x float> @shufflevector_constexpr
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: ret <4 x float> <float 1.000000e+00, float bitcast (i32 ptrtoint (ptr @shufflevector_constexpr to i32) to float), float 4.000000e+00, float 0.000000e+00>
|
|
;
|
|
ret <4 x float> shufflevector (<2 x float> <float 1.0, float bitcast (i32 ptrtoint (ptr @shufflevector_constexpr to i32) to float)>, <2 x float> <float 4.0, float 0.0>, <4 x i32> <i32 0, i32 1, i32 2, i32 3>)
|
|
}
|
|
|
|
define <4 x float> @shufflevector_concat_disjoint(<2 x float> nofpclass(nan) %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <4 x float> @shufflevector_concat_disjoint
|
|
; CHECK-SAME: (<2 x float> nofpclass(nan) [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define <4 x float> @shufflevector_concat_overlap(<2 x float> nofpclass(nan norm psub) %arg0, <2 x float> nofpclass(inf nan sub) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan psub) <4 x float> @shufflevector_concat_overlap
|
|
; CHECK-SAME: (<2 x float> nofpclass(nan psub norm) [[ARG0:%.*]], <2 x float> nofpclass(nan inf sub) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define <4 x float> @shufflevector_unknown_lhs(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <4 x float> @shufflevector_unknown_lhs
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define <4 x float> @shufflevector_unknown_rhs(<2 x float> nofpclass(inf) %arg0, <2 x float> %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <4 x float> @shufflevector_unknown_rhs
|
|
; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x float> [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define <4 x float> @shufflevector_unknown_all(<2 x float> %arg0, <2 x float> %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <4 x float> @shufflevector_unknown_all
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define <4 x float> @shufflevector_only_demand_lhs(<2 x float> nofpclass(inf) %arg0, <2 x float> %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(inf) <4 x float> @shufflevector_only_demand_lhs
|
|
; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x float> [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 0, i32 1, i32 1, i32 0>
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 0, i32 1, i32 1, i32 0>
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define <4 x float> @shufflevector_only_demand_rhs(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(inf) <4 x float> @shufflevector_only_demand_rhs
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 2, i32 3, i32 3, i32 2>
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 2, i32 3, i32 3, i32 2>
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define <4 x float> @shufflevector_undef_demanded(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <4 x float> @shufflevector_undef_demanded
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> poison
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> undef
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define <4 x float> @shufflevector_zeroinit_demanded(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <4 x float> @shufflevector_zeroinit_demanded
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> zeroinitializer
|
|
; CHECK-NEXT: ret <4 x float> [[SHUFFLE]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> zeroinitializer
|
|
ret <4 x float> %shuffle
|
|
}
|
|
|
|
define float @shufflevector_extractelt0(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @shufflevector_extractelt0
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 1, i32 3, i32 0, i32 1>
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 0
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 1, i32 3, i32 0, i32 1>
|
|
%extract = extractelement <4 x float> %shuffle, i32 0
|
|
ret float %extract
|
|
}
|
|
|
|
define float @shufflevector_extractelt1(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(inf) float @shufflevector_extractelt1
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 1, i32 3, i32 0, i32 1>
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 1
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 1, i32 3, i32 0, i32 1>
|
|
%extract = extractelement <4 x float> %shuffle, i32 1
|
|
ret float %extract
|
|
}
|
|
|
|
define float @shufflevector_extractelt2(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @shufflevector_extractelt2
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 1, i32 3, i32 0, i32 1>
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 2
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 1, i32 3, i32 0, i32 1>
|
|
%extract = extractelement <4 x float> %shuffle, i32 2
|
|
ret float %extract
|
|
}
|
|
|
|
define float @shufflevector_extractelt3(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @shufflevector_extractelt3
|
|
; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> <i32 1, i32 3, i32 0, i32 1>
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 3
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> <i32 1, i32 3, i32 0, i32 1>
|
|
%extract = extractelement <4 x float> %shuffle, i32 3
|
|
ret float %extract
|
|
}
|
|
|
|
define float @shufflevector_constantdatavector_demanded0() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @shufflevector_constantdatavector_demanded0
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <3 x float> <float 1.000000e+00, float 0x7FF8000000000000, float 0.000000e+00>, <3 x float> poison, <2 x i32> <i32 0, i32 2>
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <2 x float> [[SHUFFLE]], i32 0
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%shuffle = shufflevector <3 x float> <float 1.0, float 0x7FF8000000000000, float 0.0>, <3 x float> poison, <2 x i32> <i32 0, i32 2>
|
|
%extract = extractelement <2 x float> %shuffle, i32 0
|
|
ret float %extract
|
|
}
|
|
|
|
define float @shufflevector_constantdatavector_demanded1() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) float @shufflevector_constantdatavector_demanded1
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <3 x float> <float 1.000000e+00, float 0x7FF8000000000000, float 0.000000e+00>, <3 x float> poison, <2 x i32> <i32 0, i32 2>
|
|
; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <2 x float> [[SHUFFLE]], i32 1
|
|
; CHECK-NEXT: ret float [[EXTRACT]]
|
|
;
|
|
%shuffle = shufflevector <3 x float> <float 1.0, float 0x7FF8000000000000, float 0.0>, <3 x float> poison, <2 x i32> <i32 0, i32 2>
|
|
%extract = extractelement <2 x float> %shuffle, i32 1
|
|
ret float %extract
|
|
}
|
|
|
|
define i32 @fptosi(float nofpclass(inf nan) %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define i32 @fptosi
|
|
; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[FPTOSI:%.*]] = fptosi float [[ARG]] to i32
|
|
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[FPTOSI]], 1
|
|
; CHECK-NEXT: ret i32 [[ADD]]
|
|
;
|
|
%fptosi = fptosi float %arg to i32
|
|
%add = add i32 %fptosi, 1
|
|
ret i32 %add
|
|
}
|
|
|
|
define float @fptrunc(double nofpclass(inf nan) %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fptrunc
|
|
; CHECK-SAME: (double nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CAST:%.*]] = fptrunc double [[ARG]] to float
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[CAST]], [[CAST]]
|
|
; CHECK-NEXT: ret float [[MUL]]
|
|
;
|
|
%cast = fptrunc double %arg to float
|
|
%mul = fmul float %cast, %cast
|
|
ret float %mul
|
|
}
|
|
|
|
define double @fpext(float nofpclass(inf nan) %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) double @fpext
|
|
; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[CAST:%.*]] = fpext float [[ARG]] to double
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul double [[CAST]], [[CAST]]
|
|
; CHECK-NEXT: ret double [[MUL]]
|
|
;
|
|
%cast = fpext float %arg to double
|
|
%mul = fmul double %cast, %cast
|
|
ret double %mul
|
|
}
|
|
|
|
define float @atomicrmw_fadd(ptr %ptr, float nofpclass(inf nan) %val) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
|
|
; CHECK-LABEL: define float @atomicrmw_fadd
|
|
; CHECK-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[PTR:%.*]], float nofpclass(nan inf) [[VAL:%.*]]) #[[ATTR6:[0-9]+]] {
|
|
; CHECK-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr [[PTR]], float [[VAL]] seq_cst, align 4
|
|
; CHECK-NEXT: ret float [[RESULT]]
|
|
;
|
|
%result = atomicrmw fadd ptr %ptr, float %val seq_cst
|
|
ret float %result
|
|
}
|
|
|
|
define float @load(ptr %ptr, float nofpclass(nan inf) %val) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @load
|
|
; CHECK-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[PTR:%.*]], float nofpclass(nan inf) [[VAL:%.*]]) #[[ATTR7:[0-9]+]] {
|
|
; CHECK-NEXT: store float [[VAL]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR]], align 4
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[LOAD]], [[LOAD]]
|
|
; CHECK-NEXT: ret float [[MUL]]
|
|
;
|
|
store float %val, ptr %ptr
|
|
%load = load float, ptr %ptr
|
|
%mul = fmul float %load, %load
|
|
ret float %mul
|
|
}
|
|
|
|
define float @load_atomic(ptr %ptr, float nofpclass(nan inf) %val) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @load_atomic
|
|
; CHECK-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[PTR:%.*]], float nofpclass(nan inf) [[VAL:%.*]]) #[[ATTR6]] {
|
|
; CHECK-NEXT: store atomic float [[VAL]], ptr [[PTR]] seq_cst, align 4
|
|
; CHECK-NEXT: [[LOAD:%.*]] = load atomic float, ptr [[PTR]] seq_cst, align 4
|
|
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[LOAD]], [[LOAD]]
|
|
; CHECK-NEXT: ret float [[MUL]]
|
|
;
|
|
store atomic float %val, ptr %ptr seq_cst, align 4
|
|
%load = load atomic float, ptr %ptr seq_cst, align 4
|
|
%mul = fmul float %load, %load
|
|
ret float %mul
|
|
}
|
|
|
|
define <8 x float> @shufflevector_shufflevector(<4 x float> nofpclass(inf nan) %arg0, <4 x float> nofpclass(inf nan zero) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf) <8 x float> @shufflevector_shufflevector
|
|
; CHECK-SAME: (<4 x float> nofpclass(nan inf) [[ARG0:%.*]], <4 x float> nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHUFFLE0:%.*]] = shufflevector <4 x float> [[ARG0]], <4 x float> [[ARG0]], <4 x i32> <i32 3, i32 2, i32 1, i32 0>
|
|
; CHECK-NEXT: [[SHUFFLE1:%.*]] = shufflevector <4 x float> [[ARG1]], <4 x float> [[ARG1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
|
; CHECK-NEXT: [[SHUFFLE2:%.*]] = shufflevector <4 x float> [[SHUFFLE0]], <4 x float> [[SHUFFLE1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
|
|
; CHECK-NEXT: ret <8 x float> [[SHUFFLE2]]
|
|
;
|
|
%shuffle0 = shufflevector <4 x float> %arg0, <4 x float> %arg0, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
|
|
%shuffle1 = shufflevector <4 x float> %arg1, <4 x float> %arg1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
|
%shuffle2 = shufflevector <4 x float> %shuffle0, <4 x float> %shuffle1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
|
|
ret <8 x float> %shuffle2
|
|
}
|
|
|
|
define float @constrained_sitofp(i32 %arg) strictfp {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind strictfp willreturn memory(inaccessiblemem: readwrite)
|
|
; CHECK-LABEL: define nofpclass(nan nzero sub) float @constrained_sitofp
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR8:[0-9]+]] {
|
|
; CHECK-NEXT: [[VAL:%.*]] = call nofpclass(nan nzero sub) float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[ARG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR20]]
|
|
; CHECK-NEXT: ret float [[VAL]]
|
|
;
|
|
%val = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %arg, metadata !"round.dynamic", metadata !"fpexcept.strict")
|
|
ret float %val
|
|
}
|
|
|
|
define float @constrained_uitofp(i32 %arg) strictfp {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind strictfp willreturn memory(inaccessiblemem: readwrite)
|
|
; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @constrained_uitofp
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR8]] {
|
|
; CHECK-NEXT: [[VAL:%.*]] = call nofpclass(nan ninf nzero sub nnorm) float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[ARG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR20]]
|
|
; CHECK-NEXT: ret float [[VAL]]
|
|
;
|
|
%val = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %arg, metadata !"round.dynamic", metadata !"fpexcept.strict")
|
|
ret float %val
|
|
}
|
|
|
|
define float @fadd_p0(float %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, 0.0
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_n0(float %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fadd_n0
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, -0.0
|
|
ret float %add
|
|
}
|
|
|
|
define float @fsub_p0(float %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fsub_p0
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float %arg0, 0.0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_n0(float %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fsub_n0
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float %arg0, -0.0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_p0_commute(float %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fsub_p0_commute
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]]
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float 0.0, %arg0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_n0_commute(float %arg0) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fsub_n0_commute
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]]
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float -0.0, %arg0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fadd_p0_ftz_daz(float %arg0) #3 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_ftz_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR9:[0-9]+]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, 0.0
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_n0_ftz_daz(float %arg0) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fadd_n0_ftz_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10:[0-9]+]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, -0.0
|
|
ret float %add
|
|
}
|
|
|
|
define float @fsub_p0_ftz_daz(float %arg0) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fsub_p0_ftz_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float %arg0, 0.0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_n0_ftz_daz(float %arg0) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fsub_n0_ftz_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float %arg0, -0.0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_p0_commute_ftz_daz(float %arg0) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fsub_p0_commute_ftz_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]]
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float 0.0, %arg0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_n0_commute_ftz_daz(float %arg0) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fsub_n0_commute_ftz_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]]
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float -0.0, %arg0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fadd_p0_ieee_daz(float %arg0) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_ieee_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR11:[0-9]+]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, 0.0
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_p0_dapz_ieee(float %arg0) #4 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_dapz_ieee
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR12:[0-9]+]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, 0.0
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_n0_ieee_daz(float %arg0) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fadd_n0_ieee_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR11]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, -0.0
|
|
ret float %add
|
|
}
|
|
|
|
define float @fsub_p0_ieee_daz(float %arg0) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fsub_p0_ieee_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR11]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float %arg0, 0.0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_n0_ieee_daz(float %arg0) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fsub_n0_ieee_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR11]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float %arg0, -0.0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_p0_commute_ieee_daz(float %arg0) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fsub_p0_commute_ieee_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR11]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]]
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float 0.0, %arg0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fsub_n0_commute_ieee_daz(float %arg0) #1 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fsub_n0_commute_ieee_daz
|
|
; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR13:[0-9]+]] {
|
|
; CHECK-NEXT: [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]]
|
|
; CHECK-NEXT: ret float [[SUB]]
|
|
;
|
|
%sub = fsub float -0.0, %arg0
|
|
ret float %sub
|
|
}
|
|
|
|
define float @fadd_never_negzero_or_negsub(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub
|
|
; CHECK-SAME: (float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %a, %b
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_never_negzero_or_negsub_daz(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub_daz
|
|
; CHECK-SAME: (float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR11]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %a, %b
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_never_negzero_or_negsub_dapz(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) #5 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub_dapz
|
|
; CHECK-SAME: (float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR14:[0-9]+]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %a, %b
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_never_negzero_or_possub(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_possub
|
|
; CHECK-SAME: (float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %a, %b
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_never_negzero_or_possub_daz(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fadd_never_negzero_or_possub_daz
|
|
; CHECK-SAME: (float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR11]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %a, %b
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_never_negzero_or_possub_dapz(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) #5 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_possub_dapz
|
|
; CHECK-SAME: (float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR14]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %a, %b
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_never_negzero_or_sub_daz(float nofpclass(nzero sub) %a, float nofpclass(nzero sub) %b) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_sub_daz
|
|
; CHECK-SAME: (float nofpclass(nzero sub) [[A:%.*]], float nofpclass(nzero sub) [[B:%.*]]) #[[ATTR11]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %a, %b
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_never_negzero_or_sub_dapz(float nofpclass(nzero sub) %a, float nofpclass(nzero sub) %b) #5 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_sub_dapz
|
|
; CHECK-SAME: (float nofpclass(nzero sub) [[A:%.*]], float nofpclass(nzero sub) [[B:%.*]]) #[[ATTR14]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %a, %b
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_lhs(float nofpclass(ninf nsub nnorm) %arg0, float %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fadd_known_positive_lhs
|
|
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_rhs(float %arg0, float nofpclass(ninf nsub nnorm) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fadd_known_positive_rhs
|
|
; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive
|
|
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_daz(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_daz
|
|
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR10]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_nzero_lhs(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_lhs
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_nzero_rhs(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_rhs
|
|
; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_nzero(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_nzero_ftz_daz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_nzero_ftz_daz
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR10]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_nzero_ftz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #1 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_nzero_ftz
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR13]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_nzero_daz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #2 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_daz
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR11]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_normal(float nofpclass(ninf nnorm nzero) %arg0, float nofpclass(ninf nnorm nzero) %arg1) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_known_positive_normal
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nnorm) [[ARG1:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_normal_daz(float nofpclass(ninf nnorm nzero) %arg0, float nofpclass(ninf nnorm nzero) %arg1) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fadd_known_positive_normal_daz
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nnorm) [[ARG1:%.*]]) #[[ATTR10]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_normal_except0_daz(float nofpclass(ninf nnorm) %arg0, float nofpclass(ninf nnorm) %arg1) #0 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define float @fadd_known_positive_normal_except0_daz
|
|
; CHECK-SAME: (float nofpclass(ninf nnorm) [[ARG0:%.*]], float nofpclass(ninf nnorm) [[ARG1:%.*]]) #[[ATTR10]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define float @fadd_known_positive_normal_dapz(float nofpclass(ninf nnorm nzero) %arg0, float nofpclass(ninf nnorm nzero) %arg1) #3 {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nzero) float @fadd_known_positive_normal_dapz
|
|
; CHECK-SAME: (float nofpclass(ninf nzero nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nnorm) [[ARG1:%.*]]) #[[ATTR9]] {
|
|
; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
|
|
; CHECK-NEXT: ret float [[ADD]]
|
|
;
|
|
%add = fadd float %arg0, %arg1
|
|
ret float %add
|
|
}
|
|
|
|
define internal float @returns_fence(float %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define internal float @returns_fence
|
|
; TUNIT-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[RET:%.*]] = call float @llvm.arithmetic.fence.f32(float nofpclass(inf) [[ARG]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[RET]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define internal float @returns_fence
|
|
; CGSCC-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[RET:%.*]] = call float @llvm.arithmetic.fence.f32(float nofpclass(nan inf) [[ARG]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[RET]]
|
|
;
|
|
%ret = call float @llvm.arithmetic.fence.f32(float %arg)
|
|
ret float %ret
|
|
}
|
|
|
|
; Check that the func0 callsite is marked with both no inf and no nan
|
|
define internal float @refine_callsite_attribute(float nofpclass(inf) %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define internal float @refine_callsite_attribute
|
|
; TUNIT-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FUNC0:%.*]] = call float @returns_fence(float nofpclass(nan inf) [[ARG]]) #[[ATTR19]]
|
|
; TUNIT-NEXT: [[RET:%.*]] = call float @llvm.arithmetic.fence.f32(float [[FUNC0]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[RET]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define internal float @refine_callsite_attribute
|
|
; CGSCC-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[FUNC0:%.*]] = call float @returns_fence(float nofpclass(nan inf) [[ARG]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: [[RET:%.*]] = call float @llvm.arithmetic.fence.f32(float [[FUNC0]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[RET]]
|
|
;
|
|
%func0 = call float @returns_fence(float nofpclass(nan) %arg)
|
|
%ret = call float @llvm.arithmetic.fence.f32(float %func0)
|
|
ret float %ret
|
|
}
|
|
|
|
define float @user(float %arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define float @user
|
|
; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[FUNC1:%.*]] = call float @refine_callsite_attribute(float nofpclass(inf) [[ARG]]) #[[ATTR19]]
|
|
; TUNIT-NEXT: ret float [[FUNC1]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define float @user
|
|
; CGSCC-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[FUNC1:%.*]] = call float @refine_callsite_attribute(float nofpclass(nan inf) [[ARG]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[FUNC1]]
|
|
;
|
|
%func1 = call float @refine_callsite_attribute(float %arg)
|
|
ret float %func1
|
|
}
|
|
|
|
; value is passed through memory
|
|
define internal float @through_memory0(ptr %ptr.arg) {
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define internal float @through_memory0
|
|
; CGSCC-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[PTR_ARG_PRIV:%.*]] = alloca float, align 4
|
|
; CGSCC-NEXT: store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
|
|
; CGSCC-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4
|
|
; CGSCC-NEXT: ret float [[LOAD]]
|
|
;
|
|
%load = load float, ptr %ptr.arg
|
|
ret float %load
|
|
}
|
|
|
|
; value is passed through memory and goes through an inferrable FP user
|
|
define internal float @through_memory1(ptr %ptr.arg) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define internal float @through_memory1
|
|
; TUNIT-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[PTR_ARG_PRIV:%.*]] = alloca float, align 4
|
|
; TUNIT-NEXT: store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
|
|
; TUNIT-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4
|
|
; TUNIT-NEXT: [[CALL:%.*]] = call float @llvm.arithmetic.fence.f32(float [[LOAD]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret float [[CALL]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define internal float @through_memory1
|
|
; CGSCC-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: [[PTR_ARG_PRIV:%.*]] = alloca float, align 4
|
|
; CGSCC-NEXT: store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
|
|
; CGSCC-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call float @llvm.arithmetic.fence.f32(float [[LOAD]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[CALL]]
|
|
;
|
|
%load = load float, ptr %ptr.arg
|
|
%call = call float @llvm.arithmetic.fence.f32(float %load)
|
|
ret float %call
|
|
}
|
|
|
|
; value is passed through memory and goes through an uninferrable FP user
|
|
define internal float @through_memory2(ptr %ptr.arg) {
|
|
; CHECK: Function Attrs: memory(readwrite, argmem: none)
|
|
; CHECK-LABEL: define internal float @through_memory2
|
|
; CHECK-SAME: (float [[TMP0:%.*]]) #[[ATTR15:[0-9]+]] {
|
|
; CHECK-NEXT: [[PTR_ARG_PRIV:%.*]] = alloca float, align 4
|
|
; CHECK-NEXT: store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4
|
|
; CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4
|
|
; CHECK-NEXT: [[CALL:%.*]] = call float @extern.f32(float [[LOAD]])
|
|
; CHECK-NEXT: ret float [[CALL]]
|
|
;
|
|
%load = load float, ptr %ptr.arg
|
|
%call = call float @extern.f32(float %load)
|
|
ret float %call
|
|
}
|
|
|
|
define float @call_through_memory0(float nofpclass(nan) %val) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define nofpclass(nan) float @call_through_memory0
|
|
; TUNIT-SAME: (float returned nofpclass(nan) [[VAL:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4
|
|
; TUNIT-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4
|
|
; TUNIT-NEXT: ret float [[VAL]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define float @call_through_memory0
|
|
; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4
|
|
; CGSCC-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4
|
|
; CGSCC-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory0(float nofpclass(nan) [[VAL]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[THROUGH_MEMORY]]
|
|
;
|
|
%alloca = alloca float
|
|
store float %val, ptr %alloca
|
|
%through_memory = call float @through_memory0(ptr %alloca)
|
|
ret float %through_memory
|
|
}
|
|
|
|
define float @call_through_memory1(float nofpclass(nan) %val) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define float @call_through_memory1
|
|
; TUNIT-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4
|
|
; TUNIT-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4
|
|
; TUNIT-NEXT: [[TMP1:%.*]] = load float, ptr [[ALLOCA]], align 4
|
|
; TUNIT-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory1(float [[TMP1]]) #[[ATTR21]]
|
|
; TUNIT-NEXT: ret float [[THROUGH_MEMORY]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define float @call_through_memory1
|
|
; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR4]] {
|
|
; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4
|
|
; CGSCC-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4
|
|
; CGSCC-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory1(float nofpclass(nan) [[VAL]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret float [[THROUGH_MEMORY]]
|
|
;
|
|
%alloca = alloca float
|
|
store float %val, ptr %alloca
|
|
%through_memory = call float @through_memory1(ptr %alloca)
|
|
ret float %through_memory
|
|
}
|
|
|
|
define float @call_through_memory2(float nofpclass(nan) %val) {
|
|
; TUNIT-LABEL: define float @call_through_memory2
|
|
; TUNIT-SAME: (float nofpclass(nan) [[VAL:%.*]]) {
|
|
; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4
|
|
; TUNIT-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4
|
|
; TUNIT-NEXT: [[TMP1:%.*]] = load float, ptr [[ALLOCA]], align 4
|
|
; TUNIT-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory2(float [[TMP1]])
|
|
; TUNIT-NEXT: ret float [[THROUGH_MEMORY]]
|
|
;
|
|
; CGSCC-LABEL: define float @call_through_memory2
|
|
; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) {
|
|
; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4
|
|
; CGSCC-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4
|
|
; CGSCC-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory2(float nofpclass(nan) [[VAL]])
|
|
; CGSCC-NEXT: ret float [[THROUGH_MEMORY]]
|
|
;
|
|
%alloca = alloca float
|
|
store float %val, ptr %alloca
|
|
%through_memory = call float @through_memory2(ptr %alloca)
|
|
ret float %through_memory
|
|
}
|
|
|
|
define amdgpu_kernel void @fast_pow_kernel(ptr addrspace(1) nocapture noundef writeonly align 4 %out, ptr addrspace(1) nocapture noundef readonly align 4 %in1, ptr addrspace(1) nocapture noundef readonly align 4 %in2) {
|
|
; CHECK-LABEL: define amdgpu_kernel void @fast_pow_kernel
|
|
; CHECK-SAME: (ptr addrspace(1) nocapture nofree noundef writeonly align 4 [[OUT:%.*]], ptr addrspace(1) nocapture nofree noundef readonly align 4 [[IN1:%.*]], ptr addrspace(1) nocapture nofree noundef readonly align 4 [[IN2:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call i64 @_Z13get_global_idj(i32 noundef 0)
|
|
; CHECK-NEXT: [[SEXT:%.*]] = shl i64 [[CALL]], 32
|
|
; CHECK-NEXT: [[IDXPROM:%.*]] = ashr exact i64 [[SEXT]], 32
|
|
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN1]], i64 [[IDXPROM]]
|
|
; CHECK-NEXT: [[I:%.*]] = load float, ptr addrspace(1) [[ARRAYIDX]], align 4
|
|
; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN2]], i64 [[IDXPROM]]
|
|
; CHECK-NEXT: [[I1:%.*]] = load float, ptr addrspace(1) [[ARRAYIDX2]], align 4
|
|
; CHECK-NEXT: [[CALL3:%.*]] = tail call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) float @pow_wrapper(float noundef nofpclass(nan inf) [[I]], float noundef nofpclass(nan inf) [[I1]])
|
|
; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 [[IDXPROM]]
|
|
; CHECK-NEXT: store float [[CALL3]], ptr addrspace(1) [[ARRAYIDX5]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%call = tail call i64 @_Z13get_global_idj(i32 noundef 0)
|
|
%sext = shl i64 %call, 32
|
|
%idxprom = ashr exact i64 %sext, 32
|
|
%arrayidx = getelementptr inbounds float, ptr addrspace(1) %in1, i64 %idxprom
|
|
%i = load float, ptr addrspace(1) %arrayidx, align 4
|
|
%arrayidx2 = getelementptr inbounds float, ptr addrspace(1) %in2, i64 %idxprom
|
|
%i1 = load float, ptr addrspace(1) %arrayidx2, align 4
|
|
%call3 = tail call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) float @pow_wrapper(float noundef nofpclass(nan inf) %i, float noundef nofpclass(nan inf) %i1)
|
|
%arrayidx5 = getelementptr inbounds float, ptr addrspace(1) %out, i64 %idxprom
|
|
store float %call3, ptr addrspace(1) %arrayidx5, align 4
|
|
ret void
|
|
}
|
|
|
|
define internal float @pow_wrapper(float %arg, float %arg1) {
|
|
; TUNIT: Function Attrs: norecurse
|
|
; TUNIT-LABEL: define internal float @pow_wrapper
|
|
; TUNIT-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]], float noundef nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR16:[0-9]+]] {
|
|
; TUNIT-NEXT: bb:
|
|
; TUNIT-NEXT: [[I:%.*]] = tail call float @pow_impl(float noundef nofpclass(nan inf) [[ARG]], float noundef nofpclass(nan inf) [[ARG1]])
|
|
; TUNIT-NEXT: ret float [[I]]
|
|
;
|
|
; CGSCC-LABEL: define internal float @pow_wrapper
|
|
; CGSCC-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]], float noundef nofpclass(nan inf) [[ARG1:%.*]]) {
|
|
; CGSCC-NEXT: bb:
|
|
; CGSCC-NEXT: [[I:%.*]] = tail call float @pow_impl(float noundef nofpclass(nan inf) [[ARG]], float noundef nofpclass(nan inf) [[ARG1]])
|
|
; CGSCC-NEXT: ret float [[I]]
|
|
;
|
|
bb:
|
|
%i = tail call float @pow_impl(float %arg, float %arg1)
|
|
ret float %i
|
|
}
|
|
|
|
; nofpclass(nan inf) should reach here through pow_wrapper
|
|
define internal float @pow_impl(float %arg, float %arg1) {
|
|
; TUNIT: Function Attrs: norecurse
|
|
; TUNIT-LABEL: define internal float @pow_impl
|
|
; TUNIT-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]], float noundef nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR16]] {
|
|
; TUNIT-NEXT: bb:
|
|
; TUNIT-NEXT: [[IMPLEMENT_POW:%.*]] = call float asm "
|
|
; TUNIT-NEXT: ret float [[IMPLEMENT_POW]]
|
|
;
|
|
; CGSCC: Function Attrs: norecurse
|
|
; CGSCC-LABEL: define internal float @pow_impl
|
|
; CGSCC-SAME: (float [[ARG:%.*]], float [[ARG1:%.*]]) #[[ATTR16:[0-9]+]] {
|
|
; CGSCC-NEXT: bb:
|
|
; CGSCC-NEXT: [[IMPLEMENT_POW:%.*]] = call float asm "
|
|
; CGSCC-NEXT: ret float [[IMPLEMENT_POW]]
|
|
;
|
|
bb:
|
|
%implement.pow = call float asm " ; do pow $0, $1, $2", "=v,v,v"(float %arg, float %arg1)
|
|
ret float %implement.pow
|
|
}
|
|
|
|
define [4 x float] @constant_aggregate_zero() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) [4 x float] @constant_aggregate_zero
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: ret [4 x float] zeroinitializer
|
|
;
|
|
ret [4 x float] zeroinitializer
|
|
}
|
|
|
|
define <vscale x 4 x float> @scalable_splat_pnorm() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <vscale x 4 x float> @scalable_splat_pnorm
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: ret <vscale x 4 x float> shufflevector (<vscale x 4 x float> insertelement (<vscale x 4 x float> poison, float 1.000000e+00, i64 0), <vscale x 4 x float> poison, <vscale x 4 x i32> zeroinitializer)
|
|
;
|
|
ret <vscale x 4 x float> splat (float 1.0)
|
|
}
|
|
|
|
define <vscale x 4 x float> @scalable_splat_zero() {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define noundef nofpclass(nan inf nzero sub norm) <vscale x 4 x float> @scalable_splat_zero
|
|
; CHECK-SAME: () #[[ATTR3]] {
|
|
; CHECK-NEXT: ret <vscale x 4 x float> zeroinitializer
|
|
;
|
|
ret <vscale x 4 x float> zeroinitializer
|
|
}
|
|
|
|
; Verify we do not derive 'nofpclass(inf zero sub norm)' for the argument __x.
|
|
; See https://github.com/llvm/llvm-project/issues/78507
|
|
|
|
define double @call_abs(double noundef %__x) {
|
|
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; TUNIT-LABEL: define noundef nofpclass(ninf nzero nsub nnorm) double @call_abs
|
|
; TUNIT-SAME: (double noundef [[__X:%.*]]) #[[ATTR3]] {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: [[ABS:%.*]] = tail call noundef nofpclass(ninf nzero nsub nnorm) double @llvm.fabs.f64(double noundef [[__X]]) #[[ATTR22]]
|
|
; TUNIT-NEXT: ret double [[ABS]]
|
|
;
|
|
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CGSCC-LABEL: define noundef nofpclass(ninf nzero nsub nnorm) double @call_abs
|
|
; CGSCC-SAME: (double noundef [[__X:%.*]]) #[[ATTR3]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: [[ABS:%.*]] = tail call noundef nofpclass(ninf nzero nsub nnorm) double @llvm.fabs.f64(double noundef [[__X]]) #[[ATTR19]]
|
|
; CGSCC-NEXT: ret double [[ABS]]
|
|
;
|
|
entry:
|
|
%abs = tail call double @llvm.fabs.f64(double %__x)
|
|
ret double %abs
|
|
}
|
|
|
|
define float @bitcast_to_float_sign_0(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @bitcast_to_float_sign_0
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[ARG]], 1
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i32 [[SHR]] to float
|
|
; CHECK-NEXT: ret float [[CAST]]
|
|
;
|
|
%shr = lshr i32 %arg, 1
|
|
%cast = bitcast i32 %shr to float
|
|
ret float %cast
|
|
}
|
|
|
|
define float @bitcast_to_float_nnan(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @bitcast_to_float_nnan
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[ARG]], 2
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i32 [[SHR]] to float
|
|
; CHECK-NEXT: ret float [[CAST]]
|
|
;
|
|
%shr = lshr i32 %arg, 2
|
|
%cast = bitcast i32 %shr to float
|
|
ret float %cast
|
|
}
|
|
|
|
define float @bitcast_to_float_sign_1(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @bitcast_to_float_sign_1
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG]], -2147483648
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i32 [[OR]] to float
|
|
; CHECK-NEXT: ret float [[CAST]]
|
|
;
|
|
%or = or i32 %arg, -2147483648
|
|
%cast = bitcast i32 %or to float
|
|
ret float %cast
|
|
}
|
|
|
|
define float @bitcast_to_float_nan(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(inf zero sub norm) float @bitcast_to_float_nan
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG]], 2139095041
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i32 [[OR]] to float
|
|
; CHECK-NEXT: ret float [[CAST]]
|
|
;
|
|
%or = or i32 %arg, 2139095041
|
|
%cast = bitcast i32 %or to float
|
|
ret float %cast
|
|
}
|
|
|
|
define float @bitcast_to_float_zero(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf sub norm) float @bitcast_to_float_zero
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[ARG]], 31
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i32 [[SHL]] to float
|
|
; CHECK-NEXT: ret float [[CAST]]
|
|
;
|
|
%shl = shl i32 %arg, 31
|
|
%cast = bitcast i32 %shl to float
|
|
ret float %cast
|
|
}
|
|
|
|
define float @bitcast_to_float_nzero(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(zero) float @bitcast_to_float_nzero
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG]], 134217728
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i32 [[OR]] to float
|
|
; CHECK-NEXT: ret float [[CAST]]
|
|
;
|
|
%or = or i32 %arg, 134217728
|
|
%cast = bitcast i32 %or to float
|
|
ret float %cast
|
|
}
|
|
|
|
define float @bitcast_to_float_inf(i32 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan zero sub norm) float @bitcast_to_float_inf
|
|
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHR:%.*]] = shl i32 [[ARG]], 31
|
|
; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHR]], 2139095040
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i32 [[OR]] to float
|
|
; CHECK-NEXT: ret float [[CAST]]
|
|
;
|
|
%shr = shl i32 %arg, 31
|
|
%or = or i32 %shr, 2139095040
|
|
%cast = bitcast i32 %or to float
|
|
ret float %cast
|
|
}
|
|
|
|
define double @bitcast_to_double_sign_0(i64 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) double @bitcast_to_double_sign_0
|
|
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHR:%.*]] = lshr i64 [[ARG]], 1
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i64 [[SHR]] to double
|
|
; CHECK-NEXT: ret double [[CAST]]
|
|
;
|
|
%shr = lshr i64 %arg, 1
|
|
%cast = bitcast i64 %shr to double
|
|
ret double %cast
|
|
}
|
|
|
|
define double @bitcast_to_double_nnan(i64 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) double @bitcast_to_double_nnan
|
|
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHR:%.*]] = lshr i64 [[ARG]], 2
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i64 [[SHR]] to double
|
|
; CHECK-NEXT: ret double [[CAST]]
|
|
;
|
|
%shr = lshr i64 %arg, 2
|
|
%cast = bitcast i64 %shr to double
|
|
ret double %cast
|
|
}
|
|
|
|
define double @bitcast_to_double_sign_1(i64 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) double @bitcast_to_double_sign_1
|
|
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or i64 [[ARG]], -9223372036854775808
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i64 [[OR]] to double
|
|
; CHECK-NEXT: ret double [[CAST]]
|
|
;
|
|
%or = or i64 %arg, -9223372036854775808
|
|
%cast = bitcast i64 %or to double
|
|
ret double %cast
|
|
}
|
|
|
|
define double @bitcast_to_double_nan(i64 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(inf zero sub norm) double @bitcast_to_double_nan
|
|
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or i64 [[ARG]], -4503599627370495
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i64 [[OR]] to double
|
|
; CHECK-NEXT: ret double [[CAST]]
|
|
;
|
|
%or = or i64 %arg, -4503599627370495
|
|
%cast = bitcast i64 %or to double
|
|
ret double %cast
|
|
}
|
|
|
|
|
|
define double @bitcast_to_double_zero(i64 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf sub norm) double @bitcast_to_double_zero
|
|
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[ARG]], 63
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i64 [[SHL]] to double
|
|
; CHECK-NEXT: ret double [[CAST]]
|
|
;
|
|
%shl = shl i64 %arg, 63
|
|
%cast = bitcast i64 %shl to double
|
|
ret double %cast
|
|
}
|
|
|
|
define double @bitcast_to_double_nzero(i64 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(zero) double @bitcast_to_double_nzero
|
|
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or i64 [[ARG]], 1152921504606846976
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i64 [[OR]] to double
|
|
; CHECK-NEXT: ret double [[CAST]]
|
|
;
|
|
%or = or i64 %arg, 1152921504606846976
|
|
%cast = bitcast i64 %or to double
|
|
ret double %cast
|
|
}
|
|
|
|
define double @bitcast_to_double_inf(i64 %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan zero sub norm) double @bitcast_to_double_inf
|
|
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHR:%.*]] = shl i64 [[ARG]], 63
|
|
; CHECK-NEXT: [[OR:%.*]] = or i64 [[SHR]], 9218868437227405312
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast i64 [[OR]] to double
|
|
; CHECK-NEXT: ret double [[CAST]]
|
|
;
|
|
%shr = shl i64 %arg, 63
|
|
%or = or i64 %shr, 9218868437227405312
|
|
%cast = bitcast i64 %or to double
|
|
ret double %cast
|
|
}
|
|
|
|
|
|
define <2 x float> @bitcast_to_float_vect_sign_0(<2 x i32> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @bitcast_to_float_vect_sign_0
|
|
; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHR:%.*]] = lshr <2 x i32> [[ARG]], <i32 1, i32 2>
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast <2 x i32> [[SHR]] to <2 x float>
|
|
; CHECK-NEXT: ret <2 x float> [[CAST]]
|
|
;
|
|
%shr = lshr <2 x i32> %arg, <i32 1, i32 2>
|
|
%cast = bitcast <2 x i32> %shr to <2 x float>
|
|
ret <2 x float> %cast
|
|
}
|
|
|
|
define <2 x float> @bitcast_to_float_vect_nnan(<2 x i32> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) <2 x float> @bitcast_to_float_vect_nnan
|
|
; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[SHR:%.*]] = lshr <2 x i32> [[ARG]], <i32 4, i32 4>
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast <2 x i32> [[SHR]] to <2 x float>
|
|
; CHECK-NEXT: ret <2 x float> [[CAST]]
|
|
;
|
|
%shr = lshr <2 x i32> %arg, <i32 4, i32 4>
|
|
%cast = bitcast <2 x i32> %shr to <2 x float>
|
|
ret <2 x float> %cast
|
|
}
|
|
|
|
define <2 x float> @bitcast_to_float_vect_sign_1(<2 x i32> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @bitcast_to_float_vect_sign_1
|
|
; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[ARG]], <i32 -2147483648, i32 -2147483648>
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast <2 x i32> [[OR]] to <2 x float>
|
|
; CHECK-NEXT: ret <2 x float> [[CAST]]
|
|
;
|
|
%or = or <2 x i32> %arg, <i32 -2147483648, i32 -2147483648>
|
|
%cast = bitcast <2 x i32> %or to <2 x float>
|
|
ret <2 x float> %cast
|
|
}
|
|
|
|
define <2 x float> @bitcast_to_float_vect_nan(<2 x i32> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define nofpclass(inf zero sub norm) <2 x float> @bitcast_to_float_vect_nan
|
|
; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[ARG]], <i32 2139095041, i32 2139095041>
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast <2 x i32> [[OR]] to <2 x float>
|
|
; CHECK-NEXT: ret <2 x float> [[CAST]]
|
|
;
|
|
%or = or <2 x i32> %arg, <i32 2139095041, i32 2139095041>
|
|
%cast = bitcast <2 x i32> %or to <2 x float>
|
|
ret <2 x float> %cast
|
|
}
|
|
|
|
define <2 x float> @bitcast_to_float_vect_conservative_1(<2 x i32> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <2 x float> @bitcast_to_float_vect_conservative_1
|
|
; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[ARG]], <i32 -2147483648, i32 0>
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast <2 x i32> [[OR]] to <2 x float>
|
|
; CHECK-NEXT: ret <2 x float> [[CAST]]
|
|
;
|
|
%or = or <2 x i32> %arg, <i32 -2147483648, i32 0>
|
|
%cast = bitcast <2 x i32> %or to <2 x float>
|
|
ret <2 x float> %cast
|
|
}
|
|
|
|
define <2 x float> @bitcast_to_float_vect_conservative_2(<2 x i32> %arg) {
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
|
; CHECK-LABEL: define <2 x float> @bitcast_to_float_vect_conservative_2
|
|
; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[ARG]], <i32 0, i32 2139095041>
|
|
; CHECK-NEXT: [[CAST:%.*]] = bitcast <2 x i32> [[OR]] to <2 x float>
|
|
; CHECK-NEXT: ret <2 x float> [[CAST]]
|
|
;
|
|
%or = or <2 x i32> %arg, <i32 0, i32 2139095041>
|
|
%cast = bitcast <2 x i32> %or to <2 x float>
|
|
ret <2 x float> %cast
|
|
}
|
|
|
|
declare i64 @_Z13get_global_idj(i32 noundef)
|
|
|
|
attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }
|
|
attributes #1 = { "denormal-fp-math"="preserve-sign,ieee" }
|
|
attributes #2 = { "denormal-fp-math"="ieee,preserve-sign" }
|
|
attributes #3 = { "denormal-fp-math"="positive-zero,positive-zero" }
|
|
attributes #4 = { "denormal-fp-math"="positive-zero,ieee" }
|
|
attributes #5 = { "denormal-fp-math"="ieee,positive-zero" }
|