| # RUN: llc -O0 -run-pass=legalizer %s -o - | FileCheck %s |
| |
| --- | |
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" |
| target triple = "aarch64--" |
| define void @test_inserts_1() { ret void } |
| define void @test_inserts_2() { ret void } |
| define void @test_inserts_3() { ret void } |
| define void @test_inserts_4() { ret void } |
| define void @test_inserts_5() { ret void } |
| define void @test_inserts_6() { ret void } |
| define void @test_inserts_nonpow2() { ret void } |
| ... |
| |
| --- |
| name: test_inserts_1 |
| body: | |
| bb.0: |
| liveins: $w0 |
| |
| ; Low part of insertion wipes out the old register entirely, so %0 gets |
| ; forwarded to the G_STORE. Hi part is unchanged so (split) G_LOAD gets |
| ; forwarded. |
| ; CHECK-LABEL: name: test_inserts_1 |
| ; CHECK: [[LO:%[0-9]+]]:_(s64) = G_LOAD |
| ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD |
| ; CHECK: G_STORE %0(s64) |
| ; CHECK: G_STORE [[HI]] |
| %0:_(s64) = COPY $x0 |
| %1:_(s32) = COPY $w1 |
| %2:_(p0) = COPY $x2 |
| %3:_(s128) = G_LOAD %2(p0) :: (load 16) |
| %4:_(s128) = G_INSERT %3(s128), %0(s64), 0 |
| G_STORE %4(s128), %2(p0) :: (store 16) |
| RET_ReallyLR |
| ... |
| |
| --- |
| name: test_inserts_2 |
| body: | |
| bb.0: |
| liveins: $w0 |
| |
| ; Low insertion wipes out the old register entirely, so %0 gets forwarded |
| ; to the G_STORE again. Second insertion is real. |
| ; CHECK-LABEL: name: test_inserts_2 |
| ; CHECK: [[LO:%[0-9]+]]:_(s64) = G_LOAD |
| ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD |
| ; CHECK: [[NEWHI:%[0-9]+]]:_(s64) = G_INSERT [[HI]], %1(s32), 0 |
| ; CHECK: G_STORE %0(s64) |
| ; CHECK: G_STORE [[NEWHI]] |
| %0:_(s64) = COPY $x0 |
| %1:_(s32) = COPY $w1 |
| %2:_(p0) = COPY $x2 |
| %3:_(s128) = G_LOAD %2(p0) :: (load 16) |
| %4:_(s128) = G_INSERT %3(s128), %0(s64), 0 |
| %5:_(s128) = G_INSERT %4(s128), %1(s32), 64 |
| G_STORE %5(s128), %2(p0) :: (store 16) |
| RET_ReallyLR |
| ... |
| |
| --- |
| name: test_inserts_3 |
| body: | |
| bb.0: |
| liveins: $w0 |
| |
| ; I'm not entirely convinced inserting a p0 into an s64 is valid, but it's |
| ; certainly better than the alternative of directly forwarding the value |
| ; which would cause a nasty type mismatch. |
| ; CHECK-LABEL: name: test_inserts_3 |
| ; CHECK: [[LO:%[0-9]+]]:_(s64) = G_LOAD |
| ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD |
| ; CHECK: [[NEWLO:%[0-9]+]]:_(s64) = G_PTRTOINT %0(p0) |
| ; CHECK: G_STORE [[NEWLO]](s64) |
| ; CHECK: G_STORE [[HI]] |
| %0:_(p0) = COPY $x0 |
| %1:_(s32) = COPY $w1 |
| %2:_(p0) = COPY $x2 |
| %3:_(s128) = G_LOAD %2(p0) :: (load 16) |
| %4:_(s128) = G_INSERT %3(s128), %0(p0), 0 |
| G_STORE %4(s128), %2(p0) :: (store 16) |
| RET_ReallyLR |
| ... |
| |
| --- |
| name: test_inserts_4 |
| body: | |
| bb.0: |
| liveins: $w0 |
| |
| ; A narrow insert gets surrounded by a G_ANYEXT/G_TRUNC pair. |
| ; CHECK-LABEL: name: test_inserts_4 |
| ; CHECK: [[VALEXT:%[0-9]+]]:_(s32) = COPY %2(s32) |
| ; CHECK: [[VAL:%[0-9]+]]:_(s32) = G_INSERT [[VALEXT]], %1(s1), 0 |
| ; CHECK: %5:_(s8) = G_TRUNC [[VAL]](s32) |
| %4:_(s32) = COPY $w0 |
| %0:_(s1) = G_TRUNC %4 |
| %5:_(s32) = COPY $w1 |
| %1:_(s8) = G_TRUNC %5 |
| %2:_(p0) = COPY $x2 |
| %3:_(s8) = G_INSERT %1(s8), %0(s1), 0 |
| G_STORE %3(s8), %2(p0) :: (store 1) |
| RET_ReallyLR |
| ... |
| |
| --- |
| name: test_inserts_5 |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| |
| |
| ; CHECK-LABEL: name: test_inserts_5 |
| ; CHECK: [[INS_LO:%[0-9]+]]:_(s32) = G_EXTRACT %2(s64), 0 |
| ; CHECK: [[VAL_LO:%[0-9]+]]:_(s64) = G_INSERT %0, [[INS_LO]](s32), 32 |
| ; CHECK: [[INS_HI:%[0-9]+]]:_(s32) = G_EXTRACT %2(s64), 32 |
| ; CHECK: [[VAL_HI:%[0-9]+]]:_(s64) = G_INSERT %1, [[INS_HI]](s32), 0 |
| ; CHECK: %4:_(s128) = G_MERGE_VALUES [[VAL_LO]](s64), [[VAL_HI]](s64) |
| %0:_(s64) = COPY $x0 |
| %1:_(s64) = COPY $x1 |
| %2:_(s64) = COPY $x2 |
| %3:_(s128) = G_MERGE_VALUES %0, %1 |
| %4:_(s128) = G_INSERT %3, %2, 32 |
| %5:_(s64) = G_TRUNC %4 |
| $x0 = COPY %5 |
| RET_ReallyLR |
| ... |
| |
| --- |
| name: test_inserts_6 |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| |
| |
| ; CHECK-LABEL: name: test_inserts_6 |
| ; CHECK: [[VAL_LO:%[0-9]+]]:_(s64) = G_INSERT %0, %2(s32), 32 |
| ; CHECK: %4:_(s128) = G_MERGE_VALUES [[VAL_LO]](s64), %1(s64) |
| %0:_(s64) = COPY $x0 |
| %1:_(s64) = COPY $x1 |
| %2:_(s32) = COPY $w2 |
| %3:_(s128) = G_MERGE_VALUES %0, %1 |
| %4:_(s128) = G_INSERT %3, %2, 32 |
| %5:_(s64) = G_TRUNC %4 |
| $x0 = COPY %5 |
| RET_ReallyLR |
| ... |
| |
| --- |
| name: test_inserts_nonpow2 |
| body: | |
| bb.0: |
| liveins: $x0, $x1, $x2 |
| |
| |
| ; CHECK-LABEL: name: test_inserts_nonpow2 |
| ; CHECK: [[C:%[0-9]+]]:_(s64) = COPY $x3 |
| ; CHECK: $x0 = COPY [[C]] |
| %0:_(s64) = COPY $x0 |
| %1:_(s64) = COPY $x1 |
| %2:_(s64) = COPY $x2 |
| %3:_(s64) = COPY $x3 |
| %4:_(s192) = G_MERGE_VALUES %0, %1, %2 |
| %5:_(s192) = G_INSERT %4, %3, 0 |
| %6:_(s64), %7:_(s64), %8:_(s64) = G_UNMERGE_VALUES %5 |
| $x0 = COPY %6 |
| RET_ReallyLR |
| ... |