| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py |
| # RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-PRE |
| # RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POST |
| |
| --- |
| name: or_combine_sext |
| # or (sext X), (sext Y) --> sext (or X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: or_combine_sext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_SEXT [[OR]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_SEXT %x(s32) |
| %hand2:_(s64) = G_SEXT %y(s32) |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: or_combine_zext |
| # or (zext X), (zext Y) --> zext (or X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: or_combine_zext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ZEXT [[OR]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_ZEXT %x(s32) |
| %hand2:_(s64) = G_ZEXT %y(s32) |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: or_combine_anyext |
| # or (anyext X), (anyext Y) --> anyext (or X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: or_combine_anyext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ANYEXT [[OR]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_ANYEXT %x(s32) |
| %hand2:_(s64) = G_ANYEXT %y(s32) |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: and_combine_sext |
| # and (sext X), (sext Y) --> sext (and X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: and_combine_sext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_SEXT [[AND]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_SEXT %x(s32) |
| %hand2:_(s64) = G_SEXT %y(s32) |
| %logic_op:_(s64) = G_AND %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: and_combine_zext |
| # and (zext X), (zext Y) --> zext (and X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: and_combine_zext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ZEXT [[AND]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_ZEXT %x(s32) |
| %hand2:_(s64) = G_ZEXT %y(s32) |
| %logic_op:_(s64) = G_AND %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: and_combine_anyext |
| # and (anyext X), (anyext Y) --> anyext (and X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: and_combine_anyext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ANYEXT [[AND]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_ANYEXT %x(s32) |
| %hand2:_(s64) = G_ANYEXT %y(s32) |
| %logic_op:_(s64) = G_AND %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: xor_combine_sext |
| # xor (sext X), (sext Y) --> sext (xor X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: xor_combine_sext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_SEXT [[XOR]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_SEXT %x(s32) |
| %hand2:_(s64) = G_SEXT %y(s32) |
| %logic_op:_(s64) = G_XOR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: xor_combine_zext |
| # xor (zext X), (zext Y) --> zext (xor X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: xor_combine_zext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ZEXT [[XOR]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_ZEXT %x(s32) |
| %hand2:_(s64) = G_ZEXT %y(s32) |
| %logic_op:_(s64) = G_XOR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: xor_combine_anyext |
| # xor (anyext X), (anyext Y) --> anyext (xor X, Y) |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: xor_combine_anyext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ANYEXT [[XOR]](s32) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_ANYEXT %x(s32) |
| %hand2:_(s64) = G_ANYEXT %y(s32) |
| %logic_op:_(s64) = G_XOR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_combine_different_types |
| # When %x and %y don't have the same type, don't perform the combine. |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: dont_combine_different_types |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %hand1:_(s32) = COPY $w1 |
| ; CHECK-NEXT: %y:_(s16) = G_TRUNC %hand1(s32) |
| ; CHECK-NEXT: %hand2:_(s64) = G_SEXT %x(s32) |
| ; CHECK-NEXT: %logic_op:_(s64) = G_SEXT %y(s16) |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR %hand2, %logic_op |
| ; CHECK-NEXT: $x0 = COPY [[OR]](s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %hand1:_(s32) = COPY $w1 |
| %y:_(s16) = G_TRUNC %hand1(s32) |
| %hand2:_(s64) = G_SEXT %x(s32) |
| %logic_op:_(s64) = G_SEXT %y(s16) |
| %5:_(s64) = G_OR %hand2, %logic_op |
| $x0 = COPY %5(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: illegal_ty |
| # Pre-legalization, it's okay to produce illegal types. |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-PRE-LABEL: name: illegal_ty |
| ; CHECK-PRE: liveins: $w0, $w1 |
| ; CHECK-PRE-NEXT: {{ $}} |
| ; CHECK-PRE-NEXT: %x_wide:_(s32) = COPY $w0 |
| ; CHECK-PRE-NEXT: %y_wide:_(s32) = COPY $w1 |
| ; CHECK-PRE-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR %x_wide, %y_wide |
| ; CHECK-PRE-NEXT: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[OR]](s32) |
| ; CHECK-PRE-NEXT: %logic_op:_(s64) = G_SEXT [[TRUNC]](s1) |
| ; CHECK-PRE-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-PRE-NEXT: RET_ReallyLR implicit $x0 |
| ; |
| ; CHECK-POST-LABEL: name: illegal_ty |
| ; CHECK-POST: liveins: $w0, $w1 |
| ; CHECK-POST-NEXT: {{ $}} |
| ; CHECK-POST-NEXT: %x_wide:_(s32) = COPY $w0 |
| ; CHECK-POST-NEXT: %y_wide:_(s32) = COPY $w1 |
| ; CHECK-POST-NEXT: %x:_(s1) = G_TRUNC %x_wide(s32) |
| ; CHECK-POST-NEXT: %y:_(s1) = G_TRUNC %y_wide(s32) |
| ; CHECK-POST-NEXT: %hand1:_(s64) = G_SEXT %x(s1) |
| ; CHECK-POST-NEXT: %hand2:_(s64) = G_SEXT %y(s1) |
| ; CHECK-POST-NEXT: %logic_op:_(s64) = G_OR %hand1, %hand2 |
| ; CHECK-POST-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-POST-NEXT: RET_ReallyLR implicit $x0 |
| %x_wide:_(s32) = COPY $w0 |
| %y_wide:_(s32) = COPY $w1 |
| %x:_(s1) = G_TRUNC %x_wide |
| %y:_(s1) = G_TRUNC %y_wide |
| %hand1:_(s64) = G_SEXT %x(s1) |
| %hand2:_(s64) = G_SEXT %y(s1) |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: or_combine_and |
| # or (and x, z), (and y, z) --> and (or x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: or_combine_and |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_AND [[OR]], %z |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_AND %x(s64), %z |
| %hand2:_(s64) = G_AND %y(s64), %z |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: or_combine_ashr |
| # or (ashr x, z), (ashr y, z) --> ashr (or x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: or_combine_ashr |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ASHR [[OR]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_ASHR %x(s64), %z |
| %hand2:_(s64) = G_ASHR %y(s64), %z |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: or_combine_lshr |
| # or (lshr x, z), (lshr y, z) --> lshr (or x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: or_combine_lshr |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_LSHR [[OR]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_LSHR %x(s64), %z |
| %hand2:_(s64) = G_LSHR %y(s64), %z |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: or_combine_shl |
| # or (shl x, z), (shl y, z) --> shl (or x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: or_combine_shl |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_SHL [[OR]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_SHL %x(s64), %z |
| %hand2:_(s64) = G_SHL %y(s64), %z |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: xor_combine_and |
| # xor (and x, z), (and y, z) --> and (xor x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: xor_combine_and |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_AND [[XOR]], %z |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_AND %x(s64), %z |
| %hand2:_(s64) = G_AND %y(s64), %z |
| %logic_op:_(s64) = G_XOR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: xor_combine_ashr |
| # xor (ashr x, z), (ashr y, z) --> ashr (xor x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: xor_combine_ashr |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ASHR [[XOR]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_ASHR %x(s64), %z |
| %hand2:_(s64) = G_ASHR %y(s64), %z |
| %logic_op:_(s64) = G_XOR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: xor_combine_lshr |
| # xor (lshr x, z), (lshr y, z) --> lshr (xor x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: xor_combine_lshr |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_LSHR [[XOR]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_LSHR %x(s64), %z |
| %hand2:_(s64) = G_LSHR %y(s64), %z |
| %logic_op:_(s64) = G_XOR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: xor_combine_shl |
| # xor (shl x, z), (shl y, z) --> shl (xor x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: xor_combine_shl |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_SHL [[XOR]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_SHL %x(s64), %z |
| %hand2:_(s64) = G_SHL %y(s64), %z |
| %logic_op:_(s64) = G_XOR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: and_combine_and |
| # and (and x, z), (and y, z) --> and (and x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: and_combine_and |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_AND [[AND]], %z |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_AND %x(s64), %z |
| %hand2:_(s64) = G_AND %y(s64), %z |
| %logic_op:_(s64) = G_AND %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: and_combine_ashr |
| # and (ashr x, z), (ashr y, z) --> ashr (and x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: and_combine_ashr |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_ASHR [[AND]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_ASHR %x(s64), %z |
| %hand2:_(s64) = G_ASHR %y(s64), %z |
| %logic_op:_(s64) = G_AND %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: and_combine_lshr |
| # and (lshr x, z), (lshr y, z) --> lshr (and x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: and_combine_lshr |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_LSHR [[AND]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_LSHR %x(s64), %z |
| %hand2:_(s64) = G_LSHR %y(s64), %z |
| %logic_op:_(s64) = G_AND %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: and_combine_shl |
| # and (shl x, z), (shl y, z) --> shl (and x, y), z |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| ; CHECK-LABEL: name: and_combine_shl |
| ; CHECK: liveins: $x0, $x1, $x2 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z:_(s64) = COPY $x2 |
| ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND %x, %y |
| ; CHECK-NEXT: %logic_op:_(s64) = G_SHL [[AND]], %z(s64) |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z:_(s64) = COPY $x2 |
| %hand1:_(s64) = G_SHL %x(s64), %z |
| %hand2:_(s64) = G_SHL %y(s64), %z |
| %logic_op:_(s64) = G_AND %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_combine_different_defs_on_binop |
| # z1 != z2, so don't combine. |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2, $x3 |
| ; CHECK-LABEL: name: dont_combine_different_defs_on_binop |
| ; CHECK: liveins: $x0, $x1, $x2, $x3 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s64) = COPY $x0 |
| ; CHECK-NEXT: %y:_(s64) = COPY $x1 |
| ; CHECK-NEXT: %z1:_(s64) = COPY $x2 |
| ; CHECK-NEXT: %z2:_(s64) = COPY $x3 |
| ; CHECK-NEXT: %hand1:_(s64) = G_AND %x, %z1 |
| ; CHECK-NEXT: %hand2:_(s64) = G_AND %y, %z2 |
| ; CHECK-NEXT: %logic_op:_(s64) = G_OR %hand1, %hand2 |
| ; CHECK-NEXT: $x0 = COPY %logic_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s64) = COPY $x0 |
| %y:_(s64) = COPY $x1 |
| %z1:_(s64) = COPY $x2 |
| %z2:_(s64) = COPY $x3 |
| %hand1:_(s64) = G_AND %x(s64), %z1 |
| %hand2:_(s64) = G_AND %y(s64), %z2 |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| $x0 = COPY %logic_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_combine_more_than_one_use |
| # The LHS register is used more than once. Don't combine. |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; CHECK-LABEL: name: dont_combine_more_than_one_use |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(s32) = COPY $w0 |
| ; CHECK-NEXT: %y:_(s32) = COPY $w1 |
| ; CHECK-NEXT: %hand1:_(s64) = G_SEXT %x(s32) |
| ; CHECK-NEXT: %hand2:_(s64) = G_SEXT %y(s32) |
| ; CHECK-NEXT: %logic_op:_(s64) = G_OR %hand1, %hand2 |
| ; CHECK-NEXT: %other_op:_(s64) = G_ADD %hand1, %logic_op |
| ; CHECK-NEXT: $x0 = COPY %other_op(s64) |
| ; CHECK-NEXT: RET_ReallyLR implicit $x0 |
| %x:_(s32) = COPY $w0 |
| %y:_(s32) = COPY $w1 |
| %hand1:_(s64) = G_SEXT %x(s32) |
| %hand2:_(s64) = G_SEXT %y(s32) |
| %logic_op:_(s64) = G_OR %hand1, %hand2 |
| %other_op:_(s64) = G_ADD %hand1, %logic_op |
| $x0 = COPY %other_op(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: combine_vector |
| # Show that we can combine vector types. |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $d0, $d1 |
| ; CHECK-LABEL: name: combine_vector |
| ; CHECK: liveins: $d0, $d1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: %x:_(<2 x s32>) = COPY $d0 |
| ; CHECK-NEXT: %y:_(<2 x s32>) = COPY $d1 |
| ; CHECK-NEXT: [[OR:%[0-9]+]]:_(<2 x s32>) = G_OR %x, %y |
| ; CHECK-NEXT: %logic_op:_(<2 x s64>) = G_SEXT [[OR]](<2 x s32>) |
| ; CHECK-NEXT: $q0 = COPY %logic_op(<2 x s64>) |
| ; CHECK-NEXT: RET_ReallyLR implicit $q0 |
| %x:_(<2 x s32>) = COPY $d0 |
| %y:_(<2 x s32>) = COPY $d1 |
| %hand1:_(<2 x s64>) = G_SEXT %x(<2 x s32>) |
| %hand2:_(<2 x s64>) = G_SEXT %y(<2 x s32>) |
| %logic_op:_(<2 x s64>) = G_OR %hand1, %hand2 |
| $q0 = COPY %logic_op(<2 x s64>) |
| RET_ReallyLR implicit $q0 |
| |
| ... |
| --- |
| name: combine_vector_implicitdef |
| tracksRegLiveness: true |
| legalized: true |
| body: | |
| bb.0: |
| liveins: $d0, $d1 |
| ; CHECK-LABEL: name: combine_vector_implicitdef |
| ; CHECK: liveins: $d0, $d1 |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 |
| ; CHECK-NEXT: %logic_op:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64) |
| ; CHECK-NEXT: $q0 = COPY %logic_op(<2 x s64>) |
| ; CHECK-NEXT: RET_ReallyLR implicit $q0 |
| %x:_(<2 x s64>) = G_IMPLICIT_DEF |
| %y:_(<2 x s64>) = G_IMPLICIT_DEF |
| %logic_op:_(<2 x s64>) = G_AND %x, %y |
| $q0 = COPY %logic_op(<2 x s64>) |
| RET_ReallyLR implicit $q0 |