379 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=aarch64-apple-ios -global-isel -global-isel-abort=1 | FileCheck %s3 4define dso_local void @trunc_i16_to_i8(i16 %x, ptr %p) {5; CHECK-LABEL: trunc_i16_to_i8:6; CHECK: ; %bb.0:7; CHECK-NEXT: strh w0, [x1]8; CHECK-NEXT: ret9 %t1 = trunc i16 %x to i810 %sh = lshr i16 %x, 811 %t2 = trunc i16 %sh to i812 store i8 %t1, ptr %p, align 113 %p1 = getelementptr inbounds i8, ptr %p, i64 114 store i8 %t2, ptr %p1, align 115 ret void16}17 18define dso_local void @trunc_i32_to_i8(i32 %x, ptr %p) {19; CHECK-LABEL: trunc_i32_to_i8:20; CHECK: ; %bb.0:21; CHECK-NEXT: str w0, [x1]22; CHECK-NEXT: ret23 %t1 = trunc i32 %x to i824 %sh1 = lshr i32 %x, 825 %t2 = trunc i32 %sh1 to i826 %sh2 = lshr i32 %x, 1627 %t3 = trunc i32 %sh2 to i828 %sh3 = lshr i32 %x, 2429 %t4 = trunc i32 %sh3 to i830 store i8 %t1, ptr %p, align 131 %p1 = getelementptr inbounds i8, ptr %p, i64 132 store i8 %t2, ptr %p1, align 133 %p2 = getelementptr inbounds i8, ptr %p, i64 234 store i8 %t3, ptr %p2, align 135 %p3 = getelementptr inbounds i8, ptr %p, i64 336 store i8 %t4, ptr %p3, align 137 ret void38}39 40define dso_local void @trunc_i32_to_i16(i32 %x, ptr %p) {41; CHECK-LABEL: trunc_i32_to_i16:42; CHECK: ; %bb.0:43; CHECK-NEXT: str w0, [x1]44; CHECK-NEXT: ret45 %t1 = trunc i32 %x to i1646 %sh = lshr i32 %x, 1647 %t2 = trunc i32 %sh to i1648 store i16 %t1, ptr %p, align 249 %p1 = getelementptr inbounds i16, ptr %p, i64 150 store i16 %t2, ptr %p1, align 251 ret void52}53 54define dso_local void @be_i32_to_i16(i32 %x, ptr %p0) {55; CHECK-LABEL: be_i32_to_i16:56; CHECK: ; %bb.0:57; CHECK-NEXT: ror w8, w0, #1658; CHECK-NEXT: str w8, [x1]59; CHECK-NEXT: ret60 %sh1 = lshr i32 %x, 1661 %t0 = trunc i32 %x to i1662 %t1 = trunc i32 %sh1 to i1663 %p1 = getelementptr inbounds i16, ptr %p0, i64 164 store i16 %t0, ptr %p1, align 265 store i16 %t1, ptr %p0, align 266 ret void67}68 69define dso_local void @be_i32_to_i16_order(i32 %x, ptr %p0) {70; CHECK-LABEL: be_i32_to_i16_order:71; CHECK: ; %bb.0:72; CHECK-NEXT: ror w8, w0, #1673; CHECK-NEXT: str w8, [x1]74; CHECK-NEXT: ret75 %sh1 = lshr i32 %x, 1676 %t0 = trunc i32 %x to i1677 %t1 = trunc i32 %sh1 to i1678 %p1 = getelementptr inbounds i16, ptr %p0, i64 179 store i16 %t1, ptr %p0, align 280 store i16 %t0, ptr %p1, align 281 ret void82}83 84define dso_local void @trunc_i64_to_i8(i64 %x, ptr %p) {85; CHECK-LABEL: trunc_i64_to_i8:86; CHECK: ; %bb.0:87; CHECK-NEXT: str x0, [x1]88; CHECK-NEXT: ret89 %t1 = trunc i64 %x to i890 %sh1 = lshr i64 %x, 891 %t2 = trunc i64 %sh1 to i892 %sh2 = lshr i64 %x, 1693 %t3 = trunc i64 %sh2 to i894 %sh3 = lshr i64 %x, 2495 %t4 = trunc i64 %sh3 to i896 %sh4 = lshr i64 %x, 3297 %t5 = trunc i64 %sh4 to i898 %sh5 = lshr i64 %x, 4099 %t6 = trunc i64 %sh5 to i8100 %sh6 = lshr i64 %x, 48101 %t7 = trunc i64 %sh6 to i8102 %sh7 = lshr i64 %x, 56103 %t8 = trunc i64 %sh7 to i8104 store i8 %t1, ptr %p, align 1105 %p1 = getelementptr inbounds i8, ptr %p, i64 1106 store i8 %t2, ptr %p1, align 1107 %p2 = getelementptr inbounds i8, ptr %p, i64 2108 store i8 %t3, ptr %p2, align 1109 %p3 = getelementptr inbounds i8, ptr %p, i64 3110 store i8 %t4, ptr %p3, align 1111 %p4 = getelementptr inbounds i8, ptr %p, i64 4112 store i8 %t5, ptr %p4, align 1113 %p5 = getelementptr inbounds i8, ptr %p, i64 5114 store i8 %t6, ptr %p5, align 1115 %p6 = getelementptr inbounds i8, ptr %p, i64 6116 store i8 %t7, ptr %p6, align 1117 %p7 = getelementptr inbounds i8, ptr %p, i64 7118 store i8 %t8, ptr %p7, align 1119 ret void120}121 122define dso_local void @trunc_i64_to_i16(i64 %x, ptr %p) {123; CHECK-LABEL: trunc_i64_to_i16:124; CHECK: ; %bb.0:125; CHECK-NEXT: str x0, [x1]126; CHECK-NEXT: ret127 %t1 = trunc i64 %x to i16128 %sh1 = lshr i64 %x, 16129 %t2 = trunc i64 %sh1 to i16130 %sh2 = lshr i64 %x, 32131 %t3 = trunc i64 %sh2 to i16132 %sh3 = lshr i64 %x, 48133 %t4 = trunc i64 %sh3 to i16134 store i16 %t1, ptr %p, align 2135 %p1 = getelementptr inbounds i16, ptr %p, i64 1136 store i16 %t2, ptr %p1, align 2137 %p2 = getelementptr inbounds i16, ptr %p, i64 2138 store i16 %t3, ptr %p2, align 2139 %p3 = getelementptr inbounds i16, ptr %p, i64 3140 store i16 %t4, ptr %p3, align 2141 ret void142}143 144define dso_local void @trunc_i64_to_i32(i64 %x, ptr %p) {145; CHECK-LABEL: trunc_i64_to_i32:146; CHECK: ; %bb.0:147; CHECK-NEXT: str x0, [x1]148; CHECK-NEXT: ret149 %t1 = trunc i64 %x to i32150 %sh = lshr i64 %x, 32151 %t2 = trunc i64 %sh to i32152 store i32 %t1, ptr %p, align 4153 %p1 = getelementptr inbounds i32, ptr %p, i64 1154 store i32 %t2, ptr %p1, align 4155 ret void156}157define dso_local void @be_i64_to_i32(i64 %x, ptr %p0) {158; CHECK-LABEL: be_i64_to_i32:159; CHECK: ; %bb.0:160; CHECK-NEXT: ror x8, x0, #32161; CHECK-NEXT: str x8, [x1]162; CHECK-NEXT: ret163 %sh1 = lshr i64 %x, 32164 %t0 = trunc i64 %x to i32165 %t1 = trunc i64 %sh1 to i32166 %p1 = getelementptr inbounds i32, ptr %p0, i64 1167 store i32 %t0, ptr %p1, align 4168 store i32 %t1, ptr %p0, align 4169 ret void170}171 172define dso_local void @be_i64_to_i32_order(i64 %x, ptr %p0) {173; CHECK-LABEL: be_i64_to_i32_order:174; CHECK: ; %bb.0:175; CHECK-NEXT: ror x8, x0, #32176; CHECK-NEXT: str x8, [x1]177; CHECK-NEXT: ret178 %sh1 = lshr i64 %x, 32179 %t0 = trunc i64 %x to i32180 %t1 = trunc i64 %sh1 to i32181 %p1 = getelementptr inbounds i32, ptr %p0, i64 1182 store i32 %t1, ptr %p0, align 4183 store i32 %t0, ptr %p1, align 4184 ret void185}186 187; Negative tests.188 189define void @merge_hole(i32 %x, ptr %p) {190; CHECK-LABEL: merge_hole:191; CHECK: ; %bb.0:192; CHECK-NEXT: lsr w8, w0, #16193; CHECK-NEXT: strb w0, [x1]194; CHECK-NEXT: strh w8, [x1, #2]195; CHECK-NEXT: ret196 %p2 = getelementptr inbounds i16, ptr %p, i64 1197 %x3 = trunc i32 %x to i8198 store i8 %x3, ptr %p, align 1199 %sh = lshr i32 %x, 16200 %x01 = trunc i32 %sh to i16201 store i16 %x01, ptr %p2, align 1202 ret void203}204 205define void @merge_hole2(i32 %x, ptr %p) {206; CHECK-LABEL: merge_hole2:207; CHECK: ; %bb.0:208; CHECK-NEXT: lsr w8, w0, #16209; CHECK-NEXT: strb w0, [x1]210; CHECK-NEXT: strh w8, [x1, #2]211; CHECK-NEXT: ret212 %p2 = getelementptr inbounds i16, ptr %p, i64 1213 %sh = lshr i32 %x, 16214 %x01 = trunc i32 %sh to i16215 store i16 %x01, ptr %p2, align 1216 %x3 = trunc i32 %x to i8217 store i8 %x3, ptr %p, align 1218 ret void219}220 221define void @merge_hole3(i32 %x, ptr %p) {222; CHECK-LABEL: merge_hole3:223; CHECK: ; %bb.0:224; CHECK-NEXT: lsr w8, w0, #16225; CHECK-NEXT: strb w0, [x1, #1]226; CHECK-NEXT: strh w8, [x1, #2]227; CHECK-NEXT: ret228 %p1 = getelementptr inbounds i8, ptr %p, i64 1229 %p2 = getelementptr inbounds i16, ptr %p, i64 1230 %x3 = trunc i32 %x to i8231 store i8 %x3, ptr %p1, align 1232 %sh = lshr i32 %x, 16233 %x01 = trunc i32 %sh to i16234 store i16 %x01, ptr %p2, align 1235 ret void236}237 238define void @merge_hole4(i32 %x, ptr %p) {239; CHECK-LABEL: merge_hole4:240; CHECK: ; %bb.0:241; CHECK-NEXT: lsr w8, w0, #16242; CHECK-NEXT: strb w0, [x1, #2]243; CHECK-NEXT: strh w8, [x1]244; CHECK-NEXT: ret245 %p2 = getelementptr inbounds i8, ptr %p, i64 2246 %x3 = trunc i32 %x to i8247 store i8 %x3, ptr %p2, align 1248 %sh = lshr i32 %x, 16249 %x01 = trunc i32 %sh to i16250 store i16 %x01, ptr %p, align 1251 ret void252}253 254define dso_local i32 @load_between_stores(i32 %x, ptr %p, ptr %ptr) {255; CHECK-LABEL: load_between_stores:256; CHECK: ; %bb.0:257; CHECK-NEXT: strh w0, [x1]258; CHECK-NEXT: lsr w9, w0, #16259; CHECK-NEXT: ldr w8, [x2]260; CHECK-NEXT: strh w9, [x1, #2]261; CHECK-NEXT: mov w0, w8262; CHECK-NEXT: ret263 %t1 = trunc i32 %x to i16264 %sh = lshr i32 %x, 16265 %t2 = trunc i32 %sh to i16266 store i16 %t1, ptr %p, align 2267 %ld = load i32, ptr %ptr268 %p1 = getelementptr inbounds i16, ptr %p, i64 1269 store i16 %t2, ptr %p1, align 2270 ret i32 %ld271}272 273define dso_local void @invalid_shift(i16 %x, ptr %p) {274; CHECK-LABEL: invalid_shift:275; CHECK: ; %bb.0:276; CHECK-NEXT: ubfx w8, w0, #4, #12277; CHECK-NEXT: strb w0, [x1]278; CHECK-NEXT: strb w8, [x1, #1]279; CHECK-NEXT: ret280 %t1 = trunc i16 %x to i8281 %sh = lshr i16 %x, 4282 %t2 = trunc i16 %sh to i8283 store i8 %t1, ptr %p, align 1284 %p1 = getelementptr inbounds i8, ptr %p, i64 1285 store i8 %t2, ptr %p1, align 1286 ret void287}288 289define dso_local void @missing_store(i32 %x, ptr %p) {290; The missing store of shift 16 means we can't merge to 32 bit store,291; but we can still partially merge to a 16 bit one.292; CHECK-LABEL: missing_store:293; CHECK: ; %bb.0:294; CHECK-NEXT: lsr w8, w0, #24295; CHECK-NEXT: strh w0, [x1]296; CHECK-NEXT: strb w8, [x1, #3]297; CHECK-NEXT: ret298 %t1 = trunc i32 %x to i8299 %sh1 = lshr i32 %x, 8300 %t2 = trunc i32 %sh1 to i8301 %sh3 = lshr i32 %x, 24302 %t4 = trunc i32 %sh3 to i8303 store i8 %t1, ptr %p, align 1304 %p1 = getelementptr inbounds i8, ptr %p, i64 1305 store i8 %t2, ptr %p1, align 1306 %p3 = getelementptr inbounds i8, ptr %p, i64 3307 store i8 %t4, ptr %p3, align 1308 ret void309}310 311define dso_local void @different_base_reg(i16 %x, ptr %p, ptr %p2) {312; CHECK-LABEL: different_base_reg:313; CHECK: ; %bb.0:314; CHECK-NEXT: ubfx w8, w0, #8, #8315; CHECK-NEXT: strb w0, [x1]316; CHECK-NEXT: strb w8, [x2, #1]317; CHECK-NEXT: ret318 %t1 = trunc i16 %x to i8319 %sh = lshr i16 %x, 8320 %t2 = trunc i16 %sh to i8321 store i8 %t1, ptr %p, align 1322 %p1 = getelementptr inbounds i8, ptr %p2, i64 1323 store i8 %t2, ptr %p1, align 1324 ret void325}326 327define dso_local void @second_store_is_volatile(i16 %x, ptr %p) {328; CHECK-LABEL: second_store_is_volatile:329; CHECK: ; %bb.0:330; CHECK-NEXT: ubfx w8, w0, #8, #8331; CHECK-NEXT: strb w0, [x1]332; CHECK-NEXT: strb w8, [x1, #1]333; CHECK-NEXT: ret334 %t1 = trunc i16 %x to i8335 %sh = lshr i16 %x, 8336 %t2 = trunc i16 %sh to i8337 store volatile i8 %t1, ptr %p, align 1338 %p1 = getelementptr inbounds i8, ptr %p, i64 1339 store i8 %t2, ptr %p1, align 1340 ret void341}342 343declare void @use_ptr(ptr)344 345define dso_local void @trunc_from_larger_src_val(i64 %hold.4.lcssa, ptr %check1792) {346 ; Here we can merge these i8 stores into a single i32 store, but first we need347 ; to truncate the i64 value to i32.348; CHECK-LABEL: trunc_from_larger_src_val:349; CHECK: ; %bb.0:350; CHECK-NEXT: sub sp, sp, #32351; CHECK-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill352; CHECK-NEXT: .cfi_def_cfa_offset 32353; CHECK-NEXT: .cfi_offset w30, -8354; CHECK-NEXT: .cfi_offset w29, -16355; CHECK-NEXT: str w0, [sp, #12]356; CHECK-NEXT: add x0, sp, #12357; CHECK-NEXT: bl _use_ptr358; CHECK-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload359; CHECK-NEXT: add sp, sp, #32360; CHECK-NEXT: ret361 %hbuf = alloca [4 x i8], align 1362 %arrayidx177 = getelementptr inbounds [4 x i8], ptr %hbuf, i64 0, i64 1363 %arrayidx234 = getelementptr inbounds [4 x i8], ptr %hbuf, i64 0, i64 2364 %arrayidx237 = getelementptr inbounds [4 x i8], ptr %hbuf, i64 0, i64 3365 %conv227 = trunc i64 %hold.4.lcssa to i8366 store i8 %conv227, ptr %hbuf, align 1367 %shr229 = lshr i64 %hold.4.lcssa, 8368 %conv230 = trunc i64 %shr229 to i8369 store i8 %conv230, ptr %arrayidx177, align 1370 %shr232 = lshr i64 %hold.4.lcssa, 16371 %conv233 = trunc i64 %shr232 to i8372 store i8 %conv233, ptr %arrayidx234, align 1373 %shr235 = lshr i64 %hold.4.lcssa, 24374 %conv236 = trunc i64 %shr235 to i8375 store i8 %conv236, ptr %arrayidx237, align 1376 call void @use_ptr(ptr noundef nonnull %hbuf)377 ret void378}379