Home | History | Annotate | Download | only in AArch64
      1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
      2 ; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s
      3 
      4 ; Check that under certain conditions we can factor out a rotate
      5 ; from the following idioms:
      6 ;   (a*c0) >> s1 | (a*c1)
      7 ;   (a/c0) << s1 | (a/c1)
      8 ; This targets cases where instcombine has folded a shl/srl/mul/udiv
      9 ; with one of the shifts from the rotate idiom
     10 
     11 define i64 @ror_extract_shl(i64 %i) nounwind {
     12 ; CHECK-LABEL: ror_extract_shl:
     13 ; CHECK:       // %bb.0:
     14 ; CHECK-NEXT:    lsl x8, x0, #3
     15 ; CHECK-NEXT:    ror x0, x8, #57
     16 ; CHECK-NEXT:    ret
     17   %lhs_mul = shl i64 %i, 3
     18   %rhs_mul = shl i64 %i, 10
     19   %lhs_shift = lshr i64 %lhs_mul, 57
     20   %out = or i64 %lhs_shift, %rhs_mul
     21   ret i64 %out
     22 }
     23 
     24 define i32 @ror_extract_shrl(i32 %i) nounwind {
     25 ; CHECK-LABEL: ror_extract_shrl:
     26 ; CHECK:       // %bb.0:
     27 ; CHECK-NEXT:    lsr w8, w0, #3
     28 ; CHECK-NEXT:    ror w0, w8, #4
     29 ; CHECK-NEXT:    ret
     30   %lhs_div = lshr i32 %i, 7
     31   %rhs_div = lshr i32 %i, 3
     32   %rhs_shift = shl i32 %rhs_div, 28
     33   %out = or i32 %lhs_div, %rhs_shift
     34   ret i32 %out
     35 }
     36 
     37 define i32 @ror_extract_mul(i32 %i) nounwind {
     38 ; CHECK-LABEL: ror_extract_mul:
     39 ; CHECK:       // %bb.0:
     40 ; CHECK-NEXT:    add w8, w0, w0, lsl #3
     41 ; CHECK-NEXT:    ror w0, w8, #25
     42 ; CHECK-NEXT:    ret
     43   %lhs_mul = mul i32 %i, 9
     44   %rhs_mul = mul i32 %i, 1152
     45   %lhs_shift = lshr i32 %lhs_mul, 25
     46   %out = or i32 %lhs_shift, %rhs_mul
     47   ret i32 %out
     48 }
     49 
     50 define i64 @ror_extract_udiv(i64 %i) nounwind {
     51 ; CHECK-LABEL: ror_extract_udiv:
     52 ; CHECK:       // %bb.0:
     53 ; CHECK-NEXT:    mov x8, #-6148914691236517206
     54 ; CHECK-NEXT:    movk x8, #43691
     55 ; CHECK-NEXT:    umulh x8, x0, x8
     56 ; CHECK-NEXT:    lsr x8, x8, #1
     57 ; CHECK-NEXT:    ror x0, x8, #4
     58 ; CHECK-NEXT:    ret
     59   %lhs_div = udiv i64 %i, 3
     60   %rhs_div = udiv i64 %i, 48
     61   %lhs_shift = shl i64 %lhs_div, 60
     62   %out = or i64 %lhs_shift, %rhs_div
     63   ret i64 %out
     64 }
     65 
     66 define i64 @ror_extract_mul_with_mask(i64 %i) nounwind {
     67 ; CHECK-LABEL: ror_extract_mul_with_mask:
     68 ; CHECK:       // %bb.0:
     69 ; CHECK-NEXT:    add x8, x0, x0, lsl #3
     70 ; CHECK-NEXT:    ror x8, x8, #57
     71 ; CHECK-NEXT:    and x0, x8, #0xff
     72 ; CHECK-NEXT:    ret
     73   %lhs_mul = mul i64 %i, 1152
     74   %rhs_mul = mul i64 %i, 9
     75   %lhs_and = and i64 %lhs_mul, 160
     76   %rhs_shift = lshr i64 %rhs_mul, 57
     77   %out = or i64 %lhs_and, %rhs_shift
     78   ret i64 %out
     79 }
     80 
     81 ; Result would undershift
     82 define i64 @no_extract_shl(i64 %i) nounwind {
     83 ; CHECK-LABEL: no_extract_shl:
     84 ; CHECK:       // %bb.0:
     85 ; CHECK-NEXT:    lsl x8, x0, #10
     86 ; CHECK-NEXT:    bfxil x8, x0, #52, #7
     87 ; CHECK-NEXT:    mov x0, x8
     88 ; CHECK-NEXT:    ret
     89   %lhs_mul = shl i64 %i, 5
     90   %rhs_mul = shl i64 %i, 10
     91   %lhs_shift = lshr i64 %lhs_mul, 57
     92   %out = or i64 %lhs_shift, %rhs_mul
     93   ret i64 %out
     94 }
     95 
     96 ; Result would overshift
     97 define i32 @no_extract_shrl(i32 %i) nounwind {
     98 ; CHECK-LABEL: no_extract_shrl:
     99 ; CHECK:       // %bb.0:
    100 ; CHECK-NEXT:    lsr w8, w0, #3
    101 ; CHECK-NEXT:    lsr w0, w0, #9
    102 ; CHECK-NEXT:    bfi w0, w8, #28, #4
    103 ; CHECK-NEXT:    ret
    104   %lhs_div = lshr i32 %i, 3
    105   %rhs_div = lshr i32 %i, 9
    106   %lhs_shift = shl i32 %lhs_div, 28
    107   %out = or i32 %lhs_shift, %rhs_div
    108   ret i32 %out
    109 }
    110 
    111 ; Can factor 128 from 2304, but result is 18 instead of 9
    112 define i64 @no_extract_mul(i64 %i) nounwind {
    113 ; CHECK-LABEL: no_extract_mul:
    114 ; CHECK:       // %bb.0:
    115 ; CHECK-NEXT:    add x8, x0, x0, lsl #3
    116 ; CHECK-NEXT:    lsr x0, x8, #57
    117 ; CHECK-NEXT:    bfi x0, x8, #8, #56
    118 ; CHECK-NEXT:    ret
    119   %lhs_mul = mul i64 %i, 2304
    120   %rhs_mul = mul i64 %i, 9
    121   %rhs_shift = lshr i64 %rhs_mul, 57
    122   %out = or i64 %lhs_mul, %rhs_shift
    123   ret i64 %out
    124 }
    125 
    126 ; Can't evenly factor 16 from 49
    127 define i32 @no_extract_udiv(i32 %i) nounwind {
    128 ; CHECK-LABEL: no_extract_udiv:
    129 ; CHECK:       // %bb.0:
    130 ; CHECK-NEXT:    mov w8, #43691
    131 ; CHECK-NEXT:    mov w9, #33437
    132 ; CHECK-NEXT:    movk w8, #43690, lsl #16
    133 ; CHECK-NEXT:    movk w9, #21399, lsl #16
    134 ; CHECK-NEXT:    umull x8, w0, w8
    135 ; CHECK-NEXT:    umull x9, w0, w9
    136 ; CHECK-NEXT:    lsr x8, x8, #33
    137 ; CHECK-NEXT:    lsr x9, x9, #32
    138 ; CHECK-NEXT:    extr w0, w8, w9, #4
    139 ; CHECK-NEXT:    ret
    140   %lhs_div = udiv i32 %i, 3
    141   %rhs_div = udiv i32 %i, 49
    142   %lhs_shift = shl i32 %lhs_div, 28
    143   %out = or i32 %lhs_shift, %rhs_div
    144   ret i32 %out
    145 }
    146