| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py |
| # RUN: llc -mtriple aarch64-apple-darwin -debugify-and-strip-all-safe -run-pass=aarch64-prelegalizer-combiner -global-isel -verify-machineinstrs %s -o - | FileCheck %s |
| |
| # Check that we propagate the G_SEXT to the sources of the phi operand. |
| --- |
| name: sext_icst_through_phi |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: sext_icst_through_phi |
| ; CHECK: bb.0.entry: |
| ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 |
| ; CHECK: %one:_(s32) = G_CONSTANT i32 2 |
| ; CHECK: %cmp:_(s1) = G_ICMP intpred(sle), [[COPY]](s32), %one |
| ; CHECK: G_BRCOND %cmp(s1), %bb.2 |
| ; CHECK: G_BR %bb.1 |
| ; CHECK: bb.1: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_4:_(s32) = G_CONSTANT i32 4 |
| ; CHECK: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT %cst32_4(s32) |
| ; CHECK: G_BR %bb.3 |
| ; CHECK: bb.2: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_10:_(s32) = G_CONSTANT i32 10 |
| ; CHECK: [[SEXT1:%[0-9]+]]:_(s64) = G_SEXT %cst32_10(s32) |
| ; CHECK: bb.3: |
| ; CHECK: %ext:_(s64) = G_PHI [[SEXT]](s64), %bb.1, [[SEXT1]](s64), %bb.2 |
| ; CHECK: $x0 = COPY %ext(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| bb.1.entry: |
| liveins: $w0, $w1 |
| |
| %0:_(s32) = COPY $w0 |
| %1:_(s32) = COPY $w1 |
| %zero:_(s32) = G_CONSTANT i32 0 |
| %one:_(s32) = G_CONSTANT i32 2 |
| %cmp:_(s1) = G_ICMP intpred(sgt), %0(s32), %one |
| G_BRCOND %cmp(s1), %bb.2 |
| G_BR %bb.3 |
| |
| bb.2: |
| %cst32_4:_(s32) = G_CONSTANT i32 4 |
| G_BR %bb.4 |
| |
| bb.3: |
| %cst32_10:_(s32) = G_CONSTANT i32 10 |
| |
| bb.4: |
| %phi:_(s32) = G_PHI %cst32_4(s32), %bb.2, %cst32_10(s32), %bb.3 |
| %ext:_(s64) = G_SEXT %phi |
| $x0 = COPY %ext(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| |
| # Check that we propagate the G_ZEXT to the sources of the phi operand. |
| --- |
| name: zext_icst_through_phi |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: zext_icst_through_phi |
| ; CHECK: bb.0.entry: |
| ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 |
| ; CHECK: %one:_(s32) = G_CONSTANT i32 2 |
| ; CHECK: %cmp:_(s1) = G_ICMP intpred(sle), [[COPY]](s32), %one |
| ; CHECK: G_BRCOND %cmp(s1), %bb.2 |
| ; CHECK: G_BR %bb.1 |
| ; CHECK: bb.1: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_4:_(s32) = G_CONSTANT i32 4 |
| ; CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT %cst32_4(s32) |
| ; CHECK: G_BR %bb.3 |
| ; CHECK: bb.2: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_10:_(s32) = G_CONSTANT i32 10 |
| ; CHECK: [[ZEXT1:%[0-9]+]]:_(s64) = G_ZEXT %cst32_10(s32) |
| ; CHECK: bb.3: |
| ; CHECK: %ext:_(s64) = G_PHI [[ZEXT]](s64), %bb.1, [[ZEXT1]](s64), %bb.2 |
| ; CHECK: $x0 = COPY %ext(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| bb.1.entry: |
| liveins: $w0, $w1 |
| |
| %0:_(s32) = COPY $w0 |
| %1:_(s32) = COPY $w1 |
| %zero:_(s32) = G_CONSTANT i32 0 |
| %one:_(s32) = G_CONSTANT i32 2 |
| %cmp:_(s1) = G_ICMP intpred(sgt), %0(s32), %one |
| G_BRCOND %cmp(s1), %bb.2 |
| G_BR %bb.3 |
| |
| bb.2: |
| %cst32_4:_(s32) = G_CONSTANT i32 4 |
| G_BR %bb.4 |
| |
| bb.3: |
| %cst32_10:_(s32) = G_CONSTANT i32 10 |
| |
| bb.4: |
| %phi:_(s32) = G_PHI %cst32_4(s32), %bb.2, %cst32_10(s32), %bb.3 |
| %ext:_(s64) = G_ZEXT %phi |
| $x0 = COPY %ext(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| |
| # Don't handle vectors because of potential cost issues. |
| --- |
| name: sext_load_through_phi_vector |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: sext_load_through_phi_vector |
| ; CHECK: bb.0.entry: |
| ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) |
| ; CHECK: liveins: $x0, $q0, $q1 |
| ; CHECK: %ptr:_(p0) = COPY $x0 |
| ; CHECK: %cmp:_(s1) = G_IMPLICIT_DEF |
| ; CHECK: G_BRCOND %cmp(s1), %bb.2 |
| ; CHECK: G_BR %bb.1 |
| ; CHECK: bb.1: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %ld1:_(<4 x s32>) = G_LOAD %ptr(p0) :: (load (<4 x s32>)) |
| ; CHECK: G_BR %bb.3 |
| ; CHECK: bb.2: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %ld2:_(<4 x s32>) = G_LOAD %ptr(p0) :: (load (<4 x s32>)) |
| ; CHECK: bb.3: |
| ; CHECK: %phi:_(<4 x s32>) = G_PHI %ld1(<4 x s32>), %bb.1, %ld2(<4 x s32>), %bb.2 |
| ; CHECK: %ext:_(<4 x s64>) = G_SEXT %phi(<4 x s32>) |
| ; CHECK: G_STORE %ext(<4 x s64>), %ptr(p0) :: (store (<4 x s64>)) |
| ; CHECK: RET_ReallyLR |
| bb.1.entry: |
| liveins: $x0, $q0, $q1 |
| |
| %0:_(<4 x s32>) = COPY $q0 |
| %1:_(<4 x s32>) = COPY $q1 |
| %ptr:_(p0) = COPY $x0 |
| %cmp:_(s1) = G_IMPLICIT_DEF |
| G_BRCOND %cmp(s1), %bb.2 |
| G_BR %bb.3 |
| |
| bb.2: |
| %ld1:_(<4 x s32>) = G_LOAD %ptr(p0) :: (load (<4 x s32>)) |
| G_BR %bb.4 |
| |
| bb.3: |
| %ld2:_(<4 x s32>) = G_LOAD %ptr(p0) :: (load (<4 x s32>)) |
| |
| bb.4: |
| %phi:_(<4 x s32>) = G_PHI %ld1(<4 x s32>), %bb.2, %ld2(<4 x s32>), %bb.3 |
| %ext:_(<4 x s64>) = G_SEXT %phi |
| G_STORE %ext(<4 x s64>), %ptr(p0) :: (store (<4 x s64>)) |
| RET_ReallyLR |
| |
| ... |
| |
| |
| # Check that we don't propagate if the extend is used by a G_PTR_ADD, which on |
| # AArch64 has a good chance of folding in the extend. |
| --- |
| name: sext_icst_through_phi_used_by_ptradd |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: sext_icst_through_phi_used_by_ptradd |
| ; CHECK: bb.0.entry: |
| ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) |
| ; CHECK: liveins: $w0, $w1, $x2 |
| ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 |
| ; CHECK: %base:_(p0) = COPY $x2 |
| ; CHECK: %one:_(s32) = G_CONSTANT i32 2 |
| ; CHECK: %cmp:_(s1) = G_ICMP intpred(sle), [[COPY]](s32), %one |
| ; CHECK: G_BRCOND %cmp(s1), %bb.2 |
| ; CHECK: G_BR %bb.1 |
| ; CHECK: bb.1: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_4:_(s32) = G_CONSTANT i32 4 |
| ; CHECK: G_BR %bb.3 |
| ; CHECK: bb.2: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_10:_(s32) = G_CONSTANT i32 10 |
| ; CHECK: bb.3: |
| ; CHECK: %phi:_(s32) = G_PHI %cst32_4(s32), %bb.1, %cst32_10(s32), %bb.2 |
| ; CHECK: %ext:_(s64) = G_SEXT %phi(s32) |
| ; CHECK: %ptr:_(p0) = G_PTR_ADD %base, %ext(s64) |
| ; CHECK: $x0 = COPY %ptr(p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| bb.1.entry: |
| liveins: $w0, $w1, $x2 |
| |
| %0:_(s32) = COPY $w0 |
| %1:_(s32) = COPY $w1 |
| %base:_(p0) = COPY $x2 |
| %zero:_(s32) = G_CONSTANT i32 0 |
| %one:_(s32) = G_CONSTANT i32 2 |
| %cmp:_(s1) = G_ICMP intpred(sgt), %0(s32), %one |
| G_BRCOND %cmp(s1), %bb.2 |
| G_BR %bb.3 |
| |
| bb.2: |
| %cst32_4:_(s32) = G_CONSTANT i32 4 |
| G_BR %bb.4 |
| |
| bb.3: |
| %cst32_10:_(s32) = G_CONSTANT i32 10 |
| |
| bb.4: |
| %phi:_(s32) = G_PHI %cst32_4(s32), %bb.2, %cst32_10(s32), %bb.3 |
| %ext:_(s64) = G_SEXT %phi |
| %ptr:_(p0) = G_PTR_ADD %base, %ext |
| $x0 = COPY %ptr(p0) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| |
| # Same as above but we do it here because the extend has multiple users, so the |
| # it probably won't cost extra instructions if we remove it. |
| --- |
| name: sext_icst_through_phi_used_by_ptradd_multiuse |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: sext_icst_through_phi_used_by_ptradd_multiuse |
| ; CHECK: bb.0.entry: |
| ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) |
| ; CHECK: liveins: $w0, $w1, $x2 |
| ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 |
| ; CHECK: %base:_(p0) = COPY $x2 |
| ; CHECK: %one:_(s32) = G_CONSTANT i32 2 |
| ; CHECK: %cmp:_(s1) = G_ICMP intpred(sle), [[COPY]](s32), %one |
| ; CHECK: G_BRCOND %cmp(s1), %bb.2 |
| ; CHECK: G_BR %bb.1 |
| ; CHECK: bb.1: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_4:_(s32) = G_CONSTANT i32 4 |
| ; CHECK: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT %cst32_4(s32) |
| ; CHECK: G_BR %bb.3 |
| ; CHECK: bb.2: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_10:_(s32) = G_CONSTANT i32 10 |
| ; CHECK: [[SEXT1:%[0-9]+]]:_(s64) = G_SEXT %cst32_10(s32) |
| ; CHECK: bb.3: |
| ; CHECK: %ext:_(s64) = G_PHI [[SEXT]](s64), %bb.1, [[SEXT1]](s64), %bb.2 |
| ; CHECK: %ptr:_(p0) = G_PTR_ADD %base, %ext(s64) |
| ; CHECK: $x0 = COPY %ptr(p0) |
| ; CHECK: $x1 = COPY %ext(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| bb.1.entry: |
| liveins: $w0, $w1, $x2 |
| |
| %0:_(s32) = COPY $w0 |
| %1:_(s32) = COPY $w1 |
| %base:_(p0) = COPY $x2 |
| %zero:_(s32) = G_CONSTANT i32 0 |
| %one:_(s32) = G_CONSTANT i32 2 |
| %cmp:_(s1) = G_ICMP intpred(sgt), %0(s32), %one |
| G_BRCOND %cmp(s1), %bb.2 |
| G_BR %bb.3 |
| |
| bb.2: |
| %cst32_4:_(s32) = G_CONSTANT i32 4 |
| G_BR %bb.4 |
| |
| bb.3: |
| %cst32_10:_(s32) = G_CONSTANT i32 10 |
| |
| bb.4: |
| %phi:_(s32) = G_PHI %cst32_4(s32), %bb.2, %cst32_10(s32), %bb.3 |
| %ext:_(s64) = G_SEXT %phi |
| %ptr:_(p0) = G_PTR_ADD %base, %ext |
| $x0 = COPY %ptr(p0) |
| $x1 = COPY %ext(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| |
| # Check we don't propagate if there are more than 2 unique incoming values in the phi. |
| # Doing so might cause too much code bloat. |
| --- |
| name: zext_icst_through_phi_too_many_incoming |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: zext_icst_through_phi_too_many_incoming |
| ; CHECK: bb.0.entry: |
| ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 |
| ; CHECK: %one:_(s32) = G_CONSTANT i32 2 |
| ; CHECK: %cmp:_(s1) = G_ICMP intpred(sle), [[COPY]](s32), %one |
| ; CHECK: G_BRCOND %cmp(s1), %bb.2 |
| ; CHECK: G_BR %bb.1 |
| ; CHECK: bb.1: |
| ; CHECK: successors: %bb.3(0x40000000), %bb.4(0x40000000) |
| ; CHECK: %cst32_4:_(s32) = G_CONSTANT i32 4 |
| ; CHECK: %cond:_(s1) = G_IMPLICIT_DEF |
| ; CHECK: G_BRCOND %cond(s1), %bb.3 |
| ; CHECK: G_BR %bb.4 |
| ; CHECK: bb.2: |
| ; CHECK: successors: %bb.4(0x80000000) |
| ; CHECK: %cst32_10:_(s32) = G_CONSTANT i32 10 |
| ; CHECK: G_BR %bb.4 |
| ; CHECK: bb.3: |
| ; CHECK: successors: %bb.4(0x80000000) |
| ; CHECK: %cst32_42:_(s32) = G_CONSTANT i32 42 |
| ; CHECK: bb.4: |
| ; CHECK: %phi:_(s32) = G_PHI %cst32_4(s32), %bb.1, %cst32_10(s32), %bb.2, %cst32_42(s32), %bb.3 |
| ; CHECK: %ext:_(s64) = G_ZEXT %phi(s32) |
| ; CHECK: $x0 = COPY %ext(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| bb.1.entry: |
| liveins: $w0, $w1 |
| |
| %0:_(s32) = COPY $w0 |
| %1:_(s32) = COPY $w1 |
| %zero:_(s32) = G_CONSTANT i32 0 |
| %one:_(s32) = G_CONSTANT i32 2 |
| %cmp:_(s1) = G_ICMP intpred(sgt), %0(s32), %one |
| G_BRCOND %cmp(s1), %bb.2 |
| G_BR %bb.3 |
| |
| bb.2: |
| %cst32_4:_(s32) = G_CONSTANT i32 4 |
| %cond:_(s1) = G_IMPLICIT_DEF |
| G_BRCOND %cond, %bb.5 |
| G_BR %bb.4 |
| |
| bb.3: |
| %cst32_10:_(s32) = G_CONSTANT i32 10 |
| G_BR %bb.4 |
| |
| bb.5: |
| %cst32_42:_(s32) = G_CONSTANT i32 42 |
| |
| bb.4: |
| %phi:_(s32) = G_PHI %cst32_4(s32), %bb.2, %cst32_10(s32), %bb.3, %cst32_42(s32), %bb.5 |
| %ext:_(s64) = G_ZEXT %phi |
| $x0 = COPY %ext(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| |
| # Check that we don't propagate if the extension would be of a non-allowed inst. |
| --- |
| name: sext_add_through_phi |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: sext_add_through_phi |
| ; CHECK: bb.0.entry: |
| ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 |
| ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 |
| ; CHECK: %one:_(s32) = G_CONSTANT i32 2 |
| ; CHECK: %cmp:_(s1) = G_ICMP intpred(sle), [[COPY]](s32), %one |
| ; CHECK: G_BRCOND %cmp(s1), %bb.2 |
| ; CHECK: G_BR %bb.1 |
| ; CHECK: bb.1: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %add:_(s32) = G_ADD [[COPY]], [[COPY1]] |
| ; CHECK: G_BR %bb.3 |
| ; CHECK: bb.2: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_10:_(s32) = G_CONSTANT i32 10 |
| ; CHECK: bb.3: |
| ; CHECK: %phi:_(s32) = G_PHI %add(s32), %bb.1, %cst32_10(s32), %bb.2 |
| ; CHECK: %ext:_(s64) = G_SEXT %phi(s32) |
| ; CHECK: $x0 = COPY %ext(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| bb.1.entry: |
| liveins: $w0, $w1 |
| |
| %0:_(s32) = COPY $w0 |
| %1:_(s32) = COPY $w1 |
| %zero:_(s32) = G_CONSTANT i32 0 |
| %one:_(s32) = G_CONSTANT i32 2 |
| %cmp:_(s1) = G_ICMP intpred(sgt), %0(s32), %one |
| G_BRCOND %cmp(s1), %bb.2 |
| G_BR %bb.3 |
| |
| bb.2: |
| %add:_(s32) = G_ADD %0, %1 |
| G_BR %bb.4 |
| |
| bb.3: |
| %cst32_10:_(s32) = G_CONSTANT i32 10 |
| |
| bb.4: |
| %phi:_(s32) = G_PHI %add(s32), %bb.2, %cst32_10(s32), %bb.3 |
| %ext:_(s64) = G_SEXT %phi |
| $x0 = COPY %ext(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| |
| # Same as above but allowed with a G_ANYEXT. |
| --- |
| name: anyext_add_through_phi |
| tracksRegLiveness: true |
| body: | |
| ; CHECK-LABEL: name: anyext_add_through_phi |
| ; CHECK: bb.0.entry: |
| ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) |
| ; CHECK: liveins: $w0, $w1 |
| ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 |
| ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 |
| ; CHECK: %one:_(s32) = G_CONSTANT i32 2 |
| ; CHECK: %cmp:_(s1) = G_ICMP intpred(sle), [[COPY]](s32), %one |
| ; CHECK: G_BRCOND %cmp(s1), %bb.2 |
| ; CHECK: G_BR %bb.1 |
| ; CHECK: bb.1: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %add:_(s32) = G_ADD [[COPY]], [[COPY1]] |
| ; CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT %add(s32) |
| ; CHECK: G_BR %bb.3 |
| ; CHECK: bb.2: |
| ; CHECK: successors: %bb.3(0x80000000) |
| ; CHECK: %cst32_10:_(s32) = G_CONSTANT i32 10 |
| ; CHECK: [[ANYEXT1:%[0-9]+]]:_(s64) = G_ANYEXT %cst32_10(s32) |
| ; CHECK: bb.3: |
| ; CHECK: %ext:_(s64) = G_PHI [[ANYEXT]](s64), %bb.1, [[ANYEXT1]](s64), %bb.2 |
| ; CHECK: $x0 = COPY %ext(s64) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| bb.1.entry: |
| liveins: $w0, $w1 |
| |
| %0:_(s32) = COPY $w0 |
| %1:_(s32) = COPY $w1 |
| %zero:_(s32) = G_CONSTANT i32 0 |
| %one:_(s32) = G_CONSTANT i32 2 |
| %cmp:_(s1) = G_ICMP intpred(sgt), %0(s32), %one |
| G_BRCOND %cmp(s1), %bb.2 |
| G_BR %bb.3 |
| |
| bb.2: |
| %add:_(s32) = G_ADD %0, %1 |
| G_BR %bb.4 |
| |
| bb.3: |
| %cst32_10:_(s32) = G_CONSTANT i32 10 |
| |
| bb.4: |
| %phi:_(s32) = G_PHI %add(s32), %bb.2, %cst32_10(s32), %bb.3 |
| %ext:_(s64) = G_ANYEXT %phi |
| $x0 = COPY %ext(s64) |
| RET_ReallyLR implicit $x0 |
| |
| ... |