386 lines · plain
1; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s2;3; <rdar://problem/14486451>4 5%struct.a = type [256 x i16]6%struct.b = type [256 x i32]7%struct.c = type [256 x i64]8 9define i16 @load_halfword(ptr %ctx, i32 %xor72) nounwind {10; CHECK-LABEL: load_halfword:11; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #812; CHECK: ldrh w0, [x0, [[REG]], lsl #1]13 %shr81 = lshr i32 %xor72, 914 %conv82 = zext i32 %shr81 to i6415 %idxprom83 = and i64 %conv82, 25516 %arrayidx86 = getelementptr inbounds %struct.a, ptr %ctx, i64 0, i64 %idxprom8317 %result = load i16, ptr %arrayidx86, align 218 ret i16 %result19}20 21define i32 @load_word(ptr %ctx, i32 %xor72) nounwind {22; CHECK-LABEL: load_word:23; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #824; CHECK: ldr w0, [x0, [[REG]], lsl #2]25 %shr81 = lshr i32 %xor72, 926 %conv82 = zext i32 %shr81 to i6427 %idxprom83 = and i64 %conv82, 25528 %arrayidx86 = getelementptr inbounds %struct.b, ptr %ctx, i64 0, i64 %idxprom8329 %result = load i32, ptr %arrayidx86, align 430 ret i32 %result31}32 33define i64 @load_doubleword(ptr %ctx, i32 %xor72) nounwind {34; CHECK-LABEL: load_doubleword:35; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #836; CHECK: ldr x0, [x0, [[REG]], lsl #3]37 %shr81 = lshr i32 %xor72, 938 %conv82 = zext i32 %shr81 to i6439 %idxprom83 = and i64 %conv82, 25540 %arrayidx86 = getelementptr inbounds %struct.c, ptr %ctx, i64 0, i64 %idxprom8341 %result = load i64, ptr %arrayidx86, align 842 ret i64 %result43}44 45define void @store_halfword(ptr %ctx, i32 %xor72, i16 %val) nounwind {46; CHECK-LABEL: store_halfword:47; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #848; CHECK: strh w2, [x0, [[REG]], lsl #1]49 %shr81 = lshr i32 %xor72, 950 %conv82 = zext i32 %shr81 to i6451 %idxprom83 = and i64 %conv82, 25552 %arrayidx86 = getelementptr inbounds %struct.a, ptr %ctx, i64 0, i64 %idxprom8353 store i16 %val, ptr %arrayidx86, align 854 ret void55}56 57define void @store_word(ptr %ctx, i32 %xor72, i32 %val) nounwind {58; CHECK-LABEL: store_word:59; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #860; CHECK: str w2, [x0, [[REG]], lsl #2]61 %shr81 = lshr i32 %xor72, 962 %conv82 = zext i32 %shr81 to i6463 %idxprom83 = and i64 %conv82, 25564 %arrayidx86 = getelementptr inbounds %struct.b, ptr %ctx, i64 0, i64 %idxprom8365 store i32 %val, ptr %arrayidx86, align 866 ret void67}68 69define void @store_doubleword(ptr %ctx, i32 %xor72, i64 %val) nounwind {70; CHECK-LABEL: store_doubleword:71; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #872; CHECK: str x2, [x0, [[REG]], lsl #3]73 %shr81 = lshr i32 %xor72, 974 %conv82 = zext i32 %shr81 to i6475 %idxprom83 = and i64 %conv82, 25576 %arrayidx86 = getelementptr inbounds %struct.c, ptr %ctx, i64 0, i64 %idxprom8377 store i64 %val, ptr %arrayidx86, align 878 ret void79}80 81; Check that we combine a shift into the offset instead of using a narrower load82; when we have a load followed by a trunc83 84define i32 @load_doubleword_trunc_word(ptr %ptr, i64 %off) {85; CHECK-LABEL: load_doubleword_trunc_word:86; CHECK: ldr x0, [x0, x1, lsl #3]87entry:88 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off89 %x = load i64, ptr %idx, align 890 %trunc = trunc i64 %x to i3291 ret i32 %trunc92}93 94define i16 @load_doubleword_trunc_halfword(ptr %ptr, i64 %off) {95; CHECK-LABEL: load_doubleword_trunc_halfword:96; CHECK: ldr x0, [x0, x1, lsl #3]97entry:98 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off99 %x = load i64, ptr %idx, align 8100 %trunc = trunc i64 %x to i16101 ret i16 %trunc102}103 104define i8 @load_doubleword_trunc_byte(ptr %ptr, i64 %off) {105; CHECK-LABEL: load_doubleword_trunc_byte:106; CHECK: ldr x0, [x0, x1, lsl #3]107entry:108 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off109 %x = load i64, ptr %idx, align 8110 %trunc = trunc i64 %x to i8111 ret i8 %trunc112}113 114define i16 @load_word_trunc_halfword(ptr %ptr, i64 %off) {115entry:116; CHECK-LABEL: load_word_trunc_halfword:117; CHECK: ldr w0, [x0, x1, lsl #2]118 %idx = getelementptr inbounds i32, ptr %ptr, i64 %off119 %x = load i32, ptr %idx, align 8120 %trunc = trunc i32 %x to i16121 ret i16 %trunc122}123 124define i8 @load_word_trunc_byte(ptr %ptr, i64 %off) {125; CHECK-LABEL: load_word_trunc_byte:126; CHECK: ldr w0, [x0, x1, lsl #2]127entry:128 %idx = getelementptr inbounds i32, ptr %ptr, i64 %off129 %x = load i32, ptr %idx, align 8130 %trunc = trunc i32 %x to i8131 ret i8 %trunc132}133 134define i8 @load_halfword_trunc_byte(ptr %ptr, i64 %off) {135; CHECK-LABEL: load_halfword_trunc_byte:136; CHECK: ldrh w0, [x0, x1, lsl #1]137entry:138 %idx = getelementptr inbounds i16, ptr %ptr, i64 %off139 %x = load i16, ptr %idx, align 8140 %trunc = trunc i16 %x to i8141 ret i8 %trunc142}143 144; Check that we do use a narrower load, and so don't combine the shift, when145; the loaded value is zero-extended.146 147define i64 @load_doubleword_trunc_word_zext(ptr %ptr, i64 %off) {148; CHECK-LABEL: load_doubleword_trunc_word_zext:149; CHECK: lsl [[REG:x[0-9]+]], x1, #3150; CHECK: ldr w0, [x0, [[REG]]]151entry:152 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off153 %x = load i64, ptr %idx, align 8154 %trunc = trunc i64 %x to i32155 %ext = zext i32 %trunc to i64156 ret i64 %ext157}158 159define i64 @load_doubleword_trunc_halfword_zext(ptr %ptr, i64 %off) {160; CHECK-LABEL: load_doubleword_trunc_halfword_zext:161; CHECK: lsl [[REG:x[0-9]+]], x1, #3162; CHECK: ldrh w0, [x0, [[REG]]]163entry:164 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off165 %x = load i64, ptr %idx, align 8166 %trunc = trunc i64 %x to i16167 %ext = zext i16 %trunc to i64168 ret i64 %ext169}170 171define i64 @load_doubleword_trunc_byte_zext(ptr %ptr, i64 %off) {172; CHECK-LABEL: load_doubleword_trunc_byte_zext:173; CHECK: lsl [[REG:x[0-9]+]], x1, #3174; CHECK: ldrb w0, [x0, [[REG]]]175entry:176 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off177 %x = load i64, ptr %idx, align 8178 %trunc = trunc i64 %x to i8179 %ext = zext i8 %trunc to i64180 ret i64 %ext181}182 183define i64 @load_word_trunc_halfword_zext(ptr %ptr, i64 %off) {184; CHECK-LABEL: load_word_trunc_halfword_zext:185; CHECK: lsl [[REG:x[0-9]+]], x1, #2186; CHECK: ldrh w0, [x0, [[REG]]]187entry:188 %idx = getelementptr inbounds i32, ptr %ptr, i64 %off189 %x = load i32, ptr %idx, align 8190 %trunc = trunc i32 %x to i16191 %ext = zext i16 %trunc to i64192 ret i64 %ext193}194 195define i64 @load_word_trunc_byte_zext(ptr %ptr, i64 %off) {196; CHECK-LABEL: load_word_trunc_byte_zext:197; CHECK: lsl [[REG:x[0-9]+]], x1, #2198; CHECK: ldrb w0, [x0, [[REG]]]199entry:200 %idx = getelementptr inbounds i32, ptr %ptr, i64 %off201 %x = load i32, ptr %idx, align 8202 %trunc = trunc i32 %x to i8203 %ext = zext i8 %trunc to i64204 ret i64 %ext205}206 207define i64 @load_halfword_trunc_byte_zext(ptr %ptr, i64 %off) {208; CHECK-LABEL: load_halfword_trunc_byte_zext:209; CHECK: lsl [[REG:x[0-9]+]], x1, #1210; CHECK: ldrb w0, [x0, [[REG]]]211entry:212 %idx = getelementptr inbounds i16, ptr %ptr, i64 %off213 %x = load i16, ptr %idx, align 8214 %trunc = trunc i16 %x to i8215 %ext = zext i8 %trunc to i64216 ret i64 %ext217}218 219; Check that we do use a narrower load, and so don't combine the shift, when220; the loaded value is sign-extended.221 222define i64 @load_doubleword_trunc_word_sext(ptr %ptr, i64 %off) {223; CHECK-LABEL: load_doubleword_trunc_word_sext:224; CHECK: lsl [[REG:x[0-9]+]], x1, #3225; CHECK: ldrsw x0, [x0, [[REG]]]226entry:227 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off228 %x = load i64, ptr %idx, align 8229 %trunc = trunc i64 %x to i32230 %ext = sext i32 %trunc to i64231 ret i64 %ext232}233 234define i64 @load_doubleword_trunc_halfword_sext(ptr %ptr, i64 %off) {235; CHECK-LABEL: load_doubleword_trunc_halfword_sext:236; CHECK: lsl [[REG:x[0-9]+]], x1, #3237; CHECK: ldrsh x0, [x0, [[REG]]]238entry:239 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off240 %x = load i64, ptr %idx, align 8241 %trunc = trunc i64 %x to i16242 %ext = sext i16 %trunc to i64243 ret i64 %ext244}245 246define i64 @load_doubleword_trunc_byte_sext(ptr %ptr, i64 %off) {247; CHECK-LABEL: load_doubleword_trunc_byte_sext:248; CHECK: lsl [[REG:x[0-9]+]], x1, #3249; CHECK: ldrsb x0, [x0, [[REG]]]250entry:251 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off252 %x = load i64, ptr %idx, align 8253 %trunc = trunc i64 %x to i8254 %ext = sext i8 %trunc to i64255 ret i64 %ext256}257 258define i64 @load_word_trunc_halfword_sext(ptr %ptr, i64 %off) {259; CHECK-LABEL: load_word_trunc_halfword_sext:260; CHECK: lsl [[REG:x[0-9]+]], x1, #2261; CHECK: ldrsh x0, [x0, [[REG]]]262entry:263 %idx = getelementptr inbounds i32, ptr %ptr, i64 %off264 %x = load i32, ptr %idx, align 8265 %trunc = trunc i32 %x to i16266 %ext = sext i16 %trunc to i64267 ret i64 %ext268}269 270define i64 @load_word_trunc_byte_sext(ptr %ptr, i64 %off) {271; CHECK-LABEL: load_word_trunc_byte_sext:272; CHECK: lsl [[REG:x[0-9]+]], x1, #2273; CHECK: ldrsb x0, [x0, [[REG]]]274entry:275 %idx = getelementptr inbounds i32, ptr %ptr, i64 %off276 %x = load i32, ptr %idx, align 8277 %trunc = trunc i32 %x to i8278 %ext = sext i8 %trunc to i64279 ret i64 %ext280}281 282define i64 @load_halfword_trunc_byte_sext(ptr %ptr, i64 %off) {283; CHECK-LABEL: load_halfword_trunc_byte_sext:284; CHECK: lsl [[REG:x[0-9]+]], x1, #1285; CHECK: ldrsb x0, [x0, [[REG]]]286entry:287 %idx = getelementptr inbounds i16, ptr %ptr, i64 %off288 %x = load i16, ptr %idx, align 8289 %trunc = trunc i16 %x to i8290 %ext = sext i8 %trunc to i64291 ret i64 %ext292}293 294; Check that we don't combine the shift, and so will use a narrower load, when295; the shift is used more than once.296 297define i32 @load_doubleword_trunc_word_reuse_shift(ptr %ptr, i64 %off) {298; CHECK-LABEL: load_doubleword_trunc_word_reuse_shift:299; CHECK: lsl x[[REG1:[0-9]+]], x1, #3300; CHECK: ldr w[[REG2:[0-9]+]], [x0, x[[REG1]]]301; CHECK: add w0, w[[REG2]], w[[REG1]]302entry:303 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off304 %x = load i64, ptr %idx, align 8305 %trunc = trunc i64 %x to i32306 %lsl = shl i64 %off, 3307 %lsl.trunc = trunc i64 %lsl to i32308 %add = add i32 %trunc, %lsl.trunc309 ret i32 %add310}311 312define i16 @load_doubleword_trunc_halfword_reuse_shift(ptr %ptr, i64 %off) {313; CHECK-LABEL: load_doubleword_trunc_halfword_reuse_shift:314; CHECK: lsl x[[REG1:[0-9]+]], x1, #3315; CHECK: ldrh w[[REG2:[0-9]+]], [x0, x[[REG1]]]316; CHECK: add w0, w[[REG2]], w[[REG1]]317entry:318 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off319 %x = load i64, ptr %idx, align 8320 %trunc = trunc i64 %x to i16321 %lsl = shl i64 %off, 3322 %lsl.trunc = trunc i64 %lsl to i16323 %add = add i16 %trunc, %lsl.trunc324 ret i16 %add325}326 327define i8 @load_doubleword_trunc_byte_reuse_shift(ptr %ptr, i64 %off) {328; CHECK-LABEL: load_doubleword_trunc_byte_reuse_shift:329; CHECK: lsl x[[REG1:[0-9]+]], x1, #3330; CHECK: ldrb w[[REG2:[0-9]+]], [x0, x[[REG1]]]331; CHECK: add w0, w[[REG2]], w[[REG1]]332entry:333 %idx = getelementptr inbounds i64, ptr %ptr, i64 %off334 %x = load i64, ptr %idx, align 8335 %trunc = trunc i64 %x to i8336 %lsl = shl i64 %off, 3337 %lsl.trunc = trunc i64 %lsl to i8338 %add = add i8 %trunc, %lsl.trunc339 ret i8 %add340}341 342define i16 @load_word_trunc_halfword_reuse_shift(ptr %ptr, i64 %off) {343entry:344; CHECK-LABEL: load_word_trunc_halfword_reuse_shift:345; CHECK: lsl x[[REG1:[0-9]+]], x1, #2346; CHECK: ldrh w[[REG2:[0-9]+]], [x0, x[[REG1]]]347; CHECK: add w0, w[[REG2]], w[[REG1]]348 %idx = getelementptr inbounds i32, ptr %ptr, i64 %off349 %x = load i32, ptr %idx, align 8350 %trunc = trunc i32 %x to i16351 %lsl = shl i64 %off, 2352 %lsl.trunc = trunc i64 %lsl to i16353 %add = add i16 %trunc, %lsl.trunc354 ret i16 %add355}356 357define i8 @load_word_trunc_byte_reuse_shift(ptr %ptr, i64 %off) {358; CHECK-LABEL: load_word_trunc_byte_reuse_shift:359; CHECK: lsl x[[REG1:[0-9]+]], x1, #2360; CHECK: ldrb w[[REG2:[0-9]+]], [x0, x[[REG1]]]361; CHECK: add w0, w[[REG2]], w[[REG1]]362entry:363 %idx = getelementptr inbounds i32, ptr %ptr, i64 %off364 %x = load i32, ptr %idx, align 8365 %trunc = trunc i32 %x to i8366 %lsl = shl i64 %off, 2367 %lsl.trunc = trunc i64 %lsl to i8368 %add = add i8 %trunc, %lsl.trunc369 ret i8 %add370}371 372define i8 @load_halfword_trunc_byte_reuse_shift(ptr %ptr, i64 %off) {373; CHECK-LABEL: load_halfword_trunc_byte_reuse_shift:374; CHECK: lsl x[[REG1:[0-9]+]], x1, #1375; CHECK: ldrb w[[REG2:[0-9]+]], [x0, x[[REG1]]]376; CHECK: add w0, w[[REG2]], w[[REG1]]377entry:378 %idx = getelementptr inbounds i16, ptr %ptr, i64 %off379 %x = load i16, ptr %idx, align 8380 %trunc = trunc i16 %x to i8381 %lsl = shl i64 %off, 1382 %lsl.trunc = trunc i64 %lsl to i8383 %add = add i8 %trunc, %lsl.trunc384 ret i8 %add385}386