|  | ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | 
|  | ; RUN: llc < %s -mtriple=avr -mattr=movw -verify-machineinstrs | FileCheck %s | 
|  |  | 
|  | define i32 @shl_i32_1(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_1: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 1 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @shl_i32_2(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_2: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 2 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @shl_i32_4(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_4: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    swap r25 | 
|  | ; CHECK-NEXT:    andi r25, 240 | 
|  | ; CHECK-NEXT:    swap r24 | 
|  | ; CHECK-NEXT:    eor r25, r24 | 
|  | ; CHECK-NEXT:    andi r24, 240 | 
|  | ; CHECK-NEXT:    eor r25, r24 | 
|  | ; CHECK-NEXT:    swap r23 | 
|  | ; CHECK-NEXT:    eor r24, r23 | 
|  | ; CHECK-NEXT:    andi r23, 240 | 
|  | ; CHECK-NEXT:    eor r24, r23 | 
|  | ; CHECK-NEXT:    swap r22 | 
|  | ; CHECK-NEXT:    eor r23, r22 | 
|  | ; CHECK-NEXT:    andi r22, 240 | 
|  | ; CHECK-NEXT:    eor r23, r22 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 4 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | ; shift four bits and then shift one bit | 
|  | define i32 @shl_i32_5(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_5: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    swap r25 | 
|  | ; CHECK-NEXT:    andi r25, 240 | 
|  | ; CHECK-NEXT:    swap r24 | 
|  | ; CHECK-NEXT:    eor r25, r24 | 
|  | ; CHECK-NEXT:    andi r24, 240 | 
|  | ; CHECK-NEXT:    eor r25, r24 | 
|  | ; CHECK-NEXT:    swap r23 | 
|  | ; CHECK-NEXT:    eor r24, r23 | 
|  | ; CHECK-NEXT:    andi r23, 240 | 
|  | ; CHECK-NEXT:    eor r24, r23 | 
|  | ; CHECK-NEXT:    swap r22 | 
|  | ; CHECK-NEXT:    eor r23, r22 | 
|  | ; CHECK-NEXT:    andi r22, 240 | 
|  | ; CHECK-NEXT:    eor r23, r22 | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 5 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | ; shift two to the right and move the registers around | 
|  | define i32 @shl_i32_6(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_6: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    mov r18, r1 | 
|  | ; CHECK-NEXT:    ror r18 | 
|  | ; CHECK-NEXT:    lsr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    ror r18 | 
|  | ; CHECK-NEXT:    mov r25, r24 | 
|  | ; CHECK-NEXT:    mov r24, r23 | 
|  | ; CHECK-NEXT:    mov r19, r22 | 
|  | ; CHECK-NEXT:    movw r22, r18 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 6 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  |  | 
|  | ; shift one to the right and move registers around | 
|  | define i32 @shl_i32_7(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_7: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    mov r18, r1 | 
|  | ; CHECK-NEXT:    ror r18 | 
|  | ; CHECK-NEXT:    mov r25, r24 | 
|  | ; CHECK-NEXT:    mov r24, r23 | 
|  | ; CHECK-NEXT:    mov r19, r22 | 
|  | ; CHECK-NEXT:    movw r22, r18 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 7 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @shl_i32_8(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_8: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    mov r25, r24 | 
|  | ; CHECK-NEXT:    mov r24, r23 | 
|  | ; CHECK-NEXT:    mov r23, r22 | 
|  | ; CHECK-NEXT:    mov r22, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 8 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @shl_i32_9(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_9: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    mov r25, r24 | 
|  | ; CHECK-NEXT:    mov r24, r23 | 
|  | ; CHECK-NEXT:    mov r23, r22 | 
|  | ; CHECK-NEXT:    mov r22, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 9 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | ; shift 3 of 4 registers and move the others around | 
|  | define i32 @shl_i32_12(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_12: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    swap r24 | 
|  | ; CHECK-NEXT:    andi r24, 240 | 
|  | ; CHECK-NEXT:    swap r23 | 
|  | ; CHECK-NEXT:    eor r24, r23 | 
|  | ; CHECK-NEXT:    andi r23, 240 | 
|  | ; CHECK-NEXT:    eor r24, r23 | 
|  | ; CHECK-NEXT:    swap r22 | 
|  | ; CHECK-NEXT:    eor r23, r22 | 
|  | ; CHECK-NEXT:    andi r22, 240 | 
|  | ; CHECK-NEXT:    eor r23, r22 | 
|  | ; CHECK-NEXT:    mov r25, r24 | 
|  | ; CHECK-NEXT:    mov r24, r23 | 
|  | ; CHECK-NEXT:    mov r23, r22 | 
|  | ; CHECK-NEXT:    mov r22, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 12 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @shl_i32_15(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_15: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    movw r18, r22 | 
|  | ; CHECK-NEXT:    lsr r24 | 
|  | ; CHECK-NEXT:    ror r19 | 
|  | ; CHECK-NEXT:    ror r18 | 
|  | ; CHECK-NEXT:    mov r23, r1 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    mov r22, r1 | 
|  | ; CHECK-NEXT:    movw r24, r18 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 15 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | ; This is a special case: this shift is performed directly inside SelectionDAG | 
|  | ; instead of as a custom lowering like the other shift operations. | 
|  | define i32 @shl_i32_16(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_16: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    movw r24, r22 | 
|  | ; CHECK-NEXT:    ldi r22, 0 | 
|  | ; CHECK-NEXT:    ldi r23, 0 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 16 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | ; Combined with the register allocator, shift instructions can sometimes be | 
|  | ; optimized away entirely. The least significant registers are simply stored | 
|  | ; directly instead of moving them first. | 
|  | define void @shl_i32_16_ptr(i32 %a, ptr %ptr) { | 
|  | ; CHECK-LABEL: shl_i32_16_ptr: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    movw r30, r20 | 
|  | ; CHECK-NEXT:    std Z+3, r23 | 
|  | ; CHECK-NEXT:    std Z+2, r22 | 
|  | ; CHECK-NEXT:    ldi r24, 0 | 
|  | ; CHECK-NEXT:    ldi r25, 0 | 
|  | ; CHECK-NEXT:    std Z+1, r25 | 
|  | ; CHECK-NEXT:    st Z, r24 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 16 | 
|  | store i32 %res, ptr %ptr | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; shift only the most significant byte and then move it | 
|  | define i32 @shl_i32_28(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_28: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    swap r22 | 
|  | ; CHECK-NEXT:    andi r22, 240 | 
|  | ; CHECK-NEXT:    mov r25, r22 | 
|  | ; CHECK-NEXT:    mov r24, r1 | 
|  | ; CHECK-NEXT:    mov r23, r1 | 
|  | ; CHECK-NEXT:    mov r22, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 28 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | ; move the rightmost bit to the leftmost bit and clear the rest | 
|  | define i32 @shl_i32_31(i32 %a) { | 
|  | ; CHECK-LABEL: shl_i32_31: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsr r22 | 
|  | ; CHECK-NEXT:    mov r25, r1 | 
|  | ; CHECK-NEXT:    ror r25 | 
|  | ; CHECK-NEXT:    mov r24, r1 | 
|  | ; CHECK-NEXT:    mov r23, r1 | 
|  | ; CHECK-NEXT:    mov r22, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = shl i32 %a, 31 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_1(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_1: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 1 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_2(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_2: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    lsr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 2 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_4(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_4: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    swap r22 | 
|  | ; CHECK-NEXT:    andi r22, 15 | 
|  | ; CHECK-NEXT:    swap r23 | 
|  | ; CHECK-NEXT:    eor r22, r23 | 
|  | ; CHECK-NEXT:    andi r23, 15 | 
|  | ; CHECK-NEXT:    eor r22, r23 | 
|  | ; CHECK-NEXT:    swap r24 | 
|  | ; CHECK-NEXT:    eor r23, r24 | 
|  | ; CHECK-NEXT:    andi r24, 15 | 
|  | ; CHECK-NEXT:    eor r23, r24 | 
|  | ; CHECK-NEXT:    swap r25 | 
|  | ; CHECK-NEXT:    eor r24, r25 | 
|  | ; CHECK-NEXT:    andi r25, 15 | 
|  | ; CHECK-NEXT:    eor r24, r25 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 4 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_6(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_6: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    mov r19, r1 | 
|  | ; CHECK-NEXT:    rol r19 | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    rol r19 | 
|  | ; CHECK-NEXT:    mov r22, r23 | 
|  | ; CHECK-NEXT:    mov r23, r24 | 
|  | ; CHECK-NEXT:    mov r18, r25 | 
|  | ; CHECK-NEXT:    movw r24, r18 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 6 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_7(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_7: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    mov r19, r1 | 
|  | ; CHECK-NEXT:    rol r19 | 
|  | ; CHECK-NEXT:    mov r22, r23 | 
|  | ; CHECK-NEXT:    mov r23, r24 | 
|  | ; CHECK-NEXT:    mov r18, r25 | 
|  | ; CHECK-NEXT:    movw r24, r18 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 7 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_8(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_8: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    mov r22, r23 | 
|  | ; CHECK-NEXT:    mov r23, r24 | 
|  | ; CHECK-NEXT:    mov r24, r25 | 
|  | ; CHECK-NEXT:    mov r25, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 8 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_9(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_9: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    mov r22, r23 | 
|  | ; CHECK-NEXT:    mov r23, r24 | 
|  | ; CHECK-NEXT:    mov r24, r25 | 
|  | ; CHECK-NEXT:    mov r25, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 9 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_16(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_16: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    movw r22, r24 | 
|  | ; CHECK-NEXT:    ldi r24, 0 | 
|  | ; CHECK-NEXT:    ldi r25, 0 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 16 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_24(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_24: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    mov r22, r25 | 
|  | ; CHECK-NEXT:    mov r23, r1 | 
|  | ; CHECK-NEXT:    mov r24, r1 | 
|  | ; CHECK-NEXT:    mov r25, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 24 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @lshr_i32_31(i32 %a) { | 
|  | ; CHECK-LABEL: lshr_i32_31: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r25 | 
|  | ; CHECK-NEXT:    mov r22, r1 | 
|  | ; CHECK-NEXT:    rol r22 | 
|  | ; CHECK-NEXT:    mov r23, r1 | 
|  | ; CHECK-NEXT:    mov r24, r1 | 
|  | ; CHECK-NEXT:    mov r25, r1 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = lshr i32 %a, 31 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_1(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_1: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    asr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 1 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_2(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_2: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    asr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    asr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 2 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | ; can't use the swap/andi/eor trick here | 
|  | define i32 @ashr_i32_4(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_4: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    asr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    asr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    asr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    asr r25 | 
|  | ; CHECK-NEXT:    ror r24 | 
|  | ; CHECK-NEXT:    ror r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 4 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_7(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_7: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r22 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    rol r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    sbc r19, r19 | 
|  | ; CHECK-NEXT:    mov r22, r23 | 
|  | ; CHECK-NEXT:    mov r23, r24 | 
|  | ; CHECK-NEXT:    mov r18, r25 | 
|  | ; CHECK-NEXT:    movw r24, r18 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 7 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | ; TODO: this could be optimized to 4 movs, instead of 5. | 
|  | define i32 @ashr_i32_8(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_8: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    mov r19, r25 | 
|  | ; CHECK-NEXT:    lsl r19 | 
|  | ; CHECK-NEXT:    sbc r19, r19 | 
|  | ; CHECK-NEXT:    mov r22, r23 | 
|  | ; CHECK-NEXT:    mov r23, r24 | 
|  | ; CHECK-NEXT:    mov r18, r25 | 
|  | ; CHECK-NEXT:    movw r24, r18 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 8 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_16(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_16: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    movw r22, r24 | 
|  | ; CHECK-NEXT:    lsl r25 | 
|  | ; CHECK-NEXT:    sbc r25, r25 | 
|  | ; CHECK-NEXT:    mov r24, r25 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 16 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_17(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_17: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    movw r22, r24 | 
|  | ; CHECK-NEXT:    lsl r25 | 
|  | ; CHECK-NEXT:    sbc r25, r25 | 
|  | ; CHECK-NEXT:    asr r23 | 
|  | ; CHECK-NEXT:    ror r22 | 
|  | ; CHECK-NEXT:    mov r24, r25 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 17 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_22(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_22: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    sbc r18, r18 | 
|  | ; CHECK-NEXT:    lsl r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    mov r19, r18 | 
|  | ; CHECK-NEXT:    mov r23, r18 | 
|  | ; CHECK-NEXT:    rol r23 | 
|  | ; CHECK-NEXT:    mov r22, r25 | 
|  | ; CHECK-NEXT:    movw r24, r18 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 22 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_23(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_23: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r24 | 
|  | ; CHECK-NEXT:    rol r25 | 
|  | ; CHECK-NEXT:    sbc r23, r23 | 
|  | ; CHECK-NEXT:    mov r22, r25 | 
|  | ; CHECK-NEXT:    mov r24, r23 | 
|  | ; CHECK-NEXT:    mov r25, r23 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 23 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_30(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_30: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r25 | 
|  | ; CHECK-NEXT:    sbc r23, r23 | 
|  | ; CHECK-NEXT:    lsl r25 | 
|  | ; CHECK-NEXT:    mov r22, r23 | 
|  | ; CHECK-NEXT:    rol r22 | 
|  | ; CHECK-NEXT:    mov r24, r23 | 
|  | ; CHECK-NEXT:    mov r25, r23 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 30 | 
|  | ret i32 %res | 
|  | } | 
|  |  | 
|  | define i32 @ashr_i32_31(i32 %a) { | 
|  | ; CHECK-LABEL: ashr_i32_31: | 
|  | ; CHECK:       ; %bb.0: | 
|  | ; CHECK-NEXT:    lsl r25 | 
|  | ; CHECK-NEXT:    sbc r22, r22 | 
|  | ; CHECK-NEXT:    mov r23, r22 | 
|  | ; CHECK-NEXT:    movw r24, r22 | 
|  | ; CHECK-NEXT:    ret | 
|  | %res = ashr i32 %a, 31 | 
|  | ret i32 %res | 
|  | } |