1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64 | FileCheck %s
3 ; RUN: llc < %s -mtriple=aarch64 -mattr=-neon | FileCheck -check-prefix=CHECK-NONEON %s
4 ; Check that selection dag legalization of fcopysign works in cases with
5 ; different modes for the arguments.
7 declare fp128 @llvm.copysign.f128(fp128, fp128)
8 declare float @llvm.copysign.f32(float %a, float %b)
9 declare double @llvm.copysign.f64(double %a, double %b)
10 declare half @llvm.copysign.f16(half %a, half %b)
12 @val_float = dso_local global float zeroinitializer, align 4
13 @val_double = dso_local global double zeroinitializer, align 8
14 @val_fp128 = dso_local global fp128 zeroinitializer, align 16
16 define fp128 @copysign0() {
17 ; CHECK-LABEL: copysign0:
18 ; CHECK: // %bb.0: // %entry
19 ; CHECK-NEXT: adrp x8, .LCPI0_0
20 ; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI0_0]
21 ; CHECK-NEXT: adrp x8, val_double
22 ; CHECK-NEXT: str q0, [sp, #-16]!
23 ; CHECK-NEXT: .cfi_def_cfa_offset 16
24 ; CHECK-NEXT: ldr x8, [x8, :lo12:val_double]
25 ; CHECK-NEXT: ldrb w9, [sp, #15]
26 ; CHECK-NEXT: and x8, x8, #0x8000000000000000
27 ; CHECK-NEXT: lsr x8, x8, #56
28 ; CHECK-NEXT: bfxil w8, w9, #0, #7
29 ; CHECK-NEXT: strb w8, [sp, #15]
30 ; CHECK-NEXT: ldr q0, [sp], #16
33 ; CHECK-NONEON-LABEL: copysign0:
34 ; CHECK-NONEON: // %bb.0: // %entry
35 ; CHECK-NONEON-NEXT: adrp x8, .LCPI0_0
36 ; CHECK-NONEON-NEXT: ldr q0, [x8, :lo12:.LCPI0_0]
37 ; CHECK-NONEON-NEXT: adrp x8, val_double
38 ; CHECK-NONEON-NEXT: str q0, [sp, #-16]!
39 ; CHECK-NONEON-NEXT: .cfi_def_cfa_offset 16
40 ; CHECK-NONEON-NEXT: ldr x8, [x8, :lo12:val_double]
41 ; CHECK-NONEON-NEXT: ldrb w9, [sp, #15]
42 ; CHECK-NONEON-NEXT: and x8, x8, #0x8000000000000000
43 ; CHECK-NONEON-NEXT: lsr x8, x8, #56
44 ; CHECK-NONEON-NEXT: bfxil w8, w9, #0, #7
45 ; CHECK-NONEON-NEXT: strb w8, [sp, #15]
46 ; CHECK-NONEON-NEXT: ldr q0, [sp], #16
47 ; CHECK-NONEON-NEXT: ret
49 %v = load double, ptr @val_double, align 8
50 %conv = fpext double %v to fp128
51 %call = tail call fp128 @llvm.copysign.f128(fp128 0xL00000000000000007FFF000000000000, fp128 %conv) #2
55 define fp128@copysign1() {
56 ; CHECK-LABEL: copysign1:
57 ; CHECK: // %bb.0: // %entry
58 ; CHECK-NEXT: adrp x8, val_fp128
59 ; CHECK-NEXT: ldr q0, [x8, :lo12:val_fp128]
60 ; CHECK-NEXT: adrp x8, val_float
61 ; CHECK-NEXT: str q0, [sp, #-16]!
62 ; CHECK-NEXT: .cfi_def_cfa_offset 16
63 ; CHECK-NEXT: ldr w8, [x8, :lo12:val_float]
64 ; CHECK-NEXT: ldrb w9, [sp, #15]
65 ; CHECK-NEXT: and w8, w8, #0x80000000
66 ; CHECK-NEXT: and w9, w9, #0x7f
67 ; CHECK-NEXT: orr w8, w9, w8, lsr #24
68 ; CHECK-NEXT: strb w8, [sp, #15]
69 ; CHECK-NEXT: ldr q0, [sp], #16
72 ; CHECK-NONEON-LABEL: copysign1:
73 ; CHECK-NONEON: // %bb.0: // %entry
74 ; CHECK-NONEON-NEXT: adrp x8, val_fp128
75 ; CHECK-NONEON-NEXT: ldr q0, [x8, :lo12:val_fp128]
76 ; CHECK-NONEON-NEXT: adrp x8, val_float
77 ; CHECK-NONEON-NEXT: str q0, [sp, #-16]!
78 ; CHECK-NONEON-NEXT: .cfi_def_cfa_offset 16
79 ; CHECK-NONEON-NEXT: ldr w8, [x8, :lo12:val_float]
80 ; CHECK-NONEON-NEXT: ldrb w9, [sp, #15]
81 ; CHECK-NONEON-NEXT: and w8, w8, #0x80000000
82 ; CHECK-NONEON-NEXT: and w9, w9, #0x7f
83 ; CHECK-NONEON-NEXT: orr w8, w9, w8, lsr #24
84 ; CHECK-NONEON-NEXT: strb w8, [sp, #15]
85 ; CHECK-NONEON-NEXT: ldr q0, [sp], #16
86 ; CHECK-NONEON-NEXT: ret
88 %v0 = load fp128, ptr @val_fp128, align 16
89 %v1 = load float, ptr @val_float, align 4
90 %conv = fpext float %v1 to fp128
91 %call = tail call fp128 @llvm.copysign.f128(fp128 %v0, fp128 %conv)
95 define float @copysign32(float %a, float %b) {
96 ; CHECK-LABEL: copysign32:
97 ; CHECK: // %bb.0: // %entry
98 ; CHECK-NEXT: mvni v2.4s, #128, lsl #24
99 ; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0
100 ; CHECK-NEXT: // kill: def $s1 killed $s1 def $q1
101 ; CHECK-NEXT: bif v0.16b, v1.16b, v2.16b
102 ; CHECK-NEXT: // kill: def $s0 killed $s0 killed $q0
105 ; CHECK-NONEON-LABEL: copysign32:
106 ; CHECK-NONEON: // %bb.0: // %entry
107 ; CHECK-NONEON-NEXT: fabs s0, s0
108 ; CHECK-NONEON-NEXT: fmov w8, s1
109 ; CHECK-NONEON-NEXT: tst w8, #0x80000000
110 ; CHECK-NONEON-NEXT: fneg s2, s0
111 ; CHECK-NONEON-NEXT: fcsel s0, s2, s0, ne
112 ; CHECK-NONEON-NEXT: ret
114 %c = call float @llvm.copysign.f32(float %a, float %b)
118 define double @copysign64(double %a, double %b) {
119 ; CHECK-LABEL: copysign64:
120 ; CHECK: // %bb.0: // %entry
121 ; CHECK-NEXT: movi v2.2d, #0xffffffffffffffff
122 ; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0
123 ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1
124 ; CHECK-NEXT: fneg v2.2d, v2.2d
125 ; CHECK-NEXT: bif v0.16b, v1.16b, v2.16b
126 ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
129 ; CHECK-NONEON-LABEL: copysign64:
130 ; CHECK-NONEON: // %bb.0: // %entry
131 ; CHECK-NONEON-NEXT: fabs d0, d0
132 ; CHECK-NONEON-NEXT: fmov x8, d1
133 ; CHECK-NONEON-NEXT: tst x8, #0x8000000000000000
134 ; CHECK-NONEON-NEXT: fneg d2, d0
135 ; CHECK-NONEON-NEXT: fcsel d0, d2, d0, ne
136 ; CHECK-NONEON-NEXT: ret
138 %c = call double @llvm.copysign.f64(double %a, double %b)
142 define half @copysign16(half %a, half %b) {
143 ; CHECK-LABEL: copysign16:
144 ; CHECK: // %bb.0: // %entry
145 ; CHECK-NEXT: fcvt s1, h1
146 ; CHECK-NEXT: fcvt s0, h0
147 ; CHECK-NEXT: mvni v2.4s, #128, lsl #24
148 ; CHECK-NEXT: bif v0.16b, v1.16b, v2.16b
149 ; CHECK-NEXT: fcvt h0, s0
152 ; CHECK-NONEON-LABEL: copysign16:
153 ; CHECK-NONEON: // %bb.0: // %entry
154 ; CHECK-NONEON-NEXT: sub sp, sp, #16
155 ; CHECK-NONEON-NEXT: .cfi_def_cfa_offset 16
156 ; CHECK-NONEON-NEXT: fcvt s0, h0
157 ; CHECK-NONEON-NEXT: str h1, [sp, #12]
158 ; CHECK-NONEON-NEXT: ldrb w8, [sp, #13]
159 ; CHECK-NONEON-NEXT: tst w8, #0x80
160 ; CHECK-NONEON-NEXT: fabs s0, s0
161 ; CHECK-NONEON-NEXT: fneg s1, s0
162 ; CHECK-NONEON-NEXT: fcsel s0, s1, s0, ne
163 ; CHECK-NONEON-NEXT: fcvt h0, s0
164 ; CHECK-NONEON-NEXT: add sp, sp, #16
165 ; CHECK-NONEON-NEXT: ret
167 %c = call half @llvm.copysign.f16(half %a, half %b)