[llvm] [InstCombine] Recognize copysign idioms (PR #101324)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 31 05:59:46 PDT 2024
================
@@ -711,3 +711,171 @@ define ptr @select_bitcast_unsized_pointer(i1 %c) {
%s = select i1 %c, ptr @f1, ptr @f2
ret ptr %s
}
+
+define float @copysign_idiom_constant(float %x) {
+; CHECK-LABEL: @copysign_idiom_constant(
+; CHECK-NEXT: [[Y:%.*]] = call float @llvm.copysign.f32(float 1.000000e+00, float [[X:%.*]])
+; CHECK-NEXT: ret float [[Y]]
+;
+ %bits = bitcast float %x to i32
+ %sign = and i32 %bits, -2147483648
+ %res = or i32 %sign, 1065353216
+ %y = bitcast i32 %res to float
+ ret float %y
+}
+
+define float @copysign_idiom(float %x, i32 %mag) {
+; CHECK-LABEL: @copysign_idiom(
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[MAG:%.*]], -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 [[MAG]] to float
+; CHECK-NEXT: [[Y:%.*]] = call float @llvm.copysign.f32(float [[TMP1]], float [[X:%.*]])
+; CHECK-NEXT: ret float [[Y]]
+;
+ %cond = icmp sgt i32 %mag, -1
+ call void @llvm.assume(i1 %cond)
+
+ %bits = bitcast float %x to i32
+ %sign = and i32 %bits, -2147483648
+ %res = or i32 %sign, %mag
+ %y = bitcast i32 %res to float
+ ret float %y
+}
+
+define float @copysign_idiom_commuted(float %x, i32 %magx) {
+; CHECK-LABEL: @copysign_idiom_commuted(
+; CHECK-NEXT: [[MAG:%.*]] = add i32 [[MAGX:%.*]], -1
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[MAG]], -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32 [[MAG]] to float
+; CHECK-NEXT: [[Y:%.*]] = call float @llvm.copysign.f32(float [[TMP1]], float [[X:%.*]])
+; CHECK-NEXT: ret float [[Y]]
+;
+ %mag = add i32 %magx, -1 ; thwart complexity-based canonicalization
+ %cond = icmp sgt i32 %mag, -1
+ call void @llvm.assume(i1 %cond)
+
+ %bits = bitcast float %x to i32
+ %sign = and i32 %bits, -2147483648
+ %res = or i32 %mag, %sign
+ %y = bitcast i32 %res to float
+ ret float %y
+}
+
+define float @copysign_idiom_abs(float %x, float %mag) {
+; CHECK-LABEL: @copysign_idiom_abs(
+; CHECK-NEXT: [[Y:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[X:%.*]])
+; CHECK-NEXT: ret float [[Y]]
+;
+ %abs = call float @llvm.fabs.f32(float %mag)
+ %absbits = bitcast float %abs to i32
+ %bits = bitcast float %x to i32
+ %sign = and i32 %bits, -2147483648
+ %res = or i32 %sign, %absbits
+ %y = bitcast i32 %res to float
+ ret float %y
+}
+
+define double @copysign_idiom_f64(double %x, i64 %mag) {
+; CHECK-LABEL: @copysign_idiom_f64(
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[MAG:%.*]], -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast i64 [[MAG]] to double
+; CHECK-NEXT: [[Y:%.*]] = call double @llvm.copysign.f64(double [[TMP1]], double [[X:%.*]])
+; CHECK-NEXT: ret double [[Y]]
+;
+ %cond = icmp sgt i64 %mag, -1
+ call void @llvm.assume(i1 %cond)
+
+ %bits = bitcast double %x to i64
+ %sign = and i64 %bits, -9223372036854775808
+ %res = or i64 %sign, %mag
+ %y = bitcast i64 %res to double
+ ret double %y
+}
+
+define <2 x float> @copysign_idiom_vec(<2 x float> %x) {
+; CHECK-LABEL: @copysign_idiom_vec(
+; CHECK-NEXT: [[Y:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]])
+; CHECK-NEXT: ret <2 x float> [[Y]]
+;
+ %bits = bitcast <2 x float> %x to <2 x i32>
+ %sign = and <2 x i32> %bits, splat(i32 -2147483648)
+ %res = or <2 x i32> %sign, splat(i32 1065353216)
+ %y = bitcast <2 x i32> %res to <2 x float>
+ ret <2 x float> %y
+}
+
+; negative tests
+
+define float @copysign_idiom_without_nneg(float %x, i32 %mag) {
+; CHECK-LABEL: @copysign_idiom_without_nneg(
+; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT: [[SIGN:%.*]] = and i32 [[BITS]], -2147483648
+; CHECK-NEXT: [[RES:%.*]] = or i32 [[SIGN]], [[MAG:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = bitcast i32 [[RES]] to float
+; CHECK-NEXT: ret float [[Y]]
+;
+ %bits = bitcast float %x to i32
+ %sign = and i32 %bits, -2147483648
+ %res = or i32 %sign, %mag
+ %y = bitcast i32 %res to float
+ ret float %y
+}
+
+define float @copysign_idiom_not_signmask(float %x, i32 %mag) {
+; CHECK-LABEL: @copysign_idiom_not_signmask(
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[MAG:%.*]], -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32
+; CHECK-NEXT: [[SIGN:%.*]] = and i32 [[BITS]], -2147483647
+; CHECK-NEXT: [[RES:%.*]] = or i32 [[SIGN]], [[MAG]]
+; CHECK-NEXT: [[Y:%.*]] = bitcast i32 [[RES]] to float
+; CHECK-NEXT: ret float [[Y]]
+;
+ %cond = icmp sgt i32 %mag, -1
+ call void @llvm.assume(i1 %cond)
+
+ %bits = bitcast float %x to i32
+ %sign = and i32 %bits, -2147483647
+ %res = or i32 %sign, %mag
+ %y = bitcast i32 %res to float
+ ret float %y
+}
+
+define float @copysign_idiom_constant_wrong_type1(<1 x i32> %x) {
+; CHECK-LABEL: @copysign_idiom_constant_wrong_type1(
+; CHECK-NEXT: [[TMP1:%.*]] = extractelement <1 x i32> [[X:%.*]], i64 0
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[TMP1]], -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: ret float 1.000000e+00
+;
+ %bits = bitcast <1 x i32> %x to i32
+ %cond = icmp sgt i32 %bits, -1
+ call void @llvm.assume(i1 %cond)
+
+ %sign = and i32 %bits, -2147483648
+ %res = or i32 %sign, 1065353216
+ %y = bitcast i32 %res to float
+ ret float %y
+}
+
+define half @copysign_idiom_constant_wrong_type2(bfloat %x, i16 %mag) {
+; CHECK-LABEL: @copysign_idiom_constant_wrong_type2(
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i16 [[MAG:%.*]], -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
+; CHECK-NEXT: [[BITS:%.*]] = bitcast bfloat [[X:%.*]] to i16
+; CHECK-NEXT: [[SIGN:%.*]] = and i16 [[BITS]], -32768
+; CHECK-NEXT: [[RES:%.*]] = or disjoint i16 [[SIGN]], [[MAG]]
+; CHECK-NEXT: [[Y:%.*]] = bitcast i16 [[RES]] to half
+; CHECK-NEXT: ret half [[Y]]
+;
+ %cond = icmp sgt i16 %mag, -1
+ call void @llvm.assume(i1 %cond)
+
+ %bits = bitcast bfloat %x to i16
+ %sign = and i16 %bits, -32768
+ %res = or i16 %sign, %mag
+ %y = bitcast i16 %res to half
+ ret half %y
+}
----------------
dtcxzyw wrote:
The destination type must be an integer type.
https://github.com/llvm/llvm-project/pull/101324
More information about the llvm-commits
mailing list