| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py |
| # RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner --aarch64postlegalizercombinerhelper-only-enable-rule="bitfield_extract_from_and" -verify-machineinstrs %s -o - | FileCheck %s |
| # REQUIRES: asserts |
| |
| # Check that we can combine |
| # |
| # and (lshr x, cst), mask -> ubfx x, cst, width |
| |
| ... |
| --- |
| name: ubfx_s32 |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0 |
| |
| ; LSB = 5 |
| ; Width = LSB + trailing_ones(255) - 1 = |
| ; 5 + 8 - 1 = 12 |
| |
| ; CHECK-LABEL: name: ubfx_s32 |
| ; CHECK: liveins: $w0 |
| ; CHECK: %x:_(s32) = COPY $w0 |
| ; CHECK: %lsb:_(s32) = G_CONSTANT i32 5 |
| ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 |
| ; CHECK: %and:_(s32) = G_UBFX %x, %lsb(s32), [[C]] |
| ; CHECK: $w0 = COPY %and(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %x:_(s32) = COPY $w0 |
| %lsb:_(s32) = G_CONSTANT i32 5 |
| %mask:_(s32) = G_CONSTANT i32 255 |
| %shift:_(s32) = G_LSHR %x, %lsb |
| %and:_(s32) = G_AND %shift, %mask |
| $w0 = COPY %and |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: ubfx_s64 |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0 |
| |
| ; LSB = 5 |
| ; Width = LSB + trailing_ones(1) - 1 = |
| ; 5 + 1 - 1 = 5 |
| |
| ; CHECK-LABEL: name: ubfx_s64 |
| ; CHECK: liveins: $x0 |
| ; CHECK: %x:_(s64) = COPY $x0 |
| ; CHECK: %lsb:_(s64) = G_CONSTANT i64 5 |
| ; CHECK: %mask:_(s64) = G_CONSTANT i64 1 |
| ; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), %mask |
| ; CHECK: $x0 = COPY %and(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %lsb:_(s64) = G_CONSTANT i64 5 |
| %mask:_(s64) = G_CONSTANT i64 1 |
| %shift:_(s64) = G_LSHR %x, %lsb |
| %and:_(s64) = G_AND %shift, %mask |
| $x0 = COPY %and |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_combine_no_and_cst |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| |
| ; UBFX needs to be selected to UBFMWri/UBFMXri, so we need constants. |
| |
| ; CHECK-LABEL: name: dont_combine_no_and_cst |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: %x:_(s32) = COPY $w0 |
| ; CHECK: %y:_(s32) = COPY $w1 |
| ; CHECK: %lsb:_(s32) = G_CONSTANT i32 5 |
| ; CHECK: %shift:_(s32) = G_LSHR %x, %lsb(s32) |
| ; CHECK: %and:_(s32) = G_AND %shift, %y |
| ; CHECK: $w0 = COPY %and(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %lsb:_(s32) = G_CONSTANT i32 5 |
| %shift:_(s32) = G_LSHR %x, %lsb |
| %and:_(s32) = G_AND %shift, %y |
| $w0 = COPY %and |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: dont_combine_and_cst_not_mask |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0 |
| ; CHECK-LABEL: name: dont_combine_and_cst_not_mask |
| ; CHECK: liveins: $w0 |
| ; CHECK: %x:_(s32) = COPY $w0 |
| ; CHECK: %lsb:_(s32) = G_CONSTANT i32 5 |
| ; CHECK: %not_a_mask:_(s32) = G_CONSTANT i32 2 |
| ; CHECK: %shift:_(s32) = G_LSHR %x, %lsb(s32) |
| ; CHECK: %and:_(s32) = G_AND %shift, %not_a_mask |
| ; CHECK: $w0 = COPY %and(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %x:_(s32) = COPY $w0 |
| %lsb:_(s32) = G_CONSTANT i32 5 |
| %not_a_mask:_(s32) = G_CONSTANT i32 2 |
| %shift:_(s32) = G_LSHR %x, %lsb |
| %and:_(s32) = G_AND %shift, %not_a_mask |
| $w0 = COPY %and |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: dont_combine_shift_more_than_one_use |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0 |
| ; CHECK-LABEL: name: dont_combine_shift_more_than_one_use |
| ; CHECK: liveins: $x0 |
| ; CHECK: %x:_(s64) = COPY $x0 |
| ; CHECK: %lsb:_(s64) = G_CONSTANT i64 5 |
| ; CHECK: %mask:_(s64) = G_CONSTANT i64 1 |
| ; CHECK: %shift:_(s64) = G_LSHR %x, %lsb(s64) |
| ; CHECK: %and:_(s64) = G_AND %shift, %mask |
| ; CHECK: %sub:_(s64) = G_SUB %and, %shift |
| ; CHECK: $x0 = COPY %sub(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %lsb:_(s64) = G_CONSTANT i64 5 |
| %mask:_(s64) = G_CONSTANT i64 1 |
| %shift:_(s64) = G_LSHR %x, %lsb |
| %and:_(s64) = G_AND %shift, %mask |
| %sub:_(s64) = G_SUB %and, %shift |
| $x0 = COPY %sub |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_combine_negative_lsb |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0 |
| |
| ; LSB must be in [0, reg_size) |
| |
| ; CHECK-LABEL: name: dont_combine_negative_lsb |
| ; CHECK: liveins: $w0 |
| ; CHECK: %x:_(s32) = COPY $w0 |
| ; CHECK: %negative:_(s32) = G_CONSTANT i32 -1 |
| ; CHECK: %mask:_(s32) = G_CONSTANT i32 255 |
| ; CHECK: %shift:_(s32) = G_LSHR %x, %negative(s32) |
| ; CHECK: %and:_(s32) = G_AND %shift, %mask |
| ; CHECK: $w0 = COPY %and(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %x:_(s32) = COPY $w0 |
| %negative:_(s32) = G_CONSTANT i32 -1 |
| %mask:_(s32) = G_CONSTANT i32 255 |
| %shift:_(s32) = G_LSHR %x, %negative |
| %and:_(s32) = G_AND %shift, %mask |
| $w0 = COPY %and |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: dont_combine_lsb_too_large |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0 |
| |
| ; LSB must be in [0, reg_size) |
| |
| ; CHECK-LABEL: name: dont_combine_lsb_too_large |
| ; CHECK: liveins: $w0 |
| ; CHECK: %x:_(s32) = COPY $w0 |
| ; CHECK: %too_large:_(s32) = G_CONSTANT i32 32 |
| ; CHECK: %mask:_(s32) = G_CONSTANT i32 255 |
| ; CHECK: %shift:_(s32) = G_LSHR %x, %too_large(s32) |
| ; CHECK: %and:_(s32) = G_AND %shift, %mask |
| ; CHECK: $w0 = COPY %and(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %x:_(s32) = COPY $w0 |
| %too_large:_(s32) = G_CONSTANT i32 32 |
| %mask:_(s32) = G_CONSTANT i32 255 |
| %shift:_(s32) = G_LSHR %x, %too_large |
| %and:_(s32) = G_AND %shift, %mask |
| $w0 = COPY %and |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: dont_combine_vector |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $d0 |
| ; CHECK-LABEL: name: dont_combine_vector |
| ; CHECK: liveins: $d0 |
| ; CHECK: %x:_(<2 x s32>) = COPY $d0 |
| ; CHECK: %lsb_cst:_(s32) = G_CONSTANT i32 5 |
| ; CHECK: %lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst(s32), %lsb_cst(s32) |
| ; CHECK: %mask_cst:_(s32) = G_CONSTANT i32 255 |
| ; CHECK: %mask:_(<2 x s32>) = G_BUILD_VECTOR %mask_cst(s32), %mask_cst(s32) |
| ; CHECK: %shift:_(<2 x s32>) = G_LSHR %x, %lsb(<2 x s32>) |
| ; CHECK: %and:_(<2 x s32>) = G_AND %shift, %mask |
| ; CHECK: $d0 = COPY %and(<2 x s32>) |
| ; CHECK: RET_ReallyLR implicit $d0 |
| %x:_(<2 x s32>) = COPY $d0 |
| %lsb_cst:_(s32) = G_CONSTANT i32 5 |
| %lsb:_(<2 x s32>) = G_BUILD_VECTOR %lsb_cst, %lsb_cst |
| %mask_cst:_(s32) = G_CONSTANT i32 255 |
| %mask:_(<2 x s32>) = G_BUILD_VECTOR %mask_cst, %mask_cst |
| %shift:_(<2 x s32>) = G_LSHR %x, %lsb |
| %and:_(<2 x s32>) = G_AND %shift, %mask |
| $d0 = COPY %and |
| RET_ReallyLR implicit $d0 |
| |
| ... |
| --- |
| name: max_signed_int_mask |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0 |
| ; mask = 0111 1111 1111 ... 1111 |
| ; mask + 1 = 1000 0000 0000 ... 0000 |
| ; CHECK-LABEL: name: max_signed_int_mask |
| ; CHECK: liveins: $x0 |
| ; CHECK: %x:_(s64) = COPY $x0 |
| ; CHECK: %lsb:_(s64) = G_CONSTANT i64 0 |
| ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63 |
| ; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]] |
| ; CHECK: $x0 = COPY %and(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %lsb:_(s64) = G_CONSTANT i64 0 |
| %mask:_(s64) = G_CONSTANT i64 9223372036854775807 |
| %shift:_(s64) = G_LSHR %x, %lsb |
| %and:_(s64) = G_AND %shift, %mask |
| $x0 = COPY %and |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: max_unsigned_int_mask |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0 |
| ; mask = 1111 1111 1111 ... 1111 |
| ; mask + 1 = 0000 0000 0000 ... 000 |
| ; CHECK-LABEL: name: max_unsigned_int_mask |
| ; CHECK: liveins: $x0 |
| ; CHECK: %x:_(s64) = COPY $x0 |
| ; CHECK: %lsb:_(s64) = G_CONSTANT i64 5 |
| ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 |
| ; CHECK: %and:_(s64) = G_UBFX %x, %lsb(s64), [[C]] |
| ; CHECK: $x0 = COPY %and(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %lsb:_(s64) = G_CONSTANT i64 5 |
| %mask:_(s64) = G_CONSTANT i64 18446744073709551615 |
| %shift:_(s64) = G_LSHR %x, %lsb |
| %and:_(s64) = G_AND %shift, %mask |
| $x0 = COPY %and |
| RET_ReallyLR implicit $x0 |