1; NOTE: Assertions have been autogenerated by utils/update_llc_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 %bc1 = bitcast float %x to i32 26 %and = and i32 %bc1, %y 27 ret i32 %and 28} 29 30; Swap operands of the logic op. 31 32define i32 @f2(float %x, i32 %y) { 33; CHECK-LABEL: f2: 34; CHECK: # %bb.0: 35; CHECK-NEXT: movd %xmm0, %eax 36; CHECK-NEXT: andl %edi, %eax 37; CHECK-NEXT: retq 38 %bc1 = bitcast float %x to i32 39 %and = and i32 %y, %bc1 40 ret i32 %and 41} 42 43; 1 FP operand, 1 constant operand, int result 44 45define i32 @f3(float %x) { 46; CHECK-LABEL: f3: 47; CHECK: # %bb.0: 48; CHECK-NEXT: movd %xmm0, %eax 49; CHECK-NEXT: andl $1, %eax 50; CHECK-NEXT: retq 51 %bc1 = bitcast float %x to i32 52 %and = and i32 %bc1, 1 53 ret i32 %and 54} 55 56; Swap operands of the logic op. 57 58define i32 @f4(float %x) { 59; CHECK-LABEL: f4: 60; CHECK: # %bb.0: 61; CHECK-NEXT: movd %xmm0, %eax 62; CHECK-NEXT: andl $2, %eax 63; CHECK-NEXT: retq 64 %bc1 = bitcast float %x to i32 65 %and = and i32 2, %bc1 66 ret i32 %and 67} 68 69; 1 FP operand, 1 integer operand, FP result 70 71define float @f5(float %x, i32 %y) { 72; CHECK-LABEL: f5: 73; CHECK: # %bb.0: 74; CHECK-NEXT: movd %edi, %xmm1 75; CHECK-NEXT: pand %xmm1, %xmm0 76; CHECK-NEXT: retq 77 %bc1 = bitcast float %x to i32 78 %and = and i32 %bc1, %y 79 %bc2 = bitcast i32 %and to float 80 ret float %bc2 81} 82 83; Swap operands of the logic op. 84 85define float @f6(float %x, i32 %y) { 86; CHECK-LABEL: f6: 87; CHECK: # %bb.0: 88; CHECK-NEXT: movd %edi, %xmm1 89; CHECK-NEXT: pand %xmm1, %xmm0 90; CHECK-NEXT: retq 91 %bc1 = bitcast float %x to i32 92 %and = and i32 %y, %bc1 93 %bc2 = bitcast i32 %and to float 94 ret float %bc2 95} 96 97; 1 FP operand, 1 constant operand, FP result 98 99define float @f7(float %x) { 100; CHECK-LABEL: f7: 101; CHECK: # %bb.0: 102; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 103; CHECK-NEXT: andps %xmm1, %xmm0 104; CHECK-NEXT: retq 105 %bc1 = bitcast float %x to i32 106 %and = and i32 %bc1, 3 107 %bc2 = bitcast i32 %and to float 108 ret float %bc2 109} 110 111; Swap operands of the logic op. 112 113define float @f8(float %x) { 114; CHECK-LABEL: f8: 115; CHECK: # %bb.0: 116; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 117; CHECK-NEXT: andps %xmm1, %xmm0 118; CHECK-NEXT: retq 119 %bc1 = bitcast float %x to i32 120 %and = and i32 4, %bc1 121 %bc2 = bitcast i32 %and to float 122 ret float %bc2 123} 124 125; 2 FP operands, int result 126 127define i32 @f9(float %x, float %y) { 128; CHECK-LABEL: f9: 129; CHECK: # %bb.0: 130; CHECK-NEXT: pand %xmm1, %xmm0 131; CHECK-NEXT: movd %xmm0, %eax 132; CHECK-NEXT: retq 133 %bc1 = bitcast float %x to i32 134 %bc2 = bitcast float %y to i32 135 %and = and i32 %bc1, %bc2 136 ret i32 %and 137} 138 139; 2 FP operands, FP result 140 141define float @f10(float %x, float %y) { 142; CHECK-LABEL: f10: 143; CHECK: # %bb.0: 144; CHECK-NEXT: andps %xmm1, %xmm0 145; CHECK-NEXT: retq 146 %bc1 = bitcast float %x to i32 147 %bc2 = bitcast float %y to i32 148 %and = and i32 %bc1, %bc2 149 %bc3 = bitcast i32 %and to float 150 ret float %bc3 151} 152 153define float @or(float %x, float %y) { 154; CHECK-LABEL: or: 155; CHECK: # %bb.0: 156; CHECK-NEXT: orps %xmm1, %xmm0 157; CHECK-NEXT: retq 158 %bc1 = bitcast float %x to i32 159 %bc2 = bitcast float %y to i32 160 %and = or i32 %bc1, %bc2 161 %bc3 = bitcast i32 %and to float 162 ret float %bc3 163} 164 165define float @xor(float %x, float %y) { 166; CHECK-LABEL: xor: 167; CHECK: # %bb.0: 168; CHECK-NEXT: xorps %xmm1, %xmm0 169; CHECK-NEXT: retq 170 %bc1 = bitcast float %x to i32 171 %bc2 = bitcast float %y to i32 172 %and = xor i32 %bc1, %bc2 173 %bc3 = bitcast i32 %and to float 174 ret float %bc3 175} 176 177define float @f7_or(float %x) { 178; CHECK-LABEL: f7_or: 179; CHECK: # %bb.0: 180; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 181; CHECK-NEXT: orps %xmm1, %xmm0 182; CHECK-NEXT: retq 183 %bc1 = bitcast float %x to i32 184 %and = or i32 %bc1, 3 185 %bc2 = bitcast i32 %and to float 186 ret float %bc2 187} 188 189define float @f7_xor(float %x) { 190; CHECK-LABEL: f7_xor: 191; CHECK: # %bb.0: 192; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 193; CHECK-NEXT: xorps %xmm1, %xmm0 194; CHECK-NEXT: retq 195 %bc1 = bitcast float %x to i32 196 %and = xor i32 %bc1, 3 197 %bc2 = bitcast i32 %and to float 198 ret float %bc2 199} 200 201; Make sure that doubles work too. 202 203define double @doubles(double %x, double %y) { 204; CHECK-LABEL: doubles: 205; CHECK: # %bb.0: 206; CHECK-NEXT: andps %xmm1, %xmm0 207; CHECK-NEXT: retq 208 %bc1 = bitcast double %x to i64 209 %bc2 = bitcast double %y to i64 210 %and = and i64 %bc1, %bc2 211 %bc3 = bitcast i64 %and to double 212 ret double %bc3 213} 214 215define double @f7_double(double %x) { 216; CHECK-LABEL: f7_double: 217; CHECK: # %bb.0: 218; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero 219; CHECK-NEXT: andps %xmm1, %xmm0 220; CHECK-NEXT: retq 221 %bc1 = bitcast double %x to i64 222 %and = and i64 %bc1, 3 223 %bc2 = bitcast i64 %and to double 224 ret double %bc2 225} 226 227; Grabbing the sign bit is a special case that could be handled 228; by movmskps/movmskpd, but if we're not shifting it over, then 229; a simple FP logic op is cheaper. 230 231define float @movmsk(float %x) { 232; CHECK-LABEL: movmsk: 233; CHECK: # %bb.0: 234; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero 235; CHECK-NEXT: andps %xmm1, %xmm0 236; CHECK-NEXT: retq 237 %bc1 = bitcast float %x to i32 238 %and = and i32 %bc1, 2147483648 239 %bc2 = bitcast i32 %and to float 240 ret float %bc2 241} 242 243define double @bitcast_fabs(double %x) { 244; CHECK-LABEL: bitcast_fabs: 245; CHECK: # %bb.0: 246; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 247; CHECK-NEXT: retq 248 %bc1 = bitcast double %x to i64 249 %and = and i64 %bc1, 9223372036854775807 250 %bc2 = bitcast i64 %and to double 251 ret double %bc2 252} 253 254define float @bitcast_fneg(float %x) { 255; CHECK-LABEL: bitcast_fneg: 256; CHECK: # %bb.0: 257; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0 258; CHECK-NEXT: retq 259 %bc1 = bitcast float %x to i32 260 %xor = xor i32 %bc1, 2147483648 261 %bc2 = bitcast i32 %xor to float 262 ret float %bc2 263} 264 265define <2 x double> @bitcast_fabs_vec(<2 x double> %x) { 266; CHECK-LABEL: bitcast_fabs_vec: 267; CHECK: # %bb.0: 268; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 269; CHECK-NEXT: retq 270 %bc1 = bitcast <2 x double> %x to <2 x i64> 271 %and = and <2 x i64> %bc1, <i64 9223372036854775807, i64 9223372036854775807> 272 %bc2 = bitcast <2 x i64> %and to <2 x double> 273 ret <2 x double> %bc2 274} 275 276define <4 x float> @bitcast_fneg_vec(<4 x float> %x) { 277; CHECK-LABEL: bitcast_fneg_vec: 278; CHECK: # %bb.0: 279; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0 280; CHECK-NEXT: retq 281 %bc1 = bitcast <4 x float> %x to <4 x i32> 282 %xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648> 283 %bc2 = bitcast <4 x i32> %xor to <4 x float> 284 ret <4 x float> %bc2 285} 286 287