1; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=sse2 < %s | FileCheck %s 2 3; PR22428: https://llvm.org/bugs/show_bug.cgi?id=22428 4; f1, f2, f3, and f4 should use an integer logic instruction. 5; f9 and f10 should use an FP (SSE) logic instruction. 6; 7; f5, f6, f7, and f8 are less clear. 8; 9; For f5 and f6, we can save a register move by using an FP logic instruction, 10; but we may need to calculate the relative costs of an SSE op vs. int op vs. 11; scalar <-> SSE register moves. 12; 13; For f7 and f8, the SSE instructions don't take immediate operands, so if we 14; use one of those, we either have to load a constant from memory or move the 15; scalar immediate value from an integer register over to an SSE register. 16; Optimizing for size may affect that decision. Also, note that there are no 17; scalar versions of the FP logic ops, so if we want to fold a load into a 18; logic op, we have to load or splat a 16-byte vector constant. 19 20; 1 FP operand, 1 int operand, int result 21 22define i32 @f1(float %x, i32 %y) { 23; CHECK-LABEL: f1: 24; CHECK: # BB#0: 25; CHECK-NEXT: movd %xmm0, %eax 26; CHECK-NEXT: andl %edi, %eax 27; CHECK-NEXT: retq 28 29 %bc1 = bitcast float %x to i32 30 %and = and i32 %bc1, %y 31 ret i32 %and 32} 33 34; Swap operands of the logic op. 35 36define i32 @f2(float %x, i32 %y) { 37; CHECK-LABEL: f2: 38; CHECK: # BB#0: 39; CHECK-NEXT: movd %xmm0, %eax 40; CHECK-NEXT: andl %edi, %eax 41; CHECK-NEXT: retq 42 43 %bc1 = bitcast float %x to i32 44 %and = and i32 %y, %bc1 45 ret i32 %and 46} 47 48; 1 FP operand, 1 constant operand, int result 49 50define i32 @f3(float %x) { 51; CHECK-LABEL: f3: 52; CHECK: # BB#0: 53; CHECK-NEXT: movd %xmm0, %eax 54; CHECK-NEXT: andl $1, %eax 55; CHECK-NEXT: retq 56 57 %bc1 = bitcast float %x to i32 58 %and = and i32 %bc1, 1 59 ret i32 %and 60} 61 62; Swap operands of the logic op. 63 64define i32 @f4(float %x) { 65; CHECK-LABEL: f4: 66; CHECK: # BB#0: 67; CHECK-NEXT: movd %xmm0, %eax 68; CHECK-NEXT: andl $2, %eax 69; CHECK-NEXT: retq 70 71 %bc1 = bitcast float %x to i32 72 %and = and i32 2, %bc1 73 ret i32 %and 74} 75 76; 1 FP operand, 1 integer operand, FP result 77 78define float @f5(float %x, i32 %y) { 79; CHECK-LABEL: f5: 80; CHECK: # BB#0: 81; CHECK-NEXT: movd %xmm0, %eax 82; CHECK-NEXT: andl %edi, %eax 83; CHECK-NEXT: movd %eax, %xmm0 84; CHECK-NEXT: retq 85 86 %bc1 = bitcast float %x to i32 87 %and = and i32 %bc1, %y 88 %bc2 = bitcast i32 %and to float 89 ret float %bc2 90} 91 92; Swap operands of the logic op. 93 94define float @f6(float %x, i32 %y) { 95; CHECK-LABEL: f6: 96; CHECK: # BB#0: 97; CHECK-NEXT: movd %xmm0, %eax 98; CHECK-NEXT: andl %edi, %eax 99; CHECK-NEXT: movd %eax, %xmm0 100; CHECK-NEXT: retq 101 102 %bc1 = bitcast float %x to i32 103 %and = and i32 %y, %bc1 104 %bc2 = bitcast i32 %and to float 105 ret float %bc2 106} 107 108; 1 FP operand, 1 constant operand, FP result 109 110define float @f7(float %x) { 111; CHECK-LABEL: f7: 112; CHECK: # BB#0: 113; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 114; CHECK-NEXT: andps %xmm1, %xmm0 115; CHECK-NEXT: retq 116 117 %bc1 = bitcast float %x to i32 118 %and = and i32 %bc1, 3 119 %bc2 = bitcast i32 %and to float 120 ret float %bc2 121} 122 123; Swap operands of the logic op. 124 125define float @f8(float %x) { 126; CHECK-LABEL: f8: 127; CHECK: # BB#0: 128; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 129; CHECK-NEXT: andps %xmm1, %xmm0 130; CHECK-NEXT: retq 131 132 %bc1 = bitcast float %x to i32 133 %and = and i32 4, %bc1 134 %bc2 = bitcast i32 %and to float 135 ret float %bc2 136} 137 138; 2 FP operands, int result 139 140define i32 @f9(float %x, float %y) { 141; CHECK-LABEL: f9: 142; CHECK: # BB#0: 143; CHECK-NEXT: andps %xmm1, %xmm0 144; CHECK-NEXT: movd %xmm0, %eax 145; CHECK-NEXT: retq 146 147 %bc1 = bitcast float %x to i32 148 %bc2 = bitcast float %y to i32 149 %and = and i32 %bc1, %bc2 150 ret i32 %and 151} 152 153; 2 FP operands, FP result 154 155define float @f10(float %x, float %y) { 156; CHECK-LABEL: f10: 157; CHECK: # BB#0: 158; CHECK-NEXT: andps %xmm1, %xmm0 159; CHECK-NEXT: retq 160 161 %bc1 = bitcast float %x to i32 162 %bc2 = bitcast float %y to i32 163 %and = and i32 %bc1, %bc2 164 %bc3 = bitcast i32 %and to float 165 ret float %bc3 166} 167 168define float @or(float %x, float %y) { 169; CHECK-LABEL: or: 170; CHECK: # BB#0: 171; CHECK-NEXT: orps %xmm1, %xmm0 172; CHECK-NEXT: retq 173 174 %bc1 = bitcast float %x to i32 175 %bc2 = bitcast float %y to i32 176 %and = or i32 %bc1, %bc2 177 %bc3 = bitcast i32 %and to float 178 ret float %bc3 179} 180 181define float @xor(float %x, float %y) { 182; CHECK-LABEL: xor: 183; CHECK: # BB#0: 184; CHECK-NEXT: xorps %xmm1, %xmm0 185; CHECK-NEXT: retq 186 187 %bc1 = bitcast float %x to i32 188 %bc2 = bitcast float %y to i32 189 %and = xor i32 %bc1, %bc2 190 %bc3 = bitcast i32 %and to float 191 ret float %bc3 192} 193 194define float @f7_or(float %x) { 195; CHECK-LABEL: f7_or: 196; CHECK: # BB#0: 197; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 198; CHECK-NEXT: orps %xmm1, %xmm0 199; CHECK-NEXT: retq 200 201 %bc1 = bitcast float %x to i32 202 %and = or i32 %bc1, 3 203 %bc2 = bitcast i32 %and to float 204 ret float %bc2 205} 206 207define float @f7_xor(float %x) { 208; CHECK-LABEL: f7_xor: 209; CHECK: # BB#0: 210; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 211; CHECK-NEXT: xorps %xmm1, %xmm0 212; CHECK-NEXT: retq 213 214 %bc1 = bitcast float %x to i32 215 %and = xor i32 %bc1, 3 216 %bc2 = bitcast i32 %and to float 217 ret float %bc2 218} 219 220; Make sure that doubles work too. 221 222define double @doubles(double %x, double %y) { 223; CHECK-LABEL: doubles: 224; CHECK: # BB#0: 225; CHECK-NEXT: andpd %xmm1, %xmm0 226; CHECK-NEXT: retq 227 228 %bc1 = bitcast double %x to i64 229 %bc2 = bitcast double %y to i64 230 %and = and i64 %bc1, %bc2 231 %bc3 = bitcast i64 %and to double 232 ret double %bc3 233} 234 235define double @f7_double(double %x) { 236; CHECK-LABEL: f7_double: 237; CHECK: # BB#0: 238; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero 239; CHECK-NEXT: andpd %xmm1, %xmm0 240; CHECK-NEXT: retq 241 242 %bc1 = bitcast double %x to i64 243 %and = and i64 %bc1, 3 244 %bc2 = bitcast i64 %and to double 245 ret double %bc2 246} 247 248; Grabbing the sign bit is a special case that could be handled 249; by movmskps/movmskpd, but if we're not shifting it over, then 250; a simple FP logic op is cheaper. 251 252define float @movmsk(float %x) { 253; CHECK-LABEL: movmsk: 254; CHECK: # BB#0: 255; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 256; CHECK-NEXT: andps %xmm1, %xmm0 257; CHECK-NEXT: retq 258 259 %bc1 = bitcast float %x to i32 260 %and = and i32 %bc1, 2147483648 261 %bc2 = bitcast i32 %and to float 262 ret float %bc2 263} 264 265define double @bitcast_fabs(double %x) { 266; CHECK-LABEL: bitcast_fabs: 267; CHECK: # BB#0: 268; CHECK-NEXT: andpd {{.*}}(%rip), %xmm0 269; CHECK-NEXT: retq 270; 271 %bc1 = bitcast double %x to i64 272 %and = and i64 %bc1, 9223372036854775807 273 %bc2 = bitcast i64 %and to double 274 ret double %bc2 275} 276 277define float @bitcast_fneg(float %x) { 278; CHECK-LABEL: bitcast_fneg: 279; CHECK: # BB#0: 280; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0 281; CHECK-NEXT: retq 282; 283 %bc1 = bitcast float %x to i32 284 %xor = xor i32 %bc1, 2147483648 285 %bc2 = bitcast i32 %xor to float 286 ret float %bc2 287} 288 289define <2 x double> @bitcast_fabs_vec(<2 x double> %x) { 290; CHECK-LABEL: bitcast_fabs_vec: 291; CHECK: # BB#0: 292; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 293; CHECK-NEXT: retq 294; 295 %bc1 = bitcast <2 x double> %x to <2 x i64> 296 %and = and <2 x i64> %bc1, <i64 9223372036854775807, i64 9223372036854775807> 297 %bc2 = bitcast <2 x i64> %and to <2 x double> 298 ret <2 x double> %bc2 299} 300 301define <4 x float> @bitcast_fneg_vec(<4 x float> %x) { 302; CHECK-LABEL: bitcast_fneg_vec: 303; CHECK: # BB#0: 304; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0 305; CHECK-NEXT: retq 306; 307 %bc1 = bitcast <4 x float> %x to <4 x i32> 308 %xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648> 309 %bc2 = bitcast <4 x i32> %xor to <4 x float> 310 ret <4 x float> %bc2 311} 312 313