1# RUN: llc -O0 -run-pass=legalizer %s -o - | FileCheck %s
2
3--- |
4  target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
5  target triple = "aarch64--"
6  define void @test_inserts_1() { ret void }
7  define void @test_inserts_2() { ret void }
8  define void @test_inserts_3() { ret void }
9  define void @test_inserts_4() { ret void }
10  define void @test_inserts_5() { ret void }
11  define void @test_inserts_6() { ret void }
12  define void @test_inserts_nonpow2() { ret void }
13...
14
15---
16name:            test_inserts_1
17body: |
18  bb.0:
19    liveins: $w0
20
21      ; Low part of insertion wipes out the old register entirely, so %0 gets
22      ; forwarded to the G_STORE. Hi part is unchanged so (split) G_LOAD gets
23      ; forwarded.
24    ; CHECK-LABEL: name: test_inserts_1
25    ; CHECK: [[LO:%[0-9]+]]:_(s64) = G_LOAD
26    ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD
27    ; CHECK: G_STORE %0(s64)
28    ; CHECK: G_STORE [[HI]]
29    %0:_(s64) = COPY $x0
30    %1:_(s32) = COPY $w1
31    %2:_(p0) = COPY $x2
32    %3:_(s128) = G_LOAD %2(p0) :: (load 16)
33    %4:_(s128) = G_INSERT %3(s128), %0(s64), 0
34    G_STORE %4(s128), %2(p0) :: (store 16)
35    RET_ReallyLR
36...
37
38---
39name:            test_inserts_2
40body: |
41  bb.0:
42    liveins: $w0
43
44      ; Low insertion wipes out the old register entirely, so %0 gets forwarded
45      ; to the G_STORE again. Second insertion is real.
46    ; CHECK-LABEL: name: test_inserts_2
47    ; CHECK: [[LO:%[0-9]+]]:_(s64) = G_LOAD
48    ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD
49    ; CHECK: [[NEWHI:%[0-9]+]]:_(s64) = G_INSERT [[HI]], %1(s32), 0
50    ; CHECK: G_STORE %0(s64)
51    ; CHECK: G_STORE [[NEWHI]]
52    %0:_(s64) = COPY $x0
53    %1:_(s32) = COPY $w1
54    %2:_(p0) = COPY $x2
55    %3:_(s128) = G_LOAD %2(p0) :: (load 16)
56    %4:_(s128) = G_INSERT %3(s128), %0(s64), 0
57    %5:_(s128) = G_INSERT %4(s128), %1(s32), 64
58    G_STORE %5(s128), %2(p0) :: (store 16)
59    RET_ReallyLR
60...
61
62---
63name:            test_inserts_3
64body: |
65  bb.0:
66    liveins: $w0
67
68      ; I'm not entirely convinced inserting a p0 into an s64 is valid, but it's
69      ; certainly better than the alternative of directly forwarding the value
70      ; which would cause a nasty type mismatch.
71    ; CHECK-LABEL: name: test_inserts_3
72    ; CHECK: [[LO:%[0-9]+]]:_(s64) = G_LOAD
73    ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD
74    ; CHECK: [[NEWLO:%[0-9]+]]:_(s64) = G_PTRTOINT %0(p0)
75    ; CHECK: G_STORE [[NEWLO]](s64)
76    ; CHECK: G_STORE [[HI]]
77    %0:_(p0) = COPY $x0
78    %1:_(s32) = COPY $w1
79    %2:_(p0) = COPY $x2
80    %3:_(s128) = G_LOAD %2(p0) :: (load 16)
81    %4:_(s128) = G_INSERT %3(s128), %0(p0), 0
82    G_STORE %4(s128), %2(p0) :: (store 16)
83    RET_ReallyLR
84...
85
86---
87name:            test_inserts_4
88body: |
89  bb.0:
90    liveins: $w0
91
92      ; A narrow insert gets surrounded by a G_ANYEXT/G_TRUNC pair.
93    ; CHECK-LABEL: name: test_inserts_4
94    ; CHECK: [[VALEXT:%[0-9]+]]:_(s32) = COPY %2(s32)
95    ; CHECK: [[VAL:%[0-9]+]]:_(s32) = G_INSERT [[VALEXT]], %1(s1), 0
96    ; CHECK: %5:_(s8) = G_TRUNC [[VAL]](s32)
97    %4:_(s32) = COPY $w0
98    %0:_(s1) = G_TRUNC %4
99    %5:_(s32) = COPY $w1
100    %1:_(s8) = G_TRUNC %5
101    %2:_(p0) = COPY $x2
102    %3:_(s8) = G_INSERT %1(s8), %0(s1), 0
103    G_STORE %3(s8), %2(p0) :: (store 1)
104    RET_ReallyLR
105...
106
107---
108name:            test_inserts_5
109body: |
110  bb.0:
111    liveins: $x0, $x1, $x2
112
113
114    ; CHECK-LABEL: name: test_inserts_5
115    ; CHECK: [[INS_LO:%[0-9]+]]:_(s32) = G_EXTRACT %2(s64), 0
116    ; CHECK: [[VAL_LO:%[0-9]+]]:_(s64) = G_INSERT %0, [[INS_LO]](s32), 32
117    ; CHECK: [[INS_HI:%[0-9]+]]:_(s32) = G_EXTRACT %2(s64), 32
118    ; CHECK: [[VAL_HI:%[0-9]+]]:_(s64) = G_INSERT %1, [[INS_HI]](s32), 0
119    ; CHECK: %4:_(s128) = G_MERGE_VALUES [[VAL_LO]](s64), [[VAL_HI]](s64)
120    %0:_(s64) = COPY $x0
121    %1:_(s64) = COPY $x1
122    %2:_(s64) = COPY $x2
123    %3:_(s128) = G_MERGE_VALUES %0, %1
124    %4:_(s128) = G_INSERT %3, %2, 32
125    %5:_(s64) = G_TRUNC %4
126    $x0 = COPY %5
127    RET_ReallyLR
128...
129
130---
131name:            test_inserts_6
132body: |
133  bb.0:
134    liveins: $x0, $x1, $x2
135
136
137    ; CHECK-LABEL: name: test_inserts_6
138    ; CHECK: [[VAL_LO:%[0-9]+]]:_(s64) = G_INSERT %0, %2(s32), 32
139    ; CHECK: %4:_(s128) = G_MERGE_VALUES [[VAL_LO]](s64), %1(s64)
140    %0:_(s64) = COPY $x0
141    %1:_(s64) = COPY $x1
142    %2:_(s32) = COPY $w2
143    %3:_(s128) = G_MERGE_VALUES %0, %1
144    %4:_(s128) = G_INSERT %3, %2, 32
145    %5:_(s64) = G_TRUNC %4
146    $x0 = COPY %5
147    RET_ReallyLR
148...
149
150---
151name:            test_inserts_nonpow2
152body: |
153  bb.0:
154    liveins: $x0, $x1, $x2
155
156
157    ; CHECK-LABEL: name: test_inserts_nonpow2
158    ; CHECK: [[C:%[0-9]+]]:_(s64) = COPY $x3
159    ; CHECK: $x0 = COPY [[C]]
160    %0:_(s64) = COPY $x0
161    %1:_(s64) = COPY $x1
162    %2:_(s64) = COPY $x2
163    %3:_(s64) = COPY $x3
164    %4:_(s192) = G_MERGE_VALUES %0, %1, %2
165    %5:_(s192) = G_INSERT %4, %3, 0
166    %6:_(s64), %7:_(s64), %8:_(s64) = G_UNMERGE_VALUES %5
167    $x0 = COPY %6
168    RET_ReallyLR
169...
170