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