Home | History | Annotate | Download | only in X86
      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 
     19 define 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 
     32 define 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 
     45 define 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 
     58 define 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 
     71 define 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 
     85 define 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 
     99 define 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 
    113 define 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 
    127 define 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 
    141 define 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 
    153 define 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 
    165 define 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 
    177 define 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 
    189 define 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 
    203 define 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 
    215 define 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 
    231 define 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 
    243 define 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 
    254 define 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 
    265 define <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 
    276 define <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