blob: 59b13e6834961b62aba835b5269e6ea67d409d4a [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
declare float @llvm.fabs.f32(float)
declare float @llvm.copysign.f32(float, float)
declare float @llvm.maxnum.f32(float, float)
declare <3 x double> @llvm.copysign.v3f64(<3 x double>, <3 x double>)
define float @positive_sign_arg(float %x) {
; CHECK-LABEL: @positive_sign_arg(
; CHECK-NEXT: [[R:%.*]] = call arcp float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%r = call arcp float @llvm.copysign.f32(float %x, float 0.0)
ret float %r
}
define <3 x double> @positive_sign_arg_vec_splat(<3 x double> %x) {
; CHECK-LABEL: @positive_sign_arg_vec_splat(
; CHECK-NEXT: [[R:%.*]] = call ninf <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]])
; CHECK-NEXT: ret <3 x double> [[R]]
;
%r = call ninf <3 x double> @llvm.copysign.v3f64(<3 x double> %x, <3 x double> <double 42.0, double 42.0, double 42.0>)
ret <3 x double> %r
}
define float @negative_sign_arg(float %x) {
; CHECK-LABEL: @negative_sign_arg(
; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fneg nnan float [[TMP1]]
; CHECK-NEXT: ret float [[R]]
;
%r = call nnan float @llvm.copysign.f32(float %x, float -0.0)
ret float %r
}
define <3 x double> @negative_sign_arg_vec_splat(<3 x double> %x) {
; CHECK-LABEL: @negative_sign_arg_vec_splat(
; CHECK-NEXT: [[TMP1:%.*]] = call fast <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fneg fast <3 x double> [[TMP1]]
; CHECK-NEXT: ret <3 x double> [[R]]
;
%r = call fast <3 x double> @llvm.copysign.v3f64(<3 x double> %x, <3 x double> <double -42.0, double -42.0, double -42.0>)
ret <3 x double> %r
}
define float @known_positive_sign_arg(float %x, float %y) {
; CHECK-LABEL: @known_positive_sign_arg(
; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.fabs.f32(float [[X:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%fabs = call float @llvm.fabs.f32(float %y)
%r = call ninf float @llvm.copysign.f32(float %x, float %fabs)
ret float %r
}
define <3 x double> @known_positive_sign_arg_vec(<3 x double> %x, <3 x i32> %y) {
; CHECK-LABEL: @known_positive_sign_arg_vec(
; CHECK-NEXT: [[R:%.*]] = call arcp <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]])
; CHECK-NEXT: ret <3 x double> [[R]]
;
%yf = uitofp <3 x i32> %y to <3 x double>
%r = call arcp <3 x double> @llvm.copysign.v3f64(<3 x double> %x, <3 x double> %yf)
ret <3 x double> %r
}
; maxnum(-0.0, 0.0) can return -0.0.
define float @not_known_positive_sign_arg(float %x, float %y) {
; CHECK-LABEL: @not_known_positive_sign_arg(
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0.000000e+00)
; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.copysign.f32(float [[Y:%.*]], float [[MAX]])
; CHECK-NEXT: ret float [[R]]
;
%max = call float @llvm.maxnum.f32(float %x, float 0.0)
%r = call ninf float @llvm.copysign.f32(float %y, float %max)
ret float %r
}
; The magnitude operand of the 1st copysign is irrelevant.
; copysign(x, copysign(y, z)) --> copysign(x, z)
define float @copysign_sign_arg(float %x, float %y, float %z) {
; CHECK-LABEL: @copysign_sign_arg(
; CHECK-NEXT: [[R:%.*]] = call float @llvm.copysign.f32(float [[X:%.*]], float [[Z:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%s = call reassoc float @llvm.copysign.f32(float %y, float %z)
%r = call ninf float @llvm.copysign.f32(float %x, float %s)
ret float %r
}
define float @copysign_sign_arg_nnan(float %x, float %y, float %z) {
; CHECK-LABEL: @copysign_sign_arg_nnan(
; CHECK-NEXT: [[R:%.*]] = call nnan float @llvm.copysign.f32(float [[X:%.*]], float [[Z:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%s = call nnan float @llvm.copysign.f32(float %y, float %z)
%r = call nnan float @llvm.copysign.f32(float %x, float %s)
ret float %r
}
define float @copysign_sign_arg_mixed(float %x, float %y, float %z) {
; CHECK-LABEL: @copysign_sign_arg_mixed(
; CHECK-NEXT: [[R:%.*]] = call nsz float @llvm.copysign.f32(float [[X:%.*]], float [[Z:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%s = call ninf nsz float @llvm.copysign.f32(float %y, float %z)
%r = call nnan nsz float @llvm.copysign.f32(float %x, float %s)
ret float %r
}
define float @fneg_mag(float %x, float %y) {
; CHECK-LABEL: @fneg_mag(
; CHECK-NEXT: [[R:%.*]] = call float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%n = fneg float %x
%r = call float @llvm.copysign.f32(float %n, float %y)
ret float %r
}
define float @fabs_mag(float %x, float %y) {
; CHECK-LABEL: @fabs_mag(
; CHECK-NEXT: [[R:%.*]] = call float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]])
; CHECK-NEXT: ret float [[R]]
;
%a = call float @llvm.fabs.f32(float %x)
%r = call float @llvm.copysign.f32(float %a, float %y)
ret float %r
}
; Issue 177932
define float @copysign_simplify_demanded_bits_sign(float %mag, float %sign) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign(
; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[SIGN:%.*]])
; CHECK-NEXT: ret float [[RESULT]]
;
%sign.int = bitcast float %sign to i32
%and.sign = and i32 %sign.int, -2147483648
%cast.sign = bitcast i32 %and.sign to float
%result = call float @llvm.copysign.f32(float %mag, float %cast.sign)
ret float %result
}
define <2 x float> @copysign_simplify_demanded_bits_sign_vector(<2 x float> %mag, <2 x float> %sign) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_vector(
; CHECK-NEXT: [[RESULT:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[MAG:%.*]], <2 x float> [[SIGN:%.*]])
; CHECK-NEXT: ret <2 x float> [[RESULT]]
;
%sign.int = bitcast <2 x float> %sign to <2 x i32>
%and.sign = and <2 x i32> %sign.int, splat (i32 -2147483648)
%cast.sign = bitcast <2 x i32> %and.sign to <2 x float>
%result = call <2 x float> @llvm.copysign.v2f32(<2 x float> %mag, <2 x float> %cast.sign)
ret <2 x float> %result
}
define float @copysign_simplify_demanded_bits_sign_multiple_use_cast(float %mag, float %sign, ptr %ptr) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_multiple_use_cast(
; CHECK-NEXT: [[SIGN_INT:%.*]] = bitcast float [[SIGN:%.*]] to i32
; CHECK-NEXT: [[AND_SIGN:%.*]] = and i32 [[SIGN_INT]], -2147483648
; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast i32 [[AND_SIGN]] to float
; CHECK-NEXT: store i32 [[AND_SIGN]], ptr [[PTR:%.*]], align 4
; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[CAST_SIGN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%sign.int = bitcast float %sign to i32
%and.sign = and i32 %sign.int, -2147483648
%cast.sign = bitcast i32 %and.sign to float
store float %cast.sign, ptr %ptr
%result = call float @llvm.copysign.f32(float %mag, float %cast.sign)
ret float %result
}
define float @copysign_simplify_demanded_bits_sign_multiple_use_cast_src(float %mag, float %sign, ptr %ptr) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_multiple_use_cast_src(
; CHECK-NEXT: [[SIGN_INT:%.*]] = bitcast float [[SIGN:%.*]] to i32
; CHECK-NEXT: [[AND_SIGN:%.*]] = and i32 [[SIGN_INT]], -2147483648
; CHECK-NEXT: store i32 [[AND_SIGN]], ptr [[PTR:%.*]], align 4
; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast i32 [[AND_SIGN]] to float
; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[CAST_SIGN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%sign.int = bitcast float %sign to i32
%and.sign = and i32 %sign.int, -2147483648
store i32 %and.sign, ptr %ptr
%cast.sign = bitcast i32 %and.sign to float
%result = call float @llvm.copysign.f32(float %mag, float %cast.sign)
ret float %result
}
; Cannot simplify due to second use of %cast.sign
define i32 @issue178245(i32 %i.0.i.i) {
; CHECK-LABEL: @issue178245(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TOBOOL104_I_I_NOT:%.*]] = icmp eq i32 [[I_0_I_I:%.*]], -1177359834
; CHECK-NEXT: [[CAST_SIGN:%.*]] = select i1 [[TOBOOL104_I_I_NOT]], float 0.000000e+00, float 0xFFFFFFFF60000000
; CHECK-NEXT: [[FCMP:%.*]] = fcmp uno float [[CAST_SIGN]], 0.000000e+00
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[CAST_SIGN]])
; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[COPYSIGN]] to i32
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[FCMP]], i32 0, i32 [[TMP0]]
; CHECK-NEXT: ret i32 [[RESULT]]
;
entry:
%tobool104.i.i.not = icmp eq i32 %i.0.i.i, -1177359834
%conv111.i.i = select i1 %tobool104.i.i.not, i32 0, i32 -5
%cast.sign = bitcast i32 %conv111.i.i to float
%fcmp = fcmp uno float %cast.sign, 0.000000e+00
%copysign = call float @llvm.copysign.f32(float 0.000000e+00, float %cast.sign)
%select = select i1 %fcmp, float 0.000000e+00, float %copysign
%result = bitcast float %select to i32
ret i32 %result
}
define float @copysign_simplify_demanded_bits_sign_constexpr(float %mag, float %sign) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_constexpr(
; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float bitcast (i32 ptrtoint (ptr @copysign_simplify_demanded_bits_sign_constexpr to i32) to float))
; CHECK-NEXT: ret float [[RESULT]]
;
%result = call float @llvm.copysign.f32(float %mag, float bitcast (i32 ptrtoint (ptr @copysign_simplify_demanded_bits_sign_constexpr to i32) to float))
ret float %result
}
define <2 x half> @copysign_simplify_demanded_bits_sign_cast_not_elementwise_0(<2 x half> %mag, float %sign) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_cast_not_elementwise_0(
; CHECK-NEXT: [[SIGN_INT:%.*]] = bitcast float [[SIGN:%.*]] to i32
; CHECK-NEXT: [[AND_SIGN:%.*]] = and i32 [[SIGN_INT]], -2147483648
; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast i32 [[AND_SIGN]] to <2 x half>
; CHECK-NEXT: [[RESULT:%.*]] = call <2 x half> @llvm.copysign.v2f16(<2 x half> [[MAG:%.*]], <2 x half> [[CAST_SIGN]])
; CHECK-NEXT: ret <2 x half> [[RESULT]]
;
%sign.int = bitcast float %sign to i32
%and.sign = and i32 %sign.int, -2147483648
%cast.sign = bitcast i32 %and.sign to <2 x half>
%result = call <2 x half> @llvm.copysign.v2f16(<2 x half> %mag, <2 x half> %cast.sign)
ret <2 x half> %result
}
define float @copysign_simplify_demanded_bits_sign_not_elementwise_1(float %mag, <2 x half> %sign) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_not_elementwise_1(
; CHECK-NEXT: [[SIGN_INT:%.*]] = bitcast <2 x half> [[SIGN:%.*]] to <2 x i16>
; CHECK-NEXT: [[AND_SIGN:%.*]] = and <2 x i16> [[SIGN_INT]], splat (i16 -32768)
; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast <2 x i16> [[AND_SIGN]] to float
; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[CAST_SIGN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%sign.int = bitcast <2 x half> %sign to <2 x i16>
%and.sign = and <2 x i16> %sign.int, splat (i16 -32768)
%cast.sign = bitcast <2 x i16> %and.sign to float
%result = call float @llvm.copysign.f32(float %mag, float %cast.sign)
ret float %result
}
define ppc_fp128 @copysign_simplify_demanded_bits_sign_ppcfp128(ppc_fp128 %mag, ppc_fp128 %sign) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_ppcfp128(
; CHECK-NEXT: [[RESULT:%.*]] = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 [[MAG:%.*]], ppc_fp128 [[SIGN:%.*]])
; CHECK-NEXT: ret ppc_fp128 [[RESULT]]
;
%sign.int = bitcast ppc_fp128 %sign to i128
%sign.mask = shl i128 1, 127
%and.sign = and i128 %sign.int, %sign.mask
%cast.sign = bitcast i128 %and.sign to ppc_fp128
%result = call ppc_fp128 @llvm.copysign.ppcfp128(ppc_fp128 %mag, ppc_fp128 %cast.sign)
ret ppc_fp128 %result
}
define bfloat @copysign_simplify_demanded_bits_sign_bitcast_not_int(bfloat %mag, half %sign) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_bitcast_not_int(
; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast half [[SIGN:%.*]] to bfloat
; CHECK-NEXT: [[RESULT:%.*]] = call bfloat @llvm.copysign.bf16(bfloat [[MAG:%.*]], bfloat [[CAST_SIGN]])
; CHECK-NEXT: ret bfloat [[RESULT]]
;
%cast.sign = bitcast half %sign to bfloat
%result = call bfloat @llvm.copysign.bf16(bfloat %mag, bfloat %cast.sign)
ret bfloat %result
}
define <2 x bfloat> @copysign_simplify_demanded_bits_sign_bitcast_not_int_vec(<2 x bfloat> %mag, <2 x half> %sign) {
; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_bitcast_not_int_vec(
; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast <2 x half> [[SIGN:%.*]] to <2 x bfloat>
; CHECK-NEXT: [[RESULT:%.*]] = call <2 x bfloat> @llvm.copysign.v2bf16(<2 x bfloat> [[MAG:%.*]], <2 x bfloat> [[CAST_SIGN]])
; CHECK-NEXT: ret <2 x bfloat> [[RESULT]]
;
%cast.sign = bitcast <2 x half> %sign to <2 x bfloat>
%result = call <2 x bfloat> @llvm.copysign.v2bf16(<2 x bfloat> %mag, <2 x bfloat> %cast.sign)
ret <2 x bfloat> %result
}