| # 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 |
| --- | |
| declare void @foo() |
| define void @self() { ret void } |
| define void @self_with_copy() { ret void } |
| define void @self_not_equivalent_overwrite_w0() { ret void } |
| define void @self_not_equivalent_overwrite_w0_implicit() { ret void } |
| define void @self_not_equivalent_different_copies() { ret void } |
| define void @self_with_assert_zext() { ret void } |
| ... |
| --- |
| name: self |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; Optimize (cond ? %a : %a) -> %a |
| ; CHECK-LABEL: name: self |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: %a:_(s32) = COPY $w0 |
| ; CHECK: $w0 = COPY %a(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %a:_(s32) = COPY $w0 |
| %cond_wide:gpr(s32) = COPY $w1 |
| %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| %select:_(s32) = G_SELECT %cond(s1), %a, %a |
| $w0 = COPY %select(s32) |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: self_with_copy |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; Optimize (cond ? %a : %b) -> %a |
| ; |
| ; This shows that we are looking through copies correctly and deduce that |
| ; %b is a copy from %a. |
| ; |
| ; CHECK-LABEL: name: self_with_copy |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: %a:_(s32) = COPY $w0 |
| ; CHECK: $w0 = COPY %a(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %a:_(s32) = COPY $w0 |
| %b:_(s32) = COPY %a |
| %cond_wide:gpr(s32) = COPY $w1 |
| %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| %select:_(s32) = G_SELECT %cond(s1), %a, %b |
| $w0 = COPY %select(s32) |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: self_not_equivalent_overwrite_w0 |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; |
| ; $w0 is overwritten by a copy from $w1, so the copies for %a and %b are |
| ; not the same. |
| ; |
| ; CHECK-LABEL: name: self_not_equivalent_overwrite_w0 |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: %a:_(s32) = COPY $w0 |
| ; CHECK: $w0 = COPY $w1 |
| ; CHECK: %b:_(s32) = COPY $w0 |
| ; CHECK: %cond_wide:gpr(s32) = COPY $w1 |
| ; CHECK: %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| ; CHECK: %select:_(s32) = G_SELECT %cond(s1), %a, %b |
| ; CHECK: $w0 = COPY %select(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %a:_(s32) = COPY $w0 |
| $w0 = COPY $w1 |
| %b:_(s32) = COPY $w0 |
| %cond_wide:gpr(s32) = COPY $w1 |
| %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| %select:_(s32) = G_SELECT %cond(s1), %a, %b |
| $w0 = COPY %select(s32) |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: self_not_equivalent_overwrite_w0_implicit |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; |
| ; $w0 is overwritten by a call which defines it implicitly, so the copies |
| ; are not the same. |
| ; |
| ; CHECK-LABEL: name: self_not_equivalent_overwrite_w0_implicit |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: %a:_(s32) = COPY $w0 |
| ; CHECK: BL @foo, implicit-def $w0 |
| ; CHECK: %b:_(s32) = COPY $w0 |
| ; CHECK: %cond_wide:gpr(s32) = COPY $w1 |
| ; CHECK: %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| ; CHECK: %select:_(s32) = G_SELECT %cond(s1), %a, %b |
| ; CHECK: $w0 = COPY %select(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %a:_(s32) = COPY $w0 |
| BL @foo, implicit-def $w0 |
| %b:_(s32) = COPY $w0 |
| %cond_wide:gpr(s32) = COPY $w1 |
| %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| %select:_(s32) = G_SELECT %cond(s1), %a, %b |
| $w0 = COPY %select(s32) |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: self_not_equivalent_different_copies |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; In this case, the copies are not equivalent, so there is no optimization. |
| ; |
| ; CHECK-LABEL: name: self_not_equivalent_different_copies |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: %a:_(s32) = COPY $w0 |
| ; CHECK: %b:_(s32) = COPY $w1 |
| ; CHECK: %cond_wide:gpr(s32) = COPY $w1 |
| ; CHECK: %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| ; CHECK: %select:_(s32) = G_SELECT %cond(s1), %a, %b |
| ; CHECK: $w0 = COPY %select(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %a:_(s32) = COPY $w0 |
| %b:_(s32) = COPY $w1 |
| %c:_(s32) = COPY %b |
| %cond_wide:gpr(s32) = COPY $w1 |
| %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| %select:_(s32) = G_SELECT %cond(s1), %a, %c |
| $w0 = COPY %select(s32) |
| RET_ReallyLR implicit $w0 |
| |
| ... |
| --- |
| name: self_with_assert_zext |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $w0, $w1 |
| ; We should walk through G_ASSERT_ZEXT as if it's a copy, and remove the |
| ; G_SELECT. |
| ; |
| ; CHECK-LABEL: name: self_with_assert_zext |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: %a:_(s32) = COPY $w0 |
| ; CHECK: %a_assert_zext:_(s32) = G_ASSERT_ZEXT %a, 16 |
| ; CHECK: $w0 = COPY %a_assert_zext(s32) |
| ; CHECK: RET_ReallyLR implicit $w0 |
| %a:_(s32) = COPY $w0 |
| %a_assert_zext:_(s32) = G_ASSERT_ZEXT %a, 16 |
| %b:_(s32) = COPY %a_assert_zext |
| %cond_wide:gpr(s32) = COPY $w1 |
| %cond:gpr(s1) = G_TRUNC %cond_wide(s32) |
| %select:_(s32) = G_SELECT %cond(s1), %a_assert_zext, %b |
| $w0 = COPY %select(s32) |
| RET_ReallyLR implicit $w0 |