684 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s3 4%structTy = type { i8, i32, i32 }5 6@e = common dso_local global %structTy zeroinitializer, align 47 8;; Ensure that MergeConsecutiveStores doesn't incorrectly reorder9;; store operations. The first test stores in increasing address10;; order, the second in decreasing -- but in both cases should have11;; the same result in memory in the end.12 13define dso_local void @redundant_stores_merging() {14; CHECK-LABEL: redundant_stores_merging:15; CHECK: # %bb.0:16; CHECK-NEXT: movabsq $1958505086977, %rax # imm = 0x1C80000000117; CHECK-NEXT: movq %rax, e+4(%rip)18; CHECK-NEXT: retq19 store i32 1, ptr getelementptr inbounds (%structTy, ptr @e, i64 0, i32 1), align 420 store i32 123, ptr getelementptr inbounds (%structTy, ptr @e, i64 0, i32 2), align 421 store i32 456, ptr getelementptr inbounds (%structTy, ptr @e, i64 0, i32 2), align 422 ret void23}24 25;; This variant tests PR25154.26define dso_local void @redundant_stores_merging_reverse() {27; CHECK-LABEL: redundant_stores_merging_reverse:28; CHECK: # %bb.0:29; CHECK-NEXT: movabsq $528280977409, %rax # imm = 0x7B0000000130; CHECK-NEXT: movq %rax, e+4(%rip)31; CHECK-NEXT: movl $456, e+8(%rip) # imm = 0x1C832; CHECK-NEXT: retq33 store i32 123, ptr getelementptr inbounds (%structTy, ptr @e, i64 0, i32 2), align 434 store i32 456, ptr getelementptr inbounds (%structTy, ptr @e, i64 0, i32 2), align 435 store i32 1, ptr getelementptr inbounds (%structTy, ptr @e, i64 0, i32 1), align 436 ret void37}38 39@b = common dso_local global [8 x i8] zeroinitializer, align 240 41;; The 2-byte store to offset 3 overlaps the 2-byte store to offset 2;42;; these must not be reordered in MergeConsecutiveStores such that the43;; store to 3 comes first (e.g. by merging the stores to 0 and 2 into44;; a movl, after the store to 3).45 46define dso_local void @overlapping_stores_merging() {47; CHECK-LABEL: overlapping_stores_merging:48; CHECK: # %bb.0:49; CHECK-NEXT: movl $1, b(%rip)50; CHECK-NEXT: movw $2, b+3(%rip)51; CHECK-NEXT: retq52 store i16 0, ptr getelementptr inbounds ([8 x i8], ptr @b, i64 0, i64 2), align 253 store i16 2, ptr getelementptr inbounds ([8 x i8], ptr @b, i64 0, i64 3), align 154 store i16 1, ptr @b, align 255 ret void56}57 58define dso_local void @extract_vector_store_16_consecutive_bytes(<2 x i64> %v, ptr %ptr) #0 {59; CHECK-LABEL: extract_vector_store_16_consecutive_bytes:60; CHECK: # %bb.0:61; CHECK-NEXT: vmovups %xmm0, (%rdi)62; CHECK-NEXT: retq63 %bc = bitcast <2 x i64> %v to <16 x i8>64 %ext00 = extractelement <16 x i8> %bc, i32 065 %ext01 = extractelement <16 x i8> %bc, i32 166 %ext02 = extractelement <16 x i8> %bc, i32 267 %ext03 = extractelement <16 x i8> %bc, i32 368 %ext04 = extractelement <16 x i8> %bc, i32 469 %ext05 = extractelement <16 x i8> %bc, i32 570 %ext06 = extractelement <16 x i8> %bc, i32 671 %ext07 = extractelement <16 x i8> %bc, i32 772 %ext08 = extractelement <16 x i8> %bc, i32 873 %ext09 = extractelement <16 x i8> %bc, i32 974 %ext10 = extractelement <16 x i8> %bc, i32 1075 %ext11 = extractelement <16 x i8> %bc, i32 1176 %ext12 = extractelement <16 x i8> %bc, i32 1277 %ext13 = extractelement <16 x i8> %bc, i32 1378 %ext14 = extractelement <16 x i8> %bc, i32 1479 %ext15 = extractelement <16 x i8> %bc, i32 1580 %gep01 = getelementptr inbounds i8, ptr %ptr, i64 181 %gep02 = getelementptr inbounds i8, ptr %ptr, i64 282 %gep03 = getelementptr inbounds i8, ptr %ptr, i64 383 %gep04 = getelementptr inbounds i8, ptr %ptr, i64 484 %gep05 = getelementptr inbounds i8, ptr %ptr, i64 585 %gep06 = getelementptr inbounds i8, ptr %ptr, i64 686 %gep07 = getelementptr inbounds i8, ptr %ptr, i64 787 %gep08 = getelementptr inbounds i8, ptr %ptr, i64 888 %gep09 = getelementptr inbounds i8, ptr %ptr, i64 989 %gep10 = getelementptr inbounds i8, ptr %ptr, i64 1090 %gep11 = getelementptr inbounds i8, ptr %ptr, i64 1191 %gep12 = getelementptr inbounds i8, ptr %ptr, i64 1292 %gep13 = getelementptr inbounds i8, ptr %ptr, i64 1393 %gep14 = getelementptr inbounds i8, ptr %ptr, i64 1494 %gep15 = getelementptr inbounds i8, ptr %ptr, i64 1595 store i8 %ext00, ptr %ptr, align 196 store i8 %ext01, ptr %gep01, align 197 store i8 %ext02, ptr %gep02, align 198 store i8 %ext03, ptr %gep03, align 199 store i8 %ext04, ptr %gep04, align 1100 store i8 %ext05, ptr %gep05, align 1101 store i8 %ext06, ptr %gep06, align 1102 store i8 %ext07, ptr %gep07, align 1103 store i8 %ext08, ptr %gep08, align 1104 store i8 %ext09, ptr %gep09, align 1105 store i8 %ext10, ptr %gep10, align 1106 store i8 %ext11, ptr %gep11, align 1107 store i8 %ext12, ptr %gep12, align 1108 store i8 %ext13, ptr %gep13, align 1109 store i8 %ext14, ptr %gep14, align 1110 store i8 %ext15, ptr %gep15, align 1111 ret void112}113 114; PR34217 - https://bugs.llvm.org/show_bug.cgi?id=34217115 116define dso_local void @extract_vector_store_32_consecutive_bytes(<4 x i64> %v, ptr %ptr) #0 {117; CHECK-LABEL: extract_vector_store_32_consecutive_bytes:118; CHECK: # %bb.0:119; CHECK-NEXT: vmovups %ymm0, (%rdi)120; CHECK-NEXT: vzeroupper121; CHECK-NEXT: retq122 %bc = bitcast <4 x i64> %v to <32 x i8>123 %ext00 = extractelement <32 x i8> %bc, i32 0124 %ext01 = extractelement <32 x i8> %bc, i32 1125 %ext02 = extractelement <32 x i8> %bc, i32 2126 %ext03 = extractelement <32 x i8> %bc, i32 3127 %ext04 = extractelement <32 x i8> %bc, i32 4128 %ext05 = extractelement <32 x i8> %bc, i32 5129 %ext06 = extractelement <32 x i8> %bc, i32 6130 %ext07 = extractelement <32 x i8> %bc, i32 7131 %ext08 = extractelement <32 x i8> %bc, i32 8132 %ext09 = extractelement <32 x i8> %bc, i32 9133 %ext10 = extractelement <32 x i8> %bc, i32 10134 %ext11 = extractelement <32 x i8> %bc, i32 11135 %ext12 = extractelement <32 x i8> %bc, i32 12136 %ext13 = extractelement <32 x i8> %bc, i32 13137 %ext14 = extractelement <32 x i8> %bc, i32 14138 %ext15 = extractelement <32 x i8> %bc, i32 15139 %ext16 = extractelement <32 x i8> %bc, i32 16140 %ext17 = extractelement <32 x i8> %bc, i32 17141 %ext18 = extractelement <32 x i8> %bc, i32 18142 %ext19 = extractelement <32 x i8> %bc, i32 19143 %ext20 = extractelement <32 x i8> %bc, i32 20144 %ext21 = extractelement <32 x i8> %bc, i32 21145 %ext22 = extractelement <32 x i8> %bc, i32 22146 %ext23 = extractelement <32 x i8> %bc, i32 23147 %ext24 = extractelement <32 x i8> %bc, i32 24148 %ext25 = extractelement <32 x i8> %bc, i32 25149 %ext26 = extractelement <32 x i8> %bc, i32 26150 %ext27 = extractelement <32 x i8> %bc, i32 27151 %ext28 = extractelement <32 x i8> %bc, i32 28152 %ext29 = extractelement <32 x i8> %bc, i32 29153 %ext30 = extractelement <32 x i8> %bc, i32 30154 %ext31 = extractelement <32 x i8> %bc, i32 31155 %gep01 = getelementptr inbounds i8, ptr %ptr, i64 1156 %gep02 = getelementptr inbounds i8, ptr %ptr, i64 2157 %gep03 = getelementptr inbounds i8, ptr %ptr, i64 3158 %gep04 = getelementptr inbounds i8, ptr %ptr, i64 4159 %gep05 = getelementptr inbounds i8, ptr %ptr, i64 5160 %gep06 = getelementptr inbounds i8, ptr %ptr, i64 6161 %gep07 = getelementptr inbounds i8, ptr %ptr, i64 7162 %gep08 = getelementptr inbounds i8, ptr %ptr, i64 8163 %gep09 = getelementptr inbounds i8, ptr %ptr, i64 9164 %gep10 = getelementptr inbounds i8, ptr %ptr, i64 10165 %gep11 = getelementptr inbounds i8, ptr %ptr, i64 11166 %gep12 = getelementptr inbounds i8, ptr %ptr, i64 12167 %gep13 = getelementptr inbounds i8, ptr %ptr, i64 13168 %gep14 = getelementptr inbounds i8, ptr %ptr, i64 14169 %gep15 = getelementptr inbounds i8, ptr %ptr, i64 15170 %gep16 = getelementptr inbounds i8, ptr %ptr, i64 16171 %gep17 = getelementptr inbounds i8, ptr %ptr, i64 17172 %gep18 = getelementptr inbounds i8, ptr %ptr, i64 18173 %gep19 = getelementptr inbounds i8, ptr %ptr, i64 19174 %gep20 = getelementptr inbounds i8, ptr %ptr, i64 20175 %gep21 = getelementptr inbounds i8, ptr %ptr, i64 21176 %gep22 = getelementptr inbounds i8, ptr %ptr, i64 22177 %gep23 = getelementptr inbounds i8, ptr %ptr, i64 23178 %gep24 = getelementptr inbounds i8, ptr %ptr, i64 24179 %gep25 = getelementptr inbounds i8, ptr %ptr, i64 25180 %gep26 = getelementptr inbounds i8, ptr %ptr, i64 26181 %gep27 = getelementptr inbounds i8, ptr %ptr, i64 27182 %gep28 = getelementptr inbounds i8, ptr %ptr, i64 28183 %gep29 = getelementptr inbounds i8, ptr %ptr, i64 29184 %gep30 = getelementptr inbounds i8, ptr %ptr, i64 30185 %gep31 = getelementptr inbounds i8, ptr %ptr, i64 31186 store i8 %ext00, ptr %ptr, align 1187 store i8 %ext01, ptr %gep01, align 1188 store i8 %ext02, ptr %gep02, align 1189 store i8 %ext03, ptr %gep03, align 1190 store i8 %ext04, ptr %gep04, align 1191 store i8 %ext05, ptr %gep05, align 1192 store i8 %ext06, ptr %gep06, align 1193 store i8 %ext07, ptr %gep07, align 1194 store i8 %ext08, ptr %gep08, align 1195 store i8 %ext09, ptr %gep09, align 1196 store i8 %ext10, ptr %gep10, align 1197 store i8 %ext11, ptr %gep11, align 1198 store i8 %ext12, ptr %gep12, align 1199 store i8 %ext13, ptr %gep13, align 1200 store i8 %ext14, ptr %gep14, align 1201 store i8 %ext15, ptr %gep15, align 1202 store i8 %ext16, ptr %gep16, align 1203 store i8 %ext17, ptr %gep17, align 1204 store i8 %ext18, ptr %gep18, align 1205 store i8 %ext19, ptr %gep19, align 1206 store i8 %ext20, ptr %gep20, align 1207 store i8 %ext21, ptr %gep21, align 1208 store i8 %ext22, ptr %gep22, align 1209 store i8 %ext23, ptr %gep23, align 1210 store i8 %ext24, ptr %gep24, align 1211 store i8 %ext25, ptr %gep25, align 1212 store i8 %ext26, ptr %gep26, align 1213 store i8 %ext27, ptr %gep27, align 1214 store i8 %ext28, ptr %gep28, align 1215 store i8 %ext29, ptr %gep29, align 1216 store i8 %ext30, ptr %gep30, align 1217 store i8 %ext31, ptr %gep31, align 1218 ret void219}220 221; https://bugs.llvm.org/show_bug.cgi?id=43446222define dso_local void @pr43446_0(i64 %x) {223; CHECK-LABEL: pr43446_0:224; CHECK: # %bb.0:225; CHECK-NEXT: movb $1, (%rdi)226; CHECK-NEXT: retq227 %a = inttoptr i64 %x to ptr228 store i8 -2, ptr %a, align 1229 %b = inttoptr i64 %x to ptr230 store i1 true, ptr %b, align 1231 ret void232}233define dso_local void @pr43446_1(ptr %a) {234; CHECK-LABEL: pr43446_1:235; CHECK: # %bb.0:236; CHECK-NEXT: movb $1, (%rdi)237; CHECK-NEXT: retq238 store i8 -2, ptr %a, align 1239 store i1 true, ptr %a, align 1240 ret void241}242 243define dso_local void @rotate16_in_place(ptr %p) {244; CHECK-LABEL: rotate16_in_place:245; CHECK: # %bb.0:246; CHECK-NEXT: rolw $8, (%rdi)247; CHECK-NEXT: retq248 %p1 = getelementptr i8, ptr %p, i64 1249 %i0 = load i8, ptr %p, align 1250 %i1 = load i8, ptr %p1, align 1251 store i8 %i1, ptr %p, align 1252 store i8 %i0, ptr %p1, align 1253 ret void254}255 256define dso_local void @rotate16(ptr %p, ptr %q) {257; CHECK-LABEL: rotate16:258; CHECK: # %bb.0:259; CHECK-NEXT: movzwl (%rdi), %eax260; CHECK-NEXT: rolw $8, %ax261; CHECK-NEXT: movw %ax, (%rsi)262; CHECK-NEXT: retq263 %p1 = getelementptr i8, ptr %p, i64 1264 %q1 = getelementptr i8, ptr %q, i64 1265 %i0 = load i8, ptr %p, align 1266 %i1 = load i8, ptr %p1, align 1267 store i8 %i1, ptr %q, align 1268 store i8 %i0, ptr %q1, align 1269 ret void270}271 272define dso_local void @rotate32_in_place(ptr %p) {273; CHECK-LABEL: rotate32_in_place:274; CHECK: # %bb.0:275; CHECK-NEXT: roll $16, (%rdi)276; CHECK-NEXT: retq277 %p1 = getelementptr i16, ptr %p, i64 1278 %i0 = load i16, ptr %p, align 2279 %i1 = load i16, ptr %p1, align 2280 store i16 %i1, ptr %p, align 2281 store i16 %i0, ptr %p1, align 2282 ret void283}284 285define dso_local void @rotate32(ptr %p) {286; CHECK-LABEL: rotate32:287; CHECK: # %bb.0:288; CHECK-NEXT: movl (%rdi), %eax289; CHECK-NEXT: roll $16, %eax290; CHECK-NEXT: movl %eax, 84(%rdi)291; CHECK-NEXT: retq292 %p1 = getelementptr i16, ptr %p, i64 1293 %p42 = getelementptr i16, ptr %p, i64 42294 %p43 = getelementptr i16, ptr %p, i64 43295 %i0 = load i16, ptr %p, align 2296 %i1 = load i16, ptr %p1, align 2297 store i16 %i1, ptr %p42, align 2298 store i16 %i0, ptr %p43, align 2299 ret void300}301 302define dso_local void @rotate64_in_place(ptr %p) {303; CHECK-LABEL: rotate64_in_place:304; CHECK: # %bb.0:305; CHECK-NEXT: rolq $32, (%rdi)306; CHECK-NEXT: retq307 %p1 = getelementptr i32, ptr %p, i64 1308 %i0 = load i32, ptr %p, align 4309 %i1 = load i32, ptr %p1, align 4310 store i32 %i1, ptr %p, align 4311 store i32 %i0, ptr %p1, align 4312 ret void313}314 315define dso_local void @rotate64(ptr %p) {316; CHECK-LABEL: rotate64:317; CHECK: # %bb.0:318; CHECK-NEXT: movq (%rdi), %rax319; CHECK-NEXT: rolq $32, %rax320; CHECK-NEXT: movq %rax, 8(%rdi)321; CHECK-NEXT: retq322 %p1 = getelementptr i32, ptr %p, i64 1323 %p2 = getelementptr i32, ptr %p, i64 2324 %p3 = getelementptr i32, ptr %p, i64 3325 %i0 = load i32, ptr %p, align 4326 %i1 = load i32, ptr %p1, align 4327 store i32 %i1, ptr %p2, align 4328 store i32 %i0, ptr %p3, align 4329 ret void330}331 332define dso_local void @rotate64_iterate(ptr %p) {333; CHECK-LABEL: rotate64_iterate:334; CHECK: # %bb.0:335; CHECK-NEXT: movq (%rdi), %rax336; CHECK-NEXT: rolq $32, %rax337; CHECK-NEXT: movq %rax, 84(%rdi)338; CHECK-NEXT: retq339 %p1 = getelementptr i16, ptr %p, i64 1340 %p2 = getelementptr i16, ptr %p, i64 2341 %p3 = getelementptr i16, ptr %p, i64 3342 %p42 = getelementptr i16, ptr %p, i64 42343 %p43 = getelementptr i16, ptr %p, i64 43344 %p44 = getelementptr i16, ptr %p, i64 44345 %p45 = getelementptr i16, ptr %p, i64 45346 %i0 = load i16, ptr %p, align 2347 %i1 = load i16, ptr %p1, align 2348 %i2 = load i16, ptr %p2, align 2349 %i3 = load i16, ptr %p3, align 2350 store i16 %i2, ptr %p42, align 2351 store i16 %i3, ptr %p43, align 2352 store i16 %i0, ptr %p44, align 2353 store i16 %i1, ptr %p45, align 2354 ret void355}356 357; TODO: recognize this as 2 rotates?358 359define dso_local void @rotate32_consecutive(ptr %p) {360; CHECK-LABEL: rotate32_consecutive:361; CHECK: # %bb.0:362; CHECK-NEXT: movzwl (%rdi), %eax363; CHECK-NEXT: movzwl 2(%rdi), %ecx364; CHECK-NEXT: movzwl 4(%rdi), %edx365; CHECK-NEXT: movzwl 6(%rdi), %esi366; CHECK-NEXT: movw %cx, 84(%rdi)367; CHECK-NEXT: movw %ax, 86(%rdi)368; CHECK-NEXT: movw %si, 88(%rdi)369; CHECK-NEXT: movw %dx, 90(%rdi)370; CHECK-NEXT: retq371 %p1 = getelementptr i16, ptr %p, i64 1372 %p2 = getelementptr i16, ptr %p, i64 2373 %p3 = getelementptr i16, ptr %p, i64 3374 %p42 = getelementptr i16, ptr %p, i64 42375 %p43 = getelementptr i16, ptr %p, i64 43376 %p44 = getelementptr i16, ptr %p, i64 44377 %p45 = getelementptr i16, ptr %p, i64 45378 %i0 = load i16, ptr %p, align 2379 %i1 = load i16, ptr %p1, align 2380 %i2 = load i16, ptr %p2, align 2381 %i3 = load i16, ptr %p3, align 2382 store i16 %i1, ptr %p42, align 2383 store i16 %i0, ptr %p43, align 2384 store i16 %i3, ptr %p44, align 2385 store i16 %i2, ptr %p45, align 2386 ret void387}388 389; Same as above, but now the stores are not all consecutive.390 391define dso_local void @rotate32_twice(ptr %p) {392; CHECK-LABEL: rotate32_twice:393; CHECK: # %bb.0:394; CHECK-NEXT: movl (%rdi), %eax395; CHECK-NEXT: movl 4(%rdi), %ecx396; CHECK-NEXT: roll $16, %eax397; CHECK-NEXT: roll $16, %ecx398; CHECK-NEXT: movl %eax, 84(%rdi)399; CHECK-NEXT: movl %ecx, 108(%rdi)400; CHECK-NEXT: retq401 %p1 = getelementptr i16, ptr %p, i64 1402 %p2 = getelementptr i16, ptr %p, i64 2403 %p3 = getelementptr i16, ptr %p, i64 3404 %p42 = getelementptr i16, ptr %p, i64 42405 %p43 = getelementptr i16, ptr %p, i64 43406 %p54 = getelementptr i16, ptr %p, i64 54407 %p55 = getelementptr i16, ptr %p, i64 55408 %i0 = load i16, ptr %p, align 2409 %i1 = load i16, ptr %p1, align 2410 %i2 = load i16, ptr %p2, align 2411 %i3 = load i16, ptr %p3, align 2412 store i16 %i1, ptr %p42, align 2413 store i16 %i0, ptr %p43, align 2414 store i16 %i3, ptr %p54, align 2415 store i16 %i2, ptr %p55, align 2416 ret void417}418 419define dso_local void @trunc_i16_to_i8(i16 %x, ptr %p) {420; CHECK-LABEL: trunc_i16_to_i8:421; CHECK: # %bb.0:422; CHECK-NEXT: movw %di, (%rsi)423; CHECK-NEXT: retq424 %t1 = trunc i16 %x to i8425 %sh = lshr i16 %x, 8426 %t2 = trunc i16 %sh to i8427 store i8 %t1, ptr %p, align 1428 %p1 = getelementptr inbounds i8, ptr %p, i64 1429 store i8 %t2, ptr %p1, align 1430 ret void431}432 433define dso_local void @trunc_i32_to_i8(i32 %x, ptr %p) {434; CHECK-LABEL: trunc_i32_to_i8:435; CHECK: # %bb.0:436; CHECK-NEXT: movl %edi, (%rsi)437; CHECK-NEXT: retq438 %t1 = trunc i32 %x to i8439 %sh1 = lshr i32 %x, 8440 %t2 = trunc i32 %sh1 to i8441 %sh2 = lshr i32 %x, 16442 %t3 = trunc i32 %sh2 to i8443 %sh3 = lshr i32 %x, 24444 %t4 = trunc i32 %sh3 to i8445 store i8 %t1, ptr %p, align 1446 %p1 = getelementptr inbounds i8, ptr %p, i64 1447 store i8 %t2, ptr %p1, align 1448 %p2 = getelementptr inbounds i8, ptr %p, i64 2449 store i8 %t3, ptr %p2, align 1450 %p3 = getelementptr inbounds i8, ptr %p, i64 3451 store i8 %t4, ptr %p3, align 1452 ret void453}454 455define dso_local void @trunc_i32_to_i16(i32 %x, ptr %p) {456; CHECK-LABEL: trunc_i32_to_i16:457; CHECK: # %bb.0:458; CHECK-NEXT: movl %edi, (%rsi)459; CHECK-NEXT: retq460 %t1 = trunc i32 %x to i16461 %sh = lshr i32 %x, 16462 %t2 = trunc i32 %sh to i16463 store i16 %t1, ptr %p, align 2464 %p1 = getelementptr inbounds i16, ptr %p, i64 1465 store i16 %t2, ptr %p1, align 2466 ret void467}468 469define dso_local void @be_i32_to_i16(i32 %x, ptr %p0) {470; CHECK-LABEL: be_i32_to_i16:471; CHECK: # %bb.0:472; CHECK-NEXT: rorl $16, %edi473; CHECK-NEXT: movl %edi, (%rsi)474; CHECK-NEXT: retq475 %sh1 = lshr i32 %x, 16476 %t0 = trunc i32 %x to i16477 %t1 = trunc i32 %sh1 to i16478 %p1 = getelementptr inbounds i16, ptr %p0, i64 1479 store i16 %t0, ptr %p1, align 2480 store i16 %t1, ptr %p0, align 2481 ret void482}483 484define dso_local void @be_i32_to_i16_order(i32 %x, ptr %p0) {485; CHECK-LABEL: be_i32_to_i16_order:486; CHECK: # %bb.0:487; CHECK-NEXT: rorl $16, %edi488; CHECK-NEXT: movl %edi, (%rsi)489; CHECK-NEXT: retq490 %sh1 = lshr i32 %x, 16491 %t0 = trunc i32 %x to i16492 %t1 = trunc i32 %sh1 to i16493 %p1 = getelementptr inbounds i16, ptr %p0, i64 1494 store i16 %t1, ptr %p0, align 2495 store i16 %t0, ptr %p1, align 2496 ret void497}498 499define dso_local void @trunc_i64_to_i8(i64 %x, ptr %p) {500; CHECK-LABEL: trunc_i64_to_i8:501; CHECK: # %bb.0:502; CHECK-NEXT: movq %rdi, (%rsi)503; CHECK-NEXT: retq504 %t1 = trunc i64 %x to i8505 %sh1 = lshr i64 %x, 8506 %t2 = trunc i64 %sh1 to i8507 %sh2 = lshr i64 %x, 16508 %t3 = trunc i64 %sh2 to i8509 %sh3 = lshr i64 %x, 24510 %t4 = trunc i64 %sh3 to i8511 %sh4 = lshr i64 %x, 32512 %t5 = trunc i64 %sh4 to i8513 %sh5 = lshr i64 %x, 40514 %t6 = trunc i64 %sh5 to i8515 %sh6 = lshr i64 %x, 48516 %t7 = trunc i64 %sh6 to i8517 %sh7 = lshr i64 %x, 56518 %t8 = trunc i64 %sh7 to i8519 store i8 %t1, ptr %p, align 1520 %p1 = getelementptr inbounds i8, ptr %p, i64 1521 store i8 %t2, ptr %p1, align 1522 %p2 = getelementptr inbounds i8, ptr %p, i64 2523 store i8 %t3, ptr %p2, align 1524 %p3 = getelementptr inbounds i8, ptr %p, i64 3525 store i8 %t4, ptr %p3, align 1526 %p4 = getelementptr inbounds i8, ptr %p, i64 4527 store i8 %t5, ptr %p4, align 1528 %p5 = getelementptr inbounds i8, ptr %p, i64 5529 store i8 %t6, ptr %p5, align 1530 %p6 = getelementptr inbounds i8, ptr %p, i64 6531 store i8 %t7, ptr %p6, align 1532 %p7 = getelementptr inbounds i8, ptr %p, i64 7533 store i8 %t8, ptr %p7, align 1534 ret void535}536 537define dso_local void @trunc_i64_to_i16(i64 %x, ptr %p) {538; CHECK-LABEL: trunc_i64_to_i16:539; CHECK: # %bb.0:540; CHECK-NEXT: movq %rdi, (%rsi)541; CHECK-NEXT: retq542 %t1 = trunc i64 %x to i16543 %sh1 = lshr i64 %x, 16544 %t2 = trunc i64 %sh1 to i16545 %sh2 = lshr i64 %x, 32546 %t3 = trunc i64 %sh2 to i16547 %sh3 = lshr i64 %x, 48548 %t4 = trunc i64 %sh3 to i16549 store i16 %t1, ptr %p, align 2550 %p1 = getelementptr inbounds i16, ptr %p, i64 1551 store i16 %t2, ptr %p1, align 2552 %p2 = getelementptr inbounds i16, ptr %p, i64 2553 store i16 %t3, ptr %p2, align 2554 %p3 = getelementptr inbounds i16, ptr %p, i64 3555 store i16 %t4, ptr %p3, align 2556 ret void557}558 559define dso_local void @trunc_i64_to_i32(i64 %x, ptr %p) {560; CHECK-LABEL: trunc_i64_to_i32:561; CHECK: # %bb.0:562; CHECK-NEXT: movq %rdi, (%rsi)563; CHECK-NEXT: retq564 %t1 = trunc i64 %x to i32565 %sh = lshr i64 %x, 32566 %t2 = trunc i64 %sh to i32567 store i32 %t1, ptr %p, align 4568 %p1 = getelementptr inbounds i32, ptr %p, i64 1569 store i32 %t2, ptr %p1, align 4570 ret void571}572 573define dso_local void @be_i64_to_i32(i64 %x, ptr %p0) {574; CHECK-LABEL: be_i64_to_i32:575; CHECK: # %bb.0:576; CHECK-NEXT: rorq $32, %rdi577; CHECK-NEXT: movq %rdi, (%rsi)578; CHECK-NEXT: retq579 %sh1 = lshr i64 %x, 32580 %t0 = trunc i64 %x to i32581 %t1 = trunc i64 %sh1 to i32582 %p1 = getelementptr inbounds i32, ptr %p0, i64 1583 store i32 %t0, ptr %p1, align 4584 store i32 %t1, ptr %p0, align 4585 ret void586}587 588define dso_local void @be_i64_to_i32_order(i64 %x, ptr %p0) {589; CHECK-LABEL: be_i64_to_i32_order:590; CHECK: # %bb.0:591; CHECK-NEXT: rorq $32, %rdi592; CHECK-NEXT: movq %rdi, (%rsi)593; CHECK-NEXT: retq594 %sh1 = lshr i64 %x, 32595 %t0 = trunc i64 %x to i32596 %t1 = trunc i64 %sh1 to i32597 %p1 = getelementptr inbounds i32, ptr %p0, i64 1598 store i32 %t1, ptr %p0, align 4599 store i32 %t0, ptr %p1, align 4600 ret void601}602 603; https://llvm.org/PR50623604; It is a miscompile to merge the stores if we are not605; writing all of the bytes from the source value.606 607define void @merge_hole(i32 %x, ptr %p) {608; CHECK-LABEL: merge_hole:609; CHECK: # %bb.0:610; CHECK-NEXT: movb %dil, (%rsi)611; CHECK-NEXT: shrl $16, %edi612; CHECK-NEXT: movw %di, 2(%rsi)613; CHECK-NEXT: retq614 %p2 = getelementptr inbounds i16, ptr %p, i64 1615 %x3 = trunc i32 %x to i8616 store i8 %x3, ptr %p, align 1617 %sh = lshr i32 %x, 16618 %x01 = trunc i32 %sh to i16619 store i16 %x01, ptr %p2, align 1620 ret void621}622 623; Change the order of the stores.624; It is a miscompile to merge the stores if we are not625; writing all of the bytes from the source value.626 627define void @merge_hole2(i32 %x, ptr %p) {628; CHECK-LABEL: merge_hole2:629; CHECK: # %bb.0:630; CHECK-NEXT: movl %edi, %eax631; CHECK-NEXT: shrl $16, %eax632; CHECK-NEXT: movw %ax, 2(%rsi)633; CHECK-NEXT: movb %dil, (%rsi)634; CHECK-NEXT: retq635 %p2 = getelementptr inbounds i16, ptr %p, i64 1636 %sh = lshr i32 %x, 16637 %x01 = trunc i32 %sh to i16638 store i16 %x01, ptr %p2, align 1639 %x3 = trunc i32 %x to i8640 store i8 %x3, ptr %p, align 1641 ret void642}643 644; Change offset.645; It is a miscompile to merge the stores if we are not646; writing all of the bytes from the source value.647 648define void @merge_hole3(i32 %x, ptr %p) {649; CHECK-LABEL: merge_hole3:650; CHECK: # %bb.0:651; CHECK-NEXT: movb %dil, 1(%rsi)652; CHECK-NEXT: shrl $16, %edi653; CHECK-NEXT: movw %di, 2(%rsi)654; CHECK-NEXT: retq655 %p1 = getelementptr inbounds i8, ptr %p, i64 1656 %p2 = getelementptr inbounds i16, ptr %p, i64 1657 %x3 = trunc i32 %x to i8658 store i8 %x3, ptr %p1, align 1659 %sh = lshr i32 %x, 16660 %x01 = trunc i32 %sh to i16661 store i16 %x01, ptr %p2, align 1662 ret void663}664 665; Change offset.666; It is a miscompile to merge the stores if we are not667; writing all of the bytes from the source value.668 669define void @merge_hole4(i32 %x, ptr %p) {670; CHECK-LABEL: merge_hole4:671; CHECK: # %bb.0:672; CHECK-NEXT: movb %dil, 2(%rsi)673; CHECK-NEXT: shrl $16, %edi674; CHECK-NEXT: movw %di, (%rsi)675; CHECK-NEXT: retq676 %p2 = getelementptr inbounds i8, ptr %p, i64 2677 %x3 = trunc i32 %x to i8678 store i8 %x3, ptr %p2, align 1679 %sh = lshr i32 %x, 16680 %x01 = trunc i32 %sh to i16681 store i16 %x01, ptr %p, align 1682 ret void683}684