aboutsummaryrefslogtreecommitdiff
path: root/llvm/test/Transforms/InstCombine/copysign.ll
blob: ee093a709eab34f41b48e89cd19a27d59c1bad47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
; 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
}