1317 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=i686-unknown | FileCheck %s --check-prefix=CHECK --check-prefix=BSWAP3; RUN: llc < %s -mtriple=i686-unknown -mattr=+movbe | FileCheck %s --check-prefix=CHECK --check-prefix=MOVBE4; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s --check-prefix=CHECK64 --check-prefix=BSWAP645; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+movbe | FileCheck %s --check-prefix=CHECK64 --check-prefix=MOVBE646 7; ptr p;8; (i32) p[0] | ((i32) p[1] << 8) | ((i32) p[2] << 16) | ((i32) p[3] << 24)9define i32 @load_i32_by_i8(ptr %arg) {10; CHECK-LABEL: load_i32_by_i8:11; CHECK: # %bb.0:12; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax13; CHECK-NEXT: movl (%eax), %eax14; CHECK-NEXT: retl15;16; CHECK64-LABEL: load_i32_by_i8:17; CHECK64: # %bb.0:18; CHECK64-NEXT: movl (%rdi), %eax19; CHECK64-NEXT: retq20 %tmp1 = load i8, ptr %arg, align 121 %tmp2 = zext i8 %tmp1 to i3222 %tmp3 = getelementptr inbounds i8, ptr %arg, i32 123 %tmp4 = load i8, ptr %tmp3, align 124 %tmp5 = zext i8 %tmp4 to i3225 %tmp6 = shl nuw nsw i32 %tmp5, 826 %tmp7 = or i32 %tmp6, %tmp227 %tmp8 = getelementptr inbounds i8, ptr %arg, i32 228 %tmp9 = load i8, ptr %tmp8, align 129 %tmp10 = zext i8 %tmp9 to i3230 %tmp11 = shl nuw nsw i32 %tmp10, 1631 %tmp12 = or i32 %tmp7, %tmp1132 %tmp13 = getelementptr inbounds i8, ptr %arg, i32 333 %tmp14 = load i8, ptr %tmp13, align 134 %tmp15 = zext i8 %tmp14 to i3235 %tmp16 = shl nuw nsw i32 %tmp15, 2436 %tmp17 = or i32 %tmp12, %tmp1637 ret i32 %tmp1738}39 40; ptr p;41; ((i32) p[0] << 24) | ((i32) p[1] << 16) | ((i32) p[2] << 8) | (i32) p[3]42define i32 @load_i32_by_i8_bswap(ptr %arg) {43; BSWAP-LABEL: load_i32_by_i8_bswap:44; BSWAP: # %bb.0:45; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %eax46; BSWAP-NEXT: movl (%eax), %eax47; BSWAP-NEXT: bswapl %eax48; BSWAP-NEXT: retl49;50; MOVBE-LABEL: load_i32_by_i8_bswap:51; MOVBE: # %bb.0:52; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax53; MOVBE-NEXT: movbel (%eax), %eax54; MOVBE-NEXT: retl55;56; BSWAP64-LABEL: load_i32_by_i8_bswap:57; BSWAP64: # %bb.0:58; BSWAP64-NEXT: movl (%rdi), %eax59; BSWAP64-NEXT: bswapl %eax60; BSWAP64-NEXT: retq61;62; MOVBE64-LABEL: load_i32_by_i8_bswap:63; MOVBE64: # %bb.0:64; MOVBE64-NEXT: movbel (%rdi), %eax65; MOVBE64-NEXT: retq66 %tmp1 = load i8, ptr %arg, align 167 %tmp2 = zext i8 %tmp1 to i3268 %tmp3 = shl nuw nsw i32 %tmp2, 2469 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 170 %tmp5 = load i8, ptr %tmp4, align 171 %tmp6 = zext i8 %tmp5 to i3272 %tmp7 = shl nuw nsw i32 %tmp6, 1673 %tmp8 = or i32 %tmp7, %tmp374 %tmp9 = getelementptr inbounds i8, ptr %arg, i32 275 %tmp10 = load i8, ptr %tmp9, align 176 %tmp11 = zext i8 %tmp10 to i3277 %tmp12 = shl nuw nsw i32 %tmp11, 878 %tmp13 = or i32 %tmp8, %tmp1279 %tmp14 = getelementptr inbounds i8, ptr %arg, i32 380 %tmp15 = load i8, ptr %tmp14, align 181 %tmp16 = zext i8 %tmp15 to i3282 %tmp17 = or i32 %tmp13, %tmp1683 ret i32 %tmp1784}85 86; ptr p;87; (i32) p[0] | ((i32) p[1] << 16)88define i32 @load_i32_by_i16(ptr %arg) {89; CHECK-LABEL: load_i32_by_i16:90; CHECK: # %bb.0:91; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax92; CHECK-NEXT: movl (%eax), %eax93; CHECK-NEXT: retl94;95; CHECK64-LABEL: load_i32_by_i16:96; CHECK64: # %bb.0:97; CHECK64-NEXT: movl (%rdi), %eax98; CHECK64-NEXT: retq99 %tmp1 = load i16, ptr %arg, align 1100 %tmp2 = zext i16 %tmp1 to i32101 %tmp3 = getelementptr inbounds i16, ptr %arg, i32 1102 %tmp4 = load i16, ptr %tmp3, align 1103 %tmp5 = zext i16 %tmp4 to i32104 %tmp6 = shl nuw nsw i32 %tmp5, 16105 %tmp7 = or i32 %tmp6, %tmp2106 ret i32 %tmp7107}108 109; ptr p_16;110; ptr p_8 = (ptr) p_16;111; (i32) p_16[0] | ((i32) p[2] << 16) | ((i32) p[3] << 24)112define i32 @load_i32_by_i16_i8(ptr %arg) {113; CHECK-LABEL: load_i32_by_i16_i8:114; CHECK: # %bb.0:115; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax116; CHECK-NEXT: movl (%eax), %eax117; CHECK-NEXT: retl118;119; CHECK64-LABEL: load_i32_by_i16_i8:120; CHECK64: # %bb.0:121; CHECK64-NEXT: movl (%rdi), %eax122; CHECK64-NEXT: retq123 %tmp2 = load i16, ptr %arg, align 1124 %tmp3 = zext i16 %tmp2 to i32125 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 2126 %tmp5 = load i8, ptr %tmp4, align 1127 %tmp6 = zext i8 %tmp5 to i32128 %tmp7 = shl nuw nsw i32 %tmp6, 16129 %tmp8 = getelementptr inbounds i8, ptr %arg, i32 3130 %tmp9 = load i8, ptr %tmp8, align 1131 %tmp10 = zext i8 %tmp9 to i32132 %tmp11 = shl nuw nsw i32 %tmp10, 24133 %tmp12 = or i32 %tmp7, %tmp11134 %tmp13 = or i32 %tmp12, %tmp3135 ret i32 %tmp13136}137 138 139; ptr p;140; (i32) ((i16) p[0] | ((i16) p[1] << 8)) | (((i32) ((i16) p[3] | ((i16) p[4] << 8)) << 16)141define i32 @load_i32_by_i16_by_i8(ptr %arg) {142; CHECK-LABEL: load_i32_by_i16_by_i8:143; CHECK: # %bb.0:144; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax145; CHECK-NEXT: movl (%eax), %eax146; CHECK-NEXT: retl147;148; CHECK64-LABEL: load_i32_by_i16_by_i8:149; CHECK64: # %bb.0:150; CHECK64-NEXT: movl (%rdi), %eax151; CHECK64-NEXT: retq152 %tmp1 = load i8, ptr %arg, align 1153 %tmp2 = zext i8 %tmp1 to i16154 %tmp3 = getelementptr inbounds i8, ptr %arg, i32 1155 %tmp4 = load i8, ptr %tmp3, align 1156 %tmp5 = zext i8 %tmp4 to i16157 %tmp6 = shl nuw nsw i16 %tmp5, 8158 %tmp7 = or i16 %tmp6, %tmp2159 %tmp8 = getelementptr inbounds i8, ptr %arg, i32 2160 %tmp9 = load i8, ptr %tmp8, align 1161 %tmp10 = zext i8 %tmp9 to i16162 %tmp11 = getelementptr inbounds i8, ptr %arg, i32 3163 %tmp12 = load i8, ptr %tmp11, align 1164 %tmp13 = zext i8 %tmp12 to i16165 %tmp14 = shl nuw nsw i16 %tmp13, 8166 %tmp15 = or i16 %tmp14, %tmp10167 %tmp16 = zext i16 %tmp7 to i32168 %tmp17 = zext i16 %tmp15 to i32169 %tmp18 = shl nuw nsw i32 %tmp17, 16170 %tmp19 = or i32 %tmp18, %tmp16171 ret i32 %tmp19172}173 174; ptr p;175; ((i32) (((i16) p[0] << 8) | (i16) p[1]) << 16) | (i32) (((i16) p[3] << 8) | (i16) p[4])176define i32 @load_i32_by_i16_by_i8_bswap(ptr %arg) {177; BSWAP-LABEL: load_i32_by_i16_by_i8_bswap:178; BSWAP: # %bb.0:179; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %eax180; BSWAP-NEXT: movl (%eax), %eax181; BSWAP-NEXT: bswapl %eax182; BSWAP-NEXT: retl183;184; MOVBE-LABEL: load_i32_by_i16_by_i8_bswap:185; MOVBE: # %bb.0:186; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax187; MOVBE-NEXT: movbel (%eax), %eax188; MOVBE-NEXT: retl189;190; BSWAP64-LABEL: load_i32_by_i16_by_i8_bswap:191; BSWAP64: # %bb.0:192; BSWAP64-NEXT: movl (%rdi), %eax193; BSWAP64-NEXT: bswapl %eax194; BSWAP64-NEXT: retq195;196; MOVBE64-LABEL: load_i32_by_i16_by_i8_bswap:197; MOVBE64: # %bb.0:198; MOVBE64-NEXT: movbel (%rdi), %eax199; MOVBE64-NEXT: retq200 %tmp1 = load i8, ptr %arg, align 1201 %tmp2 = zext i8 %tmp1 to i16202 %tmp3 = getelementptr inbounds i8, ptr %arg, i32 1203 %tmp4 = load i8, ptr %tmp3, align 1204 %tmp5 = zext i8 %tmp4 to i16205 %tmp6 = shl nuw nsw i16 %tmp2, 8206 %tmp7 = or i16 %tmp6, %tmp5207 %tmp8 = getelementptr inbounds i8, ptr %arg, i32 2208 %tmp9 = load i8, ptr %tmp8, align 1209 %tmp10 = zext i8 %tmp9 to i16210 %tmp11 = getelementptr inbounds i8, ptr %arg, i32 3211 %tmp12 = load i8, ptr %tmp11, align 1212 %tmp13 = zext i8 %tmp12 to i16213 %tmp14 = shl nuw nsw i16 %tmp10, 8214 %tmp15 = or i16 %tmp14, %tmp13215 %tmp16 = zext i16 %tmp7 to i32216 %tmp17 = zext i16 %tmp15 to i32217 %tmp18 = shl nuw nsw i32 %tmp16, 16218 %tmp19 = or i32 %tmp18, %tmp17219 ret i32 %tmp19220}221 222; ptr p;223; (i64) p[0] | ((i64) p[1] << 8) | ((i64) p[2] << 16) | ((i64) p[3] << 24) | ((i64) p[4] << 32) | ((i64) p[5] << 40) | ((i64) p[6] << 48) | ((i64) p[7] << 56)224define i64 @load_i64_by_i8(ptr %arg) {225; CHECK-LABEL: load_i64_by_i8:226; CHECK: # %bb.0:227; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx228; CHECK-NEXT: movl (%ecx), %eax229; CHECK-NEXT: movl 4(%ecx), %edx230; CHECK-NEXT: retl231;232; CHECK64-LABEL: load_i64_by_i8:233; CHECK64: # %bb.0:234; CHECK64-NEXT: movq (%rdi), %rax235; CHECK64-NEXT: retq236 %tmp1 = load i8, ptr %arg, align 1237 %tmp2 = zext i8 %tmp1 to i64238 %tmp3 = getelementptr inbounds i8, ptr %arg, i64 1239 %tmp4 = load i8, ptr %tmp3, align 1240 %tmp5 = zext i8 %tmp4 to i64241 %tmp6 = shl nuw nsw i64 %tmp5, 8242 %tmp7 = or i64 %tmp6, %tmp2243 %tmp8 = getelementptr inbounds i8, ptr %arg, i64 2244 %tmp9 = load i8, ptr %tmp8, align 1245 %tmp10 = zext i8 %tmp9 to i64246 %tmp11 = shl nuw nsw i64 %tmp10, 16247 %tmp12 = or i64 %tmp7, %tmp11248 %tmp13 = getelementptr inbounds i8, ptr %arg, i64 3249 %tmp14 = load i8, ptr %tmp13, align 1250 %tmp15 = zext i8 %tmp14 to i64251 %tmp16 = shl nuw nsw i64 %tmp15, 24252 %tmp17 = or i64 %tmp12, %tmp16253 %tmp18 = getelementptr inbounds i8, ptr %arg, i64 4254 %tmp19 = load i8, ptr %tmp18, align 1255 %tmp20 = zext i8 %tmp19 to i64256 %tmp21 = shl nuw nsw i64 %tmp20, 32257 %tmp22 = or i64 %tmp17, %tmp21258 %tmp23 = getelementptr inbounds i8, ptr %arg, i64 5259 %tmp24 = load i8, ptr %tmp23, align 1260 %tmp25 = zext i8 %tmp24 to i64261 %tmp26 = shl nuw nsw i64 %tmp25, 40262 %tmp27 = or i64 %tmp22, %tmp26263 %tmp28 = getelementptr inbounds i8, ptr %arg, i64 6264 %tmp29 = load i8, ptr %tmp28, align 1265 %tmp30 = zext i8 %tmp29 to i64266 %tmp31 = shl nuw nsw i64 %tmp30, 48267 %tmp32 = or i64 %tmp27, %tmp31268 %tmp33 = getelementptr inbounds i8, ptr %arg, i64 7269 %tmp34 = load i8, ptr %tmp33, align 1270 %tmp35 = zext i8 %tmp34 to i64271 %tmp36 = shl nuw i64 %tmp35, 56272 %tmp37 = or i64 %tmp32, %tmp36273 ret i64 %tmp37274}275 276; ptr p;277; ((i64) p[0] << 56) | ((i64) p[1] << 48) | ((i64) p[2] << 40) | ((i64) p[3] << 32) | ((i64) p[4] << 24) | ((i64) p[5] << 16) | ((i64) p[6] << 8) | (i64) p[7]278define i64 @load_i64_by_i8_bswap(ptr %arg) {279; BSWAP-LABEL: load_i64_by_i8_bswap:280; BSWAP: # %bb.0:281; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %eax282; BSWAP-NEXT: movl (%eax), %edx283; BSWAP-NEXT: movl 4(%eax), %eax284; BSWAP-NEXT: bswapl %eax285; BSWAP-NEXT: bswapl %edx286; BSWAP-NEXT: retl287;288; MOVBE-LABEL: load_i64_by_i8_bswap:289; MOVBE: # %bb.0:290; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %ecx291; MOVBE-NEXT: movbel 4(%ecx), %eax292; MOVBE-NEXT: movbel (%ecx), %edx293; MOVBE-NEXT: retl294;295; BSWAP64-LABEL: load_i64_by_i8_bswap:296; BSWAP64: # %bb.0:297; BSWAP64-NEXT: movq (%rdi), %rax298; BSWAP64-NEXT: bswapq %rax299; BSWAP64-NEXT: retq300;301; MOVBE64-LABEL: load_i64_by_i8_bswap:302; MOVBE64: # %bb.0:303; MOVBE64-NEXT: movbeq (%rdi), %rax304; MOVBE64-NEXT: retq305 %tmp1 = load i8, ptr %arg, align 1306 %tmp2 = zext i8 %tmp1 to i64307 %tmp3 = shl nuw i64 %tmp2, 56308 %tmp4 = getelementptr inbounds i8, ptr %arg, i64 1309 %tmp5 = load i8, ptr %tmp4, align 1310 %tmp6 = zext i8 %tmp5 to i64311 %tmp7 = shl nuw nsw i64 %tmp6, 48312 %tmp8 = or i64 %tmp7, %tmp3313 %tmp9 = getelementptr inbounds i8, ptr %arg, i64 2314 %tmp10 = load i8, ptr %tmp9, align 1315 %tmp11 = zext i8 %tmp10 to i64316 %tmp12 = shl nuw nsw i64 %tmp11, 40317 %tmp13 = or i64 %tmp8, %tmp12318 %tmp14 = getelementptr inbounds i8, ptr %arg, i64 3319 %tmp15 = load i8, ptr %tmp14, align 1320 %tmp16 = zext i8 %tmp15 to i64321 %tmp17 = shl nuw nsw i64 %tmp16, 32322 %tmp18 = or i64 %tmp13, %tmp17323 %tmp19 = getelementptr inbounds i8, ptr %arg, i64 4324 %tmp20 = load i8, ptr %tmp19, align 1325 %tmp21 = zext i8 %tmp20 to i64326 %tmp22 = shl nuw nsw i64 %tmp21, 24327 %tmp23 = or i64 %tmp18, %tmp22328 %tmp24 = getelementptr inbounds i8, ptr %arg, i64 5329 %tmp25 = load i8, ptr %tmp24, align 1330 %tmp26 = zext i8 %tmp25 to i64331 %tmp27 = shl nuw nsw i64 %tmp26, 16332 %tmp28 = or i64 %tmp23, %tmp27333 %tmp29 = getelementptr inbounds i8, ptr %arg, i64 6334 %tmp30 = load i8, ptr %tmp29, align 1335 %tmp31 = zext i8 %tmp30 to i64336 %tmp32 = shl nuw nsw i64 %tmp31, 8337 %tmp33 = or i64 %tmp28, %tmp32338 %tmp34 = getelementptr inbounds i8, ptr %arg, i64 7339 %tmp35 = load i8, ptr %tmp34, align 1340 %tmp36 = zext i8 %tmp35 to i64341 %tmp37 = or i64 %tmp33, %tmp36342 ret i64 %tmp37343}344 345; Part of the load by bytes pattern is used outside of the pattern346; ptr p;347; i32 x = (i32) p[1]348; res = ((i32) p[0] << 24) | (x << 16) | ((i32) p[2] << 8) | (i32) p[3]349; x | res350define i32 @load_i32_by_i8_bswap_uses(ptr %arg) {351; CHECK-LABEL: load_i32_by_i8_bswap_uses:352; CHECK: # %bb.0:353; CHECK-NEXT: pushl %esi354; CHECK-NEXT: .cfi_def_cfa_offset 8355; CHECK-NEXT: .cfi_offset %esi, -8356; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax357; CHECK-NEXT: movzbl (%eax), %ecx358; CHECK-NEXT: shll $24, %ecx359; CHECK-NEXT: movzbl 1(%eax), %edx360; CHECK-NEXT: movl %edx, %esi361; CHECK-NEXT: shll $16, %esi362; CHECK-NEXT: orl %ecx, %esi363; CHECK-NEXT: movzbl 2(%eax), %ecx364; CHECK-NEXT: shll $8, %ecx365; CHECK-NEXT: orl %esi, %ecx366; CHECK-NEXT: movzbl 3(%eax), %eax367; CHECK-NEXT: orl %ecx, %eax368; CHECK-NEXT: orl %edx, %eax369; CHECK-NEXT: popl %esi370; CHECK-NEXT: .cfi_def_cfa_offset 4371; CHECK-NEXT: retl372;373; CHECK64-LABEL: load_i32_by_i8_bswap_uses:374; CHECK64: # %bb.0:375; CHECK64-NEXT: movzbl (%rdi), %eax376; CHECK64-NEXT: shll $24, %eax377; CHECK64-NEXT: movzbl 1(%rdi), %ecx378; CHECK64-NEXT: movl %ecx, %edx379; CHECK64-NEXT: shll $16, %edx380; CHECK64-NEXT: orl %eax, %edx381; CHECK64-NEXT: movzbl 2(%rdi), %esi382; CHECK64-NEXT: shll $8, %esi383; CHECK64-NEXT: orl %edx, %esi384; CHECK64-NEXT: movzbl 3(%rdi), %eax385; CHECK64-NEXT: orl %esi, %eax386; CHECK64-NEXT: orl %ecx, %eax387; CHECK64-NEXT: retq388 %tmp1 = load i8, ptr %arg, align 1389 %tmp2 = zext i8 %tmp1 to i32390 %tmp3 = shl nuw nsw i32 %tmp2, 24391 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 1392 %tmp5 = load i8, ptr %tmp4, align 1393 %tmp6 = zext i8 %tmp5 to i32394 %tmp7 = shl nuw nsw i32 %tmp6, 16395 %tmp8 = or i32 %tmp7, %tmp3396 %tmp9 = getelementptr inbounds i8, ptr %arg, i32 2397 %tmp10 = load i8, ptr %tmp9, align 1398 %tmp11 = zext i8 %tmp10 to i32399 %tmp12 = shl nuw nsw i32 %tmp11, 8400 %tmp13 = or i32 %tmp8, %tmp12401 %tmp14 = getelementptr inbounds i8, ptr %arg, i32 3402 %tmp15 = load i8, ptr %tmp14, align 1403 %tmp16 = zext i8 %tmp15 to i32404 %tmp17 = or i32 %tmp13, %tmp16405 ; Use individual part of the pattern outside of the pattern406 %tmp18 = or i32 %tmp6, %tmp17407 ret i32 %tmp18408}409 410; One of the loads is volatile411; ptr p;412; p0 = volatile *p;413; ((i32) p0 << 24) | ((i32) p[1] << 16) | ((i32) p[2] << 8) | (i32) p[3]414define i32 @load_i32_by_i8_bswap_volatile(ptr %arg) {415; CHECK-LABEL: load_i32_by_i8_bswap_volatile:416; CHECK: # %bb.0:417; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax418; CHECK-NEXT: movzbl (%eax), %ecx419; CHECK-NEXT: shll $24, %ecx420; CHECK-NEXT: movzbl 1(%eax), %edx421; CHECK-NEXT: shll $16, %edx422; CHECK-NEXT: orl %ecx, %edx423; CHECK-NEXT: movzbl 2(%eax), %ecx424; CHECK-NEXT: shll $8, %ecx425; CHECK-NEXT: orl %edx, %ecx426; CHECK-NEXT: movzbl 3(%eax), %eax427; CHECK-NEXT: orl %ecx, %eax428; CHECK-NEXT: retl429;430; CHECK64-LABEL: load_i32_by_i8_bswap_volatile:431; CHECK64: # %bb.0:432; CHECK64-NEXT: movzbl (%rdi), %eax433; CHECK64-NEXT: shll $24, %eax434; CHECK64-NEXT: movzbl 1(%rdi), %ecx435; CHECK64-NEXT: shll $16, %ecx436; CHECK64-NEXT: orl %eax, %ecx437; CHECK64-NEXT: movzbl 2(%rdi), %edx438; CHECK64-NEXT: shll $8, %edx439; CHECK64-NEXT: orl %ecx, %edx440; CHECK64-NEXT: movzbl 3(%rdi), %eax441; CHECK64-NEXT: orl %edx, %eax442; CHECK64-NEXT: retq443 %tmp1 = load volatile i8, ptr %arg, align 1444 %tmp2 = zext i8 %tmp1 to i32445 %tmp3 = shl nuw nsw i32 %tmp2, 24446 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 1447 %tmp5 = load i8, ptr %tmp4, align 1448 %tmp6 = zext i8 %tmp5 to i32449 %tmp7 = shl nuw nsw i32 %tmp6, 16450 %tmp8 = or i32 %tmp7, %tmp3451 %tmp9 = getelementptr inbounds i8, ptr %arg, i32 2452 %tmp10 = load i8, ptr %tmp9, align 1453 %tmp11 = zext i8 %tmp10 to i32454 %tmp12 = shl nuw nsw i32 %tmp11, 8455 %tmp13 = or i32 %tmp8, %tmp12456 %tmp14 = getelementptr inbounds i8, ptr %arg, i32 3457 %tmp15 = load i8, ptr %tmp14, align 1458 %tmp16 = zext i8 %tmp15 to i32459 %tmp17 = or i32 %tmp13, %tmp16460 ret i32 %tmp17461}462 463; There is a store in between individual loads464; ptr p, q;465; res1 = ((i32) p[0] << 24) | ((i32) p[1] << 16)466; *q = 0;467; res2 = ((i32) p[2] << 8) | (i32) p[3]468; res1 | res2469define i32 @load_i32_by_i8_bswap_store_in_between(ptr %arg, ptr %arg1) {470; CHECK-LABEL: load_i32_by_i8_bswap_store_in_between:471; CHECK: # %bb.0:472; CHECK-NEXT: pushl %esi473; CHECK-NEXT: .cfi_def_cfa_offset 8474; CHECK-NEXT: .cfi_offset %esi, -8475; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx476; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax477; CHECK-NEXT: movzbl (%eax), %edx478; CHECK-NEXT: shll $24, %edx479; CHECK-NEXT: movzbl 1(%eax), %esi480; CHECK-NEXT: movl $0, (%ecx)481; CHECK-NEXT: shll $16, %esi482; CHECK-NEXT: orl %edx, %esi483; CHECK-NEXT: movzbl 2(%eax), %ecx484; CHECK-NEXT: shll $8, %ecx485; CHECK-NEXT: orl %esi, %ecx486; CHECK-NEXT: movzbl 3(%eax), %eax487; CHECK-NEXT: orl %ecx, %eax488; CHECK-NEXT: popl %esi489; CHECK-NEXT: .cfi_def_cfa_offset 4490; CHECK-NEXT: retl491;492; CHECK64-LABEL: load_i32_by_i8_bswap_store_in_between:493; CHECK64: # %bb.0:494; CHECK64-NEXT: movzbl (%rdi), %eax495; CHECK64-NEXT: shll $24, %eax496; CHECK64-NEXT: movzbl 1(%rdi), %ecx497; CHECK64-NEXT: movl $0, (%rsi)498; CHECK64-NEXT: shll $16, %ecx499; CHECK64-NEXT: orl %eax, %ecx500; CHECK64-NEXT: movzbl 2(%rdi), %edx501; CHECK64-NEXT: shll $8, %edx502; CHECK64-NEXT: orl %ecx, %edx503; CHECK64-NEXT: movzbl 3(%rdi), %eax504; CHECK64-NEXT: orl %edx, %eax505; CHECK64-NEXT: retq506 %tmp2 = load i8, ptr %arg, align 1507 %tmp3 = zext i8 %tmp2 to i32508 %tmp4 = shl nuw nsw i32 %tmp3, 24509 %tmp5 = getelementptr inbounds i8, ptr %arg, i32 1510 %tmp6 = load i8, ptr %tmp5, align 1511 ; This store will prevent folding of the pattern512 store i32 0, ptr %arg1513 %tmp7 = zext i8 %tmp6 to i32514 %tmp8 = shl nuw nsw i32 %tmp7, 16515 %tmp9 = or i32 %tmp8, %tmp4516 %tmp10 = getelementptr inbounds i8, ptr %arg, i32 2517 %tmp11 = load i8, ptr %tmp10, align 1518 %tmp12 = zext i8 %tmp11 to i32519 %tmp13 = shl nuw nsw i32 %tmp12, 8520 %tmp14 = or i32 %tmp9, %tmp13521 %tmp15 = getelementptr inbounds i8, ptr %arg, i32 3522 %tmp16 = load i8, ptr %tmp15, align 1523 %tmp17 = zext i8 %tmp16 to i32524 %tmp18 = or i32 %tmp14, %tmp17525 ret i32 %tmp18526}527 528; One of the loads is from an unrelated location529; ptr p, q;530; ((i32) p[0] << 24) | ((i32) q[1] << 16) | ((i32) p[2] << 8) | (i32) p[3]531define i32 @load_i32_by_i8_bswap_unrelated_load(ptr %arg, ptr %arg1) {532; CHECK-LABEL: load_i32_by_i8_bswap_unrelated_load:533; CHECK: # %bb.0:534; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax535; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx536; CHECK-NEXT: movzbl (%ecx), %edx537; CHECK-NEXT: shll $24, %edx538; CHECK-NEXT: movzbl 1(%eax), %eax539; CHECK-NEXT: shll $16, %eax540; CHECK-NEXT: orl %edx, %eax541; CHECK-NEXT: movzbl 2(%ecx), %edx542; CHECK-NEXT: shll $8, %edx543; CHECK-NEXT: orl %eax, %edx544; CHECK-NEXT: movzbl 3(%ecx), %eax545; CHECK-NEXT: orl %edx, %eax546; CHECK-NEXT: retl547;548; CHECK64-LABEL: load_i32_by_i8_bswap_unrelated_load:549; CHECK64: # %bb.0:550; CHECK64-NEXT: movzbl (%rdi), %eax551; CHECK64-NEXT: shll $24, %eax552; CHECK64-NEXT: movzbl 1(%rsi), %ecx553; CHECK64-NEXT: shll $16, %ecx554; CHECK64-NEXT: orl %eax, %ecx555; CHECK64-NEXT: movzbl 2(%rdi), %edx556; CHECK64-NEXT: shll $8, %edx557; CHECK64-NEXT: orl %ecx, %edx558; CHECK64-NEXT: movzbl 3(%rdi), %eax559; CHECK64-NEXT: orl %edx, %eax560; CHECK64-NEXT: retq561 %tmp3 = load i8, ptr %arg, align 1562 %tmp4 = zext i8 %tmp3 to i32563 %tmp5 = shl nuw nsw i32 %tmp4, 24564 ; Load from an unrelated address565 %tmp6 = getelementptr inbounds i8, ptr %arg1, i32 1566 %tmp7 = load i8, ptr %tmp6, align 1567 %tmp8 = zext i8 %tmp7 to i32568 %tmp9 = shl nuw nsw i32 %tmp8, 16569 %tmp10 = or i32 %tmp9, %tmp5570 %tmp11 = getelementptr inbounds i8, ptr %arg, i32 2571 %tmp12 = load i8, ptr %tmp11, align 1572 %tmp13 = zext i8 %tmp12 to i32573 %tmp14 = shl nuw nsw i32 %tmp13, 8574 %tmp15 = or i32 %tmp10, %tmp14575 %tmp16 = getelementptr inbounds i8, ptr %arg, i32 3576 %tmp17 = load i8, ptr %tmp16, align 1577 %tmp18 = zext i8 %tmp17 to i32578 %tmp19 = or i32 %tmp15, %tmp18579 ret i32 %tmp19580}581 582; ptr p;583; (i32) p[1] | ((i32) p[2] << 8) | ((i32) p[3] << 16) | ((i32) p[4] << 24)584define i32 @load_i32_by_i8_nonzero_offset(ptr %arg) {585; CHECK-LABEL: load_i32_by_i8_nonzero_offset:586; CHECK: # %bb.0:587; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax588; CHECK-NEXT: movl 1(%eax), %eax589; CHECK-NEXT: retl590;591; CHECK64-LABEL: load_i32_by_i8_nonzero_offset:592; CHECK64: # %bb.0:593; CHECK64-NEXT: movl 1(%rdi), %eax594; CHECK64-NEXT: retq595 %tmp1 = getelementptr inbounds i8, ptr %arg, i32 1596 %tmp2 = load i8, ptr %tmp1, align 1597 %tmp3 = zext i8 %tmp2 to i32598 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 2599 %tmp5 = load i8, ptr %tmp4, align 1600 %tmp6 = zext i8 %tmp5 to i32601 %tmp7 = shl nuw nsw i32 %tmp6, 8602 %tmp8 = or i32 %tmp7, %tmp3603 %tmp9 = getelementptr inbounds i8, ptr %arg, i32 3604 %tmp10 = load i8, ptr %tmp9, align 1605 %tmp11 = zext i8 %tmp10 to i32606 %tmp12 = shl nuw nsw i32 %tmp11, 16607 %tmp13 = or i32 %tmp8, %tmp12608 %tmp14 = getelementptr inbounds i8, ptr %arg, i32 4609 %tmp15 = load i8, ptr %tmp14, align 1610 %tmp16 = zext i8 %tmp15 to i32611 %tmp17 = shl nuw nsw i32 %tmp16, 24612 %tmp18 = or i32 %tmp13, %tmp17613 ret i32 %tmp18614}615 616; ptr p;617; (i32) p[-4] | ((i32) p[-3] << 8) | ((i32) p[-2] << 16) | ((i32) p[-1] << 24)618define i32 @load_i32_by_i8_neg_offset(ptr %arg) {619; CHECK-LABEL: load_i32_by_i8_neg_offset:620; CHECK: # %bb.0:621; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax622; CHECK-NEXT: movl -4(%eax), %eax623; CHECK-NEXT: retl624;625; CHECK64-LABEL: load_i32_by_i8_neg_offset:626; CHECK64: # %bb.0:627; CHECK64-NEXT: movl -4(%rdi), %eax628; CHECK64-NEXT: retq629 %tmp1 = getelementptr inbounds i8, ptr %arg, i32 -4630 %tmp2 = load i8, ptr %tmp1, align 1631 %tmp3 = zext i8 %tmp2 to i32632 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 -3633 %tmp5 = load i8, ptr %tmp4, align 1634 %tmp6 = zext i8 %tmp5 to i32635 %tmp7 = shl nuw nsw i32 %tmp6, 8636 %tmp8 = or i32 %tmp7, %tmp3637 %tmp9 = getelementptr inbounds i8, ptr %arg, i32 -2638 %tmp10 = load i8, ptr %tmp9, align 1639 %tmp11 = zext i8 %tmp10 to i32640 %tmp12 = shl nuw nsw i32 %tmp11, 16641 %tmp13 = or i32 %tmp8, %tmp12642 %tmp14 = getelementptr inbounds i8, ptr %arg, i32 -1643 %tmp15 = load i8, ptr %tmp14, align 1644 %tmp16 = zext i8 %tmp15 to i32645 %tmp17 = shl nuw nsw i32 %tmp16, 24646 %tmp18 = or i32 %tmp13, %tmp17647 ret i32 %tmp18648}649 650; ptr p;651; (i32) p[4] | ((i32) p[3] << 8) | ((i32) p[2] << 16) | ((i32) p[1] << 24)652define i32 @load_i32_by_i8_nonzero_offset_bswap(ptr %arg) {653; BSWAP-LABEL: load_i32_by_i8_nonzero_offset_bswap:654; BSWAP: # %bb.0:655; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %eax656; BSWAP-NEXT: movl 1(%eax), %eax657; BSWAP-NEXT: bswapl %eax658; BSWAP-NEXT: retl659;660; MOVBE-LABEL: load_i32_by_i8_nonzero_offset_bswap:661; MOVBE: # %bb.0:662; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax663; MOVBE-NEXT: movbel 1(%eax), %eax664; MOVBE-NEXT: retl665;666; BSWAP64-LABEL: load_i32_by_i8_nonzero_offset_bswap:667; BSWAP64: # %bb.0:668; BSWAP64-NEXT: movl 1(%rdi), %eax669; BSWAP64-NEXT: bswapl %eax670; BSWAP64-NEXT: retq671;672; MOVBE64-LABEL: load_i32_by_i8_nonzero_offset_bswap:673; MOVBE64: # %bb.0:674; MOVBE64-NEXT: movbel 1(%rdi), %eax675; MOVBE64-NEXT: retq676 %tmp1 = getelementptr inbounds i8, ptr %arg, i32 4677 %tmp2 = load i8, ptr %tmp1, align 1678 %tmp3 = zext i8 %tmp2 to i32679 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 3680 %tmp5 = load i8, ptr %tmp4, align 1681 %tmp6 = zext i8 %tmp5 to i32682 %tmp7 = shl nuw nsw i32 %tmp6, 8683 %tmp8 = or i32 %tmp7, %tmp3684 %tmp9 = getelementptr inbounds i8, ptr %arg, i32 2685 %tmp10 = load i8, ptr %tmp9, align 1686 %tmp11 = zext i8 %tmp10 to i32687 %tmp12 = shl nuw nsw i32 %tmp11, 16688 %tmp13 = or i32 %tmp8, %tmp12689 %tmp14 = getelementptr inbounds i8, ptr %arg, i32 1690 %tmp15 = load i8, ptr %tmp14, align 1691 %tmp16 = zext i8 %tmp15 to i32692 %tmp17 = shl nuw nsw i32 %tmp16, 24693 %tmp18 = or i32 %tmp13, %tmp17694 ret i32 %tmp18695}696 697; ptr p;698; (i32) p[-1] | ((i32) p[-2] << 8) | ((i32) p[-3] << 16) | ((i32) p[-4] << 24)699define i32 @load_i32_by_i8_neg_offset_bswap(ptr %arg) {700; BSWAP-LABEL: load_i32_by_i8_neg_offset_bswap:701; BSWAP: # %bb.0:702; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %eax703; BSWAP-NEXT: movl -4(%eax), %eax704; BSWAP-NEXT: bswapl %eax705; BSWAP-NEXT: retl706;707; MOVBE-LABEL: load_i32_by_i8_neg_offset_bswap:708; MOVBE: # %bb.0:709; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax710; MOVBE-NEXT: movbel -4(%eax), %eax711; MOVBE-NEXT: retl712;713; BSWAP64-LABEL: load_i32_by_i8_neg_offset_bswap:714; BSWAP64: # %bb.0:715; BSWAP64-NEXT: movl -4(%rdi), %eax716; BSWAP64-NEXT: bswapl %eax717; BSWAP64-NEXT: retq718;719; MOVBE64-LABEL: load_i32_by_i8_neg_offset_bswap:720; MOVBE64: # %bb.0:721; MOVBE64-NEXT: movbel -4(%rdi), %eax722; MOVBE64-NEXT: retq723 %tmp1 = getelementptr inbounds i8, ptr %arg, i32 -1724 %tmp2 = load i8, ptr %tmp1, align 1725 %tmp3 = zext i8 %tmp2 to i32726 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 -2727 %tmp5 = load i8, ptr %tmp4, align 1728 %tmp6 = zext i8 %tmp5 to i32729 %tmp7 = shl nuw nsw i32 %tmp6, 8730 %tmp8 = or i32 %tmp7, %tmp3731 %tmp9 = getelementptr inbounds i8, ptr %arg, i32 -3732 %tmp10 = load i8, ptr %tmp9, align 1733 %tmp11 = zext i8 %tmp10 to i32734 %tmp12 = shl nuw nsw i32 %tmp11, 16735 %tmp13 = or i32 %tmp8, %tmp12736 %tmp14 = getelementptr inbounds i8, ptr %arg, i32 -4737 %tmp15 = load i8, ptr %tmp14, align 1738 %tmp16 = zext i8 %tmp15 to i32739 %tmp17 = shl nuw nsw i32 %tmp16, 24740 %tmp18 = or i32 %tmp13, %tmp17741 ret i32 %tmp18742}743 744; ptr p; i32 i;745; ((i32) p[i] << 24) | ((i32) p[i + 1] << 16) | ((i32) p[i + 2] << 8) | (i32) p[i + 3]746define i32 @load_i32_by_i8_bswap_base_index_offset(ptr %arg, i32 %arg1) {747; BSWAP-LABEL: load_i32_by_i8_bswap_base_index_offset:748; BSWAP: # %bb.0:749; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %eax750; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %ecx751; BSWAP-NEXT: movl (%ecx,%eax), %eax752; BSWAP-NEXT: bswapl %eax753; BSWAP-NEXT: retl754;755; MOVBE-LABEL: load_i32_by_i8_bswap_base_index_offset:756; MOVBE: # %bb.0:757; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax758; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %ecx759; MOVBE-NEXT: movbel (%ecx,%eax), %eax760; MOVBE-NEXT: retl761;762; BSWAP64-LABEL: load_i32_by_i8_bswap_base_index_offset:763; BSWAP64: # %bb.0:764; BSWAP64-NEXT: movslq %esi, %rax765; BSWAP64-NEXT: movl (%rdi,%rax), %eax766; BSWAP64-NEXT: bswapl %eax767; BSWAP64-NEXT: retq768;769; MOVBE64-LABEL: load_i32_by_i8_bswap_base_index_offset:770; MOVBE64: # %bb.0:771; MOVBE64-NEXT: movslq %esi, %rax772; MOVBE64-NEXT: movbel (%rdi,%rax), %eax773; MOVBE64-NEXT: retq774 %tmp2 = getelementptr inbounds i8, ptr %arg, i32 %arg1775 %tmp3 = load i8, ptr %tmp2, align 1776 %tmp4 = zext i8 %tmp3 to i32777 %tmp5 = shl nuw nsw i32 %tmp4, 24778 %tmp6 = add nuw nsw i32 %arg1, 1779 %tmp7 = getelementptr inbounds i8, ptr %arg, i32 %tmp6780 %tmp8 = load i8, ptr %tmp7, align 1781 %tmp9 = zext i8 %tmp8 to i32782 %tmp10 = shl nuw nsw i32 %tmp9, 16783 %tmp11 = or i32 %tmp10, %tmp5784 %tmp12 = add nuw nsw i32 %arg1, 2785 %tmp13 = getelementptr inbounds i8, ptr %arg, i32 %tmp12786 %tmp14 = load i8, ptr %tmp13, align 1787 %tmp15 = zext i8 %tmp14 to i32788 %tmp16 = shl nuw nsw i32 %tmp15, 8789 %tmp17 = or i32 %tmp11, %tmp16790 %tmp18 = add nuw nsw i32 %arg1, 3791 %tmp19 = getelementptr inbounds i8, ptr %arg, i32 %tmp18792 %tmp20 = load i8, ptr %tmp19, align 1793 %tmp21 = zext i8 %tmp20 to i32794 %tmp22 = or i32 %tmp17, %tmp21795 ret i32 %tmp22796}797 798; Verify that we don't crash handling shl i32 %conv57, 32799define void @shift_i32_by_32(ptr %src1, ptr %src2, ptr %dst) {800; CHECK-LABEL: shift_i32_by_32:801; CHECK: # %bb.0: # %entry802; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax803; CHECK-NEXT: movl $0, 4(%eax)804; CHECK-NEXT: movl $0, (%eax)805; CHECK-NEXT: retl806;807; CHECK64-LABEL: shift_i32_by_32:808; CHECK64: # %bb.0: # %entry809; CHECK64-NEXT: movq $0, (%rdx)810; CHECK64-NEXT: retq811entry:812 %load1 = load i8, ptr %src1, align 1813 %conv46 = zext i8 %load1 to i32814 %shl47 = shl i32 %conv46, 56815 %or55 = or i32 %shl47, 0816 %load2 = load i8, ptr %src2, align 1817 %conv57 = zext i8 %load2 to i32818 %shl58 = shl i32 %conv57, 32819 %or59 = or i32 %or55, %shl58820 %or74 = or i32 %or59, 0821 %conv75 = sext i32 %or74 to i64822 store i64 %conv75, ptr %dst, align 8823 ret void824}825 826declare i16 @llvm.bswap.i16(i16)827 828; ptr p;829; (i32) bswap(p[1]) | (i32) bswap(p[0] << 16)830define i32 @load_i32_by_bswap_i16(ptr %arg) {831; BSWAP-LABEL: load_i32_by_bswap_i16:832; BSWAP: # %bb.0:833; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %eax834; BSWAP-NEXT: movl (%eax), %eax835; BSWAP-NEXT: bswapl %eax836; BSWAP-NEXT: retl837;838; MOVBE-LABEL: load_i32_by_bswap_i16:839; MOVBE: # %bb.0:840; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax841; MOVBE-NEXT: movbel (%eax), %eax842; MOVBE-NEXT: retl843;844; BSWAP64-LABEL: load_i32_by_bswap_i16:845; BSWAP64: # %bb.0:846; BSWAP64-NEXT: movl (%rdi), %eax847; BSWAP64-NEXT: bswapl %eax848; BSWAP64-NEXT: retq849;850; MOVBE64-LABEL: load_i32_by_bswap_i16:851; MOVBE64: # %bb.0:852; MOVBE64-NEXT: movbel (%rdi), %eax853; MOVBE64-NEXT: retq854 %tmp1 = load i16, ptr %arg, align 4855 %tmp11 = call i16 @llvm.bswap.i16(i16 %tmp1)856 %tmp2 = zext i16 %tmp11 to i32857 %tmp3 = getelementptr inbounds i16, ptr %arg, i32 1858 %tmp4 = load i16, ptr %tmp3, align 1859 %tmp41 = call i16 @llvm.bswap.i16(i16 %tmp4)860 %tmp5 = zext i16 %tmp41 to i32861 %tmp6 = shl nuw nsw i32 %tmp2, 16862 %tmp7 = or i32 %tmp6, %tmp5863 ret i32 %tmp7864}865 866; ptr p;867; (i32) p[0] | (sext(p[1] << 16) to i32)868define i32 @load_i32_by_sext_i16(ptr %arg) {869; CHECK-LABEL: load_i32_by_sext_i16:870; CHECK: # %bb.0:871; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax872; CHECK-NEXT: movl (%eax), %eax873; CHECK-NEXT: retl874;875; CHECK64-LABEL: load_i32_by_sext_i16:876; CHECK64: # %bb.0:877; CHECK64-NEXT: movl (%rdi), %eax878; CHECK64-NEXT: retq879 %tmp1 = load i16, ptr %arg, align 1880 %tmp2 = zext i16 %tmp1 to i32881 %tmp3 = getelementptr inbounds i16, ptr %arg, i32 1882 %tmp4 = load i16, ptr %tmp3, align 1883 %tmp5 = sext i16 %tmp4 to i32884 %tmp6 = shl nuw nsw i32 %tmp5, 16885 %tmp7 = or i32 %tmp6, %tmp2886 ret i32 %tmp7887}888 889; ptr arg; i32 i;890; p = arg + 12;891; (i32) p[i] | ((i32) p[i + 1] << 8) | ((i32) p[i + 2] << 16) | ((i32) p[i + 3] << 24)892define i32 @load_i32_by_i8_base_offset_index(ptr %arg, i32 %i) {893; CHECK-LABEL: load_i32_by_i8_base_offset_index:894; CHECK: # %bb.0:895; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax896; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx897; CHECK-NEXT: movl 12(%eax,%ecx), %eax898; CHECK-NEXT: retl899;900; CHECK64-LABEL: load_i32_by_i8_base_offset_index:901; CHECK64: # %bb.0:902; CHECK64-NEXT: movl %esi, %eax903; CHECK64-NEXT: movl 12(%rdi,%rax), %eax904; CHECK64-NEXT: retq905 %tmp = add nuw nsw i32 %i, 3906 %tmp2 = add nuw nsw i32 %i, 2907 %tmp3 = add nuw nsw i32 %i, 1908 %tmp4 = getelementptr inbounds i8, ptr %arg, i64 12909 %tmp5 = zext i32 %i to i64910 %tmp6 = getelementptr inbounds i8, ptr %tmp4, i64 %tmp5911 %tmp7 = load i8, ptr %tmp6, align 1912 %tmp8 = zext i8 %tmp7 to i32913 %tmp9 = zext i32 %tmp3 to i64914 %tmp10 = getelementptr inbounds i8, ptr %tmp4, i64 %tmp9915 %tmp11 = load i8, ptr %tmp10, align 1916 %tmp12 = zext i8 %tmp11 to i32917 %tmp13 = shl nuw nsw i32 %tmp12, 8918 %tmp14 = or i32 %tmp13, %tmp8919 %tmp15 = zext i32 %tmp2 to i64920 %tmp16 = getelementptr inbounds i8, ptr %tmp4, i64 %tmp15921 %tmp17 = load i8, ptr %tmp16, align 1922 %tmp18 = zext i8 %tmp17 to i32923 %tmp19 = shl nuw nsw i32 %tmp18, 16924 %tmp20 = or i32 %tmp14, %tmp19925 %tmp21 = zext i32 %tmp to i64926 %tmp22 = getelementptr inbounds i8, ptr %tmp4, i64 %tmp21927 %tmp23 = load i8, ptr %tmp22, align 1928 %tmp24 = zext i8 %tmp23 to i32929 %tmp25 = shl nuw i32 %tmp24, 24930 %tmp26 = or i32 %tmp20, %tmp25931 ret i32 %tmp26932}933 934; ptr arg; i32 i;935; p = arg + 12;936; (i32) p[i + 1] | ((i32) p[i + 2] << 8) | ((i32) p[i + 3] << 16) | ((i32) p[i + 4] << 24)937define i32 @load_i32_by_i8_base_offset_index_2(ptr %arg, i32 %i) {938; CHECK-LABEL: load_i32_by_i8_base_offset_index_2:939; CHECK: # %bb.0:940; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax941; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx942; CHECK-NEXT: movl 13(%eax,%ecx), %eax943; CHECK-NEXT: retl944;945; CHECK64-LABEL: load_i32_by_i8_base_offset_index_2:946; CHECK64: # %bb.0:947; CHECK64-NEXT: movl %esi, %eax948; CHECK64-NEXT: movl 13(%rax,%rdi), %eax949; CHECK64-NEXT: retq950 %tmp = add nuw nsw i32 %i, 4951 %tmp2 = add nuw nsw i32 %i, 3952 %tmp3 = add nuw nsw i32 %i, 2953 %tmp4 = getelementptr inbounds i8, ptr %arg, i64 12954 %tmp5 = add nuw nsw i32 %i, 1955 %tmp27 = zext i32 %tmp5 to i64956 %tmp28 = getelementptr inbounds i8, ptr %tmp4, i64 %tmp27957 %tmp29 = load i8, ptr %tmp28, align 1958 %tmp30 = zext i8 %tmp29 to i32959 %tmp31 = zext i32 %tmp3 to i64960 %tmp32 = getelementptr inbounds i8, ptr %tmp4, i64 %tmp31961 %tmp33 = load i8, ptr %tmp32, align 1962 %tmp34 = zext i8 %tmp33 to i32963 %tmp35 = shl nuw nsw i32 %tmp34, 8964 %tmp36 = or i32 %tmp35, %tmp30965 %tmp37 = zext i32 %tmp2 to i64966 %tmp38 = getelementptr inbounds i8, ptr %tmp4, i64 %tmp37967 %tmp39 = load i8, ptr %tmp38, align 1968 %tmp40 = zext i8 %tmp39 to i32969 %tmp41 = shl nuw nsw i32 %tmp40, 16970 %tmp42 = or i32 %tmp36, %tmp41971 %tmp43 = zext i32 %tmp to i64972 %tmp44 = getelementptr inbounds i8, ptr %tmp4, i64 %tmp43973 %tmp45 = load i8, ptr %tmp44, align 1974 %tmp46 = zext i8 %tmp45 to i32975 %tmp47 = shl nuw i32 %tmp46, 24976 %tmp48 = or i32 %tmp42, %tmp47977 ret i32 %tmp48978}979 980; ptr arg; i32 i;981;982; p0 = arg;983; p1 = arg + i + 1;984; p2 = arg + i + 2;985; p3 = arg + i + 3;986;987; (i32) p0[12] | ((i32) p1[12] << 8) | ((i32) p2[12] << 16) | ((i32) p3[12] << 24)988;989; This test excercises zero and any extend loads as a part of load combine pattern.990; In order to fold the pattern above we need to reassociate the address computation991; first. By the time the address computation is reassociated loads are combined to992; to zext and aext loads.993define i32 @load_i32_by_i8_zaext_loads(ptr %arg, i32 %arg1) {994; CHECK-LABEL: load_i32_by_i8_zaext_loads:995; CHECK: # %bb.0:996; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax997; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx998; CHECK-NEXT: movl 12(%eax,%ecx), %eax999; CHECK-NEXT: retl1000;1001; CHECK64-LABEL: load_i32_by_i8_zaext_loads:1002; CHECK64: # %bb.0:1003; CHECK64-NEXT: movl %esi, %eax1004; CHECK64-NEXT: movl 12(%rdi,%rax), %eax1005; CHECK64-NEXT: retq1006 %tmp = add nuw nsw i32 %arg1, 31007 %tmp2 = add nuw nsw i32 %arg1, 21008 %tmp3 = add nuw nsw i32 %arg1, 11009 %tmp4 = zext i32 %tmp to i641010 %tmp5 = zext i32 %tmp2 to i641011 %tmp6 = zext i32 %tmp3 to i641012 %tmp24 = getelementptr inbounds i8, ptr %arg, i64 %tmp41013 %tmp30 = getelementptr inbounds i8, ptr %arg, i64 %tmp51014 %tmp31 = getelementptr inbounds i8, ptr %arg, i64 %tmp61015 %tmp32 = getelementptr inbounds i8, ptr %arg, i64 121016 %tmp33 = zext i32 %arg1 to i641017 %tmp34 = getelementptr inbounds i8, ptr %tmp32, i64 %tmp331018 %tmp35 = load i8, ptr %tmp34, align 11019 %tmp36 = zext i8 %tmp35 to i321020 %tmp37 = getelementptr inbounds i8, ptr %tmp31, i64 121021 %tmp38 = load i8, ptr %tmp37, align 11022 %tmp39 = zext i8 %tmp38 to i321023 %tmp40 = shl nuw nsw i32 %tmp39, 81024 %tmp41 = or i32 %tmp40, %tmp361025 %tmp42 = getelementptr inbounds i8, ptr %tmp30, i64 121026 %tmp43 = load i8, ptr %tmp42, align 11027 %tmp44 = zext i8 %tmp43 to i321028 %tmp45 = shl nuw nsw i32 %tmp44, 161029 %tmp46 = or i32 %tmp41, %tmp451030 %tmp47 = getelementptr inbounds i8, ptr %tmp24, i64 121031 %tmp48 = load i8, ptr %tmp47, align 11032 %tmp49 = zext i8 %tmp48 to i321033 %tmp50 = shl nuw i32 %tmp49, 241034 %tmp51 = or i32 %tmp46, %tmp501035 ret i32 %tmp511036}1037 1038; The same as load_i32_by_i8_zaext_loads but the last load is combined to1039; a sext load.1040;1041; ptr arg; i32 i;1042;1043; p0 = arg;1044; p1 = arg + i + 1;1045; p2 = arg + i + 2;1046; p3 = arg + i + 3;1047;1048; (i32) p0[12] | ((i32) p1[12] << 8) | ((i32) p2[12] << 16) | ((i32) p3[12] << 24)1049define i32 @load_i32_by_i8_zsext_loads(ptr %arg, i32 %arg1) {1050; CHECK-LABEL: load_i32_by_i8_zsext_loads:1051; CHECK: # %bb.0:1052; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax1053; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx1054; CHECK-NEXT: movl 12(%eax,%ecx), %eax1055; CHECK-NEXT: retl1056;1057; CHECK64-LABEL: load_i32_by_i8_zsext_loads:1058; CHECK64: # %bb.0:1059; CHECK64-NEXT: movl %esi, %eax1060; CHECK64-NEXT: movl 12(%rdi,%rax), %eax1061; CHECK64-NEXT: retq1062 %tmp = add nuw nsw i32 %arg1, 31063 %tmp2 = add nuw nsw i32 %arg1, 21064 %tmp3 = add nuw nsw i32 %arg1, 11065 %tmp4 = zext i32 %tmp to i641066 %tmp5 = zext i32 %tmp2 to i641067 %tmp6 = zext i32 %tmp3 to i641068 %tmp24 = getelementptr inbounds i8, ptr %arg, i64 %tmp41069 %tmp30 = getelementptr inbounds i8, ptr %arg, i64 %tmp51070 %tmp31 = getelementptr inbounds i8, ptr %arg, i64 %tmp61071 %tmp32 = getelementptr inbounds i8, ptr %arg, i64 121072 %tmp33 = zext i32 %arg1 to i641073 %tmp34 = getelementptr inbounds i8, ptr %tmp32, i64 %tmp331074 %tmp35 = load i8, ptr %tmp34, align 11075 %tmp36 = zext i8 %tmp35 to i321076 %tmp37 = getelementptr inbounds i8, ptr %tmp31, i64 121077 %tmp38 = load i8, ptr %tmp37, align 11078 %tmp39 = zext i8 %tmp38 to i321079 %tmp40 = shl nuw nsw i32 %tmp39, 81080 %tmp41 = or i32 %tmp40, %tmp361081 %tmp42 = getelementptr inbounds i8, ptr %tmp30, i64 121082 %tmp43 = load i8, ptr %tmp42, align 11083 %tmp44 = zext i8 %tmp43 to i321084 %tmp45 = shl nuw nsw i32 %tmp44, 161085 %tmp46 = or i32 %tmp41, %tmp451086 %tmp47 = getelementptr inbounds i8, ptr %tmp24, i64 121087 %tmp48 = load i8, ptr %tmp47, align 11088 %tmp49 = sext i8 %tmp48 to i161089 %tmp50 = zext i16 %tmp49 to i321090 %tmp51 = shl nuw i32 %tmp50, 241091 %tmp52 = or i32 %tmp46, %tmp511092 ret i32 %tmp521093}1094 1095; ptr p;1096; (i32) p[0] | ((i32) p[1] << 8)1097define i32 @zext_load_i32_by_i8(ptr %arg) {1098; CHECK-LABEL: zext_load_i32_by_i8:1099; CHECK: # %bb.0:1100; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax1101; CHECK-NEXT: movzwl (%eax), %eax1102; CHECK-NEXT: retl1103;1104; CHECK64-LABEL: zext_load_i32_by_i8:1105; CHECK64: # %bb.0:1106; CHECK64-NEXT: movzwl (%rdi), %eax1107; CHECK64-NEXT: retq1108 %tmp2 = load i8, ptr %arg, align 11109 %tmp3 = zext i8 %tmp2 to i321110 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 11111 %tmp5 = load i8, ptr %tmp4, align 11112 %tmp6 = zext i8 %tmp5 to i321113 %tmp7 = shl nuw nsw i32 %tmp6, 81114 %tmp8 = or i32 %tmp7, %tmp31115 ret i32 %tmp81116}1117 1118; ptr p;1119; ((i32) p[0] << 8) | ((i32) p[1] << 16)1120define i32 @zext_load_i32_by_i8_shl_8(ptr %arg) {1121; CHECK-LABEL: zext_load_i32_by_i8_shl_8:1122; CHECK: # %bb.0:1123; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax1124; CHECK-NEXT: movzbl (%eax), %ecx1125; CHECK-NEXT: shll $8, %ecx1126; CHECK-NEXT: movzbl 1(%eax), %eax1127; CHECK-NEXT: shll $16, %eax1128; CHECK-NEXT: orl %ecx, %eax1129; CHECK-NEXT: retl1130;1131; CHECK64-LABEL: zext_load_i32_by_i8_shl_8:1132; CHECK64: # %bb.0:1133; CHECK64-NEXT: movzbl (%rdi), %ecx1134; CHECK64-NEXT: shll $8, %ecx1135; CHECK64-NEXT: movzbl 1(%rdi), %eax1136; CHECK64-NEXT: shll $16, %eax1137; CHECK64-NEXT: orl %ecx, %eax1138; CHECK64-NEXT: retq1139 %tmp2 = load i8, ptr %arg, align 11140 %tmp3 = zext i8 %tmp2 to i321141 %tmp30 = shl nuw nsw i32 %tmp3, 81142 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 11143 %tmp5 = load i8, ptr %tmp4, align 11144 %tmp6 = zext i8 %tmp5 to i321145 %tmp7 = shl nuw nsw i32 %tmp6, 161146 %tmp8 = or i32 %tmp7, %tmp301147 ret i32 %tmp81148}1149 1150; ptr p;1151; ((i32) p[0] << 16) | ((i32) p[1] << 24)1152define i32 @zext_load_i32_by_i8_shl_16(ptr %arg) {1153; CHECK-LABEL: zext_load_i32_by_i8_shl_16:1154; CHECK: # %bb.0:1155; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax1156; CHECK-NEXT: movzbl (%eax), %ecx1157; CHECK-NEXT: shll $16, %ecx1158; CHECK-NEXT: movzbl 1(%eax), %eax1159; CHECK-NEXT: shll $24, %eax1160; CHECK-NEXT: orl %ecx, %eax1161; CHECK-NEXT: retl1162;1163; CHECK64-LABEL: zext_load_i32_by_i8_shl_16:1164; CHECK64: # %bb.0:1165; CHECK64-NEXT: movzbl (%rdi), %ecx1166; CHECK64-NEXT: shll $16, %ecx1167; CHECK64-NEXT: movzbl 1(%rdi), %eax1168; CHECK64-NEXT: shll $24, %eax1169; CHECK64-NEXT: orl %ecx, %eax1170; CHECK64-NEXT: retq1171 %tmp2 = load i8, ptr %arg, align 11172 %tmp3 = zext i8 %tmp2 to i321173 %tmp30 = shl nuw nsw i32 %tmp3, 161174 %tmp4 = getelementptr inbounds i8, ptr %arg, i32 11175 %tmp5 = load i8, ptr %tmp4, align 11176 %tmp6 = zext i8 %tmp5 to i321177 %tmp7 = shl nuw nsw i32 %tmp6, 241178 %tmp8 = or i32 %tmp7, %tmp301179 ret i32 %tmp81180}1181 1182; ptr p;1183; (i32) p[1] | ((i32) p[0] << 8)1184define i32 @zext_load_i32_by_i8_bswap(ptr %arg) {1185; BSWAP-LABEL: zext_load_i32_by_i8_bswap:1186; BSWAP: # %bb.0:1187; BSWAP-NEXT: movl {{[0-9]+}}(%esp), %eax1188; BSWAP-NEXT: movzwl (%eax), %eax1189; BSWAP-NEXT: rolw $8, %ax1190; BSWAP-NEXT: movzwl %ax, %eax1191; BSWAP-NEXT: retl1192;1193; MOVBE-LABEL: zext_load_i32_by_i8_bswap:1194; MOVBE: # %bb.0:1195; MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax1196; MOVBE-NEXT: movbew (%eax), %ax1197; MOVBE-NEXT: movzwl %ax, %eax1198; MOVBE-NEXT: retl1199;1200; BSWAP64-LABEL: zext_load_i32_by_i8_bswap:1201; BSWAP64: # %bb.0:1202; BSWAP64-NEXT: movzwl (%rdi), %eax1203; BSWAP64-NEXT: rolw $8, %ax1204; BSWAP64-NEXT: movzwl %ax, %eax1205; BSWAP64-NEXT: retq1206;1207; MOVBE64-LABEL: zext_load_i32_by_i8_bswap:1208; MOVBE64: # %bb.0:1209; MOVBE64-NEXT: movbew (%rdi), %ax1210; MOVBE64-NEXT: movzwl %ax, %eax1211; MOVBE64-NEXT: retq1212 %tmp1 = getelementptr inbounds i8, ptr %arg, i32 11213 %tmp2 = load i8, ptr %tmp1, align 11214 %tmp3 = zext i8 %tmp2 to i321215 %tmp5 = load i8, ptr %arg, align 11216 %tmp6 = zext i8 %tmp5 to i321217 %tmp7 = shl nuw nsw i32 %tmp6, 81218 %tmp8 = or i32 %tmp7, %tmp31219 ret i32 %tmp81220}1221 1222; ptr p;1223; ((i32) p[1] << 8) | ((i32) p[0] << 16)1224define i32 @zext_load_i32_by_i8_bswap_shl_8(ptr %arg) {1225; CHECK-LABEL: zext_load_i32_by_i8_bswap_shl_8:1226; CHECK: # %bb.0:1227; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax1228; CHECK-NEXT: movzbl 1(%eax), %ecx1229; CHECK-NEXT: shll $8, %ecx1230; CHECK-NEXT: movzbl (%eax), %eax1231; CHECK-NEXT: shll $16, %eax1232; CHECK-NEXT: orl %ecx, %eax1233; CHECK-NEXT: retl1234;1235; CHECK64-LABEL: zext_load_i32_by_i8_bswap_shl_8:1236; CHECK64: # %bb.0:1237; CHECK64-NEXT: movzbl 1(%rdi), %ecx1238; CHECK64-NEXT: shll $8, %ecx1239; CHECK64-NEXT: movzbl (%rdi), %eax1240; CHECK64-NEXT: shll $16, %eax1241; CHECK64-NEXT: orl %ecx, %eax1242; CHECK64-NEXT: retq1243 %tmp1 = getelementptr inbounds i8, ptr %arg, i32 11244 %tmp2 = load i8, ptr %tmp1, align 11245 %tmp3 = zext i8 %tmp2 to i321246 %tmp30 = shl nuw nsw i32 %tmp3, 81247 %tmp5 = load i8, ptr %arg, align 11248 %tmp6 = zext i8 %tmp5 to i321249 %tmp7 = shl nuw nsw i32 %tmp6, 161250 %tmp8 = or i32 %tmp7, %tmp301251 ret i32 %tmp81252}1253 1254; ptr p;1255; ((i32) p[1] << 16) | ((i32) p[0] << 24)1256define i32 @zext_load_i32_by_i8_bswap_shl_16(ptr %arg) {1257; CHECK-LABEL: zext_load_i32_by_i8_bswap_shl_16:1258; CHECK: # %bb.0:1259; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax1260; CHECK-NEXT: movzbl 1(%eax), %ecx1261; CHECK-NEXT: shll $16, %ecx1262; CHECK-NEXT: movzbl (%eax), %eax1263; CHECK-NEXT: shll $24, %eax1264; CHECK-NEXT: orl %ecx, %eax1265; CHECK-NEXT: retl1266;1267; CHECK64-LABEL: zext_load_i32_by_i8_bswap_shl_16:1268; CHECK64: # %bb.0:1269; CHECK64-NEXT: movzbl 1(%rdi), %ecx1270; CHECK64-NEXT: shll $16, %ecx1271; CHECK64-NEXT: movzbl (%rdi), %eax1272; CHECK64-NEXT: shll $24, %eax1273; CHECK64-NEXT: orl %ecx, %eax1274; CHECK64-NEXT: retq1275 %tmp1 = getelementptr inbounds i8, ptr %arg, i32 11276 %tmp2 = load i8, ptr %tmp1, align 11277 %tmp3 = zext i8 %tmp2 to i321278 %tmp30 = shl nuw nsw i32 %tmp3, 161279 %tmp5 = load i8, ptr %arg, align 11280 %tmp6 = zext i8 %tmp5 to i321281 %tmp7 = shl nuw nsw i32 %tmp6, 241282 %tmp8 = or i32 %tmp7, %tmp301283 ret i32 %tmp81284}1285 1286define i32 @pr80911_vector_load_multiuse(ptr %ptr, ptr %clobber) nounwind {1287; CHECK-LABEL: pr80911_vector_load_multiuse:1288; CHECK: # %bb.0:1289; CHECK-NEXT: pushl %esi1290; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx1291; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edx1292; CHECK-NEXT: movl (%edx), %esi1293; CHECK-NEXT: movzwl (%edx), %eax1294; CHECK-NEXT: movl $0, (%ecx)1295; CHECK-NEXT: movl %esi, (%edx)1296; CHECK-NEXT: popl %esi1297; CHECK-NEXT: retl1298;1299; CHECK64-LABEL: pr80911_vector_load_multiuse:1300; CHECK64: # %bb.0:1301; CHECK64-NEXT: movl (%rdi), %ecx1302; CHECK64-NEXT: movzwl (%rdi), %eax1303; CHECK64-NEXT: movl $0, (%rsi)1304; CHECK64-NEXT: movl %ecx, (%rdi)1305; CHECK64-NEXT: retq1306 %load = load <4 x i8>, ptr %ptr, align 161307 store i32 0, ptr %clobber1308 store <4 x i8> %load, ptr %ptr, align 161309 %e1 = extractelement <4 x i8> %load, i64 11310 %e1.ext = zext i8 %e1 to i321311 %e1.ext.shift = shl nuw nsw i32 %e1.ext, 81312 %e0 = extractelement <4 x i8> %load, i64 01313 %e0.ext = zext i8 %e0 to i321314 %res = or i32 %e1.ext.shift, %e0.ext1315 ret i32 %res1316}1317