345 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=aarch64-apple-ios -global-isel -global-isel-abort=1 - < %s | FileCheck %s3 4define void @test_simple_2xs8(ptr %ptr) {5; CHECK-LABEL: test_simple_2xs8:6; CHECK: ; %bb.0:7; CHECK-NEXT: mov w8, #4 ; =0x48; CHECK-NEXT: mov w9, #5 ; =0x59; CHECK-NEXT: strb w8, [x0]10; CHECK-NEXT: strb w9, [x0, #1]11; CHECK-NEXT: ret12 store i8 4, ptr %ptr13 %addr2 = getelementptr i8, ptr %ptr, i64 114 store i8 5, ptr %addr215 ret void16}17 18define void @test_simple_2xs16(ptr %ptr) {19; CHECK-LABEL: test_simple_2xs16:20; CHECK: ; %bb.0:21; CHECK-NEXT: mov w8, #4 ; =0x422; CHECK-NEXT: movk w8, #5, lsl #1623; CHECK-NEXT: str w8, [x0]24; CHECK-NEXT: ret25 store i16 4, ptr %ptr26 %addr2 = getelementptr i16, ptr %ptr, i64 127 store i16 5, ptr %addr228 ret void29}30 31define void @test_simple_4xs16(ptr %ptr) {32; CHECK-LABEL: test_simple_4xs16:33; CHECK: ; %bb.0:34; CHECK-NEXT: mov x8, #4 ; =0x435; CHECK-NEXT: movk x8, #5, lsl #1636; CHECK-NEXT: movk x8, #9, lsl #3237; CHECK-NEXT: movk x8, #14, lsl #4838; CHECK-NEXT: str x8, [x0]39; CHECK-NEXT: ret40 store i16 4, ptr %ptr41 %addr2 = getelementptr i16, ptr %ptr, i64 142 store i16 5, ptr %addr243 %addr3 = getelementptr i16, ptr %ptr, i64 244 store i16 9, ptr %addr345 %addr4 = getelementptr i16, ptr %ptr, i64 346 store i16 14, ptr %addr447 ret void48}49 50define void @test_simple_2xs32(ptr %ptr) {51; CHECK-LABEL: test_simple_2xs32:52; CHECK: ; %bb.0:53; CHECK-NEXT: mov x8, #4 ; =0x454; CHECK-NEXT: movk x8, #5, lsl #3255; CHECK-NEXT: str x8, [x0]56; CHECK-NEXT: ret57 store i32 4, ptr %ptr58 %addr2 = getelementptr i32, ptr %ptr, i64 159 store i32 5, ptr %addr260 ret void61}62 63define void @test_simple_2xs64_illegal(ptr %ptr) {64; CHECK-LABEL: test_simple_2xs64_illegal:65; CHECK: ; %bb.0:66; CHECK-NEXT: mov w8, #4 ; =0x467; CHECK-NEXT: mov w9, #5 ; =0x568; CHECK-NEXT: stp x8, x9, [x0]69; CHECK-NEXT: ret70 store i64 4, ptr %ptr71 %addr2 = getelementptr i64, ptr %ptr, i64 172 store i64 5, ptr %addr273 ret void74}75 76; Don't merge vectors...yet.77define void @test_simple_vector(ptr %ptr) {78; CHECK-LABEL: test_simple_vector:79; CHECK: ; %bb.0:80; CHECK-NEXT: mov w8, #4 ; =0x481; CHECK-NEXT: mov w9, #7 ; =0x782; CHECK-NEXT: strh w8, [x0]83; CHECK-NEXT: mov w8, #5 ; =0x584; CHECK-NEXT: strh w9, [x0, #2]85; CHECK-NEXT: mov w9, #8 ; =0x886; CHECK-NEXT: strh w8, [x0, #4]!87; CHECK-NEXT: strh w9, [x0, #2]88; CHECK-NEXT: ret89 store <2 x i16> <i16 4, i16 7>, ptr %ptr90 %addr2 = getelementptr <2 x i16>, ptr %ptr, i64 191 store <2 x i16> <i16 5, i16 8>, ptr %addr292 ret void93}94 95define i32 @test_unknown_alias(ptr %ptr, ptr %aliasptr) {96; CHECK-LABEL: test_unknown_alias:97; CHECK: ; %bb.0:98; CHECK-NEXT: mov w9, #4 ; =0x499; CHECK-NEXT: mov x8, x0100; CHECK-NEXT: str w9, [x0]101; CHECK-NEXT: mov w9, #5 ; =0x5102; CHECK-NEXT: ldr w0, [x1]103; CHECK-NEXT: str w9, [x8, #4]104; CHECK-NEXT: ret105 store i32 4, ptr %ptr106 %ld = load i32, ptr %aliasptr107 %addr2 = getelementptr i32, ptr %ptr, i64 1108 store i32 5, ptr %addr2109 ret i32 %ld110}111 112define void @test_2x_2xs32(ptr %ptr, ptr %ptr2) {113; CHECK-LABEL: test_2x_2xs32:114; CHECK: ; %bb.0:115; CHECK-NEXT: mov w8, #4 ; =0x4116; CHECK-NEXT: mov w9, #5 ; =0x5117; CHECK-NEXT: stp w8, w9, [x0]118; CHECK-NEXT: mov x8, #9 ; =0x9119; CHECK-NEXT: movk x8, #17, lsl #32120; CHECK-NEXT: str x8, [x1]121; CHECK-NEXT: ret122 store i32 4, ptr %ptr123 %addr2 = getelementptr i32, ptr %ptr, i64 1124 store i32 5, ptr %addr2125 126 store i32 9, ptr %ptr2127 %addr4 = getelementptr i32, ptr %ptr2, i64 1128 store i32 17, ptr %addr4129 ret void130}131 132define void @test_simple_var_2xs8(ptr %ptr, i8 %v1, i8 %v2) {133; CHECK-LABEL: test_simple_var_2xs8:134; CHECK: ; %bb.0:135; CHECK-NEXT: strb w1, [x0]136; CHECK-NEXT: strb w2, [x0, #1]137; CHECK-NEXT: ret138 store i8 %v1, ptr %ptr139 %addr2 = getelementptr i8, ptr %ptr, i64 1140 store i8 %v2, ptr %addr2141 ret void142}143 144define void @test_simple_var_2xs16(ptr %ptr, i16 %v1, i16 %v2) {145; CHECK-LABEL: test_simple_var_2xs16:146; CHECK: ; %bb.0:147; CHECK-NEXT: strh w1, [x0]148; CHECK-NEXT: strh w2, [x0, #2]149; CHECK-NEXT: ret150 store i16 %v1, ptr %ptr151 %addr2 = getelementptr i16, ptr %ptr, i64 1152 store i16 %v2, ptr %addr2153 ret void154}155 156define void @test_simple_var_2xs32(ptr %ptr, i32 %v1, i32 %v2) {157; CHECK-LABEL: test_simple_var_2xs32:158; CHECK: ; %bb.0:159; CHECK-NEXT: stp w1, w2, [x0]160; CHECK-NEXT: ret161 store i32 %v1, ptr %ptr162 %addr2 = getelementptr i32, ptr %ptr, i64 1163 store i32 %v2, ptr %addr2164 ret void165}166 167 168; The store to ptr2 prevents merging into a single store.169; We can still merge the stores into addr1 and addr2.170define void @test_alias_4xs16(ptr %ptr, ptr %ptr2) {171; CHECK-LABEL: test_alias_4xs16:172; CHECK: ; %bb.0:173; CHECK-NEXT: mov w8, #4 ; =0x4174; CHECK-NEXT: mov w9, #9 ; =0x9175; CHECK-NEXT: movk w8, #5, lsl #16176; CHECK-NEXT: strh w9, [x0, #4]177; CHECK-NEXT: str w8, [x0]178; CHECK-NEXT: mov w8, #14 ; =0xe179; CHECK-NEXT: strh wzr, [x1]180; CHECK-NEXT: strh w8, [x0, #6]181; CHECK-NEXT: ret182 store i16 4, ptr %ptr183 %addr2 = getelementptr i16, ptr %ptr, i64 1184 store i16 5, ptr %addr2185 %addr3 = getelementptr i16, ptr %ptr, i64 2186 store i16 9, ptr %addr3187 store i16 0, ptr %ptr2188 %addr4 = getelementptr i16, ptr %ptr, i64 3189 store i16 14, ptr %addr4190 ret void191}192 193; Here store of 5 and 9 can be merged, others have aliasing barriers.194define void @test_alias2_4xs16(ptr %ptr, ptr %ptr2, ptr %ptr3) {195; CHECK-LABEL: test_alias2_4xs16:196; CHECK: ; %bb.0:197; CHECK-NEXT: mov w8, #4 ; =0x4198; CHECK-NEXT: strh w8, [x0]199; CHECK-NEXT: mov w8, #5 ; =0x5200; CHECK-NEXT: movk w8, #9, lsl #16201; CHECK-NEXT: strh wzr, [x2]202; CHECK-NEXT: stur w8, [x0, #2]203; CHECK-NEXT: mov w8, #14 ; =0xe204; CHECK-NEXT: strh wzr, [x1]205; CHECK-NEXT: strh w8, [x0, #6]206; CHECK-NEXT: ret207 store i16 4, ptr %ptr208 %addr2 = getelementptr i16, ptr %ptr, i64 1209 store i16 0, ptr %ptr3210 store i16 5, ptr %addr2211 %addr3 = getelementptr i16, ptr %ptr, i64 2212 store i16 9, ptr %addr3213 store i16 0, ptr %ptr2214 %addr4 = getelementptr i16, ptr %ptr, i64 3215 store i16 14, ptr %addr4216 ret void217}218 219; No merging can be done here.220define void @test_alias3_4xs16(ptr %ptr, ptr %ptr2, ptr %ptr3, ptr %ptr4) {221; CHECK-LABEL: test_alias3_4xs16:222; CHECK: ; %bb.0:223; CHECK-NEXT: mov w8, #4 ; =0x4224; CHECK-NEXT: strh w8, [x0]225; CHECK-NEXT: mov w8, #5 ; =0x5226; CHECK-NEXT: strh wzr, [x2]227; CHECK-NEXT: strh w8, [x0, #2]228; CHECK-NEXT: mov w8, #9 ; =0x9229; CHECK-NEXT: strh wzr, [x3]230; CHECK-NEXT: strh w8, [x0, #4]231; CHECK-NEXT: mov w8, #14 ; =0xe232; CHECK-NEXT: strh wzr, [x1]233; CHECK-NEXT: strh w8, [x0, #6]234; CHECK-NEXT: ret235 store i16 4, ptr %ptr236 %addr2 = getelementptr i16, ptr %ptr, i64 1237 store i16 0, ptr %ptr3238 store i16 5, ptr %addr2239 store i16 0, ptr %ptr4240 %addr3 = getelementptr i16, ptr %ptr, i64 2241 store i16 9, ptr %addr3242 store i16 0, ptr %ptr2243 %addr4 = getelementptr i16, ptr %ptr, i64 3244 store i16 14, ptr %addr4245 ret void246}247 248; Can merge because the load is from a different alloca and can't alias.249define i32 @test_alias_allocas_2xs32(ptr %ptr) {250; CHECK-LABEL: test_alias_allocas_2xs32:251; CHECK: ; %bb.0:252; CHECK-NEXT: sub sp, sp, #32253; CHECK-NEXT: .cfi_def_cfa_offset 32254; CHECK-NEXT: mov x8, #4 ; =0x4255; CHECK-NEXT: ldr w0, [sp, #4]256; CHECK-NEXT: movk x8, #5, lsl #32257; CHECK-NEXT: str x8, [sp, #8]258; CHECK-NEXT: add sp, sp, #32259; CHECK-NEXT: ret260 %a1 = alloca [6 x i32]261 %a2 = alloca i32, align 4262 store i32 4, ptr %a1263 %ld = load i32, ptr %a2264 %addr2 = getelementptr [6 x i32], ptr %a1, i64 0, i32 1265 store i32 5, ptr %addr2266 ret i32 %ld267}268 269define void @test_volatile(ptr %ptr) {270; CHECK-LABEL: test_volatile:271; CHECK: ; %bb.0: ; %entry272; CHECK-NEXT: ldr x8, [x0]273; CHECK-NEXT: str wzr, [x8]274; CHECK-NEXT: str wzr, [x8, #4]275; CHECK-NEXT: ret276entry:277 %0 = load ptr, ptr %ptr, align 8278 store volatile i32 0, ptr %0, align 4;279 %add.ptr.i.i38 = getelementptr inbounds i32, ptr %0, i64 1280 store volatile i32 0, ptr %add.ptr.i.i38, align 4281 ret void282}283 284define void @test_atomic(ptr %ptr) {285; CHECK-LABEL: test_atomic:286; CHECK: ; %bb.0: ; %entry287; CHECK-NEXT: ldr x8, [x0]288; CHECK-NEXT: stlr wzr, [x8]289; CHECK-NEXT: add x8, x8, #4290; CHECK-NEXT: stlr wzr, [x8]291; CHECK-NEXT: ret292entry:293 %0 = load ptr, ptr %ptr, align 8294 store atomic i32 0, ptr %0 release, align 4;295 %add.ptr.i.i38 = getelementptr inbounds i32, ptr %0, i64 1296 store atomic i32 0, ptr %add.ptr.i.i38 release, align 4297 ret void298}299 300; Here store of 9 and 15 can be merged, but the store of 0 prevents the store301; of 5 from being considered. This checks a corner case where we would skip302; doing an alias check because of a >= vs > bug, due to the presence of a303; non-aliasing instruction, in this case the load %safeld.304define i32 @test_alias_3xs16(ptr %ptr, ptr %ptr2, ptr %ptr3, ptr noalias %safe_ptr) {305; CHECK-LABEL: test_alias_3xs16:306; CHECK: ; %bb.0:307; CHECK-NEXT: mov x8, x0308; CHECK-NEXT: mov w9, #5 ; =0x5309; CHECK-NEXT: ldr w0, [x3]310; CHECK-NEXT: str w9, [x8, #4]311; CHECK-NEXT: mov x9, #9 ; =0x9312; CHECK-NEXT: movk x9, #14, lsl #32313; CHECK-NEXT: strh wzr, [x8, #4]314; CHECK-NEXT: str x9, [x8, #8]315; CHECK-NEXT: ret316 %safeld = load i32, ptr %safe_ptr317 %addr2 = getelementptr i32, ptr %ptr, i64 1318 store i32 5, ptr %addr2319 store i16 0, ptr %addr2 ; aliases directly with store above.320 %addr3 = getelementptr i32, ptr %ptr, i64 2321 store i32 9, ptr %addr3322 %addr4 = getelementptr i32, ptr %ptr, i64 3323 store i32 14, ptr %addr4324 ret i32 %safeld325}326 327@G = external global [10 x i32]328 329define void @invalid_zero_offset_no_merge(i64 %0) {330; CHECK-LABEL: invalid_zero_offset_no_merge:331; CHECK: ; %bb.0:332; CHECK-NEXT: Lloh0:333; CHECK-NEXT: adrp x8, _G@GOTPAGE334; CHECK-NEXT: Lloh1:335; CHECK-NEXT: ldr x8, [x8, _G@GOTPAGEOFF]336; CHECK-NEXT: str wzr, [x8, x0, lsl #2]337; CHECK-NEXT: str wzr, [x8, #4]338; CHECK-NEXT: ret339; CHECK-NEXT: .loh AdrpLdrGot Lloh0, Lloh1340 %2 = getelementptr [10 x i32], ptr @G, i64 0, i64 %0341 store i32 0, ptr %2, align 4342 store i32 0, ptr getelementptr inbounds ([10 x i32], ptr @G, i64 0, i64 1), align 4343 ret void344}345