[llvm] [ExpandMemCmp] Apply NumLoadsPerBlock to ordering compares (PR #215186)
Pengcheng Wang via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 20:31:18 PDT 2026
https://github.com/wangpc-pp updated https://github.com/llvm/llvm-project/pull/215186
>From 06aafdbcb7d2b377c176d08a99fde8b723f50c70 Mon Sep 17 00:00:00 2001
From: Pengcheng Wang <wangpengcheng.pp at bytedance.com>
Date: Thu, 20 Aug 2026 14:34:12 +0800
Subject: [PATCH 1/2] [ExpandMemCmp][BPF] Add pre-commit tests for grouped byte
loads
Add UTC-generated regression coverage for align-1 BPF memcmp expansion.
The tests cover ordering and equality comparisons, including a short
final group, and record the one-compare-block-per-byte behavior
before grouping is implemented.
Assisted-by: TRAE CLI (GPT-5)
---
.../Transforms/ExpandMemCmp/BPF/lit.local.cfg | 2 +
.../Transforms/ExpandMemCmp/BPF/memcmp.ll | 942 ++++++++++++++++++
2 files changed, 944 insertions(+)
create mode 100644 llvm/test/Transforms/ExpandMemCmp/BPF/lit.local.cfg
create mode 100644 llvm/test/Transforms/ExpandMemCmp/BPF/memcmp.ll
diff --git a/llvm/test/Transforms/ExpandMemCmp/BPF/lit.local.cfg b/llvm/test/Transforms/ExpandMemCmp/BPF/lit.local.cfg
new file mode 100644
index 0000000000000..0fe841da7d0e7
--- /dev/null
+++ b/llvm/test/Transforms/ExpandMemCmp/BPF/lit.local.cfg
@@ -0,0 +1,2 @@
+if not "BPF" in config.root.targets:
+ config.unsupported = True
diff --git a/llvm/test/Transforms/ExpandMemCmp/BPF/memcmp.ll b/llvm/test/Transforms/ExpandMemCmp/BPF/memcmp.ll
new file mode 100644
index 0000000000000..f182dcc1b7f75
--- /dev/null
+++ b/llvm/test/Transforms/ExpandMemCmp/BPF/memcmp.ll
@@ -0,0 +1,942 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=expand-memcmp -mtriple=bpf -memcmp-num-loads-per-block=1 < %s | FileCheck %s
+
+; BPF cannot perform wide misaligned loads, so the alignment filter reduces an
+; align-1 comparison to byte loads. Grouping eight load pairs in each block
+; forms native-width values and avoids one branch per byte.
+
+target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
+
+declare i32 @memcmp(ptr, ptr, i64)
+declare i32 @bcmp(ptr, ptr, i64)
+
+define i32 @memcmp_size_32_align_1(ptr %a, ptr %b) {
+; CHECK-LABEL: define i32 @memcmp_size_32_align_1(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT: br label %[[LOADBB:.*]]
+; CHECK: [[RES_BLOCK:.*]]:
+; CHECK-NEXT: br label %[[ENDBLOCK:.*]]
+; CHECK: [[LOADBB]]:
+; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
+; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[B]], align 1
+; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT: [[TMP4:%.*]] = zext i8 [[TMP2]] to i32
+; CHECK-NEXT: [[TMP5:%.*]] = sub i32 [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
+; CHECK-NEXT: br i1 [[TMP6]], label %[[ENDBLOCK]], label %[[LOADBB1:.*]]
+; CHECK: [[LOADBB1]]:
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[A]], i64 1
+; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[B]], i64 1
+; CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[TMP7]], align 1
+; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP8]], align 1
+; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP9]] to i32
+; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP10]] to i32
+; CHECK-NEXT: [[TMP13:%.*]] = sub i32 [[TMP11]], [[TMP12]]
+; CHECK-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; CHECK-NEXT: br i1 [[TMP14]], label %[[ENDBLOCK]], label %[[LOADBB2:.*]]
+; CHECK: [[LOADBB2]]:
+; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[A]], i64 2
+; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[B]], i64 2
+; CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[TMP15]], align 1
+; CHECK-NEXT: [[TMP18:%.*]] = load i8, ptr [[TMP16]], align 1
+; CHECK-NEXT: [[TMP19:%.*]] = zext i8 [[TMP17]] to i32
+; CHECK-NEXT: [[TMP20:%.*]] = zext i8 [[TMP18]] to i32
+; CHECK-NEXT: [[TMP21:%.*]] = sub i32 [[TMP19]], [[TMP20]]
+; CHECK-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
+; CHECK-NEXT: br i1 [[TMP22]], label %[[ENDBLOCK]], label %[[LOADBB3:.*]]
+; CHECK: [[LOADBB3]]:
+; CHECK-NEXT: [[TMP23:%.*]] = getelementptr i8, ptr [[A]], i64 3
+; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[B]], i64 3
+; CHECK-NEXT: [[TMP25:%.*]] = load i8, ptr [[TMP23]], align 1
+; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP24]], align 1
+; CHECK-NEXT: [[TMP27:%.*]] = zext i8 [[TMP25]] to i32
+; CHECK-NEXT: [[TMP28:%.*]] = zext i8 [[TMP26]] to i32
+; CHECK-NEXT: [[TMP29:%.*]] = sub i32 [[TMP27]], [[TMP28]]
+; CHECK-NEXT: [[TMP30:%.*]] = icmp ne i32 [[TMP29]], 0
+; CHECK-NEXT: br i1 [[TMP30]], label %[[ENDBLOCK]], label %[[LOADBB4:.*]]
+; CHECK: [[LOADBB4]]:
+; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i8, ptr [[A]], i64 4
+; CHECK-NEXT: [[TMP32:%.*]] = getelementptr i8, ptr [[B]], i64 4
+; CHECK-NEXT: [[TMP33:%.*]] = load i8, ptr [[TMP31]], align 1
+; CHECK-NEXT: [[TMP34:%.*]] = load i8, ptr [[TMP32]], align 1
+; CHECK-NEXT: [[TMP35:%.*]] = zext i8 [[TMP33]] to i32
+; CHECK-NEXT: [[TMP36:%.*]] = zext i8 [[TMP34]] to i32
+; CHECK-NEXT: [[TMP37:%.*]] = sub i32 [[TMP35]], [[TMP36]]
+; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i32 [[TMP37]], 0
+; CHECK-NEXT: br i1 [[TMP38]], label %[[ENDBLOCK]], label %[[LOADBB5:.*]]
+; CHECK: [[LOADBB5]]:
+; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[A]], i64 5
+; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i8, ptr [[B]], i64 5
+; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[TMP39]], align 1
+; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[TMP40]], align 1
+; CHECK-NEXT: [[TMP43:%.*]] = zext i8 [[TMP41]] to i32
+; CHECK-NEXT: [[TMP44:%.*]] = zext i8 [[TMP42]] to i32
+; CHECK-NEXT: [[TMP45:%.*]] = sub i32 [[TMP43]], [[TMP44]]
+; CHECK-NEXT: [[TMP46:%.*]] = icmp ne i32 [[TMP45]], 0
+; CHECK-NEXT: br i1 [[TMP46]], label %[[ENDBLOCK]], label %[[LOADBB6:.*]]
+; CHECK: [[LOADBB6]]:
+; CHECK-NEXT: [[TMP47:%.*]] = getelementptr i8, ptr [[A]], i64 6
+; CHECK-NEXT: [[TMP48:%.*]] = getelementptr i8, ptr [[B]], i64 6
+; CHECK-NEXT: [[TMP49:%.*]] = load i8, ptr [[TMP47]], align 1
+; CHECK-NEXT: [[TMP50:%.*]] = load i8, ptr [[TMP48]], align 1
+; CHECK-NEXT: [[TMP51:%.*]] = zext i8 [[TMP49]] to i32
+; CHECK-NEXT: [[TMP52:%.*]] = zext i8 [[TMP50]] to i32
+; CHECK-NEXT: [[TMP53:%.*]] = sub i32 [[TMP51]], [[TMP52]]
+; CHECK-NEXT: [[TMP54:%.*]] = icmp ne i32 [[TMP53]], 0
+; CHECK-NEXT: br i1 [[TMP54]], label %[[ENDBLOCK]], label %[[LOADBB7:.*]]
+; CHECK: [[LOADBB7]]:
+; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[A]], i64 7
+; CHECK-NEXT: [[TMP56:%.*]] = getelementptr i8, ptr [[B]], i64 7
+; CHECK-NEXT: [[TMP57:%.*]] = load i8, ptr [[TMP55]], align 1
+; CHECK-NEXT: [[TMP58:%.*]] = load i8, ptr [[TMP56]], align 1
+; CHECK-NEXT: [[TMP59:%.*]] = zext i8 [[TMP57]] to i32
+; CHECK-NEXT: [[TMP60:%.*]] = zext i8 [[TMP58]] to i32
+; CHECK-NEXT: [[TMP61:%.*]] = sub i32 [[TMP59]], [[TMP60]]
+; CHECK-NEXT: [[TMP62:%.*]] = icmp ne i32 [[TMP61]], 0
+; CHECK-NEXT: br i1 [[TMP62]], label %[[ENDBLOCK]], label %[[LOADBB8:.*]]
+; CHECK: [[LOADBB8]]:
+; CHECK-NEXT: [[TMP63:%.*]] = getelementptr i8, ptr [[A]], i64 8
+; CHECK-NEXT: [[TMP64:%.*]] = getelementptr i8, ptr [[B]], i64 8
+; CHECK-NEXT: [[TMP65:%.*]] = load i8, ptr [[TMP63]], align 1
+; CHECK-NEXT: [[TMP66:%.*]] = load i8, ptr [[TMP64]], align 1
+; CHECK-NEXT: [[TMP67:%.*]] = zext i8 [[TMP65]] to i32
+; CHECK-NEXT: [[TMP68:%.*]] = zext i8 [[TMP66]] to i32
+; CHECK-NEXT: [[TMP69:%.*]] = sub i32 [[TMP67]], [[TMP68]]
+; CHECK-NEXT: [[TMP70:%.*]] = icmp ne i32 [[TMP69]], 0
+; CHECK-NEXT: br i1 [[TMP70]], label %[[ENDBLOCK]], label %[[LOADBB9:.*]]
+; CHECK: [[LOADBB9]]:
+; CHECK-NEXT: [[TMP71:%.*]] = getelementptr i8, ptr [[A]], i64 9
+; CHECK-NEXT: [[TMP72:%.*]] = getelementptr i8, ptr [[B]], i64 9
+; CHECK-NEXT: [[TMP73:%.*]] = load i8, ptr [[TMP71]], align 1
+; CHECK-NEXT: [[TMP74:%.*]] = load i8, ptr [[TMP72]], align 1
+; CHECK-NEXT: [[TMP75:%.*]] = zext i8 [[TMP73]] to i32
+; CHECK-NEXT: [[TMP76:%.*]] = zext i8 [[TMP74]] to i32
+; CHECK-NEXT: [[TMP77:%.*]] = sub i32 [[TMP75]], [[TMP76]]
+; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i32 [[TMP77]], 0
+; CHECK-NEXT: br i1 [[TMP78]], label %[[ENDBLOCK]], label %[[LOADBB10:.*]]
+; CHECK: [[LOADBB10]]:
+; CHECK-NEXT: [[TMP79:%.*]] = getelementptr i8, ptr [[A]], i64 10
+; CHECK-NEXT: [[TMP80:%.*]] = getelementptr i8, ptr [[B]], i64 10
+; CHECK-NEXT: [[TMP81:%.*]] = load i8, ptr [[TMP79]], align 1
+; CHECK-NEXT: [[TMP82:%.*]] = load i8, ptr [[TMP80]], align 1
+; CHECK-NEXT: [[TMP83:%.*]] = zext i8 [[TMP81]] to i32
+; CHECK-NEXT: [[TMP84:%.*]] = zext i8 [[TMP82]] to i32
+; CHECK-NEXT: [[TMP85:%.*]] = sub i32 [[TMP83]], [[TMP84]]
+; CHECK-NEXT: [[TMP86:%.*]] = icmp ne i32 [[TMP85]], 0
+; CHECK-NEXT: br i1 [[TMP86]], label %[[ENDBLOCK]], label %[[LOADBB11:.*]]
+; CHECK: [[LOADBB11]]:
+; CHECK-NEXT: [[TMP87:%.*]] = getelementptr i8, ptr [[A]], i64 11
+; CHECK-NEXT: [[TMP88:%.*]] = getelementptr i8, ptr [[B]], i64 11
+; CHECK-NEXT: [[TMP89:%.*]] = load i8, ptr [[TMP87]], align 1
+; CHECK-NEXT: [[TMP90:%.*]] = load i8, ptr [[TMP88]], align 1
+; CHECK-NEXT: [[TMP91:%.*]] = zext i8 [[TMP89]] to i32
+; CHECK-NEXT: [[TMP92:%.*]] = zext i8 [[TMP90]] to i32
+; CHECK-NEXT: [[TMP93:%.*]] = sub i32 [[TMP91]], [[TMP92]]
+; CHECK-NEXT: [[TMP94:%.*]] = icmp ne i32 [[TMP93]], 0
+; CHECK-NEXT: br i1 [[TMP94]], label %[[ENDBLOCK]], label %[[LOADBB12:.*]]
+; CHECK: [[LOADBB12]]:
+; CHECK-NEXT: [[TMP95:%.*]] = getelementptr i8, ptr [[A]], i64 12
+; CHECK-NEXT: [[TMP96:%.*]] = getelementptr i8, ptr [[B]], i64 12
+; CHECK-NEXT: [[TMP97:%.*]] = load i8, ptr [[TMP95]], align 1
+; CHECK-NEXT: [[TMP98:%.*]] = load i8, ptr [[TMP96]], align 1
+; CHECK-NEXT: [[TMP99:%.*]] = zext i8 [[TMP97]] to i32
+; CHECK-NEXT: [[TMP100:%.*]] = zext i8 [[TMP98]] to i32
+; CHECK-NEXT: [[TMP101:%.*]] = sub i32 [[TMP99]], [[TMP100]]
+; CHECK-NEXT: [[TMP102:%.*]] = icmp ne i32 [[TMP101]], 0
+; CHECK-NEXT: br i1 [[TMP102]], label %[[ENDBLOCK]], label %[[LOADBB13:.*]]
+; CHECK: [[LOADBB13]]:
+; CHECK-NEXT: [[TMP103:%.*]] = getelementptr i8, ptr [[A]], i64 13
+; CHECK-NEXT: [[TMP104:%.*]] = getelementptr i8, ptr [[B]], i64 13
+; CHECK-NEXT: [[TMP105:%.*]] = load i8, ptr [[TMP103]], align 1
+; CHECK-NEXT: [[TMP106:%.*]] = load i8, ptr [[TMP104]], align 1
+; CHECK-NEXT: [[TMP107:%.*]] = zext i8 [[TMP105]] to i32
+; CHECK-NEXT: [[TMP108:%.*]] = zext i8 [[TMP106]] to i32
+; CHECK-NEXT: [[TMP109:%.*]] = sub i32 [[TMP107]], [[TMP108]]
+; CHECK-NEXT: [[TMP110:%.*]] = icmp ne i32 [[TMP109]], 0
+; CHECK-NEXT: br i1 [[TMP110]], label %[[ENDBLOCK]], label %[[LOADBB14:.*]]
+; CHECK: [[LOADBB14]]:
+; CHECK-NEXT: [[TMP111:%.*]] = getelementptr i8, ptr [[A]], i64 14
+; CHECK-NEXT: [[TMP112:%.*]] = getelementptr i8, ptr [[B]], i64 14
+; CHECK-NEXT: [[TMP113:%.*]] = load i8, ptr [[TMP111]], align 1
+; CHECK-NEXT: [[TMP114:%.*]] = load i8, ptr [[TMP112]], align 1
+; CHECK-NEXT: [[TMP115:%.*]] = zext i8 [[TMP113]] to i32
+; CHECK-NEXT: [[TMP116:%.*]] = zext i8 [[TMP114]] to i32
+; CHECK-NEXT: [[TMP117:%.*]] = sub i32 [[TMP115]], [[TMP116]]
+; CHECK-NEXT: [[TMP118:%.*]] = icmp ne i32 [[TMP117]], 0
+; CHECK-NEXT: br i1 [[TMP118]], label %[[ENDBLOCK]], label %[[LOADBB15:.*]]
+; CHECK: [[LOADBB15]]:
+; CHECK-NEXT: [[TMP119:%.*]] = getelementptr i8, ptr [[A]], i64 15
+; CHECK-NEXT: [[TMP120:%.*]] = getelementptr i8, ptr [[B]], i64 15
+; CHECK-NEXT: [[TMP121:%.*]] = load i8, ptr [[TMP119]], align 1
+; CHECK-NEXT: [[TMP122:%.*]] = load i8, ptr [[TMP120]], align 1
+; CHECK-NEXT: [[TMP123:%.*]] = zext i8 [[TMP121]] to i32
+; CHECK-NEXT: [[TMP124:%.*]] = zext i8 [[TMP122]] to i32
+; CHECK-NEXT: [[TMP125:%.*]] = sub i32 [[TMP123]], [[TMP124]]
+; CHECK-NEXT: [[TMP126:%.*]] = icmp ne i32 [[TMP125]], 0
+; CHECK-NEXT: br i1 [[TMP126]], label %[[ENDBLOCK]], label %[[LOADBB16:.*]]
+; CHECK: [[LOADBB16]]:
+; CHECK-NEXT: [[TMP127:%.*]] = getelementptr i8, ptr [[A]], i64 16
+; CHECK-NEXT: [[TMP128:%.*]] = getelementptr i8, ptr [[B]], i64 16
+; CHECK-NEXT: [[TMP129:%.*]] = load i8, ptr [[TMP127]], align 1
+; CHECK-NEXT: [[TMP130:%.*]] = load i8, ptr [[TMP128]], align 1
+; CHECK-NEXT: [[TMP131:%.*]] = zext i8 [[TMP129]] to i32
+; CHECK-NEXT: [[TMP132:%.*]] = zext i8 [[TMP130]] to i32
+; CHECK-NEXT: [[TMP133:%.*]] = sub i32 [[TMP131]], [[TMP132]]
+; CHECK-NEXT: [[TMP134:%.*]] = icmp ne i32 [[TMP133]], 0
+; CHECK-NEXT: br i1 [[TMP134]], label %[[ENDBLOCK]], label %[[LOADBB17:.*]]
+; CHECK: [[LOADBB17]]:
+; CHECK-NEXT: [[TMP135:%.*]] = getelementptr i8, ptr [[A]], i64 17
+; CHECK-NEXT: [[TMP136:%.*]] = getelementptr i8, ptr [[B]], i64 17
+; CHECK-NEXT: [[TMP137:%.*]] = load i8, ptr [[TMP135]], align 1
+; CHECK-NEXT: [[TMP138:%.*]] = load i8, ptr [[TMP136]], align 1
+; CHECK-NEXT: [[TMP139:%.*]] = zext i8 [[TMP137]] to i32
+; CHECK-NEXT: [[TMP140:%.*]] = zext i8 [[TMP138]] to i32
+; CHECK-NEXT: [[TMP141:%.*]] = sub i32 [[TMP139]], [[TMP140]]
+; CHECK-NEXT: [[TMP142:%.*]] = icmp ne i32 [[TMP141]], 0
+; CHECK-NEXT: br i1 [[TMP142]], label %[[ENDBLOCK]], label %[[LOADBB18:.*]]
+; CHECK: [[LOADBB18]]:
+; CHECK-NEXT: [[TMP143:%.*]] = getelementptr i8, ptr [[A]], i64 18
+; CHECK-NEXT: [[TMP144:%.*]] = getelementptr i8, ptr [[B]], i64 18
+; CHECK-NEXT: [[TMP145:%.*]] = load i8, ptr [[TMP143]], align 1
+; CHECK-NEXT: [[TMP146:%.*]] = load i8, ptr [[TMP144]], align 1
+; CHECK-NEXT: [[TMP147:%.*]] = zext i8 [[TMP145]] to i32
+; CHECK-NEXT: [[TMP148:%.*]] = zext i8 [[TMP146]] to i32
+; CHECK-NEXT: [[TMP149:%.*]] = sub i32 [[TMP147]], [[TMP148]]
+; CHECK-NEXT: [[TMP150:%.*]] = icmp ne i32 [[TMP149]], 0
+; CHECK-NEXT: br i1 [[TMP150]], label %[[ENDBLOCK]], label %[[LOADBB19:.*]]
+; CHECK: [[LOADBB19]]:
+; CHECK-NEXT: [[TMP151:%.*]] = getelementptr i8, ptr [[A]], i64 19
+; CHECK-NEXT: [[TMP152:%.*]] = getelementptr i8, ptr [[B]], i64 19
+; CHECK-NEXT: [[TMP153:%.*]] = load i8, ptr [[TMP151]], align 1
+; CHECK-NEXT: [[TMP154:%.*]] = load i8, ptr [[TMP152]], align 1
+; CHECK-NEXT: [[TMP155:%.*]] = zext i8 [[TMP153]] to i32
+; CHECK-NEXT: [[TMP156:%.*]] = zext i8 [[TMP154]] to i32
+; CHECK-NEXT: [[TMP157:%.*]] = sub i32 [[TMP155]], [[TMP156]]
+; CHECK-NEXT: [[TMP158:%.*]] = icmp ne i32 [[TMP157]], 0
+; CHECK-NEXT: br i1 [[TMP158]], label %[[ENDBLOCK]], label %[[LOADBB20:.*]]
+; CHECK: [[LOADBB20]]:
+; CHECK-NEXT: [[TMP159:%.*]] = getelementptr i8, ptr [[A]], i64 20
+; CHECK-NEXT: [[TMP160:%.*]] = getelementptr i8, ptr [[B]], i64 20
+; CHECK-NEXT: [[TMP161:%.*]] = load i8, ptr [[TMP159]], align 1
+; CHECK-NEXT: [[TMP162:%.*]] = load i8, ptr [[TMP160]], align 1
+; CHECK-NEXT: [[TMP163:%.*]] = zext i8 [[TMP161]] to i32
+; CHECK-NEXT: [[TMP164:%.*]] = zext i8 [[TMP162]] to i32
+; CHECK-NEXT: [[TMP165:%.*]] = sub i32 [[TMP163]], [[TMP164]]
+; CHECK-NEXT: [[TMP166:%.*]] = icmp ne i32 [[TMP165]], 0
+; CHECK-NEXT: br i1 [[TMP166]], label %[[ENDBLOCK]], label %[[LOADBB21:.*]]
+; CHECK: [[LOADBB21]]:
+; CHECK-NEXT: [[TMP167:%.*]] = getelementptr i8, ptr [[A]], i64 21
+; CHECK-NEXT: [[TMP168:%.*]] = getelementptr i8, ptr [[B]], i64 21
+; CHECK-NEXT: [[TMP169:%.*]] = load i8, ptr [[TMP167]], align 1
+; CHECK-NEXT: [[TMP170:%.*]] = load i8, ptr [[TMP168]], align 1
+; CHECK-NEXT: [[TMP171:%.*]] = zext i8 [[TMP169]] to i32
+; CHECK-NEXT: [[TMP172:%.*]] = zext i8 [[TMP170]] to i32
+; CHECK-NEXT: [[TMP173:%.*]] = sub i32 [[TMP171]], [[TMP172]]
+; CHECK-NEXT: [[TMP174:%.*]] = icmp ne i32 [[TMP173]], 0
+; CHECK-NEXT: br i1 [[TMP174]], label %[[ENDBLOCK]], label %[[LOADBB22:.*]]
+; CHECK: [[LOADBB22]]:
+; CHECK-NEXT: [[TMP175:%.*]] = getelementptr i8, ptr [[A]], i64 22
+; CHECK-NEXT: [[TMP176:%.*]] = getelementptr i8, ptr [[B]], i64 22
+; CHECK-NEXT: [[TMP177:%.*]] = load i8, ptr [[TMP175]], align 1
+; CHECK-NEXT: [[TMP178:%.*]] = load i8, ptr [[TMP176]], align 1
+; CHECK-NEXT: [[TMP179:%.*]] = zext i8 [[TMP177]] to i32
+; CHECK-NEXT: [[TMP180:%.*]] = zext i8 [[TMP178]] to i32
+; CHECK-NEXT: [[TMP181:%.*]] = sub i32 [[TMP179]], [[TMP180]]
+; CHECK-NEXT: [[TMP182:%.*]] = icmp ne i32 [[TMP181]], 0
+; CHECK-NEXT: br i1 [[TMP182]], label %[[ENDBLOCK]], label %[[LOADBB23:.*]]
+; CHECK: [[LOADBB23]]:
+; CHECK-NEXT: [[TMP183:%.*]] = getelementptr i8, ptr [[A]], i64 23
+; CHECK-NEXT: [[TMP184:%.*]] = getelementptr i8, ptr [[B]], i64 23
+; CHECK-NEXT: [[TMP185:%.*]] = load i8, ptr [[TMP183]], align 1
+; CHECK-NEXT: [[TMP186:%.*]] = load i8, ptr [[TMP184]], align 1
+; CHECK-NEXT: [[TMP187:%.*]] = zext i8 [[TMP185]] to i32
+; CHECK-NEXT: [[TMP188:%.*]] = zext i8 [[TMP186]] to i32
+; CHECK-NEXT: [[TMP189:%.*]] = sub i32 [[TMP187]], [[TMP188]]
+; CHECK-NEXT: [[TMP190:%.*]] = icmp ne i32 [[TMP189]], 0
+; CHECK-NEXT: br i1 [[TMP190]], label %[[ENDBLOCK]], label %[[LOADBB24:.*]]
+; CHECK: [[LOADBB24]]:
+; CHECK-NEXT: [[TMP191:%.*]] = getelementptr i8, ptr [[A]], i64 24
+; CHECK-NEXT: [[TMP192:%.*]] = getelementptr i8, ptr [[B]], i64 24
+; CHECK-NEXT: [[TMP193:%.*]] = load i8, ptr [[TMP191]], align 1
+; CHECK-NEXT: [[TMP194:%.*]] = load i8, ptr [[TMP192]], align 1
+; CHECK-NEXT: [[TMP195:%.*]] = zext i8 [[TMP193]] to i32
+; CHECK-NEXT: [[TMP196:%.*]] = zext i8 [[TMP194]] to i32
+; CHECK-NEXT: [[TMP197:%.*]] = sub i32 [[TMP195]], [[TMP196]]
+; CHECK-NEXT: [[TMP198:%.*]] = icmp ne i32 [[TMP197]], 0
+; CHECK-NEXT: br i1 [[TMP198]], label %[[ENDBLOCK]], label %[[LOADBB25:.*]]
+; CHECK: [[LOADBB25]]:
+; CHECK-NEXT: [[TMP199:%.*]] = getelementptr i8, ptr [[A]], i64 25
+; CHECK-NEXT: [[TMP200:%.*]] = getelementptr i8, ptr [[B]], i64 25
+; CHECK-NEXT: [[TMP201:%.*]] = load i8, ptr [[TMP199]], align 1
+; CHECK-NEXT: [[TMP202:%.*]] = load i8, ptr [[TMP200]], align 1
+; CHECK-NEXT: [[TMP203:%.*]] = zext i8 [[TMP201]] to i32
+; CHECK-NEXT: [[TMP204:%.*]] = zext i8 [[TMP202]] to i32
+; CHECK-NEXT: [[TMP205:%.*]] = sub i32 [[TMP203]], [[TMP204]]
+; CHECK-NEXT: [[TMP206:%.*]] = icmp ne i32 [[TMP205]], 0
+; CHECK-NEXT: br i1 [[TMP206]], label %[[ENDBLOCK]], label %[[LOADBB26:.*]]
+; CHECK: [[LOADBB26]]:
+; CHECK-NEXT: [[TMP207:%.*]] = getelementptr i8, ptr [[A]], i64 26
+; CHECK-NEXT: [[TMP208:%.*]] = getelementptr i8, ptr [[B]], i64 26
+; CHECK-NEXT: [[TMP209:%.*]] = load i8, ptr [[TMP207]], align 1
+; CHECK-NEXT: [[TMP210:%.*]] = load i8, ptr [[TMP208]], align 1
+; CHECK-NEXT: [[TMP211:%.*]] = zext i8 [[TMP209]] to i32
+; CHECK-NEXT: [[TMP212:%.*]] = zext i8 [[TMP210]] to i32
+; CHECK-NEXT: [[TMP213:%.*]] = sub i32 [[TMP211]], [[TMP212]]
+; CHECK-NEXT: [[TMP214:%.*]] = icmp ne i32 [[TMP213]], 0
+; CHECK-NEXT: br i1 [[TMP214]], label %[[ENDBLOCK]], label %[[LOADBB27:.*]]
+; CHECK: [[LOADBB27]]:
+; CHECK-NEXT: [[TMP215:%.*]] = getelementptr i8, ptr [[A]], i64 27
+; CHECK-NEXT: [[TMP216:%.*]] = getelementptr i8, ptr [[B]], i64 27
+; CHECK-NEXT: [[TMP217:%.*]] = load i8, ptr [[TMP215]], align 1
+; CHECK-NEXT: [[TMP218:%.*]] = load i8, ptr [[TMP216]], align 1
+; CHECK-NEXT: [[TMP219:%.*]] = zext i8 [[TMP217]] to i32
+; CHECK-NEXT: [[TMP220:%.*]] = zext i8 [[TMP218]] to i32
+; CHECK-NEXT: [[TMP221:%.*]] = sub i32 [[TMP219]], [[TMP220]]
+; CHECK-NEXT: [[TMP222:%.*]] = icmp ne i32 [[TMP221]], 0
+; CHECK-NEXT: br i1 [[TMP222]], label %[[ENDBLOCK]], label %[[LOADBB28:.*]]
+; CHECK: [[LOADBB28]]:
+; CHECK-NEXT: [[TMP223:%.*]] = getelementptr i8, ptr [[A]], i64 28
+; CHECK-NEXT: [[TMP224:%.*]] = getelementptr i8, ptr [[B]], i64 28
+; CHECK-NEXT: [[TMP225:%.*]] = load i8, ptr [[TMP223]], align 1
+; CHECK-NEXT: [[TMP226:%.*]] = load i8, ptr [[TMP224]], align 1
+; CHECK-NEXT: [[TMP227:%.*]] = zext i8 [[TMP225]] to i32
+; CHECK-NEXT: [[TMP228:%.*]] = zext i8 [[TMP226]] to i32
+; CHECK-NEXT: [[TMP229:%.*]] = sub i32 [[TMP227]], [[TMP228]]
+; CHECK-NEXT: [[TMP230:%.*]] = icmp ne i32 [[TMP229]], 0
+; CHECK-NEXT: br i1 [[TMP230]], label %[[ENDBLOCK]], label %[[LOADBB29:.*]]
+; CHECK: [[LOADBB29]]:
+; CHECK-NEXT: [[TMP231:%.*]] = getelementptr i8, ptr [[A]], i64 29
+; CHECK-NEXT: [[TMP232:%.*]] = getelementptr i8, ptr [[B]], i64 29
+; CHECK-NEXT: [[TMP233:%.*]] = load i8, ptr [[TMP231]], align 1
+; CHECK-NEXT: [[TMP234:%.*]] = load i8, ptr [[TMP232]], align 1
+; CHECK-NEXT: [[TMP235:%.*]] = zext i8 [[TMP233]] to i32
+; CHECK-NEXT: [[TMP236:%.*]] = zext i8 [[TMP234]] to i32
+; CHECK-NEXT: [[TMP237:%.*]] = sub i32 [[TMP235]], [[TMP236]]
+; CHECK-NEXT: [[TMP238:%.*]] = icmp ne i32 [[TMP237]], 0
+; CHECK-NEXT: br i1 [[TMP238]], label %[[ENDBLOCK]], label %[[LOADBB30:.*]]
+; CHECK: [[LOADBB30]]:
+; CHECK-NEXT: [[TMP239:%.*]] = getelementptr i8, ptr [[A]], i64 30
+; CHECK-NEXT: [[TMP240:%.*]] = getelementptr i8, ptr [[B]], i64 30
+; CHECK-NEXT: [[TMP241:%.*]] = load i8, ptr [[TMP239]], align 1
+; CHECK-NEXT: [[TMP242:%.*]] = load i8, ptr [[TMP240]], align 1
+; CHECK-NEXT: [[TMP243:%.*]] = zext i8 [[TMP241]] to i32
+; CHECK-NEXT: [[TMP244:%.*]] = zext i8 [[TMP242]] to i32
+; CHECK-NEXT: [[TMP245:%.*]] = sub i32 [[TMP243]], [[TMP244]]
+; CHECK-NEXT: [[TMP246:%.*]] = icmp ne i32 [[TMP245]], 0
+; CHECK-NEXT: br i1 [[TMP246]], label %[[ENDBLOCK]], label %[[LOADBB31:.*]]
+; CHECK: [[LOADBB31]]:
+; CHECK-NEXT: [[TMP247:%.*]] = getelementptr i8, ptr [[A]], i64 31
+; CHECK-NEXT: [[TMP248:%.*]] = getelementptr i8, ptr [[B]], i64 31
+; CHECK-NEXT: [[TMP249:%.*]] = load i8, ptr [[TMP247]], align 1
+; CHECK-NEXT: [[TMP250:%.*]] = load i8, ptr [[TMP248]], align 1
+; CHECK-NEXT: [[TMP251:%.*]] = zext i8 [[TMP249]] to i32
+; CHECK-NEXT: [[TMP252:%.*]] = zext i8 [[TMP250]] to i32
+; CHECK-NEXT: [[TMP253:%.*]] = sub i32 [[TMP251]], [[TMP252]]
+; CHECK-NEXT: br label %[[ENDBLOCK]]
+; CHECK: [[ENDBLOCK]]:
+; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ [[TMP5]], %[[LOADBB]] ], [ [[TMP13]], %[[LOADBB1]] ], [ [[TMP21]], %[[LOADBB2]] ], [ [[TMP29]], %[[LOADBB3]] ], [ [[TMP37]], %[[LOADBB4]] ], [ [[TMP45]], %[[LOADBB5]] ], [ [[TMP53]], %[[LOADBB6]] ], [ [[TMP61]], %[[LOADBB7]] ], [ [[TMP69]], %[[LOADBB8]] ], [ [[TMP77]], %[[LOADBB9]] ], [ [[TMP85]], %[[LOADBB10]] ], [ [[TMP93]], %[[LOADBB11]] ], [ [[TMP101]], %[[LOADBB12]] ], [ [[TMP109]], %[[LOADBB13]] ], [ [[TMP117]], %[[LOADBB14]] ], [ [[TMP125]], %[[LOADBB15]] ], [ [[TMP133]], %[[LOADBB16]] ], [ [[TMP141]], %[[LOADBB17]] ], [ [[TMP149]], %[[LOADBB18]] ], [ [[TMP157]], %[[LOADBB19]] ], [ [[TMP165]], %[[LOADBB20]] ], [ [[TMP173]], %[[LOADBB21]] ], [ [[TMP181]], %[[LOADBB22]] ], [ [[TMP189]], %[[LOADBB23]] ], [ [[TMP197]], %[[LOADBB24]] ], [ [[TMP205]], %[[LOADBB25]] ], [ [[TMP213]], %[[LOADBB26]] ], [ [[TMP221]], %[[LOADBB27]] ], [ [[TMP229]], %[[LOADBB28]] ], [ [[TMP237]], %[[LOADBB29]] ], [ [[TMP245]], %[[LOADBB30]] ], [ [[TMP253]], %[[LOADBB31]] ], [ poison, %[[RES_BLOCK]] ]
+; CHECK-NEXT: ret i32 [[PHI_RES]]
+;
+ %call = call i32 @memcmp(ptr %a, ptr %b, i64 32)
+ ret i32 %call
+}
+
+; The final short block is packed into the same i64 type as the first block.
+define i32 @memcmp_size_11_align_1(ptr %a, ptr %b) {
+; CHECK-LABEL: define i32 @memcmp_size_11_align_1(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT: br label %[[LOADBB:.*]]
+; CHECK: [[RES_BLOCK:.*]]:
+; CHECK-NEXT: br label %[[ENDBLOCK:.*]]
+; CHECK: [[LOADBB]]:
+; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
+; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[B]], align 1
+; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT: [[TMP4:%.*]] = zext i8 [[TMP2]] to i32
+; CHECK-NEXT: [[TMP5:%.*]] = sub i32 [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
+; CHECK-NEXT: br i1 [[TMP6]], label %[[ENDBLOCK]], label %[[LOADBB1:.*]]
+; CHECK: [[LOADBB1]]:
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[A]], i64 1
+; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[B]], i64 1
+; CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[TMP7]], align 1
+; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP8]], align 1
+; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP9]] to i32
+; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP10]] to i32
+; CHECK-NEXT: [[TMP13:%.*]] = sub i32 [[TMP11]], [[TMP12]]
+; CHECK-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; CHECK-NEXT: br i1 [[TMP14]], label %[[ENDBLOCK]], label %[[LOADBB2:.*]]
+; CHECK: [[LOADBB2]]:
+; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[A]], i64 2
+; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[B]], i64 2
+; CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[TMP15]], align 1
+; CHECK-NEXT: [[TMP18:%.*]] = load i8, ptr [[TMP16]], align 1
+; CHECK-NEXT: [[TMP19:%.*]] = zext i8 [[TMP17]] to i32
+; CHECK-NEXT: [[TMP20:%.*]] = zext i8 [[TMP18]] to i32
+; CHECK-NEXT: [[TMP21:%.*]] = sub i32 [[TMP19]], [[TMP20]]
+; CHECK-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
+; CHECK-NEXT: br i1 [[TMP22]], label %[[ENDBLOCK]], label %[[LOADBB3:.*]]
+; CHECK: [[LOADBB3]]:
+; CHECK-NEXT: [[TMP23:%.*]] = getelementptr i8, ptr [[A]], i64 3
+; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[B]], i64 3
+; CHECK-NEXT: [[TMP25:%.*]] = load i8, ptr [[TMP23]], align 1
+; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP24]], align 1
+; CHECK-NEXT: [[TMP27:%.*]] = zext i8 [[TMP25]] to i32
+; CHECK-NEXT: [[TMP28:%.*]] = zext i8 [[TMP26]] to i32
+; CHECK-NEXT: [[TMP29:%.*]] = sub i32 [[TMP27]], [[TMP28]]
+; CHECK-NEXT: [[TMP30:%.*]] = icmp ne i32 [[TMP29]], 0
+; CHECK-NEXT: br i1 [[TMP30]], label %[[ENDBLOCK]], label %[[LOADBB4:.*]]
+; CHECK: [[LOADBB4]]:
+; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i8, ptr [[A]], i64 4
+; CHECK-NEXT: [[TMP32:%.*]] = getelementptr i8, ptr [[B]], i64 4
+; CHECK-NEXT: [[TMP33:%.*]] = load i8, ptr [[TMP31]], align 1
+; CHECK-NEXT: [[TMP34:%.*]] = load i8, ptr [[TMP32]], align 1
+; CHECK-NEXT: [[TMP35:%.*]] = zext i8 [[TMP33]] to i32
+; CHECK-NEXT: [[TMP36:%.*]] = zext i8 [[TMP34]] to i32
+; CHECK-NEXT: [[TMP37:%.*]] = sub i32 [[TMP35]], [[TMP36]]
+; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i32 [[TMP37]], 0
+; CHECK-NEXT: br i1 [[TMP38]], label %[[ENDBLOCK]], label %[[LOADBB5:.*]]
+; CHECK: [[LOADBB5]]:
+; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[A]], i64 5
+; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i8, ptr [[B]], i64 5
+; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[TMP39]], align 1
+; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[TMP40]], align 1
+; CHECK-NEXT: [[TMP43:%.*]] = zext i8 [[TMP41]] to i32
+; CHECK-NEXT: [[TMP44:%.*]] = zext i8 [[TMP42]] to i32
+; CHECK-NEXT: [[TMP45:%.*]] = sub i32 [[TMP43]], [[TMP44]]
+; CHECK-NEXT: [[TMP46:%.*]] = icmp ne i32 [[TMP45]], 0
+; CHECK-NEXT: br i1 [[TMP46]], label %[[ENDBLOCK]], label %[[LOADBB6:.*]]
+; CHECK: [[LOADBB6]]:
+; CHECK-NEXT: [[TMP47:%.*]] = getelementptr i8, ptr [[A]], i64 6
+; CHECK-NEXT: [[TMP48:%.*]] = getelementptr i8, ptr [[B]], i64 6
+; CHECK-NEXT: [[TMP49:%.*]] = load i8, ptr [[TMP47]], align 1
+; CHECK-NEXT: [[TMP50:%.*]] = load i8, ptr [[TMP48]], align 1
+; CHECK-NEXT: [[TMP51:%.*]] = zext i8 [[TMP49]] to i32
+; CHECK-NEXT: [[TMP52:%.*]] = zext i8 [[TMP50]] to i32
+; CHECK-NEXT: [[TMP53:%.*]] = sub i32 [[TMP51]], [[TMP52]]
+; CHECK-NEXT: [[TMP54:%.*]] = icmp ne i32 [[TMP53]], 0
+; CHECK-NEXT: br i1 [[TMP54]], label %[[ENDBLOCK]], label %[[LOADBB7:.*]]
+; CHECK: [[LOADBB7]]:
+; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[A]], i64 7
+; CHECK-NEXT: [[TMP56:%.*]] = getelementptr i8, ptr [[B]], i64 7
+; CHECK-NEXT: [[TMP57:%.*]] = load i8, ptr [[TMP55]], align 1
+; CHECK-NEXT: [[TMP58:%.*]] = load i8, ptr [[TMP56]], align 1
+; CHECK-NEXT: [[TMP59:%.*]] = zext i8 [[TMP57]] to i32
+; CHECK-NEXT: [[TMP60:%.*]] = zext i8 [[TMP58]] to i32
+; CHECK-NEXT: [[TMP61:%.*]] = sub i32 [[TMP59]], [[TMP60]]
+; CHECK-NEXT: [[TMP62:%.*]] = icmp ne i32 [[TMP61]], 0
+; CHECK-NEXT: br i1 [[TMP62]], label %[[ENDBLOCK]], label %[[LOADBB8:.*]]
+; CHECK: [[LOADBB8]]:
+; CHECK-NEXT: [[TMP63:%.*]] = getelementptr i8, ptr [[A]], i64 8
+; CHECK-NEXT: [[TMP64:%.*]] = getelementptr i8, ptr [[B]], i64 8
+; CHECK-NEXT: [[TMP65:%.*]] = load i8, ptr [[TMP63]], align 1
+; CHECK-NEXT: [[TMP66:%.*]] = load i8, ptr [[TMP64]], align 1
+; CHECK-NEXT: [[TMP67:%.*]] = zext i8 [[TMP65]] to i32
+; CHECK-NEXT: [[TMP68:%.*]] = zext i8 [[TMP66]] to i32
+; CHECK-NEXT: [[TMP69:%.*]] = sub i32 [[TMP67]], [[TMP68]]
+; CHECK-NEXT: [[TMP70:%.*]] = icmp ne i32 [[TMP69]], 0
+; CHECK-NEXT: br i1 [[TMP70]], label %[[ENDBLOCK]], label %[[LOADBB9:.*]]
+; CHECK: [[LOADBB9]]:
+; CHECK-NEXT: [[TMP71:%.*]] = getelementptr i8, ptr [[A]], i64 9
+; CHECK-NEXT: [[TMP72:%.*]] = getelementptr i8, ptr [[B]], i64 9
+; CHECK-NEXT: [[TMP73:%.*]] = load i8, ptr [[TMP71]], align 1
+; CHECK-NEXT: [[TMP74:%.*]] = load i8, ptr [[TMP72]], align 1
+; CHECK-NEXT: [[TMP75:%.*]] = zext i8 [[TMP73]] to i32
+; CHECK-NEXT: [[TMP76:%.*]] = zext i8 [[TMP74]] to i32
+; CHECK-NEXT: [[TMP77:%.*]] = sub i32 [[TMP75]], [[TMP76]]
+; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i32 [[TMP77]], 0
+; CHECK-NEXT: br i1 [[TMP78]], label %[[ENDBLOCK]], label %[[LOADBB10:.*]]
+; CHECK: [[LOADBB10]]:
+; CHECK-NEXT: [[TMP79:%.*]] = getelementptr i8, ptr [[A]], i64 10
+; CHECK-NEXT: [[TMP80:%.*]] = getelementptr i8, ptr [[B]], i64 10
+; CHECK-NEXT: [[TMP81:%.*]] = load i8, ptr [[TMP79]], align 1
+; CHECK-NEXT: [[TMP82:%.*]] = load i8, ptr [[TMP80]], align 1
+; CHECK-NEXT: [[TMP83:%.*]] = zext i8 [[TMP81]] to i32
+; CHECK-NEXT: [[TMP84:%.*]] = zext i8 [[TMP82]] to i32
+; CHECK-NEXT: [[TMP85:%.*]] = sub i32 [[TMP83]], [[TMP84]]
+; CHECK-NEXT: br label %[[ENDBLOCK]]
+; CHECK: [[ENDBLOCK]]:
+; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ [[TMP5]], %[[LOADBB]] ], [ [[TMP13]], %[[LOADBB1]] ], [ [[TMP21]], %[[LOADBB2]] ], [ [[TMP29]], %[[LOADBB3]] ], [ [[TMP37]], %[[LOADBB4]] ], [ [[TMP45]], %[[LOADBB5]] ], [ [[TMP53]], %[[LOADBB6]] ], [ [[TMP61]], %[[LOADBB7]] ], [ [[TMP69]], %[[LOADBB8]] ], [ [[TMP77]], %[[LOADBB9]] ], [ [[TMP85]], %[[LOADBB10]] ], [ poison, %[[RES_BLOCK]] ]
+; CHECK-NEXT: ret i32 [[PHI_RES]]
+;
+ %call = call i32 @memcmp(ptr %a, ptr %b, i64 11)
+ ret i32 %call
+}
+
+; Equality expansion still uses xor/or aggregation, with eight load pairs per
+; block and four branches for a 32-byte comparison.
+define i1 @memcmp_eq_size_32_align_1(ptr %a, ptr %b) {
+; CHECK-LABEL: define i1 @memcmp_eq_size_32_align_1(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT: br label %[[LOADBB:.*]]
+; CHECK: [[RES_BLOCK:.*]]:
+; CHECK-NEXT: br label %[[ENDBLOCK:.*]]
+; CHECK: [[LOADBB]]:
+; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
+; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[B]], align 1
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: br i1 [[TMP3]], label %[[RES_BLOCK]], label %[[LOADBB1:.*]]
+; CHECK: [[LOADBB1]]:
+; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[A]], i64 1
+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[B]], i64 1
+; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP4]], align 1
+; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[TMP5]], align 1
+; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i8 [[TMP6]], [[TMP7]]
+; CHECK-NEXT: br i1 [[TMP8]], label %[[RES_BLOCK]], label %[[LOADBB2:.*]]
+; CHECK: [[LOADBB2]]:
+; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[A]], i64 2
+; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[B]], i64 2
+; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP9]], align 1
+; CHECK-NEXT: [[TMP12:%.*]] = load i8, ptr [[TMP10]], align 1
+; CHECK-NEXT: [[TMP13:%.*]] = icmp ne i8 [[TMP11]], [[TMP12]]
+; CHECK-NEXT: br i1 [[TMP13]], label %[[RES_BLOCK]], label %[[LOADBB3:.*]]
+; CHECK: [[LOADBB3]]:
+; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[A]], i64 3
+; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[B]], i64 3
+; CHECK-NEXT: [[TMP16:%.*]] = load i8, ptr [[TMP14]], align 1
+; CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[TMP15]], align 1
+; CHECK-NEXT: [[TMP18:%.*]] = icmp ne i8 [[TMP16]], [[TMP17]]
+; CHECK-NEXT: br i1 [[TMP18]], label %[[RES_BLOCK]], label %[[LOADBB4:.*]]
+; CHECK: [[LOADBB4]]:
+; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[A]], i64 4
+; CHECK-NEXT: [[TMP20:%.*]] = getelementptr i8, ptr [[B]], i64 4
+; CHECK-NEXT: [[TMP21:%.*]] = load i8, ptr [[TMP19]], align 1
+; CHECK-NEXT: [[TMP22:%.*]] = load i8, ptr [[TMP20]], align 1
+; CHECK-NEXT: [[TMP23:%.*]] = icmp ne i8 [[TMP21]], [[TMP22]]
+; CHECK-NEXT: br i1 [[TMP23]], label %[[RES_BLOCK]], label %[[LOADBB5:.*]]
+; CHECK: [[LOADBB5]]:
+; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[A]], i64 5
+; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[B]], i64 5
+; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP24]], align 1
+; CHECK-NEXT: [[TMP27:%.*]] = load i8, ptr [[TMP25]], align 1
+; CHECK-NEXT: [[TMP28:%.*]] = icmp ne i8 [[TMP26]], [[TMP27]]
+; CHECK-NEXT: br i1 [[TMP28]], label %[[RES_BLOCK]], label %[[LOADBB6:.*]]
+; CHECK: [[LOADBB6]]:
+; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[A]], i64 6
+; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[B]], i64 6
+; CHECK-NEXT: [[TMP31:%.*]] = load i8, ptr [[TMP29]], align 1
+; CHECK-NEXT: [[TMP32:%.*]] = load i8, ptr [[TMP30]], align 1
+; CHECK-NEXT: [[TMP33:%.*]] = icmp ne i8 [[TMP31]], [[TMP32]]
+; CHECK-NEXT: br i1 [[TMP33]], label %[[RES_BLOCK]], label %[[LOADBB7:.*]]
+; CHECK: [[LOADBB7]]:
+; CHECK-NEXT: [[TMP34:%.*]] = getelementptr i8, ptr [[A]], i64 7
+; CHECK-NEXT: [[TMP35:%.*]] = getelementptr i8, ptr [[B]], i64 7
+; CHECK-NEXT: [[TMP36:%.*]] = load i8, ptr [[TMP34]], align 1
+; CHECK-NEXT: [[TMP37:%.*]] = load i8, ptr [[TMP35]], align 1
+; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i8 [[TMP36]], [[TMP37]]
+; CHECK-NEXT: br i1 [[TMP38]], label %[[RES_BLOCK]], label %[[LOADBB8:.*]]
+; CHECK: [[LOADBB8]]:
+; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[A]], i64 8
+; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i8, ptr [[B]], i64 8
+; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[TMP39]], align 1
+; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[TMP40]], align 1
+; CHECK-NEXT: [[TMP43:%.*]] = icmp ne i8 [[TMP41]], [[TMP42]]
+; CHECK-NEXT: br i1 [[TMP43]], label %[[RES_BLOCK]], label %[[LOADBB9:.*]]
+; CHECK: [[LOADBB9]]:
+; CHECK-NEXT: [[TMP44:%.*]] = getelementptr i8, ptr [[A]], i64 9
+; CHECK-NEXT: [[TMP45:%.*]] = getelementptr i8, ptr [[B]], i64 9
+; CHECK-NEXT: [[TMP46:%.*]] = load i8, ptr [[TMP44]], align 1
+; CHECK-NEXT: [[TMP47:%.*]] = load i8, ptr [[TMP45]], align 1
+; CHECK-NEXT: [[TMP48:%.*]] = icmp ne i8 [[TMP46]], [[TMP47]]
+; CHECK-NEXT: br i1 [[TMP48]], label %[[RES_BLOCK]], label %[[LOADBB10:.*]]
+; CHECK: [[LOADBB10]]:
+; CHECK-NEXT: [[TMP49:%.*]] = getelementptr i8, ptr [[A]], i64 10
+; CHECK-NEXT: [[TMP50:%.*]] = getelementptr i8, ptr [[B]], i64 10
+; CHECK-NEXT: [[TMP51:%.*]] = load i8, ptr [[TMP49]], align 1
+; CHECK-NEXT: [[TMP52:%.*]] = load i8, ptr [[TMP50]], align 1
+; CHECK-NEXT: [[TMP53:%.*]] = icmp ne i8 [[TMP51]], [[TMP52]]
+; CHECK-NEXT: br i1 [[TMP53]], label %[[RES_BLOCK]], label %[[LOADBB11:.*]]
+; CHECK: [[LOADBB11]]:
+; CHECK-NEXT: [[TMP54:%.*]] = getelementptr i8, ptr [[A]], i64 11
+; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[B]], i64 11
+; CHECK-NEXT: [[TMP56:%.*]] = load i8, ptr [[TMP54]], align 1
+; CHECK-NEXT: [[TMP57:%.*]] = load i8, ptr [[TMP55]], align 1
+; CHECK-NEXT: [[TMP58:%.*]] = icmp ne i8 [[TMP56]], [[TMP57]]
+; CHECK-NEXT: br i1 [[TMP58]], label %[[RES_BLOCK]], label %[[LOADBB12:.*]]
+; CHECK: [[LOADBB12]]:
+; CHECK-NEXT: [[TMP59:%.*]] = getelementptr i8, ptr [[A]], i64 12
+; CHECK-NEXT: [[TMP60:%.*]] = getelementptr i8, ptr [[B]], i64 12
+; CHECK-NEXT: [[TMP61:%.*]] = load i8, ptr [[TMP59]], align 1
+; CHECK-NEXT: [[TMP62:%.*]] = load i8, ptr [[TMP60]], align 1
+; CHECK-NEXT: [[TMP63:%.*]] = icmp ne i8 [[TMP61]], [[TMP62]]
+; CHECK-NEXT: br i1 [[TMP63]], label %[[RES_BLOCK]], label %[[LOADBB13:.*]]
+; CHECK: [[LOADBB13]]:
+; CHECK-NEXT: [[TMP64:%.*]] = getelementptr i8, ptr [[A]], i64 13
+; CHECK-NEXT: [[TMP65:%.*]] = getelementptr i8, ptr [[B]], i64 13
+; CHECK-NEXT: [[TMP66:%.*]] = load i8, ptr [[TMP64]], align 1
+; CHECK-NEXT: [[TMP67:%.*]] = load i8, ptr [[TMP65]], align 1
+; CHECK-NEXT: [[TMP68:%.*]] = icmp ne i8 [[TMP66]], [[TMP67]]
+; CHECK-NEXT: br i1 [[TMP68]], label %[[RES_BLOCK]], label %[[LOADBB14:.*]]
+; CHECK: [[LOADBB14]]:
+; CHECK-NEXT: [[TMP69:%.*]] = getelementptr i8, ptr [[A]], i64 14
+; CHECK-NEXT: [[TMP70:%.*]] = getelementptr i8, ptr [[B]], i64 14
+; CHECK-NEXT: [[TMP71:%.*]] = load i8, ptr [[TMP69]], align 1
+; CHECK-NEXT: [[TMP72:%.*]] = load i8, ptr [[TMP70]], align 1
+; CHECK-NEXT: [[TMP73:%.*]] = icmp ne i8 [[TMP71]], [[TMP72]]
+; CHECK-NEXT: br i1 [[TMP73]], label %[[RES_BLOCK]], label %[[LOADBB15:.*]]
+; CHECK: [[LOADBB15]]:
+; CHECK-NEXT: [[TMP74:%.*]] = getelementptr i8, ptr [[A]], i64 15
+; CHECK-NEXT: [[TMP75:%.*]] = getelementptr i8, ptr [[B]], i64 15
+; CHECK-NEXT: [[TMP76:%.*]] = load i8, ptr [[TMP74]], align 1
+; CHECK-NEXT: [[TMP77:%.*]] = load i8, ptr [[TMP75]], align 1
+; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i8 [[TMP76]], [[TMP77]]
+; CHECK-NEXT: br i1 [[TMP78]], label %[[RES_BLOCK]], label %[[LOADBB16:.*]]
+; CHECK: [[LOADBB16]]:
+; CHECK-NEXT: [[TMP79:%.*]] = getelementptr i8, ptr [[A]], i64 16
+; CHECK-NEXT: [[TMP80:%.*]] = getelementptr i8, ptr [[B]], i64 16
+; CHECK-NEXT: [[TMP81:%.*]] = load i8, ptr [[TMP79]], align 1
+; CHECK-NEXT: [[TMP82:%.*]] = load i8, ptr [[TMP80]], align 1
+; CHECK-NEXT: [[TMP83:%.*]] = icmp ne i8 [[TMP81]], [[TMP82]]
+; CHECK-NEXT: br i1 [[TMP83]], label %[[RES_BLOCK]], label %[[LOADBB17:.*]]
+; CHECK: [[LOADBB17]]:
+; CHECK-NEXT: [[TMP84:%.*]] = getelementptr i8, ptr [[A]], i64 17
+; CHECK-NEXT: [[TMP85:%.*]] = getelementptr i8, ptr [[B]], i64 17
+; CHECK-NEXT: [[TMP86:%.*]] = load i8, ptr [[TMP84]], align 1
+; CHECK-NEXT: [[TMP87:%.*]] = load i8, ptr [[TMP85]], align 1
+; CHECK-NEXT: [[TMP88:%.*]] = icmp ne i8 [[TMP86]], [[TMP87]]
+; CHECK-NEXT: br i1 [[TMP88]], label %[[RES_BLOCK]], label %[[LOADBB18:.*]]
+; CHECK: [[LOADBB18]]:
+; CHECK-NEXT: [[TMP89:%.*]] = getelementptr i8, ptr [[A]], i64 18
+; CHECK-NEXT: [[TMP90:%.*]] = getelementptr i8, ptr [[B]], i64 18
+; CHECK-NEXT: [[TMP91:%.*]] = load i8, ptr [[TMP89]], align 1
+; CHECK-NEXT: [[TMP92:%.*]] = load i8, ptr [[TMP90]], align 1
+; CHECK-NEXT: [[TMP93:%.*]] = icmp ne i8 [[TMP91]], [[TMP92]]
+; CHECK-NEXT: br i1 [[TMP93]], label %[[RES_BLOCK]], label %[[LOADBB19:.*]]
+; CHECK: [[LOADBB19]]:
+; CHECK-NEXT: [[TMP94:%.*]] = getelementptr i8, ptr [[A]], i64 19
+; CHECK-NEXT: [[TMP95:%.*]] = getelementptr i8, ptr [[B]], i64 19
+; CHECK-NEXT: [[TMP96:%.*]] = load i8, ptr [[TMP94]], align 1
+; CHECK-NEXT: [[TMP97:%.*]] = load i8, ptr [[TMP95]], align 1
+; CHECK-NEXT: [[TMP98:%.*]] = icmp ne i8 [[TMP96]], [[TMP97]]
+; CHECK-NEXT: br i1 [[TMP98]], label %[[RES_BLOCK]], label %[[LOADBB20:.*]]
+; CHECK: [[LOADBB20]]:
+; CHECK-NEXT: [[TMP99:%.*]] = getelementptr i8, ptr [[A]], i64 20
+; CHECK-NEXT: [[TMP100:%.*]] = getelementptr i8, ptr [[B]], i64 20
+; CHECK-NEXT: [[TMP101:%.*]] = load i8, ptr [[TMP99]], align 1
+; CHECK-NEXT: [[TMP102:%.*]] = load i8, ptr [[TMP100]], align 1
+; CHECK-NEXT: [[TMP103:%.*]] = icmp ne i8 [[TMP101]], [[TMP102]]
+; CHECK-NEXT: br i1 [[TMP103]], label %[[RES_BLOCK]], label %[[LOADBB21:.*]]
+; CHECK: [[LOADBB21]]:
+; CHECK-NEXT: [[TMP104:%.*]] = getelementptr i8, ptr [[A]], i64 21
+; CHECK-NEXT: [[TMP105:%.*]] = getelementptr i8, ptr [[B]], i64 21
+; CHECK-NEXT: [[TMP106:%.*]] = load i8, ptr [[TMP104]], align 1
+; CHECK-NEXT: [[TMP107:%.*]] = load i8, ptr [[TMP105]], align 1
+; CHECK-NEXT: [[TMP108:%.*]] = icmp ne i8 [[TMP106]], [[TMP107]]
+; CHECK-NEXT: br i1 [[TMP108]], label %[[RES_BLOCK]], label %[[LOADBB22:.*]]
+; CHECK: [[LOADBB22]]:
+; CHECK-NEXT: [[TMP109:%.*]] = getelementptr i8, ptr [[A]], i64 22
+; CHECK-NEXT: [[TMP110:%.*]] = getelementptr i8, ptr [[B]], i64 22
+; CHECK-NEXT: [[TMP111:%.*]] = load i8, ptr [[TMP109]], align 1
+; CHECK-NEXT: [[TMP112:%.*]] = load i8, ptr [[TMP110]], align 1
+; CHECK-NEXT: [[TMP113:%.*]] = icmp ne i8 [[TMP111]], [[TMP112]]
+; CHECK-NEXT: br i1 [[TMP113]], label %[[RES_BLOCK]], label %[[LOADBB23:.*]]
+; CHECK: [[LOADBB23]]:
+; CHECK-NEXT: [[TMP114:%.*]] = getelementptr i8, ptr [[A]], i64 23
+; CHECK-NEXT: [[TMP115:%.*]] = getelementptr i8, ptr [[B]], i64 23
+; CHECK-NEXT: [[TMP116:%.*]] = load i8, ptr [[TMP114]], align 1
+; CHECK-NEXT: [[TMP117:%.*]] = load i8, ptr [[TMP115]], align 1
+; CHECK-NEXT: [[TMP118:%.*]] = icmp ne i8 [[TMP116]], [[TMP117]]
+; CHECK-NEXT: br i1 [[TMP118]], label %[[RES_BLOCK]], label %[[LOADBB24:.*]]
+; CHECK: [[LOADBB24]]:
+; CHECK-NEXT: [[TMP119:%.*]] = getelementptr i8, ptr [[A]], i64 24
+; CHECK-NEXT: [[TMP120:%.*]] = getelementptr i8, ptr [[B]], i64 24
+; CHECK-NEXT: [[TMP121:%.*]] = load i8, ptr [[TMP119]], align 1
+; CHECK-NEXT: [[TMP122:%.*]] = load i8, ptr [[TMP120]], align 1
+; CHECK-NEXT: [[TMP123:%.*]] = icmp ne i8 [[TMP121]], [[TMP122]]
+; CHECK-NEXT: br i1 [[TMP123]], label %[[RES_BLOCK]], label %[[LOADBB25:.*]]
+; CHECK: [[LOADBB25]]:
+; CHECK-NEXT: [[TMP124:%.*]] = getelementptr i8, ptr [[A]], i64 25
+; CHECK-NEXT: [[TMP125:%.*]] = getelementptr i8, ptr [[B]], i64 25
+; CHECK-NEXT: [[TMP126:%.*]] = load i8, ptr [[TMP124]], align 1
+; CHECK-NEXT: [[TMP127:%.*]] = load i8, ptr [[TMP125]], align 1
+; CHECK-NEXT: [[TMP128:%.*]] = icmp ne i8 [[TMP126]], [[TMP127]]
+; CHECK-NEXT: br i1 [[TMP128]], label %[[RES_BLOCK]], label %[[LOADBB26:.*]]
+; CHECK: [[LOADBB26]]:
+; CHECK-NEXT: [[TMP129:%.*]] = getelementptr i8, ptr [[A]], i64 26
+; CHECK-NEXT: [[TMP130:%.*]] = getelementptr i8, ptr [[B]], i64 26
+; CHECK-NEXT: [[TMP131:%.*]] = load i8, ptr [[TMP129]], align 1
+; CHECK-NEXT: [[TMP132:%.*]] = load i8, ptr [[TMP130]], align 1
+; CHECK-NEXT: [[TMP133:%.*]] = icmp ne i8 [[TMP131]], [[TMP132]]
+; CHECK-NEXT: br i1 [[TMP133]], label %[[RES_BLOCK]], label %[[LOADBB27:.*]]
+; CHECK: [[LOADBB27]]:
+; CHECK-NEXT: [[TMP134:%.*]] = getelementptr i8, ptr [[A]], i64 27
+; CHECK-NEXT: [[TMP135:%.*]] = getelementptr i8, ptr [[B]], i64 27
+; CHECK-NEXT: [[TMP136:%.*]] = load i8, ptr [[TMP134]], align 1
+; CHECK-NEXT: [[TMP137:%.*]] = load i8, ptr [[TMP135]], align 1
+; CHECK-NEXT: [[TMP138:%.*]] = icmp ne i8 [[TMP136]], [[TMP137]]
+; CHECK-NEXT: br i1 [[TMP138]], label %[[RES_BLOCK]], label %[[LOADBB28:.*]]
+; CHECK: [[LOADBB28]]:
+; CHECK-NEXT: [[TMP139:%.*]] = getelementptr i8, ptr [[A]], i64 28
+; CHECK-NEXT: [[TMP140:%.*]] = getelementptr i8, ptr [[B]], i64 28
+; CHECK-NEXT: [[TMP141:%.*]] = load i8, ptr [[TMP139]], align 1
+; CHECK-NEXT: [[TMP142:%.*]] = load i8, ptr [[TMP140]], align 1
+; CHECK-NEXT: [[TMP143:%.*]] = icmp ne i8 [[TMP141]], [[TMP142]]
+; CHECK-NEXT: br i1 [[TMP143]], label %[[RES_BLOCK]], label %[[LOADBB29:.*]]
+; CHECK: [[LOADBB29]]:
+; CHECK-NEXT: [[TMP144:%.*]] = getelementptr i8, ptr [[A]], i64 29
+; CHECK-NEXT: [[TMP145:%.*]] = getelementptr i8, ptr [[B]], i64 29
+; CHECK-NEXT: [[TMP146:%.*]] = load i8, ptr [[TMP144]], align 1
+; CHECK-NEXT: [[TMP147:%.*]] = load i8, ptr [[TMP145]], align 1
+; CHECK-NEXT: [[TMP148:%.*]] = icmp ne i8 [[TMP146]], [[TMP147]]
+; CHECK-NEXT: br i1 [[TMP148]], label %[[RES_BLOCK]], label %[[LOADBB30:.*]]
+; CHECK: [[LOADBB30]]:
+; CHECK-NEXT: [[TMP149:%.*]] = getelementptr i8, ptr [[A]], i64 30
+; CHECK-NEXT: [[TMP150:%.*]] = getelementptr i8, ptr [[B]], i64 30
+; CHECK-NEXT: [[TMP151:%.*]] = load i8, ptr [[TMP149]], align 1
+; CHECK-NEXT: [[TMP152:%.*]] = load i8, ptr [[TMP150]], align 1
+; CHECK-NEXT: [[TMP153:%.*]] = icmp ne i8 [[TMP151]], [[TMP152]]
+; CHECK-NEXT: br i1 [[TMP153]], label %[[RES_BLOCK]], label %[[LOADBB31:.*]]
+; CHECK: [[LOADBB31]]:
+; CHECK-NEXT: [[TMP154:%.*]] = getelementptr i8, ptr [[A]], i64 31
+; CHECK-NEXT: [[TMP155:%.*]] = getelementptr i8, ptr [[B]], i64 31
+; CHECK-NEXT: [[TMP156:%.*]] = load i8, ptr [[TMP154]], align 1
+; CHECK-NEXT: [[TMP157:%.*]] = load i8, ptr [[TMP155]], align 1
+; CHECK-NEXT: [[TMP158:%.*]] = icmp ne i8 [[TMP156]], [[TMP157]]
+; CHECK-NEXT: br i1 [[TMP158]], label %[[RES_BLOCK]], label %[[ENDBLOCK]]
+; CHECK: [[ENDBLOCK]]:
+; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, %[[LOADBB31]] ], [ 1, %[[RES_BLOCK]] ]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %call = call i32 @memcmp(ptr %a, ptr %b, i64 32)
+ %cmp = icmp eq i32 %call, 0
+ ret i1 %cmp
+}
+
+define i1 @bcmp_size_32_align_1(ptr %a, ptr %b) {
+; CHECK-LABEL: define i1 @bcmp_size_32_align_1(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT: br label %[[LOADBB:.*]]
+; CHECK: [[RES_BLOCK:.*]]:
+; CHECK-NEXT: br label %[[ENDBLOCK:.*]]
+; CHECK: [[LOADBB]]:
+; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
+; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[B]], align 1
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], [[TMP2]]
+; CHECK-NEXT: br i1 [[TMP3]], label %[[RES_BLOCK]], label %[[LOADBB1:.*]]
+; CHECK: [[LOADBB1]]:
+; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[A]], i64 1
+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[B]], i64 1
+; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP4]], align 1
+; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[TMP5]], align 1
+; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i8 [[TMP6]], [[TMP7]]
+; CHECK-NEXT: br i1 [[TMP8]], label %[[RES_BLOCK]], label %[[LOADBB2:.*]]
+; CHECK: [[LOADBB2]]:
+; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[A]], i64 2
+; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[B]], i64 2
+; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP9]], align 1
+; CHECK-NEXT: [[TMP12:%.*]] = load i8, ptr [[TMP10]], align 1
+; CHECK-NEXT: [[TMP13:%.*]] = icmp ne i8 [[TMP11]], [[TMP12]]
+; CHECK-NEXT: br i1 [[TMP13]], label %[[RES_BLOCK]], label %[[LOADBB3:.*]]
+; CHECK: [[LOADBB3]]:
+; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[A]], i64 3
+; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[B]], i64 3
+; CHECK-NEXT: [[TMP16:%.*]] = load i8, ptr [[TMP14]], align 1
+; CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[TMP15]], align 1
+; CHECK-NEXT: [[TMP18:%.*]] = icmp ne i8 [[TMP16]], [[TMP17]]
+; CHECK-NEXT: br i1 [[TMP18]], label %[[RES_BLOCK]], label %[[LOADBB4:.*]]
+; CHECK: [[LOADBB4]]:
+; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[A]], i64 4
+; CHECK-NEXT: [[TMP20:%.*]] = getelementptr i8, ptr [[B]], i64 4
+; CHECK-NEXT: [[TMP21:%.*]] = load i8, ptr [[TMP19]], align 1
+; CHECK-NEXT: [[TMP22:%.*]] = load i8, ptr [[TMP20]], align 1
+; CHECK-NEXT: [[TMP23:%.*]] = icmp ne i8 [[TMP21]], [[TMP22]]
+; CHECK-NEXT: br i1 [[TMP23]], label %[[RES_BLOCK]], label %[[LOADBB5:.*]]
+; CHECK: [[LOADBB5]]:
+; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[A]], i64 5
+; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[B]], i64 5
+; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP24]], align 1
+; CHECK-NEXT: [[TMP27:%.*]] = load i8, ptr [[TMP25]], align 1
+; CHECK-NEXT: [[TMP28:%.*]] = icmp ne i8 [[TMP26]], [[TMP27]]
+; CHECK-NEXT: br i1 [[TMP28]], label %[[RES_BLOCK]], label %[[LOADBB6:.*]]
+; CHECK: [[LOADBB6]]:
+; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[A]], i64 6
+; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[B]], i64 6
+; CHECK-NEXT: [[TMP31:%.*]] = load i8, ptr [[TMP29]], align 1
+; CHECK-NEXT: [[TMP32:%.*]] = load i8, ptr [[TMP30]], align 1
+; CHECK-NEXT: [[TMP33:%.*]] = icmp ne i8 [[TMP31]], [[TMP32]]
+; CHECK-NEXT: br i1 [[TMP33]], label %[[RES_BLOCK]], label %[[LOADBB7:.*]]
+; CHECK: [[LOADBB7]]:
+; CHECK-NEXT: [[TMP34:%.*]] = getelementptr i8, ptr [[A]], i64 7
+; CHECK-NEXT: [[TMP35:%.*]] = getelementptr i8, ptr [[B]], i64 7
+; CHECK-NEXT: [[TMP36:%.*]] = load i8, ptr [[TMP34]], align 1
+; CHECK-NEXT: [[TMP37:%.*]] = load i8, ptr [[TMP35]], align 1
+; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i8 [[TMP36]], [[TMP37]]
+; CHECK-NEXT: br i1 [[TMP38]], label %[[RES_BLOCK]], label %[[LOADBB8:.*]]
+; CHECK: [[LOADBB8]]:
+; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[A]], i64 8
+; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i8, ptr [[B]], i64 8
+; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[TMP39]], align 1
+; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[TMP40]], align 1
+; CHECK-NEXT: [[TMP43:%.*]] = icmp ne i8 [[TMP41]], [[TMP42]]
+; CHECK-NEXT: br i1 [[TMP43]], label %[[RES_BLOCK]], label %[[LOADBB9:.*]]
+; CHECK: [[LOADBB9]]:
+; CHECK-NEXT: [[TMP44:%.*]] = getelementptr i8, ptr [[A]], i64 9
+; CHECK-NEXT: [[TMP45:%.*]] = getelementptr i8, ptr [[B]], i64 9
+; CHECK-NEXT: [[TMP46:%.*]] = load i8, ptr [[TMP44]], align 1
+; CHECK-NEXT: [[TMP47:%.*]] = load i8, ptr [[TMP45]], align 1
+; CHECK-NEXT: [[TMP48:%.*]] = icmp ne i8 [[TMP46]], [[TMP47]]
+; CHECK-NEXT: br i1 [[TMP48]], label %[[RES_BLOCK]], label %[[LOADBB10:.*]]
+; CHECK: [[LOADBB10]]:
+; CHECK-NEXT: [[TMP49:%.*]] = getelementptr i8, ptr [[A]], i64 10
+; CHECK-NEXT: [[TMP50:%.*]] = getelementptr i8, ptr [[B]], i64 10
+; CHECK-NEXT: [[TMP51:%.*]] = load i8, ptr [[TMP49]], align 1
+; CHECK-NEXT: [[TMP52:%.*]] = load i8, ptr [[TMP50]], align 1
+; CHECK-NEXT: [[TMP53:%.*]] = icmp ne i8 [[TMP51]], [[TMP52]]
+; CHECK-NEXT: br i1 [[TMP53]], label %[[RES_BLOCK]], label %[[LOADBB11:.*]]
+; CHECK: [[LOADBB11]]:
+; CHECK-NEXT: [[TMP54:%.*]] = getelementptr i8, ptr [[A]], i64 11
+; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[B]], i64 11
+; CHECK-NEXT: [[TMP56:%.*]] = load i8, ptr [[TMP54]], align 1
+; CHECK-NEXT: [[TMP57:%.*]] = load i8, ptr [[TMP55]], align 1
+; CHECK-NEXT: [[TMP58:%.*]] = icmp ne i8 [[TMP56]], [[TMP57]]
+; CHECK-NEXT: br i1 [[TMP58]], label %[[RES_BLOCK]], label %[[LOADBB12:.*]]
+; CHECK: [[LOADBB12]]:
+; CHECK-NEXT: [[TMP59:%.*]] = getelementptr i8, ptr [[A]], i64 12
+; CHECK-NEXT: [[TMP60:%.*]] = getelementptr i8, ptr [[B]], i64 12
+; CHECK-NEXT: [[TMP61:%.*]] = load i8, ptr [[TMP59]], align 1
+; CHECK-NEXT: [[TMP62:%.*]] = load i8, ptr [[TMP60]], align 1
+; CHECK-NEXT: [[TMP63:%.*]] = icmp ne i8 [[TMP61]], [[TMP62]]
+; CHECK-NEXT: br i1 [[TMP63]], label %[[RES_BLOCK]], label %[[LOADBB13:.*]]
+; CHECK: [[LOADBB13]]:
+; CHECK-NEXT: [[TMP64:%.*]] = getelementptr i8, ptr [[A]], i64 13
+; CHECK-NEXT: [[TMP65:%.*]] = getelementptr i8, ptr [[B]], i64 13
+; CHECK-NEXT: [[TMP66:%.*]] = load i8, ptr [[TMP64]], align 1
+; CHECK-NEXT: [[TMP67:%.*]] = load i8, ptr [[TMP65]], align 1
+; CHECK-NEXT: [[TMP68:%.*]] = icmp ne i8 [[TMP66]], [[TMP67]]
+; CHECK-NEXT: br i1 [[TMP68]], label %[[RES_BLOCK]], label %[[LOADBB14:.*]]
+; CHECK: [[LOADBB14]]:
+; CHECK-NEXT: [[TMP69:%.*]] = getelementptr i8, ptr [[A]], i64 14
+; CHECK-NEXT: [[TMP70:%.*]] = getelementptr i8, ptr [[B]], i64 14
+; CHECK-NEXT: [[TMP71:%.*]] = load i8, ptr [[TMP69]], align 1
+; CHECK-NEXT: [[TMP72:%.*]] = load i8, ptr [[TMP70]], align 1
+; CHECK-NEXT: [[TMP73:%.*]] = icmp ne i8 [[TMP71]], [[TMP72]]
+; CHECK-NEXT: br i1 [[TMP73]], label %[[RES_BLOCK]], label %[[LOADBB15:.*]]
+; CHECK: [[LOADBB15]]:
+; CHECK-NEXT: [[TMP74:%.*]] = getelementptr i8, ptr [[A]], i64 15
+; CHECK-NEXT: [[TMP75:%.*]] = getelementptr i8, ptr [[B]], i64 15
+; CHECK-NEXT: [[TMP76:%.*]] = load i8, ptr [[TMP74]], align 1
+; CHECK-NEXT: [[TMP77:%.*]] = load i8, ptr [[TMP75]], align 1
+; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i8 [[TMP76]], [[TMP77]]
+; CHECK-NEXT: br i1 [[TMP78]], label %[[RES_BLOCK]], label %[[LOADBB16:.*]]
+; CHECK: [[LOADBB16]]:
+; CHECK-NEXT: [[TMP79:%.*]] = getelementptr i8, ptr [[A]], i64 16
+; CHECK-NEXT: [[TMP80:%.*]] = getelementptr i8, ptr [[B]], i64 16
+; CHECK-NEXT: [[TMP81:%.*]] = load i8, ptr [[TMP79]], align 1
+; CHECK-NEXT: [[TMP82:%.*]] = load i8, ptr [[TMP80]], align 1
+; CHECK-NEXT: [[TMP83:%.*]] = icmp ne i8 [[TMP81]], [[TMP82]]
+; CHECK-NEXT: br i1 [[TMP83]], label %[[RES_BLOCK]], label %[[LOADBB17:.*]]
+; CHECK: [[LOADBB17]]:
+; CHECK-NEXT: [[TMP84:%.*]] = getelementptr i8, ptr [[A]], i64 17
+; CHECK-NEXT: [[TMP85:%.*]] = getelementptr i8, ptr [[B]], i64 17
+; CHECK-NEXT: [[TMP86:%.*]] = load i8, ptr [[TMP84]], align 1
+; CHECK-NEXT: [[TMP87:%.*]] = load i8, ptr [[TMP85]], align 1
+; CHECK-NEXT: [[TMP88:%.*]] = icmp ne i8 [[TMP86]], [[TMP87]]
+; CHECK-NEXT: br i1 [[TMP88]], label %[[RES_BLOCK]], label %[[LOADBB18:.*]]
+; CHECK: [[LOADBB18]]:
+; CHECK-NEXT: [[TMP89:%.*]] = getelementptr i8, ptr [[A]], i64 18
+; CHECK-NEXT: [[TMP90:%.*]] = getelementptr i8, ptr [[B]], i64 18
+; CHECK-NEXT: [[TMP91:%.*]] = load i8, ptr [[TMP89]], align 1
+; CHECK-NEXT: [[TMP92:%.*]] = load i8, ptr [[TMP90]], align 1
+; CHECK-NEXT: [[TMP93:%.*]] = icmp ne i8 [[TMP91]], [[TMP92]]
+; CHECK-NEXT: br i1 [[TMP93]], label %[[RES_BLOCK]], label %[[LOADBB19:.*]]
+; CHECK: [[LOADBB19]]:
+; CHECK-NEXT: [[TMP94:%.*]] = getelementptr i8, ptr [[A]], i64 19
+; CHECK-NEXT: [[TMP95:%.*]] = getelementptr i8, ptr [[B]], i64 19
+; CHECK-NEXT: [[TMP96:%.*]] = load i8, ptr [[TMP94]], align 1
+; CHECK-NEXT: [[TMP97:%.*]] = load i8, ptr [[TMP95]], align 1
+; CHECK-NEXT: [[TMP98:%.*]] = icmp ne i8 [[TMP96]], [[TMP97]]
+; CHECK-NEXT: br i1 [[TMP98]], label %[[RES_BLOCK]], label %[[LOADBB20:.*]]
+; CHECK: [[LOADBB20]]:
+; CHECK-NEXT: [[TMP99:%.*]] = getelementptr i8, ptr [[A]], i64 20
+; CHECK-NEXT: [[TMP100:%.*]] = getelementptr i8, ptr [[B]], i64 20
+; CHECK-NEXT: [[TMP101:%.*]] = load i8, ptr [[TMP99]], align 1
+; CHECK-NEXT: [[TMP102:%.*]] = load i8, ptr [[TMP100]], align 1
+; CHECK-NEXT: [[TMP103:%.*]] = icmp ne i8 [[TMP101]], [[TMP102]]
+; CHECK-NEXT: br i1 [[TMP103]], label %[[RES_BLOCK]], label %[[LOADBB21:.*]]
+; CHECK: [[LOADBB21]]:
+; CHECK-NEXT: [[TMP104:%.*]] = getelementptr i8, ptr [[A]], i64 21
+; CHECK-NEXT: [[TMP105:%.*]] = getelementptr i8, ptr [[B]], i64 21
+; CHECK-NEXT: [[TMP106:%.*]] = load i8, ptr [[TMP104]], align 1
+; CHECK-NEXT: [[TMP107:%.*]] = load i8, ptr [[TMP105]], align 1
+; CHECK-NEXT: [[TMP108:%.*]] = icmp ne i8 [[TMP106]], [[TMP107]]
+; CHECK-NEXT: br i1 [[TMP108]], label %[[RES_BLOCK]], label %[[LOADBB22:.*]]
+; CHECK: [[LOADBB22]]:
+; CHECK-NEXT: [[TMP109:%.*]] = getelementptr i8, ptr [[A]], i64 22
+; CHECK-NEXT: [[TMP110:%.*]] = getelementptr i8, ptr [[B]], i64 22
+; CHECK-NEXT: [[TMP111:%.*]] = load i8, ptr [[TMP109]], align 1
+; CHECK-NEXT: [[TMP112:%.*]] = load i8, ptr [[TMP110]], align 1
+; CHECK-NEXT: [[TMP113:%.*]] = icmp ne i8 [[TMP111]], [[TMP112]]
+; CHECK-NEXT: br i1 [[TMP113]], label %[[RES_BLOCK]], label %[[LOADBB23:.*]]
+; CHECK: [[LOADBB23]]:
+; CHECK-NEXT: [[TMP114:%.*]] = getelementptr i8, ptr [[A]], i64 23
+; CHECK-NEXT: [[TMP115:%.*]] = getelementptr i8, ptr [[B]], i64 23
+; CHECK-NEXT: [[TMP116:%.*]] = load i8, ptr [[TMP114]], align 1
+; CHECK-NEXT: [[TMP117:%.*]] = load i8, ptr [[TMP115]], align 1
+; CHECK-NEXT: [[TMP118:%.*]] = icmp ne i8 [[TMP116]], [[TMP117]]
+; CHECK-NEXT: br i1 [[TMP118]], label %[[RES_BLOCK]], label %[[LOADBB24:.*]]
+; CHECK: [[LOADBB24]]:
+; CHECK-NEXT: [[TMP119:%.*]] = getelementptr i8, ptr [[A]], i64 24
+; CHECK-NEXT: [[TMP120:%.*]] = getelementptr i8, ptr [[B]], i64 24
+; CHECK-NEXT: [[TMP121:%.*]] = load i8, ptr [[TMP119]], align 1
+; CHECK-NEXT: [[TMP122:%.*]] = load i8, ptr [[TMP120]], align 1
+; CHECK-NEXT: [[TMP123:%.*]] = icmp ne i8 [[TMP121]], [[TMP122]]
+; CHECK-NEXT: br i1 [[TMP123]], label %[[RES_BLOCK]], label %[[LOADBB25:.*]]
+; CHECK: [[LOADBB25]]:
+; CHECK-NEXT: [[TMP124:%.*]] = getelementptr i8, ptr [[A]], i64 25
+; CHECK-NEXT: [[TMP125:%.*]] = getelementptr i8, ptr [[B]], i64 25
+; CHECK-NEXT: [[TMP126:%.*]] = load i8, ptr [[TMP124]], align 1
+; CHECK-NEXT: [[TMP127:%.*]] = load i8, ptr [[TMP125]], align 1
+; CHECK-NEXT: [[TMP128:%.*]] = icmp ne i8 [[TMP126]], [[TMP127]]
+; CHECK-NEXT: br i1 [[TMP128]], label %[[RES_BLOCK]], label %[[LOADBB26:.*]]
+; CHECK: [[LOADBB26]]:
+; CHECK-NEXT: [[TMP129:%.*]] = getelementptr i8, ptr [[A]], i64 26
+; CHECK-NEXT: [[TMP130:%.*]] = getelementptr i8, ptr [[B]], i64 26
+; CHECK-NEXT: [[TMP131:%.*]] = load i8, ptr [[TMP129]], align 1
+; CHECK-NEXT: [[TMP132:%.*]] = load i8, ptr [[TMP130]], align 1
+; CHECK-NEXT: [[TMP133:%.*]] = icmp ne i8 [[TMP131]], [[TMP132]]
+; CHECK-NEXT: br i1 [[TMP133]], label %[[RES_BLOCK]], label %[[LOADBB27:.*]]
+; CHECK: [[LOADBB27]]:
+; CHECK-NEXT: [[TMP134:%.*]] = getelementptr i8, ptr [[A]], i64 27
+; CHECK-NEXT: [[TMP135:%.*]] = getelementptr i8, ptr [[B]], i64 27
+; CHECK-NEXT: [[TMP136:%.*]] = load i8, ptr [[TMP134]], align 1
+; CHECK-NEXT: [[TMP137:%.*]] = load i8, ptr [[TMP135]], align 1
+; CHECK-NEXT: [[TMP138:%.*]] = icmp ne i8 [[TMP136]], [[TMP137]]
+; CHECK-NEXT: br i1 [[TMP138]], label %[[RES_BLOCK]], label %[[LOADBB28:.*]]
+; CHECK: [[LOADBB28]]:
+; CHECK-NEXT: [[TMP139:%.*]] = getelementptr i8, ptr [[A]], i64 28
+; CHECK-NEXT: [[TMP140:%.*]] = getelementptr i8, ptr [[B]], i64 28
+; CHECK-NEXT: [[TMP141:%.*]] = load i8, ptr [[TMP139]], align 1
+; CHECK-NEXT: [[TMP142:%.*]] = load i8, ptr [[TMP140]], align 1
+; CHECK-NEXT: [[TMP143:%.*]] = icmp ne i8 [[TMP141]], [[TMP142]]
+; CHECK-NEXT: br i1 [[TMP143]], label %[[RES_BLOCK]], label %[[LOADBB29:.*]]
+; CHECK: [[LOADBB29]]:
+; CHECK-NEXT: [[TMP144:%.*]] = getelementptr i8, ptr [[A]], i64 29
+; CHECK-NEXT: [[TMP145:%.*]] = getelementptr i8, ptr [[B]], i64 29
+; CHECK-NEXT: [[TMP146:%.*]] = load i8, ptr [[TMP144]], align 1
+; CHECK-NEXT: [[TMP147:%.*]] = load i8, ptr [[TMP145]], align 1
+; CHECK-NEXT: [[TMP148:%.*]] = icmp ne i8 [[TMP146]], [[TMP147]]
+; CHECK-NEXT: br i1 [[TMP148]], label %[[RES_BLOCK]], label %[[LOADBB30:.*]]
+; CHECK: [[LOADBB30]]:
+; CHECK-NEXT: [[TMP149:%.*]] = getelementptr i8, ptr [[A]], i64 30
+; CHECK-NEXT: [[TMP150:%.*]] = getelementptr i8, ptr [[B]], i64 30
+; CHECK-NEXT: [[TMP151:%.*]] = load i8, ptr [[TMP149]], align 1
+; CHECK-NEXT: [[TMP152:%.*]] = load i8, ptr [[TMP150]], align 1
+; CHECK-NEXT: [[TMP153:%.*]] = icmp ne i8 [[TMP151]], [[TMP152]]
+; CHECK-NEXT: br i1 [[TMP153]], label %[[RES_BLOCK]], label %[[LOADBB31:.*]]
+; CHECK: [[LOADBB31]]:
+; CHECK-NEXT: [[TMP154:%.*]] = getelementptr i8, ptr [[A]], i64 31
+; CHECK-NEXT: [[TMP155:%.*]] = getelementptr i8, ptr [[B]], i64 31
+; CHECK-NEXT: [[TMP156:%.*]] = load i8, ptr [[TMP154]], align 1
+; CHECK-NEXT: [[TMP157:%.*]] = load i8, ptr [[TMP155]], align 1
+; CHECK-NEXT: [[TMP158:%.*]] = icmp ne i8 [[TMP156]], [[TMP157]]
+; CHECK-NEXT: br i1 [[TMP158]], label %[[RES_BLOCK]], label %[[ENDBLOCK]]
+; CHECK: [[ENDBLOCK]]:
+; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, %[[LOADBB31]] ], [ 1, %[[RES_BLOCK]] ]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %call = call i32 @bcmp(ptr %a, ptr %b, i64 32)
+ %cmp = icmp eq i32 %call, 0
+ ret i1 %cmp
+}
>From aca613271267a7e887bafb7fa12f26d61dc500d4 Mon Sep 17 00:00:00 2001
From: Pengcheng Wang <wangpengcheng.pp at bytedance.com>
Date: Thu, 20 Aug 2026 14:34:12 +0800
Subject: [PATCH 2/2] [ExpandMemCmp] Apply NumLoadsPerBlock to ordering
compares
Make NumLoadsPerBlock control both equality and ordering memcmp
expansions. For ordering comparisons, pack consecutive legal loads
in memory order into a value no wider than the target preferred
load width, then compare the packed values. This preserves
lexicographic semantics while reducing conditional branches.
BPF uses groups of eight byte-load pairs, so an align-1 32-byte
comparison forms four i64 compare blocks instead of 32 byte compare
blocks.
Other targets retain their existing default ordering behavior unless
grouping is explicitly requested.
Assisted-by: TRAE CLI (GPT-5)
---
.../llvm/Analysis/TargetTransformInfo.h | 8 +-
.../AArch64/AArch64TargetTransformInfo.cpp | 2 +-
llvm/lib/Target/BPF/BPFTargetTransformInfo.h | 3 +
.../LoongArchTargetTransformInfo.cpp | 2 +-
.../Target/RISCV/RISCVTargetTransformInfo.cpp | 2 +-
.../WebAssemblyTargetTransformInfo.cpp | 2 +-
.../lib/Target/X86/X86TargetTransformInfo.cpp | 2 +-
llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp | 243 ++++--
llvm/test/CodeGen/BPF/memcmp.ll | 2 +-
.../CodeGen/X86/memcmp-more-load-pairs-x32.ll | 28 +-
.../CodeGen/X86/memcmp-more-load-pairs.ll | 127 ++-
.../Transforms/ExpandMemCmp/BPF/memcmp.ll | 818 +++++++++---------
.../Transforms/ExpandMemCmp/X86/memcmp.ll | 297 ++++---
13 files changed, 827 insertions(+), 709 deletions(-)
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 107ae4dba5075..e7d490c8dd716 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -1120,14 +1120,16 @@ class TargetTransformInfo {
// The list of available load sizes (in bytes), sorted in decreasing order.
SmallVector<unsigned, 8> LoadSizes;
- // For memcmp expansion when the memcmp result is only compared equal or
- // not-equal to 0, allow up to this number of load pairs per block. As an
- // example, this may allow 'memcmp(a, b, 3) == 0' in a single block:
+ // For memcmp expansion, allow up to this number of load pairs per block.
+ // As an example, this may allow 'memcmp(a, b, 3) == 0' in a single block:
// a0 = load2bytes &a[0]
// b0 = load2bytes &b[0]
// a2 = load1byte &a[2]
// b2 = load1byte &b[2]
// r = cmp eq (a0 ^ b0 | a2 ^ b2), 0
+ // Equality comparisons combine the differences with xor/or. Ordering
+ // comparisons pack the loads in memory order into a wider integer before
+ // comparing, without exceeding the target's preferred load width.
unsigned NumLoadsPerBlock = 1;
// Set to true to allow overlapping loads. For example, 7-byte compares can
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index b55e0856c792e..d7778a3baacfe 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -5377,7 +5377,7 @@ AArch64TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
}
Options.AllowOverlappingLoads = true;
Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
- Options.NumLoadsPerBlock = Options.MaxNumLoads;
+ Options.NumLoadsPerBlock = IsZeroCmp ? Options.MaxNumLoads : 1;
// TODO: Though vector loads usually perform well on AArch64, in some targets
// they may wake up the FP unit, which raises the power consumption. Perhaps
// they could be used with no holds barred (-O3).
diff --git a/llvm/lib/Target/BPF/BPFTargetTransformInfo.h b/llvm/lib/Target/BPF/BPFTargetTransformInfo.h
index 97f7fc62166d6..95defdc7b8379 100644
--- a/llvm/lib/Target/BPF/BPFTargetTransformInfo.h
+++ b/llvm/lib/Target/BPF/BPFTargetTransformInfo.h
@@ -77,6 +77,9 @@ class BPFTTIImpl final : public BasicTTIImplBase<BPFTTIImpl> {
TTI::MemCmpExpansionOptions Options;
Options.LoadSizes = {8, 4, 2, 1};
Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
+ // Group byte loads into a native-width value before comparing. This keeps
+ // the number of branches bounded when wide misaligned loads are split.
+ Options.NumLoadsPerBlock = 8;
return Options;
}
};
diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp
index 9f63714db64a1..6646841b93215 100644
--- a/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchTargetTransformInfo.cpp
@@ -121,7 +121,7 @@ LoongArchTTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
return Options;
Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
- Options.NumLoadsPerBlock = Options.MaxNumLoads;
+ Options.NumLoadsPerBlock = IsZeroCmp ? Options.MaxNumLoads : 1;
Options.AllowOverlappingLoads = true;
// TODO: Support for vectors.
diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
index 9868e4d02f905..ff3d8e6758847 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
@@ -3680,7 +3680,7 @@ RISCVTTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
Options.AllowOverlappingLoads = true;
Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
- Options.NumLoadsPerBlock = Options.MaxNumLoads;
+ Options.NumLoadsPerBlock = IsZeroCmp ? Options.MaxNumLoads : 1;
if (ST->is64Bit()) {
Options.LoadSizes = {8, 4, 2, 1};
Options.AllowedTailExpansions = {3, 5, 6};
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
index 75c631055ae2d..478ced6c4d0a6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
@@ -242,7 +242,7 @@ WebAssemblyTTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
Options.LoadSizes.append({8, 4, 2, 1});
Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
- Options.NumLoadsPerBlock = Options.MaxNumLoads;
+ Options.NumLoadsPerBlock = IsZeroCmp ? Options.MaxNumLoads : 1;
return Options;
}
diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
index 828d79ab0cb45..0a02b07945941 100644
--- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
+++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp
@@ -6988,7 +6988,7 @@ X86TTIImpl::TTI::MemCmpExpansionOptions
X86TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
TTI::MemCmpExpansionOptions Options;
Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
- Options.NumLoadsPerBlock = 2;
+ Options.NumLoadsPerBlock = IsZeroCmp ? 2 : 1;
// All GPR and vector loads can be unaligned.
Options.AllowOverlappingLoads = true;
if (IsZeroCmp) {
diff --git a/llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp b/llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp
index 62e9c82ea7756..239eb47e35bad 100644
--- a/llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp
+++ b/llvm/lib/Transforms/Scalar/ExpandMemCmp.cpp
@@ -41,10 +41,10 @@ STATISTIC(NumMemCmpGreaterThanMax,
"Number of memcmp calls with size greater than max size");
STATISTIC(NumMemCmpInlined, "Number of inlined memcmp calls");
-static cl::opt<unsigned> MemCmpEqZeroNumLoadsPerBlock(
+static cl::opt<unsigned> MemCmpNumLoadsPerBlock(
"memcmp-num-loads-per-block", cl::Hidden, cl::init(1),
cl::desc("The number of loads per basic block for inline expansion of "
- "memcmp that is only being compared against zero."));
+ "memcmp."));
static cl::opt<unsigned> MaxLoadsPerMemcmp(
"max-loads-per-memcmp", cl::Hidden,
@@ -70,6 +70,11 @@ static Align getMemCmpArgAlignment(const CallInst *CI, unsigned ArgNo,
// This class provides helper functions to expand a memcmp library call into an
// inline expansion.
class MemCmpExpansion {
+ struct LoadPair {
+ Value *Lhs = nullptr;
+ Value *Rhs = nullptr;
+ };
+
struct ResultBlock {
BasicBlock *BB = nullptr;
PHINode *PhiSrc1 = nullptr;
@@ -82,8 +87,9 @@ class MemCmpExpansion {
ResultBlock ResBlock;
const uint64_t Size;
unsigned MaxLoadSize = 0;
- uint64_t NumLoadsNonOneByte = 0;
- const uint64_t NumLoadsPerBlockForZeroCmp;
+ const uint64_t NumLoadsPerBlock;
+ const unsigned MaxBytesPerBlock;
+ unsigned MaxBlockSize = 0;
std::vector<BasicBlock *> LoadCmpBlocks;
BasicBlock *EndBlock = nullptr;
PHINode *PhiRes = nullptr;
@@ -115,7 +121,8 @@ class MemCmpExpansion {
void setupResultBlockPHINodes();
void setupEndBlockPHINodes();
Value *getCompareLoadPairs(unsigned BlockIndex, unsigned &LoadIndex);
- void emitLoadCompareBlock(unsigned BlockIndex);
+ LoadPair getPackedLoadPair(unsigned BlockIndex, unsigned &LoadIndex);
+ void emitLoadCompareBlock(unsigned BlockIndex, unsigned &LoadIndex);
void emitLoadCompareBlockMultipleLoads(unsigned BlockIndex,
unsigned &LoadIndex);
void emitLoadCompareByteBlock(unsigned BlockIndex, unsigned OffsetBytes);
@@ -123,10 +130,8 @@ class MemCmpExpansion {
Value *getMemCmpExpansionZeroCase();
Value *getMemCmpEqZeroOneBlock();
Value *getMemCmpOneBlock();
- struct LoadPair {
- Value *Lhs = nullptr;
- Value *Rhs = nullptr;
- };
+ Value *getMemCmpOneBlockMultipleLoads();
+ Value *getMemCmpResult(const LoadPair &Loads);
LoadPair getLoadPair(Type *LoadSizeType, Type *BSwapSizeType,
Type *CmpSizeType, unsigned OffsetBytes);
@@ -138,11 +143,10 @@ class MemCmpExpansion {
static LoadEntryVector
computeGreedyLoadSequence(uint64_t Size, llvm::ArrayRef<unsigned> LoadSizes,
- unsigned MaxNumLoads, unsigned &NumLoadsNonOneByte);
- LoadEntryVector
- computeOverlappingLoadSequence(uint64_t Size, unsigned MaxLoadSize,
- unsigned MaxNumLoads,
- unsigned &NumLoadsNonOneByte) const;
+ unsigned MaxNumLoads);
+ LoadEntryVector computeOverlappingLoadSequence(uint64_t Size,
+ unsigned MaxLoadSize,
+ unsigned MaxNumLoads) const;
void optimiseLoadSequence(
LoadEntryVector &LoadSequence,
@@ -154,9 +158,11 @@ class MemCmpExpansion {
const TargetTransformInfo::MemCmpExpansionOptions &Options,
const bool IsUsedForZeroCmp, const DataLayout &TheDataLayout,
DomTreeUpdater *DTU, const TargetTransformInfo &TTI,
- Align CommonAlign);
+ Align CommonAlign, unsigned MaxBytesPerBlock);
unsigned getNumBlocks();
+ unsigned getNumLoadsInBlock(unsigned LoadIndex) const;
+ unsigned getNumBytesInBlock(unsigned LoadIndex, unsigned NumLoads) const;
uint64_t getNumLoads() const { return LoadSequence.size(); }
Value *getMemCmpExpansion();
@@ -193,10 +199,10 @@ bool MemCmpExpansion::isAccessAllowed(unsigned LoadSize,
return ::isAccessAllowed(CI, TTI, CommonAlign, LoadSize, Offset);
}
-MemCmpExpansion::LoadEntryVector MemCmpExpansion::computeGreedyLoadSequence(
- uint64_t Size, llvm::ArrayRef<unsigned> LoadSizes,
- const unsigned MaxNumLoads, unsigned &NumLoadsNonOneByte) {
- NumLoadsNonOneByte = 0;
+MemCmpExpansion::LoadEntryVector
+MemCmpExpansion::computeGreedyLoadSequence(uint64_t Size,
+ llvm::ArrayRef<unsigned> LoadSizes,
+ const unsigned MaxNumLoads) {
LoadEntryVector LoadSequence;
uint64_t Offset = 0;
while (Size && !LoadSizes.empty()) {
@@ -214,8 +220,6 @@ MemCmpExpansion::LoadEntryVector MemCmpExpansion::computeGreedyLoadSequence(
LoadSequence.push_back({LoadSize, Offset});
Offset += LoadSize;
}
- if (LoadSize > 1)
- ++NumLoadsNonOneByte;
Size = Size % LoadSize;
}
LoadSizes = LoadSizes.drop_front();
@@ -225,8 +229,8 @@ MemCmpExpansion::LoadEntryVector MemCmpExpansion::computeGreedyLoadSequence(
MemCmpExpansion::LoadEntryVector
MemCmpExpansion::computeOverlappingLoadSequence(
- uint64_t Size, const unsigned MaxLoadSize, const unsigned MaxNumLoads,
- unsigned &NumLoadsNonOneByte) const {
+ uint64_t Size, const unsigned MaxLoadSize,
+ const unsigned MaxNumLoads) const {
// These are already handled by the greedy approach.
if (Size < 2 || MaxLoadSize < 2)
return {};
@@ -263,7 +267,6 @@ MemCmpExpansion::computeOverlappingLoadSequence(
return {};
LoadSequence.push_back({MaxLoadSize, OverlapOffset});
- NumLoadsNonOneByte = 1;
return LoadSequence;
}
@@ -319,11 +322,14 @@ MemCmpExpansion::MemCmpExpansion(
CallInst *const CI, uint64_t Size,
const TargetTransformInfo::MemCmpExpansionOptions &Options,
const bool IsUsedForZeroCmp, const DataLayout &TheDataLayout,
- DomTreeUpdater *DTU, const TargetTransformInfo &TTI, Align CommonAlign)
- : CI(CI), Size(Size), NumLoadsPerBlockForZeroCmp(Options.NumLoadsPerBlock),
- IsUsedForZeroCmp(IsUsedForZeroCmp), DL(TheDataLayout), TTI(TTI),
- CommonAlign(CommonAlign), DTU(DTU), Builder(CI) {
+ DomTreeUpdater *DTU, const TargetTransformInfo &TTI, Align CommonAlign,
+ unsigned MaxBytesPerBlock)
+ : CI(CI), Size(Size), NumLoadsPerBlock(Options.NumLoadsPerBlock),
+ MaxBytesPerBlock(MaxBytesPerBlock), IsUsedForZeroCmp(IsUsedForZeroCmp),
+ DL(TheDataLayout), TTI(TTI), CommonAlign(CommonAlign), DTU(DTU),
+ Builder(CI) {
assert(Size > 0 && "zero blocks");
+ assert(NumLoadsPerBlock > 0 && "zero loads per block");
// Scale the max size down if the target can load more bytes than we need.
llvm::ArrayRef<unsigned> LoadSizes(Options.LoadSizes);
while (!LoadSizes.empty() && LoadSizes.front() > Size) {
@@ -332,34 +338,64 @@ MemCmpExpansion::MemCmpExpansion(
assert(!LoadSizes.empty() && "cannot load Size bytes");
MaxLoadSize = LoadSizes.front();
// Compute the decomposition.
- unsigned GreedyNumLoadsNonOneByte = 0;
- LoadSequence = computeGreedyLoadSequence(Size, LoadSizes, Options.MaxNumLoads,
- GreedyNumLoadsNonOneByte);
- NumLoadsNonOneByte = GreedyNumLoadsNonOneByte;
+ LoadSequence =
+ computeGreedyLoadSequence(Size, LoadSizes, Options.MaxNumLoads);
assert(LoadSequence.size() <= Options.MaxNumLoads && "broken invariant");
// If we allow overlapping loads and the load sequence is not already optimal,
// use overlapping loads.
if (Options.AllowOverlappingLoads &&
(LoadSequence.empty() || LoadSequence.size() > 2)) {
- unsigned OverlappingNumLoadsNonOneByte = 0;
- auto OverlappingLoads = computeOverlappingLoadSequence(
- Size, MaxLoadSize, Options.MaxNumLoads, OverlappingNumLoadsNonOneByte);
+ auto OverlappingLoads =
+ computeOverlappingLoadSequence(Size, MaxLoadSize, Options.MaxNumLoads);
if (!OverlappingLoads.empty() &&
(LoadSequence.empty() ||
OverlappingLoads.size() < LoadSequence.size())) {
LoadSequence = OverlappingLoads;
- NumLoadsNonOneByte = OverlappingNumLoadsNonOneByte;
}
}
assert(LoadSequence.size() <= Options.MaxNumLoads && "broken invariant");
optimiseLoadSequence(LoadSequence, Options, IsUsedForZeroCmp);
+
+ unsigned LoadIndex = 0;
+ while (LoadIndex < getNumLoads()) {
+ unsigned NumLoads = getNumLoadsInBlock(LoadIndex);
+ MaxBlockSize =
+ std::max(MaxBlockSize, getNumBytesInBlock(LoadIndex, NumLoads));
+ LoadIndex += NumLoads;
+ }
+ if (MaxBlockSize)
+ MaxBlockSize = PowerOf2Ceil(MaxBlockSize);
}
-unsigned MemCmpExpansion::getNumBlocks() {
+unsigned MemCmpExpansion::getNumLoadsInBlock(unsigned LoadIndex) const {
if (IsUsedForZeroCmp)
- return getNumLoads() / NumLoadsPerBlockForZeroCmp +
- (getNumLoads() % NumLoadsPerBlockForZeroCmp != 0 ? 1 : 0);
- return getNumLoads();
+ return std::min<uint64_t>(getNumLoads() - LoadIndex, NumLoadsPerBlock);
+
+ unsigned NumLoads = 0;
+ unsigned NumBytes = 0;
+ while (LoadIndex + NumLoads < getNumLoads() && NumLoads < NumLoadsPerBlock &&
+ NumBytes + LoadSequence[LoadIndex + NumLoads].LoadSize <=
+ MaxBytesPerBlock) {
+ NumBytes += LoadSequence[LoadIndex + NumLoads].LoadSize;
+ ++NumLoads;
+ }
+ assert(NumLoads && "at least one load must fit in a block");
+ return NumLoads;
+}
+
+unsigned MemCmpExpansion::getNumBytesInBlock(unsigned LoadIndex,
+ unsigned NumLoads) const {
+ unsigned NumBytes = 0;
+ for (unsigned I = 0; I != NumLoads; ++I)
+ NumBytes += LoadSequence[LoadIndex + I].LoadSize;
+ return NumBytes;
+}
+
+unsigned MemCmpExpansion::getNumBlocks() {
+ unsigned NumBlocks = 0;
+ for (unsigned LoadIndex = 0; LoadIndex < getNumLoads(); ++NumBlocks)
+ LoadIndex += getNumLoadsInBlock(LoadIndex);
+ return NumBlocks;
}
void MemCmpExpansion::createLoadCmpBlocks() {
@@ -470,8 +506,7 @@ Value *MemCmpExpansion::getCompareLoadPairs(unsigned BlockIndex,
std::vector<Value *> XorList, OrList;
Value *Diff = nullptr;
- const unsigned NumLoads =
- std::min(getNumLoads() - LoadIndex, NumLoadsPerBlockForZeroCmp);
+ const unsigned NumLoads = getNumLoadsInBlock(LoadIndex);
// For a single-block expansion, start inserting before the memcmp call.
if (LoadCmpBlocks.empty())
@@ -532,6 +567,51 @@ Value *MemCmpExpansion::getCompareLoadPairs(unsigned BlockIndex,
return Cmp;
}
+MemCmpExpansion::LoadPair
+MemCmpExpansion::getPackedLoadPair(unsigned BlockIndex, unsigned &LoadIndex) {
+ assert(LoadIndex < getNumLoads() &&
+ "getPackedLoadPair() called with no remaining loads");
+ if (LoadCmpBlocks.empty())
+ Builder.SetInsertPoint(CI);
+ else
+ Builder.SetInsertPoint(LoadCmpBlocks[BlockIndex]);
+
+ const unsigned NumLoads = getNumLoadsInBlock(LoadIndex);
+ const unsigned NumBytes = getNumBytesInBlock(LoadIndex, NumLoads);
+ // Pack the loads so that the byte at the lowest address occupies the most
+ // significant bits. An unsigned comparison of the packed values therefore
+ // has the same lexicographic ordering as memcmp.
+ auto *BlockType = IntegerType::get(CI->getContext(), MaxBlockSize * 8);
+ Value *PackedLhs = ConstantInt::get(BlockType, 0);
+ Value *PackedRhs = ConstantInt::get(BlockType, 0);
+ unsigned RemainingBytes = NumBytes;
+
+ for (unsigned I = 0; I != NumLoads; ++I, ++LoadIndex) {
+ const LoadEntry &Entry = LoadSequence[LoadIndex];
+ auto *LoadType = IntegerType::get(CI->getContext(), Entry.LoadSize * 8);
+ auto *BSwapType = DL.isLittleEndian() && Entry.LoadSize != 1
+ ? IntegerType::get(CI->getContext(),
+ PowerOf2Ceil(Entry.LoadSize * 8))
+ : nullptr;
+ LoadPair Loads = getLoadPair(LoadType, BSwapType, BlockType, Entry.Offset);
+
+ if (BSwapType && BSwapType->getIntegerBitWidth() != Entry.LoadSize * 8) {
+ unsigned Padding = BSwapType->getIntegerBitWidth() - Entry.LoadSize * 8;
+ Loads.Lhs = Builder.CreateLShr(Loads.Lhs, Padding);
+ Loads.Rhs = Builder.CreateLShr(Loads.Rhs, Padding);
+ }
+
+ RemainingBytes -= Entry.LoadSize;
+ unsigned Shift = RemainingBytes * 8;
+ PackedLhs =
+ Builder.CreateOr(PackedLhs, Builder.CreateShl(Loads.Lhs, Shift));
+ PackedRhs =
+ Builder.CreateOr(PackedRhs, Builder.CreateShl(Loads.Rhs, Shift));
+ }
+
+ return {PackedLhs, PackedRhs};
+}
+
void MemCmpExpansion::emitLoadCompareBlockMultipleLoads(unsigned BlockIndex,
unsigned &LoadIndex) {
Value *Cmp = getCompareLoadPairs(BlockIndex, LoadIndex);
@@ -567,31 +647,30 @@ void MemCmpExpansion::emitLoadCompareBlockMultipleLoads(unsigned BlockIndex,
// the EndBlock if this is the last LoadCmpBlock. Loading 1 byte is handled with
// a special case through emitLoadCompareByteBlock. The special handling can
// simply subtract the loaded values and add it to the result phi node.
-void MemCmpExpansion::emitLoadCompareBlock(unsigned BlockIndex) {
- // There is one load per block in this case, BlockIndex == LoadIndex.
- const LoadEntry &CurLoadEntry = LoadSequence[BlockIndex];
-
- if (CurLoadEntry.LoadSize == 1) {
- MemCmpExpansion::emitLoadCompareByteBlock(BlockIndex, CurLoadEntry.Offset);
+void MemCmpExpansion::emitLoadCompareBlock(unsigned BlockIndex,
+ unsigned &LoadIndex) {
+ const unsigned NumLoads = getNumLoadsInBlock(LoadIndex);
+ if (NumLoads == 1 && LoadSequence[LoadIndex].LoadSize == 1) {
+ MemCmpExpansion::emitLoadCompareByteBlock(BlockIndex,
+ LoadSequence[LoadIndex].Offset);
+ ++LoadIndex;
return;
}
- Type *LoadSizeType =
- IntegerType::get(CI->getContext(), CurLoadEntry.LoadSize * 8);
- Type *BSwapSizeType =
- DL.isLittleEndian()
- ? IntegerType::get(CI->getContext(),
- PowerOf2Ceil(CurLoadEntry.LoadSize * 8))
- : nullptr;
- Type *MaxLoadType = IntegerType::get(
- CI->getContext(),
- std::max(MaxLoadSize, (unsigned)PowerOf2Ceil(CurLoadEntry.LoadSize)) * 8);
- assert(CurLoadEntry.LoadSize <= MaxLoadSize && "Unexpected load type");
-
- Builder.SetInsertPoint(LoadCmpBlocks[BlockIndex]);
-
- const LoadPair Loads = getLoadPair(LoadSizeType, BSwapSizeType, MaxLoadType,
- CurLoadEntry.Offset);
+ LoadPair Loads;
+ if (NumLoads == 1) {
+ const LoadEntry &Entry = LoadSequence[LoadIndex++];
+ auto *LoadType = IntegerType::get(CI->getContext(), Entry.LoadSize * 8);
+ auto *BSwapType = DL.isLittleEndian()
+ ? IntegerType::get(CI->getContext(),
+ PowerOf2Ceil(Entry.LoadSize * 8))
+ : nullptr;
+ auto *CmpType = IntegerType::get(CI->getContext(), MaxBlockSize * 8);
+ Builder.SetInsertPoint(LoadCmpBlocks[BlockIndex]);
+ Loads = getLoadPair(LoadType, BSwapType, CmpType, Entry.Offset);
+ } else {
+ Loads = getPackedLoadPair(BlockIndex, LoadIndex);
+ }
// Add the loaded values to the phi nodes for calculating memcmp result only
// if result is not used in a zero equality.
@@ -658,13 +737,10 @@ void MemCmpExpansion::emitMemCmpResultBlock() {
}
void MemCmpExpansion::setupResultBlockPHINodes() {
- Type *MaxLoadType = IntegerType::get(CI->getContext(), MaxLoadSize * 8);
+ Type *MaxLoadType = IntegerType::get(CI->getContext(), MaxBlockSize * 8);
Builder.SetInsertPoint(ResBlock.BB);
- // Note: this assumes one load per block.
- ResBlock.PhiSrc1 =
- Builder.CreatePHI(MaxLoadType, NumLoadsNonOneByte, "phi.src1");
- ResBlock.PhiSrc2 =
- Builder.CreatePHI(MaxLoadType, NumLoadsNonOneByte, "phi.src2");
+ ResBlock.PhiSrc1 = Builder.CreatePHI(MaxLoadType, getNumBlocks(), "phi.src1");
+ ResBlock.PhiSrc2 = Builder.CreatePHI(MaxLoadType, getNumBlocks(), "phi.src2");
}
void MemCmpExpansion::setupEndBlockPHINodes() {
@@ -720,6 +796,17 @@ Value *MemCmpExpansion::getMemCmpOneBlock() {
const LoadPair Loads = getLoadPair(LoadSizeType, BSwapSizeType, MaxLoadType,
/*Offset*/ 0);
+ return getMemCmpResult(Loads);
+}
+
+Value *MemCmpExpansion::getMemCmpOneBlockMultipleLoads() {
+ unsigned LoadIndex = 0;
+ LoadPair Loads = getPackedLoadPair(/*BlockIndex=*/0, LoadIndex);
+ assert(LoadIndex == getNumLoads() && "some entries were not consumed");
+ return getMemCmpResult(Loads);
+}
+
+Value *MemCmpExpansion::getMemCmpResult(const LoadPair &Loads) {
// If a user of memcmp cares only about two outcomes, for example:
// bool result = memcmp(a, b, NBYTES) > 0;
// We can generate more optimal code with a smaller number of operations
@@ -801,10 +888,12 @@ Value *MemCmpExpansion::getMemCmpExpansion() {
: getMemCmpExpansionZeroCase();
if (getNumBlocks() == 1)
- return getMemCmpOneBlock();
+ return getNumLoads() == 1 ? getMemCmpOneBlock()
+ : getMemCmpOneBlockMultipleLoads();
+ unsigned LoadIndex = 0;
for (unsigned I = 0; I < getNumBlocks(); ++I) {
- emitLoadCompareBlock(I);
+ emitLoadCompareBlock(I, LoadIndex);
}
emitMemCmpResultBlock();
@@ -914,8 +1003,8 @@ static bool expandMemCmp(CallInst *CI, const TargetTransformInfo *TTI,
IsUsedForZeroCmp);
if (!Options) return false;
- if (MemCmpEqZeroNumLoadsPerBlock.getNumOccurrences())
- Options.NumLoadsPerBlock = MemCmpEqZeroNumLoadsPerBlock;
+ if (MemCmpNumLoadsPerBlock.getNumOccurrences())
+ Options.NumLoadsPerBlock = MemCmpNumLoadsPerBlock;
if (OptForSize &&
MaxLoadsPerMemcmpOptSize.getNumOccurrences())
@@ -935,6 +1024,10 @@ static bool expandMemCmp(CallInst *CI, const TargetTransformInfo *TTI,
// in MemCmpExpansion.
const Align CommonAlign = std::min(getMemCmpArgAlignment(CI, 0, *DL),
getMemCmpArgAlignment(CI, 1, *DL));
+ // Remember the target's preferred load width before filtering inaccessible
+ // sizes. It is also the maximum width of the value formed by packing the
+ // surviving loads in one ordering-compare block.
+ const unsigned MaxBytesPerBlock = Options.LoadSizes.front();
llvm::erase_if(Options.LoadSizes, [&](unsigned LoadSize) {
return !isAccessAllowed(CI, *TTI, CommonAlign, LoadSize, /*Offset=*/0);
});
@@ -946,7 +1039,7 @@ static bool expandMemCmp(CallInst *CI, const TargetTransformInfo *TTI,
return false;
MemCmpExpansion Expansion(CI, SizeVal, Options, IsUsedForZeroCmp, *DL, DTU,
- *TTI, CommonAlign);
+ *TTI, CommonAlign, MaxBytesPerBlock);
// Don't expand if this will require more loads than desired by the target.
if (Expansion.getNumLoads() == 0) {
diff --git a/llvm/test/CodeGen/BPF/memcmp.ll b/llvm/test/CodeGen/BPF/memcmp.ll
index 694d1fb2057ba..50406105aed70 100644
--- a/llvm/test/CodeGen/BPF/memcmp.ll
+++ b/llvm/test/CodeGen/BPF/memcmp.ll
@@ -49,7 +49,7 @@ entry:
; CHECK-DAG: *(u32 *)(r10 - 12)
; CHECK-DAG: *(u32 *)(r1 + 8)
; CHECK-DAG: *(u32 *)(r1 + 12)
-; CHECK-DAG: *(u32 *)(r2 + 16)
+; CHECK-DAG: *(u32 *)(r1 + 16)
; CHECK-DAG: *(u32 *)(r10 - 4)
; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
diff --git a/llvm/test/CodeGen/X86/memcmp-more-load-pairs-x32.ll b/llvm/test/CodeGen/X86/memcmp-more-load-pairs-x32.ll
index ef19991f13c17..477e72ad18f08 100644
--- a/llvm/test/CodeGen/X86/memcmp-more-load-pairs-x32.ll
+++ b/llvm/test/CodeGen/X86/memcmp-more-load-pairs-x32.ll
@@ -144,24 +144,24 @@ define i32 @length3(ptr %X, ptr %Y) nounwind {
; X86-LABEL: length3:
; X86: # %bb.0:
; X86-NEXT: pushl %esi
-; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movzwl (%eax), %edx
-; X86-NEXT: movzwl (%ecx), %esi
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: movzwl (%ecx), %edx
+; X86-NEXT: movzwl (%eax), %esi
; X86-NEXT: rolw $8, %dx
; X86-NEXT: rolw $8, %si
-; X86-NEXT: cmpw %si, %dx
-; X86-NEXT: jne .LBB9_3
-; X86-NEXT: # %bb.1: # %loadbb1
-; X86-NEXT: movzbl 2(%eax), %eax
+; X86-NEXT: movzwl %dx, %edx
+; X86-NEXT: movzwl %si, %esi
+; X86-NEXT: shll $8, %edx
+; X86-NEXT: shll $8, %esi
; X86-NEXT: movzbl 2(%ecx), %ecx
-; X86-NEXT: subl %ecx, %eax
-; X86-NEXT: popl %esi
-; X86-NEXT: retl
-; X86-NEXT: .LBB9_3: # %res_block
-; X86-NEXT: setae %al
-; X86-NEXT: movzbl %al, %eax
-; X86-NEXT: leal -1(%eax,%eax), %eax
+; X86-NEXT: orl %edx, %ecx
+; X86-NEXT: movzbl 2(%eax), %eax
+; X86-NEXT: orl %esi, %eax
+; X86-NEXT: cmpl %eax, %ecx
+; X86-NEXT: seta %al
+; X86-NEXT: sbbb $0, %al
+; X86-NEXT: movsbl %al, %eax
; X86-NEXT: popl %esi
; X86-NEXT: retl
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i32 3) nounwind
diff --git a/llvm/test/CodeGen/X86/memcmp-more-load-pairs.ll b/llvm/test/CodeGen/X86/memcmp-more-load-pairs.ll
index b487e9421caed..e0bc0072b1d79 100644
--- a/llvm/test/CodeGen/X86/memcmp-more-load-pairs.ll
+++ b/llvm/test/CodeGen/X86/memcmp-more-load-pairs.ll
@@ -143,17 +143,18 @@ define i32 @length3(ptr %X, ptr %Y) nounwind {
; X64-NEXT: movzwl (%rsi), %ecx
; X64-NEXT: rolw $8, %ax
; X64-NEXT: rolw $8, %cx
-; X64-NEXT: cmpw %cx, %ax
-; X64-NEXT: jne .LBB9_3
-; X64-NEXT: # %bb.1: # %loadbb1
-; X64-NEXT: movzbl 2(%rdi), %eax
-; X64-NEXT: movzbl 2(%rsi), %ecx
-; X64-NEXT: subl %ecx, %eax
-; X64-NEXT: retq
-; X64-NEXT: .LBB9_3: # %res_block
-; X64-NEXT: setae %al
-; X64-NEXT: movzbl %al, %eax
-; X64-NEXT: leal -1(%rax,%rax), %eax
+; X64-NEXT: movzwl %ax, %eax
+; X64-NEXT: movzwl %cx, %ecx
+; X64-NEXT: shll $8, %eax
+; X64-NEXT: shll $8, %ecx
+; X64-NEXT: movzbl 2(%rdi), %edx
+; X64-NEXT: orl %eax, %edx
+; X64-NEXT: movzbl 2(%rsi), %eax
+; X64-NEXT: orl %ecx, %eax
+; X64-NEXT: cmpl %eax, %edx
+; X64-NEXT: seta %al
+; X64-NEXT: sbbb $0, %al
+; X64-NEXT: movsbl %al, %eax
; X64-NEXT: retq
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 3) nounwind
ret i32 %m
@@ -251,17 +252,16 @@ define i32 @length5(ptr %X, ptr %Y) nounwind {
; X64-NEXT: movl (%rsi), %ecx
; X64-NEXT: bswapl %eax
; X64-NEXT: bswapl %ecx
-; X64-NEXT: cmpl %ecx, %eax
-; X64-NEXT: jne .LBB16_3
-; X64-NEXT: # %bb.1: # %loadbb1
-; X64-NEXT: movzbl 4(%rdi), %eax
-; X64-NEXT: movzbl 4(%rsi), %ecx
-; X64-NEXT: subl %ecx, %eax
-; X64-NEXT: retq
-; X64-NEXT: .LBB16_3: # %res_block
-; X64-NEXT: setae %al
-; X64-NEXT: movzbl %al, %eax
-; X64-NEXT: leal -1(%rax,%rax), %eax
+; X64-NEXT: shlq $8, %rax
+; X64-NEXT: shlq $8, %rcx
+; X64-NEXT: movzbl 4(%rdi), %edx
+; X64-NEXT: orq %rax, %rdx
+; X64-NEXT: movzbl 4(%rsi), %eax
+; X64-NEXT: orq %rcx, %rax
+; X64-NEXT: cmpq %rax, %rdx
+; X64-NEXT: seta %al
+; X64-NEXT: sbbb $0, %al
+; X64-NEXT: movsbl %al, %eax
; X64-NEXT: retq
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 5) nounwind
ret i32 %m
@@ -290,21 +290,14 @@ define i1 @length5_lt(ptr %X, ptr %Y) nounwind {
; X64-NEXT: movl (%rsi), %ecx
; X64-NEXT: bswapl %eax
; X64-NEXT: bswapl %ecx
-; X64-NEXT: cmpl %ecx, %eax
-; X64-NEXT: jne .LBB18_3
-; X64-NEXT: # %bb.1: # %loadbb1
-; X64-NEXT: movzbl 4(%rdi), %eax
-; X64-NEXT: movzbl 4(%rsi), %ecx
-; X64-NEXT: subl %ecx, %eax
-; X64-NEXT: shrl $31, %eax
-; X64-NEXT: # kill: def $al killed $al killed $eax
-; X64-NEXT: retq
-; X64-NEXT: .LBB18_3: # %res_block
-; X64-NEXT: setae %al
-; X64-NEXT: movzbl %al, %eax
-; X64-NEXT: leal -1(%rax,%rax), %eax
-; X64-NEXT: shrl $31, %eax
-; X64-NEXT: # kill: def $al killed $al killed $eax
+; X64-NEXT: shlq $8, %rax
+; X64-NEXT: shlq $8, %rcx
+; X64-NEXT: movzbl 4(%rdi), %edx
+; X64-NEXT: orq %rax, %rdx
+; X64-NEXT: movzbl 4(%rsi), %eax
+; X64-NEXT: orq %rcx, %rax
+; X64-NEXT: cmpq %rax, %rdx
+; X64-NEXT: setb %al
; X64-NEXT: retq
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 5) nounwind
%c = icmp slt i32 %m, 0
@@ -314,26 +307,22 @@ define i1 @length5_lt(ptr %X, ptr %Y) nounwind {
define i32 @length7(ptr %X, ptr %Y) nounwind {
; X64-LABEL: length7:
; X64: # %bb.0:
-; X64-NEXT: movl (%rdi), %ecx
+; X64-NEXT: movl (%rdi), %eax
+; X64-NEXT: movl 3(%rdi), %ecx
+; X64-NEXT: bswapl %eax
; X64-NEXT: movl (%rsi), %edx
-; X64-NEXT: bswapl %ecx
+; X64-NEXT: movl 3(%rsi), %esi
; X64-NEXT: bswapl %edx
-; X64-NEXT: cmpl %edx, %ecx
-; X64-NEXT: jne .LBB19_2
-; X64-NEXT: # %bb.1: # %loadbb1
-; X64-NEXT: movl 3(%rdi), %ecx
-; X64-NEXT: movl 3(%rsi), %edx
+; X64-NEXT: shlq $32, %rax
+; X64-NEXT: shlq $32, %rdx
; X64-NEXT: bswapl %ecx
-; X64-NEXT: bswapl %edx
-; X64-NEXT: xorl %eax, %eax
-; X64-NEXT: cmpl %edx, %ecx
-; X64-NEXT: je .LBB19_3
-; X64-NEXT: .LBB19_2: # %res_block
-; X64-NEXT: xorl %eax, %eax
-; X64-NEXT: cmpl %edx, %ecx
-; X64-NEXT: setae %al
-; X64-NEXT: leal -1(%rax,%rax), %eax
-; X64-NEXT: .LBB19_3: # %endblock
+; X64-NEXT: bswapl %esi
+; X64-NEXT: orq %rax, %rcx
+; X64-NEXT: orq %rdx, %rsi
+; X64-NEXT: cmpq %rsi, %rcx
+; X64-NEXT: seta %al
+; X64-NEXT: sbbb $0, %al
+; X64-NEXT: movsbl %al, %eax
; X64-NEXT: retq
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 7) nounwind
ret i32 %m
@@ -357,28 +346,20 @@ define i1 @length7_eq(ptr %X, ptr %Y) nounwind {
define i1 @length7_lt(ptr %X, ptr %Y) nounwind {
; X64-LABEL: length7_lt:
; X64: # %bb.0:
-; X64-NEXT: movl (%rdi), %ecx
+; X64-NEXT: movl (%rdi), %eax
+; X64-NEXT: movl 3(%rdi), %ecx
+; X64-NEXT: bswapl %eax
; X64-NEXT: movl (%rsi), %edx
-; X64-NEXT: bswapl %ecx
+; X64-NEXT: movl 3(%rsi), %esi
; X64-NEXT: bswapl %edx
-; X64-NEXT: cmpl %edx, %ecx
-; X64-NEXT: jne .LBB21_2
-; X64-NEXT: # %bb.1: # %loadbb1
-; X64-NEXT: movl 3(%rdi), %ecx
-; X64-NEXT: movl 3(%rsi), %edx
+; X64-NEXT: shlq $32, %rax
+; X64-NEXT: shlq $32, %rdx
; X64-NEXT: bswapl %ecx
-; X64-NEXT: bswapl %edx
-; X64-NEXT: xorl %eax, %eax
-; X64-NEXT: cmpl %edx, %ecx
-; X64-NEXT: je .LBB21_3
-; X64-NEXT: .LBB21_2: # %res_block
-; X64-NEXT: xorl %eax, %eax
-; X64-NEXT: cmpl %edx, %ecx
-; X64-NEXT: setae %al
-; X64-NEXT: leal -1(%rax,%rax), %eax
-; X64-NEXT: .LBB21_3: # %endblock
-; X64-NEXT: shrl $31, %eax
-; X64-NEXT: # kill: def $al killed $al killed $eax
+; X64-NEXT: bswapl %esi
+; X64-NEXT: orq %rax, %rcx
+; X64-NEXT: orq %rdx, %rsi
+; X64-NEXT: cmpq %rsi, %rcx
+; X64-NEXT: setb %al
; X64-NEXT: retq
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 7) nounwind
%c = icmp slt i32 %m, 0
diff --git a/llvm/test/Transforms/ExpandMemCmp/BPF/memcmp.ll b/llvm/test/Transforms/ExpandMemCmp/BPF/memcmp.ll
index f182dcc1b7f75..03bd2ac37cb40 100644
--- a/llvm/test/Transforms/ExpandMemCmp/BPF/memcmp.ll
+++ b/llvm/test/Transforms/ExpandMemCmp/BPF/memcmp.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -passes=expand-memcmp -mtriple=bpf -memcmp-num-loads-per-block=1 < %s | FileCheck %s
+; RUN: opt -S -passes=expand-memcmp -mtriple=bpf < %s | FileCheck %s
; BPF cannot perform wide misaligned loads, so the alignment filter reduces an
; align-1 comparison to byte loads. Grouping eight load pairs in each block
@@ -15,326 +15,327 @@ define i32 @memcmp_size_32_align_1(ptr %a, ptr %b) {
; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
; CHECK-NEXT: br label %[[LOADBB:.*]]
; CHECK: [[RES_BLOCK:.*]]:
+; CHECK-NEXT: [[PHI_SRC1:%.*]] = phi i64 [ [[TMP75:%.*]], %[[LOADBB]] ], [ [[TMP155:%.*]], %[[LOADBB8:.*]] ], [ [[TMP229:%.*]], %[[LOADBB16:.*]] ], [ [[TMP306:%.*]], %[[LOADBB24:.*]] ]
+; CHECK-NEXT: [[PHI_SRC2:%.*]] = phi i64 [ [[TMP76:%.*]], %[[LOADBB]] ], [ [[TMP156:%.*]], %[[LOADBB8]] ], [ [[TMP230:%.*]], %[[LOADBB16]] ], [ [[TMP307:%.*]], %[[LOADBB24]] ]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[PHI_SRC1]], [[PHI_SRC2]]
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i32 -1, i32 1
; CHECK-NEXT: br label %[[ENDBLOCK:.*]]
; CHECK: [[LOADBB]]:
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[B]], align 1
-; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[TMP1]] to i32
-; CHECK-NEXT: [[TMP4:%.*]] = zext i8 [[TMP2]] to i32
-; CHECK-NEXT: [[TMP5:%.*]] = sub i32 [[TMP3]], [[TMP4]]
-; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
-; CHECK-NEXT: br i1 [[TMP6]], label %[[ENDBLOCK]], label %[[LOADBB1:.*]]
-; CHECK: [[LOADBB1]]:
+; CHECK-NEXT: [[TMP5:%.*]] = zext i8 [[TMP1]] to i64
+; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP2]] to i64
+; CHECK-NEXT: [[TMP11:%.*]] = shl i64 [[TMP5]], 56
+; CHECK-NEXT: [[TMP12:%.*]] = shl i64 [[TMP6]], 56
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[A]], i64 1
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[B]], i64 1
; CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[TMP7]], align 1
; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP8]], align 1
-; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP9]] to i32
-; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP10]] to i32
-; CHECK-NEXT: [[TMP13:%.*]] = sub i32 [[TMP11]], [[TMP12]]
-; CHECK-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
-; CHECK-NEXT: br i1 [[TMP14]], label %[[ENDBLOCK]], label %[[LOADBB2:.*]]
-; CHECK: [[LOADBB2]]:
+; CHECK-NEXT: [[TMP13:%.*]] = zext i8 [[TMP9]] to i64
+; CHECK-NEXT: [[TMP14:%.*]] = zext i8 [[TMP10]] to i64
+; CHECK-NEXT: [[TMP19:%.*]] = shl i64 [[TMP13]], 48
+; CHECK-NEXT: [[TMP20:%.*]] = or i64 [[TMP11]], [[TMP19]]
+; CHECK-NEXT: [[TMP21:%.*]] = shl i64 [[TMP14]], 48
+; CHECK-NEXT: [[TMP22:%.*]] = or i64 [[TMP12]], [[TMP21]]
; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[A]], i64 2
; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[B]], i64 2
; CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[TMP15]], align 1
; CHECK-NEXT: [[TMP18:%.*]] = load i8, ptr [[TMP16]], align 1
-; CHECK-NEXT: [[TMP19:%.*]] = zext i8 [[TMP17]] to i32
-; CHECK-NEXT: [[TMP20:%.*]] = zext i8 [[TMP18]] to i32
-; CHECK-NEXT: [[TMP21:%.*]] = sub i32 [[TMP19]], [[TMP20]]
-; CHECK-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
-; CHECK-NEXT: br i1 [[TMP22]], label %[[ENDBLOCK]], label %[[LOADBB3:.*]]
-; CHECK: [[LOADBB3]]:
+; CHECK-NEXT: [[TMP29:%.*]] = zext i8 [[TMP17]] to i64
+; CHECK-NEXT: [[TMP30:%.*]] = zext i8 [[TMP18]] to i64
+; CHECK-NEXT: [[TMP51:%.*]] = shl i64 [[TMP29]], 40
+; CHECK-NEXT: [[TMP52:%.*]] = or i64 [[TMP20]], [[TMP51]]
+; CHECK-NEXT: [[TMP27:%.*]] = shl i64 [[TMP30]], 40
+; CHECK-NEXT: [[TMP28:%.*]] = or i64 [[TMP22]], [[TMP27]]
; CHECK-NEXT: [[TMP23:%.*]] = getelementptr i8, ptr [[A]], i64 3
; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[B]], i64 3
; CHECK-NEXT: [[TMP25:%.*]] = load i8, ptr [[TMP23]], align 1
; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP24]], align 1
-; CHECK-NEXT: [[TMP27:%.*]] = zext i8 [[TMP25]] to i32
-; CHECK-NEXT: [[TMP28:%.*]] = zext i8 [[TMP26]] to i32
-; CHECK-NEXT: [[TMP29:%.*]] = sub i32 [[TMP27]], [[TMP28]]
-; CHECK-NEXT: [[TMP30:%.*]] = icmp ne i32 [[TMP29]], 0
-; CHECK-NEXT: br i1 [[TMP30]], label %[[ENDBLOCK]], label %[[LOADBB4:.*]]
-; CHECK: [[LOADBB4]]:
+; CHECK-NEXT: [[TMP59:%.*]] = zext i8 [[TMP25]] to i64
+; CHECK-NEXT: [[TMP60:%.*]] = zext i8 [[TMP26]] to i64
+; CHECK-NEXT: [[TMP35:%.*]] = shl i64 [[TMP59]], 32
+; CHECK-NEXT: [[TMP36:%.*]] = or i64 [[TMP52]], [[TMP35]]
+; CHECK-NEXT: [[TMP37:%.*]] = shl i64 [[TMP60]], 32
+; CHECK-NEXT: [[TMP38:%.*]] = or i64 [[TMP28]], [[TMP37]]
; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i8, ptr [[A]], i64 4
; CHECK-NEXT: [[TMP32:%.*]] = getelementptr i8, ptr [[B]], i64 4
; CHECK-NEXT: [[TMP33:%.*]] = load i8, ptr [[TMP31]], align 1
; CHECK-NEXT: [[TMP34:%.*]] = load i8, ptr [[TMP32]], align 1
-; CHECK-NEXT: [[TMP35:%.*]] = zext i8 [[TMP33]] to i32
-; CHECK-NEXT: [[TMP36:%.*]] = zext i8 [[TMP34]] to i32
-; CHECK-NEXT: [[TMP37:%.*]] = sub i32 [[TMP35]], [[TMP36]]
-; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i32 [[TMP37]], 0
-; CHECK-NEXT: br i1 [[TMP38]], label %[[ENDBLOCK]], label %[[LOADBB5:.*]]
-; CHECK: [[LOADBB5]]:
+; CHECK-NEXT: [[TMP43:%.*]] = zext i8 [[TMP33]] to i64
+; CHECK-NEXT: [[TMP44:%.*]] = zext i8 [[TMP34]] to i64
+; CHECK-NEXT: [[TMP45:%.*]] = shl i64 [[TMP43]], 24
+; CHECK-NEXT: [[TMP46:%.*]] = or i64 [[TMP36]], [[TMP45]]
+; CHECK-NEXT: [[TMP61:%.*]] = shl i64 [[TMP44]], 24
+; CHECK-NEXT: [[TMP62:%.*]] = or i64 [[TMP38]], [[TMP61]]
; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[A]], i64 5
; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i8, ptr [[B]], i64 5
; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[TMP39]], align 1
; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[TMP40]], align 1
-; CHECK-NEXT: [[TMP43:%.*]] = zext i8 [[TMP41]] to i32
-; CHECK-NEXT: [[TMP44:%.*]] = zext i8 [[TMP42]] to i32
-; CHECK-NEXT: [[TMP45:%.*]] = sub i32 [[TMP43]], [[TMP44]]
-; CHECK-NEXT: [[TMP46:%.*]] = icmp ne i32 [[TMP45]], 0
-; CHECK-NEXT: br i1 [[TMP46]], label %[[ENDBLOCK]], label %[[LOADBB6:.*]]
-; CHECK: [[LOADBB6]]:
+; CHECK-NEXT: [[TMP53:%.*]] = zext i8 [[TMP41]] to i64
+; CHECK-NEXT: [[TMP54:%.*]] = zext i8 [[TMP42]] to i64
+; CHECK-NEXT: [[TMP69:%.*]] = shl i64 [[TMP53]], 16
+; CHECK-NEXT: [[TMP70:%.*]] = or i64 [[TMP46]], [[TMP69]]
+; CHECK-NEXT: [[TMP78:%.*]] = shl i64 [[TMP54]], 16
+; CHECK-NEXT: [[TMP86:%.*]] = or i64 [[TMP62]], [[TMP78]]
; CHECK-NEXT: [[TMP47:%.*]] = getelementptr i8, ptr [[A]], i64 6
; CHECK-NEXT: [[TMP48:%.*]] = getelementptr i8, ptr [[B]], i64 6
; CHECK-NEXT: [[TMP49:%.*]] = load i8, ptr [[TMP47]], align 1
; CHECK-NEXT: [[TMP50:%.*]] = load i8, ptr [[TMP48]], align 1
-; CHECK-NEXT: [[TMP51:%.*]] = zext i8 [[TMP49]] to i32
-; CHECK-NEXT: [[TMP52:%.*]] = zext i8 [[TMP50]] to i32
-; CHECK-NEXT: [[TMP53:%.*]] = sub i32 [[TMP51]], [[TMP52]]
-; CHECK-NEXT: [[TMP54:%.*]] = icmp ne i32 [[TMP53]], 0
-; CHECK-NEXT: br i1 [[TMP54]], label %[[ENDBLOCK]], label %[[LOADBB7:.*]]
-; CHECK: [[LOADBB7]]:
+; CHECK-NEXT: [[TMP99:%.*]] = zext i8 [[TMP49]] to i64
+; CHECK-NEXT: [[TMP107:%.*]] = zext i8 [[TMP50]] to i64
+; CHECK-NEXT: [[TMP108:%.*]] = shl i64 [[TMP99]], 8
+; CHECK-NEXT: [[TMP109:%.*]] = or i64 [[TMP70]], [[TMP108]]
+; CHECK-NEXT: [[TMP67:%.*]] = shl i64 [[TMP107]], 8
+; CHECK-NEXT: [[TMP68:%.*]] = or i64 [[TMP86]], [[TMP67]]
; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[A]], i64 7
; CHECK-NEXT: [[TMP56:%.*]] = getelementptr i8, ptr [[B]], i64 7
; CHECK-NEXT: [[TMP57:%.*]] = load i8, ptr [[TMP55]], align 1
; CHECK-NEXT: [[TMP58:%.*]] = load i8, ptr [[TMP56]], align 1
-; CHECK-NEXT: [[TMP59:%.*]] = zext i8 [[TMP57]] to i32
-; CHECK-NEXT: [[TMP60:%.*]] = zext i8 [[TMP58]] to i32
-; CHECK-NEXT: [[TMP61:%.*]] = sub i32 [[TMP59]], [[TMP60]]
-; CHECK-NEXT: [[TMP62:%.*]] = icmp ne i32 [[TMP61]], 0
-; CHECK-NEXT: br i1 [[TMP62]], label %[[ENDBLOCK]], label %[[LOADBB8:.*]]
+; CHECK-NEXT: [[TMP116:%.*]] = zext i8 [[TMP57]] to i64
+; CHECK-NEXT: [[TMP117:%.*]] = zext i8 [[TMP58]] to i64
+; CHECK-NEXT: [[TMP75]] = or i64 [[TMP109]], [[TMP116]]
+; CHECK-NEXT: [[TMP76]] = or i64 [[TMP68]], [[TMP117]]
+; CHECK-NEXT: [[TMP77:%.*]] = icmp eq i64 [[TMP75]], [[TMP76]]
+; CHECK-NEXT: br i1 [[TMP77]], label %[[LOADBB8]], label %[[RES_BLOCK]]
; CHECK: [[LOADBB8]]:
; CHECK-NEXT: [[TMP63:%.*]] = getelementptr i8, ptr [[A]], i64 8
; CHECK-NEXT: [[TMP64:%.*]] = getelementptr i8, ptr [[B]], i64 8
; CHECK-NEXT: [[TMP65:%.*]] = load i8, ptr [[TMP63]], align 1
; CHECK-NEXT: [[TMP66:%.*]] = load i8, ptr [[TMP64]], align 1
-; CHECK-NEXT: [[TMP67:%.*]] = zext i8 [[TMP65]] to i32
-; CHECK-NEXT: [[TMP68:%.*]] = zext i8 [[TMP66]] to i32
-; CHECK-NEXT: [[TMP69:%.*]] = sub i32 [[TMP67]], [[TMP68]]
-; CHECK-NEXT: [[TMP70:%.*]] = icmp ne i32 [[TMP69]], 0
-; CHECK-NEXT: br i1 [[TMP70]], label %[[ENDBLOCK]], label %[[LOADBB9:.*]]
-; CHECK: [[LOADBB9]]:
+; CHECK-NEXT: [[TMP118:%.*]] = zext i8 [[TMP65]] to i64
+; CHECK-NEXT: [[TMP83:%.*]] = zext i8 [[TMP66]] to i64
+; CHECK-NEXT: [[TMP84:%.*]] = shl i64 [[TMP118]], 56
+; CHECK-NEXT: [[TMP85:%.*]] = shl i64 [[TMP83]], 56
; CHECK-NEXT: [[TMP71:%.*]] = getelementptr i8, ptr [[A]], i64 9
; CHECK-NEXT: [[TMP72:%.*]] = getelementptr i8, ptr [[B]], i64 9
; CHECK-NEXT: [[TMP73:%.*]] = load i8, ptr [[TMP71]], align 1
; CHECK-NEXT: [[TMP74:%.*]] = load i8, ptr [[TMP72]], align 1
-; CHECK-NEXT: [[TMP75:%.*]] = zext i8 [[TMP73]] to i32
-; CHECK-NEXT: [[TMP76:%.*]] = zext i8 [[TMP74]] to i32
-; CHECK-NEXT: [[TMP77:%.*]] = sub i32 [[TMP75]], [[TMP76]]
-; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i32 [[TMP77]], 0
-; CHECK-NEXT: br i1 [[TMP78]], label %[[ENDBLOCK]], label %[[LOADBB10:.*]]
-; CHECK: [[LOADBB10]]:
+; CHECK-NEXT: [[TMP126:%.*]] = zext i8 [[TMP73]] to i64
+; CHECK-NEXT: [[TMP91:%.*]] = zext i8 [[TMP74]] to i64
+; CHECK-NEXT: [[TMP92:%.*]] = shl i64 [[TMP126]], 48
+; CHECK-NEXT: [[TMP93:%.*]] = or i64 [[TMP84]], [[TMP92]]
+; CHECK-NEXT: [[TMP94:%.*]] = shl i64 [[TMP91]], 48
+; CHECK-NEXT: [[TMP139:%.*]] = or i64 [[TMP85]], [[TMP94]]
; CHECK-NEXT: [[TMP79:%.*]] = getelementptr i8, ptr [[A]], i64 10
; CHECK-NEXT: [[TMP80:%.*]] = getelementptr i8, ptr [[B]], i64 10
; CHECK-NEXT: [[TMP81:%.*]] = load i8, ptr [[TMP79]], align 1
; CHECK-NEXT: [[TMP82:%.*]] = load i8, ptr [[TMP80]], align 1
-; CHECK-NEXT: [[TMP83:%.*]] = zext i8 [[TMP81]] to i32
-; CHECK-NEXT: [[TMP84:%.*]] = zext i8 [[TMP82]] to i32
-; CHECK-NEXT: [[TMP85:%.*]] = sub i32 [[TMP83]], [[TMP84]]
-; CHECK-NEXT: [[TMP86:%.*]] = icmp ne i32 [[TMP85]], 0
-; CHECK-NEXT: br i1 [[TMP86]], label %[[ENDBLOCK]], label %[[LOADBB11:.*]]
-; CHECK: [[LOADBB11]]:
+; CHECK-NEXT: [[TMP100:%.*]] = zext i8 [[TMP81]] to i64
+; CHECK-NEXT: [[TMP101:%.*]] = zext i8 [[TMP82]] to i64
+; CHECK-NEXT: [[TMP102:%.*]] = shl i64 [[TMP100]], 40
+; CHECK-NEXT: [[TMP147:%.*]] = or i64 [[TMP93]], [[TMP102]]
+; CHECK-NEXT: [[TMP148:%.*]] = shl i64 [[TMP101]], 40
+; CHECK-NEXT: [[TMP149:%.*]] = or i64 [[TMP139]], [[TMP148]]
; CHECK-NEXT: [[TMP87:%.*]] = getelementptr i8, ptr [[A]], i64 11
; CHECK-NEXT: [[TMP88:%.*]] = getelementptr i8, ptr [[B]], i64 11
; CHECK-NEXT: [[TMP89:%.*]] = load i8, ptr [[TMP87]], align 1
; CHECK-NEXT: [[TMP90:%.*]] = load i8, ptr [[TMP88]], align 1
-; CHECK-NEXT: [[TMP91:%.*]] = zext i8 [[TMP89]] to i32
-; CHECK-NEXT: [[TMP92:%.*]] = zext i8 [[TMP90]] to i32
-; CHECK-NEXT: [[TMP93:%.*]] = sub i32 [[TMP91]], [[TMP92]]
-; CHECK-NEXT: [[TMP94:%.*]] = icmp ne i32 [[TMP93]], 0
-; CHECK-NEXT: br i1 [[TMP94]], label %[[ENDBLOCK]], label %[[LOADBB12:.*]]
-; CHECK: [[LOADBB12]]:
+; CHECK-NEXT: [[TMP110:%.*]] = zext i8 [[TMP89]] to i64
+; CHECK-NEXT: [[TMP157:%.*]] = zext i8 [[TMP90]] to i64
+; CHECK-NEXT: [[TMP158:%.*]] = shl i64 [[TMP110]], 32
+; CHECK-NEXT: [[TMP163:%.*]] = or i64 [[TMP147]], [[TMP158]]
+; CHECK-NEXT: [[TMP164:%.*]] = shl i64 [[TMP157]], 32
+; CHECK-NEXT: [[TMP115:%.*]] = or i64 [[TMP149]], [[TMP164]]
; CHECK-NEXT: [[TMP95:%.*]] = getelementptr i8, ptr [[A]], i64 12
; CHECK-NEXT: [[TMP96:%.*]] = getelementptr i8, ptr [[B]], i64 12
; CHECK-NEXT: [[TMP97:%.*]] = load i8, ptr [[TMP95]], align 1
; CHECK-NEXT: [[TMP98:%.*]] = load i8, ptr [[TMP96]], align 1
-; CHECK-NEXT: [[TMP99:%.*]] = zext i8 [[TMP97]] to i32
-; CHECK-NEXT: [[TMP100:%.*]] = zext i8 [[TMP98]] to i32
-; CHECK-NEXT: [[TMP101:%.*]] = sub i32 [[TMP99]], [[TMP100]]
-; CHECK-NEXT: [[TMP102:%.*]] = icmp ne i32 [[TMP101]], 0
-; CHECK-NEXT: br i1 [[TMP102]], label %[[ENDBLOCK]], label %[[LOADBB13:.*]]
-; CHECK: [[LOADBB13]]:
+; CHECK-NEXT: [[TMP165:%.*]] = zext i8 [[TMP97]] to i64
+; CHECK-NEXT: [[TMP166:%.*]] = zext i8 [[TMP98]] to i64
+; CHECK-NEXT: [[TMP173:%.*]] = shl i64 [[TMP165]], 24
+; CHECK-NEXT: [[TMP123:%.*]] = or i64 [[TMP163]], [[TMP173]]
+; CHECK-NEXT: [[TMP124:%.*]] = shl i64 [[TMP166]], 24
+; CHECK-NEXT: [[TMP125:%.*]] = or i64 [[TMP115]], [[TMP124]]
; CHECK-NEXT: [[TMP103:%.*]] = getelementptr i8, ptr [[A]], i64 13
; CHECK-NEXT: [[TMP104:%.*]] = getelementptr i8, ptr [[B]], i64 13
; CHECK-NEXT: [[TMP105:%.*]] = load i8, ptr [[TMP103]], align 1
; CHECK-NEXT: [[TMP106:%.*]] = load i8, ptr [[TMP104]], align 1
-; CHECK-NEXT: [[TMP107:%.*]] = zext i8 [[TMP105]] to i32
-; CHECK-NEXT: [[TMP108:%.*]] = zext i8 [[TMP106]] to i32
-; CHECK-NEXT: [[TMP109:%.*]] = sub i32 [[TMP107]], [[TMP108]]
-; CHECK-NEXT: [[TMP110:%.*]] = icmp ne i32 [[TMP109]], 0
-; CHECK-NEXT: br i1 [[TMP110]], label %[[ENDBLOCK]], label %[[LOADBB14:.*]]
-; CHECK: [[LOADBB14]]:
+; CHECK-NEXT: [[TMP174:%.*]] = zext i8 [[TMP105]] to i64
+; CHECK-NEXT: [[TMP131:%.*]] = zext i8 [[TMP106]] to i64
+; CHECK-NEXT: [[TMP132:%.*]] = shl i64 [[TMP174]], 16
+; CHECK-NEXT: [[TMP133:%.*]] = or i64 [[TMP123]], [[TMP132]]
+; CHECK-NEXT: [[TMP134:%.*]] = shl i64 [[TMP131]], 16
+; CHECK-NEXT: [[TMP195:%.*]] = or i64 [[TMP125]], [[TMP134]]
; CHECK-NEXT: [[TMP111:%.*]] = getelementptr i8, ptr [[A]], i64 14
; CHECK-NEXT: [[TMP112:%.*]] = getelementptr i8, ptr [[B]], i64 14
; CHECK-NEXT: [[TMP113:%.*]] = load i8, ptr [[TMP111]], align 1
; CHECK-NEXT: [[TMP114:%.*]] = load i8, ptr [[TMP112]], align 1
-; CHECK-NEXT: [[TMP115:%.*]] = zext i8 [[TMP113]] to i32
-; CHECK-NEXT: [[TMP116:%.*]] = zext i8 [[TMP114]] to i32
-; CHECK-NEXT: [[TMP117:%.*]] = sub i32 [[TMP115]], [[TMP116]]
-; CHECK-NEXT: [[TMP118:%.*]] = icmp ne i32 [[TMP117]], 0
-; CHECK-NEXT: br i1 [[TMP118]], label %[[ENDBLOCK]], label %[[LOADBB15:.*]]
-; CHECK: [[LOADBB15]]:
+; CHECK-NEXT: [[TMP140:%.*]] = zext i8 [[TMP113]] to i64
+; CHECK-NEXT: [[TMP141:%.*]] = zext i8 [[TMP114]] to i64
+; CHECK-NEXT: [[TMP142:%.*]] = shl i64 [[TMP140]], 8
+; CHECK-NEXT: [[TMP196:%.*]] = or i64 [[TMP133]], [[TMP142]]
+; CHECK-NEXT: [[TMP203:%.*]] = shl i64 [[TMP141]], 8
+; CHECK-NEXT: [[TMP204:%.*]] = or i64 [[TMP195]], [[TMP203]]
; CHECK-NEXT: [[TMP119:%.*]] = getelementptr i8, ptr [[A]], i64 15
; CHECK-NEXT: [[TMP120:%.*]] = getelementptr i8, ptr [[B]], i64 15
; CHECK-NEXT: [[TMP121:%.*]] = load i8, ptr [[TMP119]], align 1
; CHECK-NEXT: [[TMP122:%.*]] = load i8, ptr [[TMP120]], align 1
-; CHECK-NEXT: [[TMP123:%.*]] = zext i8 [[TMP121]] to i32
-; CHECK-NEXT: [[TMP124:%.*]] = zext i8 [[TMP122]] to i32
-; CHECK-NEXT: [[TMP125:%.*]] = sub i32 [[TMP123]], [[TMP124]]
-; CHECK-NEXT: [[TMP126:%.*]] = icmp ne i32 [[TMP125]], 0
-; CHECK-NEXT: br i1 [[TMP126]], label %[[ENDBLOCK]], label %[[LOADBB16:.*]]
+; CHECK-NEXT: [[TMP150:%.*]] = zext i8 [[TMP121]] to i64
+; CHECK-NEXT: [[TMP205:%.*]] = zext i8 [[TMP122]] to i64
+; CHECK-NEXT: [[TMP155]] = or i64 [[TMP196]], [[TMP150]]
+; CHECK-NEXT: [[TMP156]] = or i64 [[TMP204]], [[TMP205]]
+; CHECK-NEXT: [[TMP206:%.*]] = icmp eq i64 [[TMP155]], [[TMP156]]
+; CHECK-NEXT: br i1 [[TMP206]], label %[[LOADBB16]], label %[[RES_BLOCK]]
; CHECK: [[LOADBB16]]:
; CHECK-NEXT: [[TMP127:%.*]] = getelementptr i8, ptr [[A]], i64 16
; CHECK-NEXT: [[TMP128:%.*]] = getelementptr i8, ptr [[B]], i64 16
; CHECK-NEXT: [[TMP129:%.*]] = load i8, ptr [[TMP127]], align 1
; CHECK-NEXT: [[TMP130:%.*]] = load i8, ptr [[TMP128]], align 1
-; CHECK-NEXT: [[TMP131:%.*]] = zext i8 [[TMP129]] to i32
-; CHECK-NEXT: [[TMP132:%.*]] = zext i8 [[TMP130]] to i32
-; CHECK-NEXT: [[TMP133:%.*]] = sub i32 [[TMP131]], [[TMP132]]
-; CHECK-NEXT: [[TMP134:%.*]] = icmp ne i32 [[TMP133]], 0
-; CHECK-NEXT: br i1 [[TMP134]], label %[[ENDBLOCK]], label %[[LOADBB17:.*]]
-; CHECK: [[LOADBB17]]:
+; CHECK-NEXT: [[TMP213:%.*]] = zext i8 [[TMP129]] to i64
+; CHECK-NEXT: [[TMP214:%.*]] = zext i8 [[TMP130]] to i64
+; CHECK-NEXT: [[TMP235:%.*]] = shl i64 [[TMP213]], 56
+; CHECK-NEXT: [[TMP243:%.*]] = shl i64 [[TMP214]], 56
; CHECK-NEXT: [[TMP135:%.*]] = getelementptr i8, ptr [[A]], i64 17
; CHECK-NEXT: [[TMP136:%.*]] = getelementptr i8, ptr [[B]], i64 17
; CHECK-NEXT: [[TMP137:%.*]] = load i8, ptr [[TMP135]], align 1
; CHECK-NEXT: [[TMP138:%.*]] = load i8, ptr [[TMP136]], align 1
-; CHECK-NEXT: [[TMP139:%.*]] = zext i8 [[TMP137]] to i32
-; CHECK-NEXT: [[TMP140:%.*]] = zext i8 [[TMP138]] to i32
-; CHECK-NEXT: [[TMP141:%.*]] = sub i32 [[TMP139]], [[TMP140]]
-; CHECK-NEXT: [[TMP142:%.*]] = icmp ne i32 [[TMP141]], 0
-; CHECK-NEXT: br i1 [[TMP142]], label %[[ENDBLOCK]], label %[[LOADBB18:.*]]
-; CHECK: [[LOADBB18]]:
+; CHECK-NEXT: [[TMP251:%.*]] = zext i8 [[TMP137]] to i64
+; CHECK-NEXT: [[TMP252:%.*]] = zext i8 [[TMP138]] to i64
+; CHECK-NEXT: [[TMP253:%.*]] = shl i64 [[TMP251]], 48
+; CHECK-NEXT: [[TMP260:%.*]] = or i64 [[TMP235]], [[TMP253]]
+; CHECK-NEXT: [[TMP171:%.*]] = shl i64 [[TMP252]], 48
+; CHECK-NEXT: [[TMP172:%.*]] = or i64 [[TMP243]], [[TMP171]]
; CHECK-NEXT: [[TMP143:%.*]] = getelementptr i8, ptr [[A]], i64 18
; CHECK-NEXT: [[TMP144:%.*]] = getelementptr i8, ptr [[B]], i64 18
; CHECK-NEXT: [[TMP145:%.*]] = load i8, ptr [[TMP143]], align 1
; CHECK-NEXT: [[TMP146:%.*]] = load i8, ptr [[TMP144]], align 1
-; CHECK-NEXT: [[TMP147:%.*]] = zext i8 [[TMP145]] to i32
-; CHECK-NEXT: [[TMP148:%.*]] = zext i8 [[TMP146]] to i32
-; CHECK-NEXT: [[TMP149:%.*]] = sub i32 [[TMP147]], [[TMP148]]
-; CHECK-NEXT: [[TMP150:%.*]] = icmp ne i32 [[TMP149]], 0
-; CHECK-NEXT: br i1 [[TMP150]], label %[[ENDBLOCK]], label %[[LOADBB19:.*]]
-; CHECK: [[LOADBB19]]:
+; CHECK-NEXT: [[TMP261:%.*]] = zext i8 [[TMP145]] to i64
+; CHECK-NEXT: [[TMP262:%.*]] = zext i8 [[TMP146]] to i64
+; CHECK-NEXT: [[TMP179:%.*]] = shl i64 [[TMP261]], 40
+; CHECK-NEXT: [[TMP180:%.*]] = or i64 [[TMP260]], [[TMP179]]
+; CHECK-NEXT: [[TMP181:%.*]] = shl i64 [[TMP262]], 40
+; CHECK-NEXT: [[TMP182:%.*]] = or i64 [[TMP172]], [[TMP181]]
; CHECK-NEXT: [[TMP151:%.*]] = getelementptr i8, ptr [[A]], i64 19
; CHECK-NEXT: [[TMP152:%.*]] = getelementptr i8, ptr [[B]], i64 19
; CHECK-NEXT: [[TMP153:%.*]] = load i8, ptr [[TMP151]], align 1
; CHECK-NEXT: [[TMP154:%.*]] = load i8, ptr [[TMP152]], align 1
-; CHECK-NEXT: [[TMP155:%.*]] = zext i8 [[TMP153]] to i32
-; CHECK-NEXT: [[TMP156:%.*]] = zext i8 [[TMP154]] to i32
-; CHECK-NEXT: [[TMP157:%.*]] = sub i32 [[TMP155]], [[TMP156]]
-; CHECK-NEXT: [[TMP158:%.*]] = icmp ne i32 [[TMP157]], 0
-; CHECK-NEXT: br i1 [[TMP158]], label %[[ENDBLOCK]], label %[[LOADBB20:.*]]
-; CHECK: [[LOADBB20]]:
+; CHECK-NEXT: [[TMP187:%.*]] = zext i8 [[TMP153]] to i64
+; CHECK-NEXT: [[TMP188:%.*]] = zext i8 [[TMP154]] to i64
+; CHECK-NEXT: [[TMP189:%.*]] = shl i64 [[TMP187]], 32
+; CHECK-NEXT: [[TMP190:%.*]] = or i64 [[TMP180]], [[TMP189]]
+; CHECK-NEXT: [[TMP263:%.*]] = shl i64 [[TMP188]], 32
+; CHECK-NEXT: [[TMP270:%.*]] = or i64 [[TMP182]], [[TMP263]]
; CHECK-NEXT: [[TMP159:%.*]] = getelementptr i8, ptr [[A]], i64 20
; CHECK-NEXT: [[TMP160:%.*]] = getelementptr i8, ptr [[B]], i64 20
; CHECK-NEXT: [[TMP161:%.*]] = load i8, ptr [[TMP159]], align 1
; CHECK-NEXT: [[TMP162:%.*]] = load i8, ptr [[TMP160]], align 1
-; CHECK-NEXT: [[TMP163:%.*]] = zext i8 [[TMP161]] to i32
-; CHECK-NEXT: [[TMP164:%.*]] = zext i8 [[TMP162]] to i32
-; CHECK-NEXT: [[TMP165:%.*]] = sub i32 [[TMP163]], [[TMP164]]
-; CHECK-NEXT: [[TMP166:%.*]] = icmp ne i32 [[TMP165]], 0
-; CHECK-NEXT: br i1 [[TMP166]], label %[[ENDBLOCK]], label %[[LOADBB21:.*]]
-; CHECK: [[LOADBB21]]:
+; CHECK-NEXT: [[TMP197:%.*]] = zext i8 [[TMP161]] to i64
+; CHECK-NEXT: [[TMP198:%.*]] = zext i8 [[TMP162]] to i64
+; CHECK-NEXT: [[TMP271:%.*]] = shl i64 [[TMP197]], 24
+; CHECK-NEXT: [[TMP272:%.*]] = or i64 [[TMP190]], [[TMP271]]
+; CHECK-NEXT: [[TMP273:%.*]] = shl i64 [[TMP198]], 24
+; CHECK-NEXT: [[TMP280:%.*]] = or i64 [[TMP270]], [[TMP273]]
; CHECK-NEXT: [[TMP167:%.*]] = getelementptr i8, ptr [[A]], i64 21
; CHECK-NEXT: [[TMP168:%.*]] = getelementptr i8, ptr [[B]], i64 21
; CHECK-NEXT: [[TMP169:%.*]] = load i8, ptr [[TMP167]], align 1
; CHECK-NEXT: [[TMP170:%.*]] = load i8, ptr [[TMP168]], align 1
-; CHECK-NEXT: [[TMP171:%.*]] = zext i8 [[TMP169]] to i32
-; CHECK-NEXT: [[TMP172:%.*]] = zext i8 [[TMP170]] to i32
-; CHECK-NEXT: [[TMP173:%.*]] = sub i32 [[TMP171]], [[TMP172]]
-; CHECK-NEXT: [[TMP174:%.*]] = icmp ne i32 [[TMP173]], 0
-; CHECK-NEXT: br i1 [[TMP174]], label %[[ENDBLOCK]], label %[[LOADBB22:.*]]
-; CHECK: [[LOADBB22]]:
+; CHECK-NEXT: [[TMP281:%.*]] = zext i8 [[TMP169]] to i64
+; CHECK-NEXT: [[TMP282:%.*]] = zext i8 [[TMP170]] to i64
+; CHECK-NEXT: [[TMP283:%.*]] = shl i64 [[TMP281]], 16
+; CHECK-NEXT: [[TMP290:%.*]] = or i64 [[TMP272]], [[TMP283]]
+; CHECK-NEXT: [[TMP211:%.*]] = shl i64 [[TMP282]], 16
+; CHECK-NEXT: [[TMP212:%.*]] = or i64 [[TMP280]], [[TMP211]]
; CHECK-NEXT: [[TMP175:%.*]] = getelementptr i8, ptr [[A]], i64 22
; CHECK-NEXT: [[TMP176:%.*]] = getelementptr i8, ptr [[B]], i64 22
; CHECK-NEXT: [[TMP177:%.*]] = load i8, ptr [[TMP175]], align 1
; CHECK-NEXT: [[TMP178:%.*]] = load i8, ptr [[TMP176]], align 1
-; CHECK-NEXT: [[TMP179:%.*]] = zext i8 [[TMP177]] to i32
-; CHECK-NEXT: [[TMP180:%.*]] = zext i8 [[TMP178]] to i32
-; CHECK-NEXT: [[TMP181:%.*]] = sub i32 [[TMP179]], [[TMP180]]
-; CHECK-NEXT: [[TMP182:%.*]] = icmp ne i32 [[TMP181]], 0
-; CHECK-NEXT: br i1 [[TMP182]], label %[[ENDBLOCK]], label %[[LOADBB23:.*]]
-; CHECK: [[LOADBB23]]:
+; CHECK-NEXT: [[TMP291:%.*]] = zext i8 [[TMP177]] to i64
+; CHECK-NEXT: [[TMP292:%.*]] = zext i8 [[TMP178]] to i64
+; CHECK-NEXT: [[TMP219:%.*]] = shl i64 [[TMP291]], 8
+; CHECK-NEXT: [[TMP220:%.*]] = or i64 [[TMP290]], [[TMP219]]
+; CHECK-NEXT: [[TMP221:%.*]] = shl i64 [[TMP292]], 8
+; CHECK-NEXT: [[TMP222:%.*]] = or i64 [[TMP212]], [[TMP221]]
; CHECK-NEXT: [[TMP183:%.*]] = getelementptr i8, ptr [[A]], i64 23
; CHECK-NEXT: [[TMP184:%.*]] = getelementptr i8, ptr [[B]], i64 23
; CHECK-NEXT: [[TMP185:%.*]] = load i8, ptr [[TMP183]], align 1
; CHECK-NEXT: [[TMP186:%.*]] = load i8, ptr [[TMP184]], align 1
-; CHECK-NEXT: [[TMP187:%.*]] = zext i8 [[TMP185]] to i32
-; CHECK-NEXT: [[TMP188:%.*]] = zext i8 [[TMP186]] to i32
-; CHECK-NEXT: [[TMP189:%.*]] = sub i32 [[TMP187]], [[TMP188]]
-; CHECK-NEXT: [[TMP190:%.*]] = icmp ne i32 [[TMP189]], 0
-; CHECK-NEXT: br i1 [[TMP190]], label %[[ENDBLOCK]], label %[[LOADBB24:.*]]
+; CHECK-NEXT: [[TMP227:%.*]] = zext i8 [[TMP185]] to i64
+; CHECK-NEXT: [[TMP228:%.*]] = zext i8 [[TMP186]] to i64
+; CHECK-NEXT: [[TMP229]] = or i64 [[TMP220]], [[TMP227]]
+; CHECK-NEXT: [[TMP230]] = or i64 [[TMP222]], [[TMP228]]
+; CHECK-NEXT: [[TMP293:%.*]] = icmp eq i64 [[TMP229]], [[TMP230]]
+; CHECK-NEXT: br i1 [[TMP293]], label %[[LOADBB24]], label %[[RES_BLOCK]]
; CHECK: [[LOADBB24]]:
; CHECK-NEXT: [[TMP191:%.*]] = getelementptr i8, ptr [[A]], i64 24
; CHECK-NEXT: [[TMP192:%.*]] = getelementptr i8, ptr [[B]], i64 24
; CHECK-NEXT: [[TMP193:%.*]] = load i8, ptr [[TMP191]], align 1
; CHECK-NEXT: [[TMP194:%.*]] = load i8, ptr [[TMP192]], align 1
-; CHECK-NEXT: [[TMP195:%.*]] = zext i8 [[TMP193]] to i32
-; CHECK-NEXT: [[TMP196:%.*]] = zext i8 [[TMP194]] to i32
-; CHECK-NEXT: [[TMP197:%.*]] = sub i32 [[TMP195]], [[TMP196]]
-; CHECK-NEXT: [[TMP198:%.*]] = icmp ne i32 [[TMP197]], 0
-; CHECK-NEXT: br i1 [[TMP198]], label %[[ENDBLOCK]], label %[[LOADBB25:.*]]
-; CHECK: [[LOADBB25]]:
+; CHECK-NEXT: [[TMP236:%.*]] = zext i8 [[TMP193]] to i64
+; CHECK-NEXT: [[TMP237:%.*]] = zext i8 [[TMP194]] to i64
+; CHECK-NEXT: [[TMP238:%.*]] = shl i64 [[TMP236]], 56
+; CHECK-NEXT: [[TMP300:%.*]] = shl i64 [[TMP237]], 56
; CHECK-NEXT: [[TMP199:%.*]] = getelementptr i8, ptr [[A]], i64 25
; CHECK-NEXT: [[TMP200:%.*]] = getelementptr i8, ptr [[B]], i64 25
; CHECK-NEXT: [[TMP201:%.*]] = load i8, ptr [[TMP199]], align 1
; CHECK-NEXT: [[TMP202:%.*]] = load i8, ptr [[TMP200]], align 1
-; CHECK-NEXT: [[TMP203:%.*]] = zext i8 [[TMP201]] to i32
-; CHECK-NEXT: [[TMP204:%.*]] = zext i8 [[TMP202]] to i32
-; CHECK-NEXT: [[TMP205:%.*]] = sub i32 [[TMP203]], [[TMP204]]
-; CHECK-NEXT: [[TMP206:%.*]] = icmp ne i32 [[TMP205]], 0
-; CHECK-NEXT: br i1 [[TMP206]], label %[[ENDBLOCK]], label %[[LOADBB26:.*]]
-; CHECK: [[LOADBB26]]:
+; CHECK-NEXT: [[TMP244:%.*]] = zext i8 [[TMP201]] to i64
+; CHECK-NEXT: [[TMP245:%.*]] = zext i8 [[TMP202]] to i64
+; CHECK-NEXT: [[TMP246:%.*]] = shl i64 [[TMP244]], 48
+; CHECK-NEXT: [[TMP301:%.*]] = or i64 [[TMP238]], [[TMP246]]
+; CHECK-NEXT: [[TMP302:%.*]] = shl i64 [[TMP245]], 48
+; CHECK-NEXT: [[TMP303:%.*]] = or i64 [[TMP300]], [[TMP302]]
; CHECK-NEXT: [[TMP207:%.*]] = getelementptr i8, ptr [[A]], i64 26
; CHECK-NEXT: [[TMP208:%.*]] = getelementptr i8, ptr [[B]], i64 26
; CHECK-NEXT: [[TMP209:%.*]] = load i8, ptr [[TMP207]], align 1
; CHECK-NEXT: [[TMP210:%.*]] = load i8, ptr [[TMP208]], align 1
-; CHECK-NEXT: [[TMP211:%.*]] = zext i8 [[TMP209]] to i32
-; CHECK-NEXT: [[TMP212:%.*]] = zext i8 [[TMP210]] to i32
-; CHECK-NEXT: [[TMP213:%.*]] = sub i32 [[TMP211]], [[TMP212]]
-; CHECK-NEXT: [[TMP214:%.*]] = icmp ne i32 [[TMP213]], 0
-; CHECK-NEXT: br i1 [[TMP214]], label %[[ENDBLOCK]], label %[[LOADBB27:.*]]
-; CHECK: [[LOADBB27]]:
+; CHECK-NEXT: [[TMP254:%.*]] = zext i8 [[TMP209]] to i64
+; CHECK-NEXT: [[TMP255:%.*]] = zext i8 [[TMP210]] to i64
+; CHECK-NEXT: [[TMP256:%.*]] = shl i64 [[TMP254]], 40
+; CHECK-NEXT: [[TMP257:%.*]] = or i64 [[TMP301]], [[TMP256]]
+; CHECK-NEXT: [[TMP258:%.*]] = shl i64 [[TMP255]], 40
+; CHECK-NEXT: [[TMP259:%.*]] = or i64 [[TMP303]], [[TMP258]]
; CHECK-NEXT: [[TMP215:%.*]] = getelementptr i8, ptr [[A]], i64 27
; CHECK-NEXT: [[TMP216:%.*]] = getelementptr i8, ptr [[B]], i64 27
; CHECK-NEXT: [[TMP217:%.*]] = load i8, ptr [[TMP215]], align 1
; CHECK-NEXT: [[TMP218:%.*]] = load i8, ptr [[TMP216]], align 1
-; CHECK-NEXT: [[TMP219:%.*]] = zext i8 [[TMP217]] to i32
-; CHECK-NEXT: [[TMP220:%.*]] = zext i8 [[TMP218]] to i32
-; CHECK-NEXT: [[TMP221:%.*]] = sub i32 [[TMP219]], [[TMP220]]
-; CHECK-NEXT: [[TMP222:%.*]] = icmp ne i32 [[TMP221]], 0
-; CHECK-NEXT: br i1 [[TMP222]], label %[[ENDBLOCK]], label %[[LOADBB28:.*]]
-; CHECK: [[LOADBB28]]:
+; CHECK-NEXT: [[TMP264:%.*]] = zext i8 [[TMP217]] to i64
+; CHECK-NEXT: [[TMP265:%.*]] = zext i8 [[TMP218]] to i64
+; CHECK-NEXT: [[TMP266:%.*]] = shl i64 [[TMP264]], 32
+; CHECK-NEXT: [[TMP267:%.*]] = or i64 [[TMP257]], [[TMP266]]
+; CHECK-NEXT: [[TMP268:%.*]] = shl i64 [[TMP265]], 32
+; CHECK-NEXT: [[TMP269:%.*]] = or i64 [[TMP259]], [[TMP268]]
; CHECK-NEXT: [[TMP223:%.*]] = getelementptr i8, ptr [[A]], i64 28
; CHECK-NEXT: [[TMP224:%.*]] = getelementptr i8, ptr [[B]], i64 28
; CHECK-NEXT: [[TMP225:%.*]] = load i8, ptr [[TMP223]], align 1
; CHECK-NEXT: [[TMP226:%.*]] = load i8, ptr [[TMP224]], align 1
-; CHECK-NEXT: [[TMP227:%.*]] = zext i8 [[TMP225]] to i32
-; CHECK-NEXT: [[TMP228:%.*]] = zext i8 [[TMP226]] to i32
-; CHECK-NEXT: [[TMP229:%.*]] = sub i32 [[TMP227]], [[TMP228]]
-; CHECK-NEXT: [[TMP230:%.*]] = icmp ne i32 [[TMP229]], 0
-; CHECK-NEXT: br i1 [[TMP230]], label %[[ENDBLOCK]], label %[[LOADBB29:.*]]
-; CHECK: [[LOADBB29]]:
+; CHECK-NEXT: [[TMP274:%.*]] = zext i8 [[TMP225]] to i64
+; CHECK-NEXT: [[TMP275:%.*]] = zext i8 [[TMP226]] to i64
+; CHECK-NEXT: [[TMP276:%.*]] = shl i64 [[TMP274]], 24
+; CHECK-NEXT: [[TMP277:%.*]] = or i64 [[TMP267]], [[TMP276]]
+; CHECK-NEXT: [[TMP278:%.*]] = shl i64 [[TMP275]], 24
+; CHECK-NEXT: [[TMP279:%.*]] = or i64 [[TMP269]], [[TMP278]]
; CHECK-NEXT: [[TMP231:%.*]] = getelementptr i8, ptr [[A]], i64 29
; CHECK-NEXT: [[TMP232:%.*]] = getelementptr i8, ptr [[B]], i64 29
; CHECK-NEXT: [[TMP233:%.*]] = load i8, ptr [[TMP231]], align 1
; CHECK-NEXT: [[TMP234:%.*]] = load i8, ptr [[TMP232]], align 1
-; CHECK-NEXT: [[TMP235:%.*]] = zext i8 [[TMP233]] to i32
-; CHECK-NEXT: [[TMP236:%.*]] = zext i8 [[TMP234]] to i32
-; CHECK-NEXT: [[TMP237:%.*]] = sub i32 [[TMP235]], [[TMP236]]
-; CHECK-NEXT: [[TMP238:%.*]] = icmp ne i32 [[TMP237]], 0
-; CHECK-NEXT: br i1 [[TMP238]], label %[[ENDBLOCK]], label %[[LOADBB30:.*]]
-; CHECK: [[LOADBB30]]:
+; CHECK-NEXT: [[TMP284:%.*]] = zext i8 [[TMP233]] to i64
+; CHECK-NEXT: [[TMP285:%.*]] = zext i8 [[TMP234]] to i64
+; CHECK-NEXT: [[TMP286:%.*]] = shl i64 [[TMP284]], 16
+; CHECK-NEXT: [[TMP287:%.*]] = or i64 [[TMP277]], [[TMP286]]
+; CHECK-NEXT: [[TMP288:%.*]] = shl i64 [[TMP285]], 16
+; CHECK-NEXT: [[TMP289:%.*]] = or i64 [[TMP279]], [[TMP288]]
; CHECK-NEXT: [[TMP239:%.*]] = getelementptr i8, ptr [[A]], i64 30
; CHECK-NEXT: [[TMP240:%.*]] = getelementptr i8, ptr [[B]], i64 30
; CHECK-NEXT: [[TMP241:%.*]] = load i8, ptr [[TMP239]], align 1
; CHECK-NEXT: [[TMP242:%.*]] = load i8, ptr [[TMP240]], align 1
-; CHECK-NEXT: [[TMP243:%.*]] = zext i8 [[TMP241]] to i32
-; CHECK-NEXT: [[TMP244:%.*]] = zext i8 [[TMP242]] to i32
-; CHECK-NEXT: [[TMP245:%.*]] = sub i32 [[TMP243]], [[TMP244]]
-; CHECK-NEXT: [[TMP246:%.*]] = icmp ne i32 [[TMP245]], 0
-; CHECK-NEXT: br i1 [[TMP246]], label %[[ENDBLOCK]], label %[[LOADBB31:.*]]
-; CHECK: [[LOADBB31]]:
+; CHECK-NEXT: [[TMP294:%.*]] = zext i8 [[TMP241]] to i64
+; CHECK-NEXT: [[TMP295:%.*]] = zext i8 [[TMP242]] to i64
+; CHECK-NEXT: [[TMP296:%.*]] = shl i64 [[TMP294]], 8
+; CHECK-NEXT: [[TMP297:%.*]] = or i64 [[TMP287]], [[TMP296]]
+; CHECK-NEXT: [[TMP298:%.*]] = shl i64 [[TMP295]], 8
+; CHECK-NEXT: [[TMP299:%.*]] = or i64 [[TMP289]], [[TMP298]]
; CHECK-NEXT: [[TMP247:%.*]] = getelementptr i8, ptr [[A]], i64 31
; CHECK-NEXT: [[TMP248:%.*]] = getelementptr i8, ptr [[B]], i64 31
; CHECK-NEXT: [[TMP249:%.*]] = load i8, ptr [[TMP247]], align 1
; CHECK-NEXT: [[TMP250:%.*]] = load i8, ptr [[TMP248]], align 1
-; CHECK-NEXT: [[TMP251:%.*]] = zext i8 [[TMP249]] to i32
-; CHECK-NEXT: [[TMP252:%.*]] = zext i8 [[TMP250]] to i32
-; CHECK-NEXT: [[TMP253:%.*]] = sub i32 [[TMP251]], [[TMP252]]
-; CHECK-NEXT: br label %[[ENDBLOCK]]
+; CHECK-NEXT: [[TMP304:%.*]] = zext i8 [[TMP249]] to i64
+; CHECK-NEXT: [[TMP305:%.*]] = zext i8 [[TMP250]] to i64
+; CHECK-NEXT: [[TMP306]] = or i64 [[TMP297]], [[TMP304]]
+; CHECK-NEXT: [[TMP307]] = or i64 [[TMP299]], [[TMP305]]
+; CHECK-NEXT: [[TMP308:%.*]] = icmp eq i64 [[TMP306]], [[TMP307]]
+; CHECK-NEXT: br i1 [[TMP308]], label %[[ENDBLOCK]], label %[[RES_BLOCK]]
; CHECK: [[ENDBLOCK]]:
-; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ [[TMP5]], %[[LOADBB]] ], [ [[TMP13]], %[[LOADBB1]] ], [ [[TMP21]], %[[LOADBB2]] ], [ [[TMP29]], %[[LOADBB3]] ], [ [[TMP37]], %[[LOADBB4]] ], [ [[TMP45]], %[[LOADBB5]] ], [ [[TMP53]], %[[LOADBB6]] ], [ [[TMP61]], %[[LOADBB7]] ], [ [[TMP69]], %[[LOADBB8]] ], [ [[TMP77]], %[[LOADBB9]] ], [ [[TMP85]], %[[LOADBB10]] ], [ [[TMP93]], %[[LOADBB11]] ], [ [[TMP101]], %[[LOADBB12]] ], [ [[TMP109]], %[[LOADBB13]] ], [ [[TMP117]], %[[LOADBB14]] ], [ [[TMP125]], %[[LOADBB15]] ], [ [[TMP133]], %[[LOADBB16]] ], [ [[TMP141]], %[[LOADBB17]] ], [ [[TMP149]], %[[LOADBB18]] ], [ [[TMP157]], %[[LOADBB19]] ], [ [[TMP165]], %[[LOADBB20]] ], [ [[TMP173]], %[[LOADBB21]] ], [ [[TMP181]], %[[LOADBB22]] ], [ [[TMP189]], %[[LOADBB23]] ], [ [[TMP197]], %[[LOADBB24]] ], [ [[TMP205]], %[[LOADBB25]] ], [ [[TMP213]], %[[LOADBB26]] ], [ [[TMP221]], %[[LOADBB27]] ], [ [[TMP229]], %[[LOADBB28]] ], [ [[TMP237]], %[[LOADBB29]] ], [ [[TMP245]], %[[LOADBB30]] ], [ [[TMP253]], %[[LOADBB31]] ], [ poison, %[[RES_BLOCK]] ]
+; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, %[[LOADBB24]] ], [ [[TMP4]], %[[RES_BLOCK]] ]
; CHECK-NEXT: ret i32 [[PHI_RES]]
;
%call = call i32 @memcmp(ptr %a, ptr %b, i64 32)
@@ -347,116 +348,119 @@ define i32 @memcmp_size_11_align_1(ptr %a, ptr %b) {
; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
; CHECK-NEXT: br label %[[LOADBB:.*]]
; CHECK: [[RES_BLOCK:.*]]:
+; CHECK-NEXT: [[PHI_SRC1:%.*]] = phi i64 [ [[TMP75:%.*]], %[[LOADBB]] ], [ [[TMP102:%.*]], %[[LOADBB8:.*]] ]
+; CHECK-NEXT: [[PHI_SRC2:%.*]] = phi i64 [ [[TMP76:%.*]], %[[LOADBB]] ], [ [[TMP103:%.*]], %[[LOADBB8]] ]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[PHI_SRC1]], [[PHI_SRC2]]
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i32 -1, i32 1
; CHECK-NEXT: br label %[[ENDBLOCK:.*]]
; CHECK: [[LOADBB]]:
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[B]], align 1
-; CHECK-NEXT: [[TMP3:%.*]] = zext i8 [[TMP1]] to i32
-; CHECK-NEXT: [[TMP4:%.*]] = zext i8 [[TMP2]] to i32
-; CHECK-NEXT: [[TMP5:%.*]] = sub i32 [[TMP3]], [[TMP4]]
-; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
-; CHECK-NEXT: br i1 [[TMP6]], label %[[ENDBLOCK]], label %[[LOADBB1:.*]]
-; CHECK: [[LOADBB1]]:
+; CHECK-NEXT: [[TMP5:%.*]] = zext i8 [[TMP1]] to i64
+; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP2]] to i64
+; CHECK-NEXT: [[TMP11:%.*]] = shl i64 [[TMP5]], 56
+; CHECK-NEXT: [[TMP12:%.*]] = shl i64 [[TMP6]], 56
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[A]], i64 1
; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[B]], i64 1
; CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[TMP7]], align 1
; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP8]], align 1
-; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP9]] to i32
-; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP10]] to i32
-; CHECK-NEXT: [[TMP13:%.*]] = sub i32 [[TMP11]], [[TMP12]]
-; CHECK-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
-; CHECK-NEXT: br i1 [[TMP14]], label %[[ENDBLOCK]], label %[[LOADBB2:.*]]
-; CHECK: [[LOADBB2]]:
+; CHECK-NEXT: [[TMP13:%.*]] = zext i8 [[TMP9]] to i64
+; CHECK-NEXT: [[TMP14:%.*]] = zext i8 [[TMP10]] to i64
+; CHECK-NEXT: [[TMP19:%.*]] = shl i64 [[TMP13]], 48
+; CHECK-NEXT: [[TMP20:%.*]] = or i64 [[TMP11]], [[TMP19]]
+; CHECK-NEXT: [[TMP21:%.*]] = shl i64 [[TMP14]], 48
+; CHECK-NEXT: [[TMP22:%.*]] = or i64 [[TMP12]], [[TMP21]]
; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[A]], i64 2
; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[B]], i64 2
; CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[TMP15]], align 1
; CHECK-NEXT: [[TMP18:%.*]] = load i8, ptr [[TMP16]], align 1
-; CHECK-NEXT: [[TMP19:%.*]] = zext i8 [[TMP17]] to i32
-; CHECK-NEXT: [[TMP20:%.*]] = zext i8 [[TMP18]] to i32
-; CHECK-NEXT: [[TMP21:%.*]] = sub i32 [[TMP19]], [[TMP20]]
-; CHECK-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
-; CHECK-NEXT: br i1 [[TMP22]], label %[[ENDBLOCK]], label %[[LOADBB3:.*]]
-; CHECK: [[LOADBB3]]:
+; CHECK-NEXT: [[TMP29:%.*]] = zext i8 [[TMP17]] to i64
+; CHECK-NEXT: [[TMP30:%.*]] = zext i8 [[TMP18]] to i64
+; CHECK-NEXT: [[TMP51:%.*]] = shl i64 [[TMP29]], 40
+; CHECK-NEXT: [[TMP52:%.*]] = or i64 [[TMP20]], [[TMP51]]
+; CHECK-NEXT: [[TMP27:%.*]] = shl i64 [[TMP30]], 40
+; CHECK-NEXT: [[TMP28:%.*]] = or i64 [[TMP22]], [[TMP27]]
; CHECK-NEXT: [[TMP23:%.*]] = getelementptr i8, ptr [[A]], i64 3
; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[B]], i64 3
; CHECK-NEXT: [[TMP25:%.*]] = load i8, ptr [[TMP23]], align 1
; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP24]], align 1
-; CHECK-NEXT: [[TMP27:%.*]] = zext i8 [[TMP25]] to i32
-; CHECK-NEXT: [[TMP28:%.*]] = zext i8 [[TMP26]] to i32
-; CHECK-NEXT: [[TMP29:%.*]] = sub i32 [[TMP27]], [[TMP28]]
-; CHECK-NEXT: [[TMP30:%.*]] = icmp ne i32 [[TMP29]], 0
-; CHECK-NEXT: br i1 [[TMP30]], label %[[ENDBLOCK]], label %[[LOADBB4:.*]]
-; CHECK: [[LOADBB4]]:
+; CHECK-NEXT: [[TMP59:%.*]] = zext i8 [[TMP25]] to i64
+; CHECK-NEXT: [[TMP60:%.*]] = zext i8 [[TMP26]] to i64
+; CHECK-NEXT: [[TMP35:%.*]] = shl i64 [[TMP59]], 32
+; CHECK-NEXT: [[TMP36:%.*]] = or i64 [[TMP52]], [[TMP35]]
+; CHECK-NEXT: [[TMP37:%.*]] = shl i64 [[TMP60]], 32
+; CHECK-NEXT: [[TMP38:%.*]] = or i64 [[TMP28]], [[TMP37]]
; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i8, ptr [[A]], i64 4
; CHECK-NEXT: [[TMP32:%.*]] = getelementptr i8, ptr [[B]], i64 4
; CHECK-NEXT: [[TMP33:%.*]] = load i8, ptr [[TMP31]], align 1
; CHECK-NEXT: [[TMP34:%.*]] = load i8, ptr [[TMP32]], align 1
-; CHECK-NEXT: [[TMP35:%.*]] = zext i8 [[TMP33]] to i32
-; CHECK-NEXT: [[TMP36:%.*]] = zext i8 [[TMP34]] to i32
-; CHECK-NEXT: [[TMP37:%.*]] = sub i32 [[TMP35]], [[TMP36]]
-; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i32 [[TMP37]], 0
-; CHECK-NEXT: br i1 [[TMP38]], label %[[ENDBLOCK]], label %[[LOADBB5:.*]]
-; CHECK: [[LOADBB5]]:
+; CHECK-NEXT: [[TMP43:%.*]] = zext i8 [[TMP33]] to i64
+; CHECK-NEXT: [[TMP44:%.*]] = zext i8 [[TMP34]] to i64
+; CHECK-NEXT: [[TMP45:%.*]] = shl i64 [[TMP43]], 24
+; CHECK-NEXT: [[TMP46:%.*]] = or i64 [[TMP36]], [[TMP45]]
+; CHECK-NEXT: [[TMP61:%.*]] = shl i64 [[TMP44]], 24
+; CHECK-NEXT: [[TMP62:%.*]] = or i64 [[TMP38]], [[TMP61]]
; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[A]], i64 5
; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i8, ptr [[B]], i64 5
; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[TMP39]], align 1
; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[TMP40]], align 1
-; CHECK-NEXT: [[TMP43:%.*]] = zext i8 [[TMP41]] to i32
-; CHECK-NEXT: [[TMP44:%.*]] = zext i8 [[TMP42]] to i32
-; CHECK-NEXT: [[TMP45:%.*]] = sub i32 [[TMP43]], [[TMP44]]
-; CHECK-NEXT: [[TMP46:%.*]] = icmp ne i32 [[TMP45]], 0
-; CHECK-NEXT: br i1 [[TMP46]], label %[[ENDBLOCK]], label %[[LOADBB6:.*]]
-; CHECK: [[LOADBB6]]:
+; CHECK-NEXT: [[TMP53:%.*]] = zext i8 [[TMP41]] to i64
+; CHECK-NEXT: [[TMP54:%.*]] = zext i8 [[TMP42]] to i64
+; CHECK-NEXT: [[TMP69:%.*]] = shl i64 [[TMP53]], 16
+; CHECK-NEXT: [[TMP70:%.*]] = or i64 [[TMP46]], [[TMP69]]
+; CHECK-NEXT: [[TMP78:%.*]] = shl i64 [[TMP54]], 16
+; CHECK-NEXT: [[TMP86:%.*]] = or i64 [[TMP62]], [[TMP78]]
; CHECK-NEXT: [[TMP47:%.*]] = getelementptr i8, ptr [[A]], i64 6
; CHECK-NEXT: [[TMP48:%.*]] = getelementptr i8, ptr [[B]], i64 6
; CHECK-NEXT: [[TMP49:%.*]] = load i8, ptr [[TMP47]], align 1
; CHECK-NEXT: [[TMP50:%.*]] = load i8, ptr [[TMP48]], align 1
-; CHECK-NEXT: [[TMP51:%.*]] = zext i8 [[TMP49]] to i32
-; CHECK-NEXT: [[TMP52:%.*]] = zext i8 [[TMP50]] to i32
-; CHECK-NEXT: [[TMP53:%.*]] = sub i32 [[TMP51]], [[TMP52]]
-; CHECK-NEXT: [[TMP54:%.*]] = icmp ne i32 [[TMP53]], 0
-; CHECK-NEXT: br i1 [[TMP54]], label %[[ENDBLOCK]], label %[[LOADBB7:.*]]
-; CHECK: [[LOADBB7]]:
+; CHECK-NEXT: [[TMP87:%.*]] = zext i8 [[TMP49]] to i64
+; CHECK-NEXT: [[TMP88:%.*]] = zext i8 [[TMP50]] to i64
+; CHECK-NEXT: [[TMP89:%.*]] = shl i64 [[TMP87]], 8
+; CHECK-NEXT: [[TMP96:%.*]] = or i64 [[TMP70]], [[TMP89]]
+; CHECK-NEXT: [[TMP67:%.*]] = shl i64 [[TMP88]], 8
+; CHECK-NEXT: [[TMP68:%.*]] = or i64 [[TMP86]], [[TMP67]]
; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[A]], i64 7
; CHECK-NEXT: [[TMP56:%.*]] = getelementptr i8, ptr [[B]], i64 7
; CHECK-NEXT: [[TMP57:%.*]] = load i8, ptr [[TMP55]], align 1
; CHECK-NEXT: [[TMP58:%.*]] = load i8, ptr [[TMP56]], align 1
-; CHECK-NEXT: [[TMP59:%.*]] = zext i8 [[TMP57]] to i32
-; CHECK-NEXT: [[TMP60:%.*]] = zext i8 [[TMP58]] to i32
-; CHECK-NEXT: [[TMP61:%.*]] = sub i32 [[TMP59]], [[TMP60]]
-; CHECK-NEXT: [[TMP62:%.*]] = icmp ne i32 [[TMP61]], 0
-; CHECK-NEXT: br i1 [[TMP62]], label %[[ENDBLOCK]], label %[[LOADBB8:.*]]
+; CHECK-NEXT: [[TMP97:%.*]] = zext i8 [[TMP57]] to i64
+; CHECK-NEXT: [[TMP98:%.*]] = zext i8 [[TMP58]] to i64
+; CHECK-NEXT: [[TMP75]] = or i64 [[TMP96]], [[TMP97]]
+; CHECK-NEXT: [[TMP76]] = or i64 [[TMP68]], [[TMP98]]
+; CHECK-NEXT: [[TMP77:%.*]] = icmp eq i64 [[TMP75]], [[TMP76]]
+; CHECK-NEXT: br i1 [[TMP77]], label %[[LOADBB8]], label %[[RES_BLOCK]]
; CHECK: [[LOADBB8]]:
; CHECK-NEXT: [[TMP63:%.*]] = getelementptr i8, ptr [[A]], i64 8
; CHECK-NEXT: [[TMP64:%.*]] = getelementptr i8, ptr [[B]], i64 8
; CHECK-NEXT: [[TMP65:%.*]] = load i8, ptr [[TMP63]], align 1
; CHECK-NEXT: [[TMP66:%.*]] = load i8, ptr [[TMP64]], align 1
-; CHECK-NEXT: [[TMP67:%.*]] = zext i8 [[TMP65]] to i32
-; CHECK-NEXT: [[TMP68:%.*]] = zext i8 [[TMP66]] to i32
-; CHECK-NEXT: [[TMP69:%.*]] = sub i32 [[TMP67]], [[TMP68]]
-; CHECK-NEXT: [[TMP70:%.*]] = icmp ne i32 [[TMP69]], 0
-; CHECK-NEXT: br i1 [[TMP70]], label %[[ENDBLOCK]], label %[[LOADBB9:.*]]
-; CHECK: [[LOADBB9]]:
+; CHECK-NEXT: [[TMP99:%.*]] = zext i8 [[TMP65]] to i64
+; CHECK-NEXT: [[TMP83:%.*]] = zext i8 [[TMP66]] to i64
+; CHECK-NEXT: [[TMP84:%.*]] = shl i64 [[TMP99]], 16
+; CHECK-NEXT: [[TMP85:%.*]] = shl i64 [[TMP83]], 16
; CHECK-NEXT: [[TMP71:%.*]] = getelementptr i8, ptr [[A]], i64 9
; CHECK-NEXT: [[TMP72:%.*]] = getelementptr i8, ptr [[B]], i64 9
; CHECK-NEXT: [[TMP73:%.*]] = load i8, ptr [[TMP71]], align 1
; CHECK-NEXT: [[TMP74:%.*]] = load i8, ptr [[TMP72]], align 1
-; CHECK-NEXT: [[TMP75:%.*]] = zext i8 [[TMP73]] to i32
-; CHECK-NEXT: [[TMP76:%.*]] = zext i8 [[TMP74]] to i32
-; CHECK-NEXT: [[TMP77:%.*]] = sub i32 [[TMP75]], [[TMP76]]
-; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i32 [[TMP77]], 0
-; CHECK-NEXT: br i1 [[TMP78]], label %[[ENDBLOCK]], label %[[LOADBB10:.*]]
-; CHECK: [[LOADBB10]]:
+; CHECK-NEXT: [[TMP90:%.*]] = zext i8 [[TMP73]] to i64
+; CHECK-NEXT: [[TMP91:%.*]] = zext i8 [[TMP74]] to i64
+; CHECK-NEXT: [[TMP92:%.*]] = shl i64 [[TMP90]], 8
+; CHECK-NEXT: [[TMP93:%.*]] = or i64 [[TMP84]], [[TMP92]]
+; CHECK-NEXT: [[TMP94:%.*]] = shl i64 [[TMP91]], 8
+; CHECK-NEXT: [[TMP95:%.*]] = or i64 [[TMP85]], [[TMP94]]
; CHECK-NEXT: [[TMP79:%.*]] = getelementptr i8, ptr [[A]], i64 10
; CHECK-NEXT: [[TMP80:%.*]] = getelementptr i8, ptr [[B]], i64 10
; CHECK-NEXT: [[TMP81:%.*]] = load i8, ptr [[TMP79]], align 1
; CHECK-NEXT: [[TMP82:%.*]] = load i8, ptr [[TMP80]], align 1
-; CHECK-NEXT: [[TMP83:%.*]] = zext i8 [[TMP81]] to i32
-; CHECK-NEXT: [[TMP84:%.*]] = zext i8 [[TMP82]] to i32
-; CHECK-NEXT: [[TMP85:%.*]] = sub i32 [[TMP83]], [[TMP84]]
-; CHECK-NEXT: br label %[[ENDBLOCK]]
+; CHECK-NEXT: [[TMP100:%.*]] = zext i8 [[TMP81]] to i64
+; CHECK-NEXT: [[TMP101:%.*]] = zext i8 [[TMP82]] to i64
+; CHECK-NEXT: [[TMP102]] = or i64 [[TMP93]], [[TMP100]]
+; CHECK-NEXT: [[TMP103]] = or i64 [[TMP95]], [[TMP101]]
+; CHECK-NEXT: [[TMP104:%.*]] = icmp eq i64 [[TMP102]], [[TMP103]]
+; CHECK-NEXT: br i1 [[TMP104]], label %[[ENDBLOCK]], label %[[RES_BLOCK]]
; CHECK: [[ENDBLOCK]]:
-; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ [[TMP5]], %[[LOADBB]] ], [ [[TMP13]], %[[LOADBB1]] ], [ [[TMP21]], %[[LOADBB2]] ], [ [[TMP29]], %[[LOADBB3]] ], [ [[TMP37]], %[[LOADBB4]] ], [ [[TMP45]], %[[LOADBB5]] ], [ [[TMP53]], %[[LOADBB6]] ], [ [[TMP61]], %[[LOADBB7]] ], [ [[TMP69]], %[[LOADBB8]] ], [ [[TMP77]], %[[LOADBB9]] ], [ [[TMP85]], %[[LOADBB10]] ], [ poison, %[[RES_BLOCK]] ]
+; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, %[[LOADBB8]] ], [ [[TMP4]], %[[RES_BLOCK]] ]
; CHECK-NEXT: ret i32 [[PHI_RES]]
;
%call = call i32 @memcmp(ptr %a, ptr %b, i64 11)
@@ -474,227 +478,203 @@ define i1 @memcmp_eq_size_32_align_1(ptr %a, ptr %b) {
; CHECK: [[LOADBB]]:
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[B]], align 1
-; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], [[TMP2]]
-; CHECK-NEXT: br i1 [[TMP3]], label %[[RES_BLOCK]], label %[[LOADBB1:.*]]
-; CHECK: [[LOADBB1]]:
+; CHECK-NEXT: [[TMP3:%.*]] = xor i8 [[TMP1]], [[TMP2]]
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[A]], i64 1
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[B]], i64 1
; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP4]], align 1
; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[TMP5]], align 1
-; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i8 [[TMP6]], [[TMP7]]
-; CHECK-NEXT: br i1 [[TMP8]], label %[[RES_BLOCK]], label %[[LOADBB2:.*]]
-; CHECK: [[LOADBB2]]:
+; CHECK-NEXT: [[TMP8:%.*]] = xor i8 [[TMP6]], [[TMP7]]
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[A]], i64 2
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[B]], i64 2
; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP9]], align 1
; CHECK-NEXT: [[TMP12:%.*]] = load i8, ptr [[TMP10]], align 1
-; CHECK-NEXT: [[TMP13:%.*]] = icmp ne i8 [[TMP11]], [[TMP12]]
-; CHECK-NEXT: br i1 [[TMP13]], label %[[RES_BLOCK]], label %[[LOADBB3:.*]]
-; CHECK: [[LOADBB3]]:
+; CHECK-NEXT: [[TMP13:%.*]] = xor i8 [[TMP11]], [[TMP12]]
; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[A]], i64 3
; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[B]], i64 3
; CHECK-NEXT: [[TMP16:%.*]] = load i8, ptr [[TMP14]], align 1
; CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[TMP15]], align 1
-; CHECK-NEXT: [[TMP18:%.*]] = icmp ne i8 [[TMP16]], [[TMP17]]
-; CHECK-NEXT: br i1 [[TMP18]], label %[[RES_BLOCK]], label %[[LOADBB4:.*]]
-; CHECK: [[LOADBB4]]:
+; CHECK-NEXT: [[TMP18:%.*]] = xor i8 [[TMP16]], [[TMP17]]
; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[A]], i64 4
; CHECK-NEXT: [[TMP20:%.*]] = getelementptr i8, ptr [[B]], i64 4
; CHECK-NEXT: [[TMP21:%.*]] = load i8, ptr [[TMP19]], align 1
; CHECK-NEXT: [[TMP22:%.*]] = load i8, ptr [[TMP20]], align 1
-; CHECK-NEXT: [[TMP23:%.*]] = icmp ne i8 [[TMP21]], [[TMP22]]
-; CHECK-NEXT: br i1 [[TMP23]], label %[[RES_BLOCK]], label %[[LOADBB5:.*]]
-; CHECK: [[LOADBB5]]:
+; CHECK-NEXT: [[TMP23:%.*]] = xor i8 [[TMP21]], [[TMP22]]
; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[A]], i64 5
; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[B]], i64 5
; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP24]], align 1
; CHECK-NEXT: [[TMP27:%.*]] = load i8, ptr [[TMP25]], align 1
-; CHECK-NEXT: [[TMP28:%.*]] = icmp ne i8 [[TMP26]], [[TMP27]]
-; CHECK-NEXT: br i1 [[TMP28]], label %[[RES_BLOCK]], label %[[LOADBB6:.*]]
-; CHECK: [[LOADBB6]]:
+; CHECK-NEXT: [[TMP28:%.*]] = xor i8 [[TMP26]], [[TMP27]]
; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[A]], i64 6
; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[B]], i64 6
; CHECK-NEXT: [[TMP31:%.*]] = load i8, ptr [[TMP29]], align 1
; CHECK-NEXT: [[TMP32:%.*]] = load i8, ptr [[TMP30]], align 1
-; CHECK-NEXT: [[TMP33:%.*]] = icmp ne i8 [[TMP31]], [[TMP32]]
-; CHECK-NEXT: br i1 [[TMP33]], label %[[RES_BLOCK]], label %[[LOADBB7:.*]]
-; CHECK: [[LOADBB7]]:
+; CHECK-NEXT: [[TMP33:%.*]] = xor i8 [[TMP31]], [[TMP32]]
; CHECK-NEXT: [[TMP34:%.*]] = getelementptr i8, ptr [[A]], i64 7
; CHECK-NEXT: [[TMP35:%.*]] = getelementptr i8, ptr [[B]], i64 7
; CHECK-NEXT: [[TMP36:%.*]] = load i8, ptr [[TMP34]], align 1
; CHECK-NEXT: [[TMP37:%.*]] = load i8, ptr [[TMP35]], align 1
-; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i8 [[TMP36]], [[TMP37]]
+; CHECK-NEXT: [[TMP48:%.*]] = xor i8 [[TMP36]], [[TMP37]]
+; CHECK-NEXT: [[TMP53:%.*]] = or i8 [[TMP3]], [[TMP8]]
+; CHECK-NEXT: [[TMP58:%.*]] = or i8 [[TMP13]], [[TMP18]]
+; CHECK-NEXT: [[TMP63:%.*]] = or i8 [[TMP23]], [[TMP28]]
+; CHECK-NEXT: [[TMP68:%.*]] = or i8 [[TMP33]], [[TMP48]]
+; CHECK-NEXT: [[TMP43:%.*]] = or i8 [[TMP53]], [[TMP58]]
+; CHECK-NEXT: [[TMP73:%.*]] = or i8 [[TMP63]], [[TMP68]]
+; CHECK-NEXT: [[TMP83:%.*]] = or i8 [[TMP43]], [[TMP73]]
+; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i8 [[TMP83]], 0
; CHECK-NEXT: br i1 [[TMP38]], label %[[RES_BLOCK]], label %[[LOADBB8:.*]]
; CHECK: [[LOADBB8]]:
; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[A]], i64 8
; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i8, ptr [[B]], i64 8
; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[TMP39]], align 1
; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[TMP40]], align 1
-; CHECK-NEXT: [[TMP43:%.*]] = icmp ne i8 [[TMP41]], [[TMP42]]
-; CHECK-NEXT: br i1 [[TMP43]], label %[[RES_BLOCK]], label %[[LOADBB9:.*]]
-; CHECK: [[LOADBB9]]:
+; CHECK-NEXT: [[TMP98:%.*]] = xor i8 [[TMP41]], [[TMP42]]
; CHECK-NEXT: [[TMP44:%.*]] = getelementptr i8, ptr [[A]], i64 9
; CHECK-NEXT: [[TMP45:%.*]] = getelementptr i8, ptr [[B]], i64 9
; CHECK-NEXT: [[TMP46:%.*]] = load i8, ptr [[TMP44]], align 1
; CHECK-NEXT: [[TMP47:%.*]] = load i8, ptr [[TMP45]], align 1
-; CHECK-NEXT: [[TMP48:%.*]] = icmp ne i8 [[TMP46]], [[TMP47]]
-; CHECK-NEXT: br i1 [[TMP48]], label %[[RES_BLOCK]], label %[[LOADBB10:.*]]
-; CHECK: [[LOADBB10]]:
+; CHECK-NEXT: [[TMP103:%.*]] = xor i8 [[TMP46]], [[TMP47]]
; CHECK-NEXT: [[TMP49:%.*]] = getelementptr i8, ptr [[A]], i64 10
; CHECK-NEXT: [[TMP50:%.*]] = getelementptr i8, ptr [[B]], i64 10
; CHECK-NEXT: [[TMP51:%.*]] = load i8, ptr [[TMP49]], align 1
; CHECK-NEXT: [[TMP52:%.*]] = load i8, ptr [[TMP50]], align 1
-; CHECK-NEXT: [[TMP53:%.*]] = icmp ne i8 [[TMP51]], [[TMP52]]
-; CHECK-NEXT: br i1 [[TMP53]], label %[[RES_BLOCK]], label %[[LOADBB11:.*]]
-; CHECK: [[LOADBB11]]:
+; CHECK-NEXT: [[TMP108:%.*]] = xor i8 [[TMP51]], [[TMP52]]
; CHECK-NEXT: [[TMP54:%.*]] = getelementptr i8, ptr [[A]], i64 11
; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[B]], i64 11
; CHECK-NEXT: [[TMP56:%.*]] = load i8, ptr [[TMP54]], align 1
; CHECK-NEXT: [[TMP57:%.*]] = load i8, ptr [[TMP55]], align 1
-; CHECK-NEXT: [[TMP58:%.*]] = icmp ne i8 [[TMP56]], [[TMP57]]
-; CHECK-NEXT: br i1 [[TMP58]], label %[[RES_BLOCK]], label %[[LOADBB12:.*]]
-; CHECK: [[LOADBB12]]:
+; CHECK-NEXT: [[TMP113:%.*]] = xor i8 [[TMP56]], [[TMP57]]
; CHECK-NEXT: [[TMP59:%.*]] = getelementptr i8, ptr [[A]], i64 12
; CHECK-NEXT: [[TMP60:%.*]] = getelementptr i8, ptr [[B]], i64 12
; CHECK-NEXT: [[TMP61:%.*]] = load i8, ptr [[TMP59]], align 1
; CHECK-NEXT: [[TMP62:%.*]] = load i8, ptr [[TMP60]], align 1
-; CHECK-NEXT: [[TMP63:%.*]] = icmp ne i8 [[TMP61]], [[TMP62]]
-; CHECK-NEXT: br i1 [[TMP63]], label %[[RES_BLOCK]], label %[[LOADBB13:.*]]
-; CHECK: [[LOADBB13]]:
+; CHECK-NEXT: [[TMP123:%.*]] = xor i8 [[TMP61]], [[TMP62]]
; CHECK-NEXT: [[TMP64:%.*]] = getelementptr i8, ptr [[A]], i64 13
; CHECK-NEXT: [[TMP65:%.*]] = getelementptr i8, ptr [[B]], i64 13
; CHECK-NEXT: [[TMP66:%.*]] = load i8, ptr [[TMP64]], align 1
; CHECK-NEXT: [[TMP67:%.*]] = load i8, ptr [[TMP65]], align 1
-; CHECK-NEXT: [[TMP68:%.*]] = icmp ne i8 [[TMP66]], [[TMP67]]
-; CHECK-NEXT: br i1 [[TMP68]], label %[[RES_BLOCK]], label %[[LOADBB14:.*]]
-; CHECK: [[LOADBB14]]:
+; CHECK-NEXT: [[TMP128:%.*]] = xor i8 [[TMP66]], [[TMP67]]
; CHECK-NEXT: [[TMP69:%.*]] = getelementptr i8, ptr [[A]], i64 14
; CHECK-NEXT: [[TMP70:%.*]] = getelementptr i8, ptr [[B]], i64 14
; CHECK-NEXT: [[TMP71:%.*]] = load i8, ptr [[TMP69]], align 1
; CHECK-NEXT: [[TMP72:%.*]] = load i8, ptr [[TMP70]], align 1
-; CHECK-NEXT: [[TMP73:%.*]] = icmp ne i8 [[TMP71]], [[TMP72]]
-; CHECK-NEXT: br i1 [[TMP73]], label %[[RES_BLOCK]], label %[[LOADBB15:.*]]
-; CHECK: [[LOADBB15]]:
+; CHECK-NEXT: [[TMP133:%.*]] = xor i8 [[TMP71]], [[TMP72]]
; CHECK-NEXT: [[TMP74:%.*]] = getelementptr i8, ptr [[A]], i64 15
; CHECK-NEXT: [[TMP75:%.*]] = getelementptr i8, ptr [[B]], i64 15
; CHECK-NEXT: [[TMP76:%.*]] = load i8, ptr [[TMP74]], align 1
; CHECK-NEXT: [[TMP77:%.*]] = load i8, ptr [[TMP75]], align 1
-; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i8 [[TMP76]], [[TMP77]]
+; CHECK-NEXT: [[TMP143:%.*]] = xor i8 [[TMP76]], [[TMP77]]
+; CHECK-NEXT: [[TMP148:%.*]] = or i8 [[TMP98]], [[TMP103]]
+; CHECK-NEXT: [[TMP88:%.*]] = or i8 [[TMP108]], [[TMP113]]
+; CHECK-NEXT: [[TMP153:%.*]] = or i8 [[TMP123]], [[TMP128]]
+; CHECK-NEXT: [[TMP159:%.*]] = or i8 [[TMP133]], [[TMP143]]
+; CHECK-NEXT: [[TMP160:%.*]] = or i8 [[TMP148]], [[TMP88]]
+; CHECK-NEXT: [[TMP161:%.*]] = or i8 [[TMP153]], [[TMP159]]
+; CHECK-NEXT: [[TMP93:%.*]] = or i8 [[TMP160]], [[TMP161]]
+; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i8 [[TMP93]], 0
; CHECK-NEXT: br i1 [[TMP78]], label %[[RES_BLOCK]], label %[[LOADBB16:.*]]
; CHECK: [[LOADBB16]]:
; CHECK-NEXT: [[TMP79:%.*]] = getelementptr i8, ptr [[A]], i64 16
; CHECK-NEXT: [[TMP80:%.*]] = getelementptr i8, ptr [[B]], i64 16
; CHECK-NEXT: [[TMP81:%.*]] = load i8, ptr [[TMP79]], align 1
; CHECK-NEXT: [[TMP82:%.*]] = load i8, ptr [[TMP80]], align 1
-; CHECK-NEXT: [[TMP83:%.*]] = icmp ne i8 [[TMP81]], [[TMP82]]
-; CHECK-NEXT: br i1 [[TMP83]], label %[[RES_BLOCK]], label %[[LOADBB17:.*]]
-; CHECK: [[LOADBB17]]:
+; CHECK-NEXT: [[TMP163:%.*]] = xor i8 [[TMP81]], [[TMP82]]
; CHECK-NEXT: [[TMP84:%.*]] = getelementptr i8, ptr [[A]], i64 17
; CHECK-NEXT: [[TMP85:%.*]] = getelementptr i8, ptr [[B]], i64 17
; CHECK-NEXT: [[TMP86:%.*]] = load i8, ptr [[TMP84]], align 1
; CHECK-NEXT: [[TMP87:%.*]] = load i8, ptr [[TMP85]], align 1
-; CHECK-NEXT: [[TMP88:%.*]] = icmp ne i8 [[TMP86]], [[TMP87]]
-; CHECK-NEXT: br i1 [[TMP88]], label %[[RES_BLOCK]], label %[[LOADBB18:.*]]
-; CHECK: [[LOADBB18]]:
+; CHECK-NEXT: [[TMP164:%.*]] = xor i8 [[TMP86]], [[TMP87]]
; CHECK-NEXT: [[TMP89:%.*]] = getelementptr i8, ptr [[A]], i64 18
; CHECK-NEXT: [[TMP90:%.*]] = getelementptr i8, ptr [[B]], i64 18
; CHECK-NEXT: [[TMP91:%.*]] = load i8, ptr [[TMP89]], align 1
; CHECK-NEXT: [[TMP92:%.*]] = load i8, ptr [[TMP90]], align 1
-; CHECK-NEXT: [[TMP93:%.*]] = icmp ne i8 [[TMP91]], [[TMP92]]
-; CHECK-NEXT: br i1 [[TMP93]], label %[[RES_BLOCK]], label %[[LOADBB19:.*]]
-; CHECK: [[LOADBB19]]:
+; CHECK-NEXT: [[TMP165:%.*]] = xor i8 [[TMP91]], [[TMP92]]
; CHECK-NEXT: [[TMP94:%.*]] = getelementptr i8, ptr [[A]], i64 19
; CHECK-NEXT: [[TMP95:%.*]] = getelementptr i8, ptr [[B]], i64 19
; CHECK-NEXT: [[TMP96:%.*]] = load i8, ptr [[TMP94]], align 1
; CHECK-NEXT: [[TMP97:%.*]] = load i8, ptr [[TMP95]], align 1
-; CHECK-NEXT: [[TMP98:%.*]] = icmp ne i8 [[TMP96]], [[TMP97]]
-; CHECK-NEXT: br i1 [[TMP98]], label %[[RES_BLOCK]], label %[[LOADBB20:.*]]
-; CHECK: [[LOADBB20]]:
+; CHECK-NEXT: [[TMP166:%.*]] = xor i8 [[TMP96]], [[TMP97]]
; CHECK-NEXT: [[TMP99:%.*]] = getelementptr i8, ptr [[A]], i64 20
; CHECK-NEXT: [[TMP100:%.*]] = getelementptr i8, ptr [[B]], i64 20
; CHECK-NEXT: [[TMP101:%.*]] = load i8, ptr [[TMP99]], align 1
; CHECK-NEXT: [[TMP102:%.*]] = load i8, ptr [[TMP100]], align 1
-; CHECK-NEXT: [[TMP103:%.*]] = icmp ne i8 [[TMP101]], [[TMP102]]
-; CHECK-NEXT: br i1 [[TMP103]], label %[[RES_BLOCK]], label %[[LOADBB21:.*]]
-; CHECK: [[LOADBB21]]:
+; CHECK-NEXT: [[TMP168:%.*]] = xor i8 [[TMP101]], [[TMP102]]
; CHECK-NEXT: [[TMP104:%.*]] = getelementptr i8, ptr [[A]], i64 21
; CHECK-NEXT: [[TMP105:%.*]] = getelementptr i8, ptr [[B]], i64 21
; CHECK-NEXT: [[TMP106:%.*]] = load i8, ptr [[TMP104]], align 1
; CHECK-NEXT: [[TMP107:%.*]] = load i8, ptr [[TMP105]], align 1
-; CHECK-NEXT: [[TMP108:%.*]] = icmp ne i8 [[TMP106]], [[TMP107]]
-; CHECK-NEXT: br i1 [[TMP108]], label %[[RES_BLOCK]], label %[[LOADBB22:.*]]
-; CHECK: [[LOADBB22]]:
+; CHECK-NEXT: [[TMP169:%.*]] = xor i8 [[TMP106]], [[TMP107]]
; CHECK-NEXT: [[TMP109:%.*]] = getelementptr i8, ptr [[A]], i64 22
; CHECK-NEXT: [[TMP110:%.*]] = getelementptr i8, ptr [[B]], i64 22
; CHECK-NEXT: [[TMP111:%.*]] = load i8, ptr [[TMP109]], align 1
; CHECK-NEXT: [[TMP112:%.*]] = load i8, ptr [[TMP110]], align 1
-; CHECK-NEXT: [[TMP113:%.*]] = icmp ne i8 [[TMP111]], [[TMP112]]
-; CHECK-NEXT: br i1 [[TMP113]], label %[[RES_BLOCK]], label %[[LOADBB23:.*]]
-; CHECK: [[LOADBB23]]:
+; CHECK-NEXT: [[TMP170:%.*]] = xor i8 [[TMP111]], [[TMP112]]
; CHECK-NEXT: [[TMP114:%.*]] = getelementptr i8, ptr [[A]], i64 23
; CHECK-NEXT: [[TMP115:%.*]] = getelementptr i8, ptr [[B]], i64 23
; CHECK-NEXT: [[TMP116:%.*]] = load i8, ptr [[TMP114]], align 1
; CHECK-NEXT: [[TMP117:%.*]] = load i8, ptr [[TMP115]], align 1
-; CHECK-NEXT: [[TMP118:%.*]] = icmp ne i8 [[TMP116]], [[TMP117]]
+; CHECK-NEXT: [[TMP171:%.*]] = xor i8 [[TMP116]], [[TMP117]]
+; CHECK-NEXT: [[TMP173:%.*]] = or i8 [[TMP163]], [[TMP164]]
+; CHECK-NEXT: [[TMP174:%.*]] = or i8 [[TMP165]], [[TMP166]]
+; CHECK-NEXT: [[TMP175:%.*]] = or i8 [[TMP168]], [[TMP169]]
+; CHECK-NEXT: [[TMP138:%.*]] = or i8 [[TMP170]], [[TMP171]]
+; CHECK-NEXT: [[TMP176:%.*]] = or i8 [[TMP173]], [[TMP174]]
+; CHECK-NEXT: [[TMP178:%.*]] = or i8 [[TMP175]], [[TMP138]]
+; CHECK-NEXT: [[TMP179:%.*]] = or i8 [[TMP176]], [[TMP178]]
+; CHECK-NEXT: [[TMP118:%.*]] = icmp ne i8 [[TMP179]], 0
; CHECK-NEXT: br i1 [[TMP118]], label %[[RES_BLOCK]], label %[[LOADBB24:.*]]
; CHECK: [[LOADBB24]]:
; CHECK-NEXT: [[TMP119:%.*]] = getelementptr i8, ptr [[A]], i64 24
; CHECK-NEXT: [[TMP120:%.*]] = getelementptr i8, ptr [[B]], i64 24
; CHECK-NEXT: [[TMP121:%.*]] = load i8, ptr [[TMP119]], align 1
; CHECK-NEXT: [[TMP122:%.*]] = load i8, ptr [[TMP120]], align 1
-; CHECK-NEXT: [[TMP123:%.*]] = icmp ne i8 [[TMP121]], [[TMP122]]
-; CHECK-NEXT: br i1 [[TMP123]], label %[[RES_BLOCK]], label %[[LOADBB25:.*]]
-; CHECK: [[LOADBB25]]:
+; CHECK-NEXT: [[TMP180:%.*]] = xor i8 [[TMP121]], [[TMP122]]
; CHECK-NEXT: [[TMP124:%.*]] = getelementptr i8, ptr [[A]], i64 25
; CHECK-NEXT: [[TMP125:%.*]] = getelementptr i8, ptr [[B]], i64 25
; CHECK-NEXT: [[TMP126:%.*]] = load i8, ptr [[TMP124]], align 1
; CHECK-NEXT: [[TMP127:%.*]] = load i8, ptr [[TMP125]], align 1
-; CHECK-NEXT: [[TMP128:%.*]] = icmp ne i8 [[TMP126]], [[TMP127]]
-; CHECK-NEXT: br i1 [[TMP128]], label %[[RES_BLOCK]], label %[[LOADBB26:.*]]
-; CHECK: [[LOADBB26]]:
+; CHECK-NEXT: [[TMP181:%.*]] = xor i8 [[TMP126]], [[TMP127]]
; CHECK-NEXT: [[TMP129:%.*]] = getelementptr i8, ptr [[A]], i64 26
; CHECK-NEXT: [[TMP130:%.*]] = getelementptr i8, ptr [[B]], i64 26
; CHECK-NEXT: [[TMP131:%.*]] = load i8, ptr [[TMP129]], align 1
; CHECK-NEXT: [[TMP132:%.*]] = load i8, ptr [[TMP130]], align 1
-; CHECK-NEXT: [[TMP133:%.*]] = icmp ne i8 [[TMP131]], [[TMP132]]
-; CHECK-NEXT: br i1 [[TMP133]], label %[[RES_BLOCK]], label %[[LOADBB27:.*]]
-; CHECK: [[LOADBB27]]:
+; CHECK-NEXT: [[TMP190:%.*]] = xor i8 [[TMP131]], [[TMP132]]
; CHECK-NEXT: [[TMP134:%.*]] = getelementptr i8, ptr [[A]], i64 27
; CHECK-NEXT: [[TMP135:%.*]] = getelementptr i8, ptr [[B]], i64 27
; CHECK-NEXT: [[TMP136:%.*]] = load i8, ptr [[TMP134]], align 1
; CHECK-NEXT: [[TMP137:%.*]] = load i8, ptr [[TMP135]], align 1
-; CHECK-NEXT: [[TMP138:%.*]] = icmp ne i8 [[TMP136]], [[TMP137]]
-; CHECK-NEXT: br i1 [[TMP138]], label %[[RES_BLOCK]], label %[[LOADBB28:.*]]
-; CHECK: [[LOADBB28]]:
+; CHECK-NEXT: [[TMP162:%.*]] = xor i8 [[TMP136]], [[TMP137]]
; CHECK-NEXT: [[TMP139:%.*]] = getelementptr i8, ptr [[A]], i64 28
; CHECK-NEXT: [[TMP140:%.*]] = getelementptr i8, ptr [[B]], i64 28
; CHECK-NEXT: [[TMP141:%.*]] = load i8, ptr [[TMP139]], align 1
; CHECK-NEXT: [[TMP142:%.*]] = load i8, ptr [[TMP140]], align 1
-; CHECK-NEXT: [[TMP143:%.*]] = icmp ne i8 [[TMP141]], [[TMP142]]
-; CHECK-NEXT: br i1 [[TMP143]], label %[[RES_BLOCK]], label %[[LOADBB29:.*]]
-; CHECK: [[LOADBB29]]:
+; CHECK-NEXT: [[TMP167:%.*]] = xor i8 [[TMP141]], [[TMP142]]
; CHECK-NEXT: [[TMP144:%.*]] = getelementptr i8, ptr [[A]], i64 29
; CHECK-NEXT: [[TMP145:%.*]] = getelementptr i8, ptr [[B]], i64 29
; CHECK-NEXT: [[TMP146:%.*]] = load i8, ptr [[TMP144]], align 1
; CHECK-NEXT: [[TMP147:%.*]] = load i8, ptr [[TMP145]], align 1
-; CHECK-NEXT: [[TMP148:%.*]] = icmp ne i8 [[TMP146]], [[TMP147]]
-; CHECK-NEXT: br i1 [[TMP148]], label %[[RES_BLOCK]], label %[[LOADBB30:.*]]
-; CHECK: [[LOADBB30]]:
+; CHECK-NEXT: [[TMP172:%.*]] = xor i8 [[TMP146]], [[TMP147]]
; CHECK-NEXT: [[TMP149:%.*]] = getelementptr i8, ptr [[A]], i64 30
; CHECK-NEXT: [[TMP150:%.*]] = getelementptr i8, ptr [[B]], i64 30
; CHECK-NEXT: [[TMP151:%.*]] = load i8, ptr [[TMP149]], align 1
; CHECK-NEXT: [[TMP152:%.*]] = load i8, ptr [[TMP150]], align 1
-; CHECK-NEXT: [[TMP153:%.*]] = icmp ne i8 [[TMP151]], [[TMP152]]
-; CHECK-NEXT: br i1 [[TMP153]], label %[[RES_BLOCK]], label %[[LOADBB31:.*]]
-; CHECK: [[LOADBB31]]:
+; CHECK-NEXT: [[TMP177:%.*]] = xor i8 [[TMP151]], [[TMP152]]
; CHECK-NEXT: [[TMP154:%.*]] = getelementptr i8, ptr [[A]], i64 31
; CHECK-NEXT: [[TMP155:%.*]] = getelementptr i8, ptr [[B]], i64 31
; CHECK-NEXT: [[TMP156:%.*]] = load i8, ptr [[TMP154]], align 1
; CHECK-NEXT: [[TMP157:%.*]] = load i8, ptr [[TMP155]], align 1
-; CHECK-NEXT: [[TMP158:%.*]] = icmp ne i8 [[TMP156]], [[TMP157]]
+; CHECK-NEXT: [[TMP182:%.*]] = xor i8 [[TMP156]], [[TMP157]]
+; CHECK-NEXT: [[TMP183:%.*]] = or i8 [[TMP180]], [[TMP181]]
+; CHECK-NEXT: [[TMP184:%.*]] = or i8 [[TMP190]], [[TMP162]]
+; CHECK-NEXT: [[TMP185:%.*]] = or i8 [[TMP167]], [[TMP172]]
+; CHECK-NEXT: [[TMP186:%.*]] = or i8 [[TMP177]], [[TMP182]]
+; CHECK-NEXT: [[TMP187:%.*]] = or i8 [[TMP183]], [[TMP184]]
+; CHECK-NEXT: [[TMP188:%.*]] = or i8 [[TMP185]], [[TMP186]]
+; CHECK-NEXT: [[TMP189:%.*]] = or i8 [[TMP187]], [[TMP188]]
+; CHECK-NEXT: [[TMP158:%.*]] = icmp ne i8 [[TMP189]], 0
; CHECK-NEXT: br i1 [[TMP158]], label %[[RES_BLOCK]], label %[[ENDBLOCK]]
; CHECK: [[ENDBLOCK]]:
-; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, %[[LOADBB31]] ], [ 1, %[[RES_BLOCK]] ]
+; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, %[[LOADBB24]] ], [ 1, %[[RES_BLOCK]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
@@ -712,227 +692,203 @@ define i1 @bcmp_size_32_align_1(ptr %a, ptr %b) {
; CHECK: [[LOADBB]]:
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[B]], align 1
-; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i8 [[TMP1]], [[TMP2]]
-; CHECK-NEXT: br i1 [[TMP3]], label %[[RES_BLOCK]], label %[[LOADBB1:.*]]
-; CHECK: [[LOADBB1]]:
+; CHECK-NEXT: [[TMP3:%.*]] = xor i8 [[TMP1]], [[TMP2]]
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[A]], i64 1
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[B]], i64 1
; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP4]], align 1
; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[TMP5]], align 1
-; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i8 [[TMP6]], [[TMP7]]
-; CHECK-NEXT: br i1 [[TMP8]], label %[[RES_BLOCK]], label %[[LOADBB2:.*]]
-; CHECK: [[LOADBB2]]:
+; CHECK-NEXT: [[TMP8:%.*]] = xor i8 [[TMP6]], [[TMP7]]
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[A]], i64 2
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[B]], i64 2
; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP9]], align 1
; CHECK-NEXT: [[TMP12:%.*]] = load i8, ptr [[TMP10]], align 1
-; CHECK-NEXT: [[TMP13:%.*]] = icmp ne i8 [[TMP11]], [[TMP12]]
-; CHECK-NEXT: br i1 [[TMP13]], label %[[RES_BLOCK]], label %[[LOADBB3:.*]]
-; CHECK: [[LOADBB3]]:
+; CHECK-NEXT: [[TMP13:%.*]] = xor i8 [[TMP11]], [[TMP12]]
; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[A]], i64 3
; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[B]], i64 3
; CHECK-NEXT: [[TMP16:%.*]] = load i8, ptr [[TMP14]], align 1
; CHECK-NEXT: [[TMP17:%.*]] = load i8, ptr [[TMP15]], align 1
-; CHECK-NEXT: [[TMP18:%.*]] = icmp ne i8 [[TMP16]], [[TMP17]]
-; CHECK-NEXT: br i1 [[TMP18]], label %[[RES_BLOCK]], label %[[LOADBB4:.*]]
-; CHECK: [[LOADBB4]]:
+; CHECK-NEXT: [[TMP18:%.*]] = xor i8 [[TMP16]], [[TMP17]]
; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[A]], i64 4
; CHECK-NEXT: [[TMP20:%.*]] = getelementptr i8, ptr [[B]], i64 4
; CHECK-NEXT: [[TMP21:%.*]] = load i8, ptr [[TMP19]], align 1
; CHECK-NEXT: [[TMP22:%.*]] = load i8, ptr [[TMP20]], align 1
-; CHECK-NEXT: [[TMP23:%.*]] = icmp ne i8 [[TMP21]], [[TMP22]]
-; CHECK-NEXT: br i1 [[TMP23]], label %[[RES_BLOCK]], label %[[LOADBB5:.*]]
-; CHECK: [[LOADBB5]]:
+; CHECK-NEXT: [[TMP23:%.*]] = xor i8 [[TMP21]], [[TMP22]]
; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[A]], i64 5
; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[B]], i64 5
; CHECK-NEXT: [[TMP26:%.*]] = load i8, ptr [[TMP24]], align 1
; CHECK-NEXT: [[TMP27:%.*]] = load i8, ptr [[TMP25]], align 1
-; CHECK-NEXT: [[TMP28:%.*]] = icmp ne i8 [[TMP26]], [[TMP27]]
-; CHECK-NEXT: br i1 [[TMP28]], label %[[RES_BLOCK]], label %[[LOADBB6:.*]]
-; CHECK: [[LOADBB6]]:
+; CHECK-NEXT: [[TMP28:%.*]] = xor i8 [[TMP26]], [[TMP27]]
; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[A]], i64 6
; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[B]], i64 6
; CHECK-NEXT: [[TMP31:%.*]] = load i8, ptr [[TMP29]], align 1
; CHECK-NEXT: [[TMP32:%.*]] = load i8, ptr [[TMP30]], align 1
-; CHECK-NEXT: [[TMP33:%.*]] = icmp ne i8 [[TMP31]], [[TMP32]]
-; CHECK-NEXT: br i1 [[TMP33]], label %[[RES_BLOCK]], label %[[LOADBB7:.*]]
-; CHECK: [[LOADBB7]]:
+; CHECK-NEXT: [[TMP33:%.*]] = xor i8 [[TMP31]], [[TMP32]]
; CHECK-NEXT: [[TMP34:%.*]] = getelementptr i8, ptr [[A]], i64 7
; CHECK-NEXT: [[TMP35:%.*]] = getelementptr i8, ptr [[B]], i64 7
; CHECK-NEXT: [[TMP36:%.*]] = load i8, ptr [[TMP34]], align 1
; CHECK-NEXT: [[TMP37:%.*]] = load i8, ptr [[TMP35]], align 1
-; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i8 [[TMP36]], [[TMP37]]
+; CHECK-NEXT: [[TMP48:%.*]] = xor i8 [[TMP36]], [[TMP37]]
+; CHECK-NEXT: [[TMP53:%.*]] = or i8 [[TMP3]], [[TMP8]]
+; CHECK-NEXT: [[TMP58:%.*]] = or i8 [[TMP13]], [[TMP18]]
+; CHECK-NEXT: [[TMP63:%.*]] = or i8 [[TMP23]], [[TMP28]]
+; CHECK-NEXT: [[TMP68:%.*]] = or i8 [[TMP33]], [[TMP48]]
+; CHECK-NEXT: [[TMP43:%.*]] = or i8 [[TMP53]], [[TMP58]]
+; CHECK-NEXT: [[TMP73:%.*]] = or i8 [[TMP63]], [[TMP68]]
+; CHECK-NEXT: [[TMP83:%.*]] = or i8 [[TMP43]], [[TMP73]]
+; CHECK-NEXT: [[TMP38:%.*]] = icmp ne i8 [[TMP83]], 0
; CHECK-NEXT: br i1 [[TMP38]], label %[[RES_BLOCK]], label %[[LOADBB8:.*]]
; CHECK: [[LOADBB8]]:
; CHECK-NEXT: [[TMP39:%.*]] = getelementptr i8, ptr [[A]], i64 8
; CHECK-NEXT: [[TMP40:%.*]] = getelementptr i8, ptr [[B]], i64 8
; CHECK-NEXT: [[TMP41:%.*]] = load i8, ptr [[TMP39]], align 1
; CHECK-NEXT: [[TMP42:%.*]] = load i8, ptr [[TMP40]], align 1
-; CHECK-NEXT: [[TMP43:%.*]] = icmp ne i8 [[TMP41]], [[TMP42]]
-; CHECK-NEXT: br i1 [[TMP43]], label %[[RES_BLOCK]], label %[[LOADBB9:.*]]
-; CHECK: [[LOADBB9]]:
+; CHECK-NEXT: [[TMP98:%.*]] = xor i8 [[TMP41]], [[TMP42]]
; CHECK-NEXT: [[TMP44:%.*]] = getelementptr i8, ptr [[A]], i64 9
; CHECK-NEXT: [[TMP45:%.*]] = getelementptr i8, ptr [[B]], i64 9
; CHECK-NEXT: [[TMP46:%.*]] = load i8, ptr [[TMP44]], align 1
; CHECK-NEXT: [[TMP47:%.*]] = load i8, ptr [[TMP45]], align 1
-; CHECK-NEXT: [[TMP48:%.*]] = icmp ne i8 [[TMP46]], [[TMP47]]
-; CHECK-NEXT: br i1 [[TMP48]], label %[[RES_BLOCK]], label %[[LOADBB10:.*]]
-; CHECK: [[LOADBB10]]:
+; CHECK-NEXT: [[TMP103:%.*]] = xor i8 [[TMP46]], [[TMP47]]
; CHECK-NEXT: [[TMP49:%.*]] = getelementptr i8, ptr [[A]], i64 10
; CHECK-NEXT: [[TMP50:%.*]] = getelementptr i8, ptr [[B]], i64 10
; CHECK-NEXT: [[TMP51:%.*]] = load i8, ptr [[TMP49]], align 1
; CHECK-NEXT: [[TMP52:%.*]] = load i8, ptr [[TMP50]], align 1
-; CHECK-NEXT: [[TMP53:%.*]] = icmp ne i8 [[TMP51]], [[TMP52]]
-; CHECK-NEXT: br i1 [[TMP53]], label %[[RES_BLOCK]], label %[[LOADBB11:.*]]
-; CHECK: [[LOADBB11]]:
+; CHECK-NEXT: [[TMP108:%.*]] = xor i8 [[TMP51]], [[TMP52]]
; CHECK-NEXT: [[TMP54:%.*]] = getelementptr i8, ptr [[A]], i64 11
; CHECK-NEXT: [[TMP55:%.*]] = getelementptr i8, ptr [[B]], i64 11
; CHECK-NEXT: [[TMP56:%.*]] = load i8, ptr [[TMP54]], align 1
; CHECK-NEXT: [[TMP57:%.*]] = load i8, ptr [[TMP55]], align 1
-; CHECK-NEXT: [[TMP58:%.*]] = icmp ne i8 [[TMP56]], [[TMP57]]
-; CHECK-NEXT: br i1 [[TMP58]], label %[[RES_BLOCK]], label %[[LOADBB12:.*]]
-; CHECK: [[LOADBB12]]:
+; CHECK-NEXT: [[TMP113:%.*]] = xor i8 [[TMP56]], [[TMP57]]
; CHECK-NEXT: [[TMP59:%.*]] = getelementptr i8, ptr [[A]], i64 12
; CHECK-NEXT: [[TMP60:%.*]] = getelementptr i8, ptr [[B]], i64 12
; CHECK-NEXT: [[TMP61:%.*]] = load i8, ptr [[TMP59]], align 1
; CHECK-NEXT: [[TMP62:%.*]] = load i8, ptr [[TMP60]], align 1
-; CHECK-NEXT: [[TMP63:%.*]] = icmp ne i8 [[TMP61]], [[TMP62]]
-; CHECK-NEXT: br i1 [[TMP63]], label %[[RES_BLOCK]], label %[[LOADBB13:.*]]
-; CHECK: [[LOADBB13]]:
+; CHECK-NEXT: [[TMP123:%.*]] = xor i8 [[TMP61]], [[TMP62]]
; CHECK-NEXT: [[TMP64:%.*]] = getelementptr i8, ptr [[A]], i64 13
; CHECK-NEXT: [[TMP65:%.*]] = getelementptr i8, ptr [[B]], i64 13
; CHECK-NEXT: [[TMP66:%.*]] = load i8, ptr [[TMP64]], align 1
; CHECK-NEXT: [[TMP67:%.*]] = load i8, ptr [[TMP65]], align 1
-; CHECK-NEXT: [[TMP68:%.*]] = icmp ne i8 [[TMP66]], [[TMP67]]
-; CHECK-NEXT: br i1 [[TMP68]], label %[[RES_BLOCK]], label %[[LOADBB14:.*]]
-; CHECK: [[LOADBB14]]:
+; CHECK-NEXT: [[TMP128:%.*]] = xor i8 [[TMP66]], [[TMP67]]
; CHECK-NEXT: [[TMP69:%.*]] = getelementptr i8, ptr [[A]], i64 14
; CHECK-NEXT: [[TMP70:%.*]] = getelementptr i8, ptr [[B]], i64 14
; CHECK-NEXT: [[TMP71:%.*]] = load i8, ptr [[TMP69]], align 1
; CHECK-NEXT: [[TMP72:%.*]] = load i8, ptr [[TMP70]], align 1
-; CHECK-NEXT: [[TMP73:%.*]] = icmp ne i8 [[TMP71]], [[TMP72]]
-; CHECK-NEXT: br i1 [[TMP73]], label %[[RES_BLOCK]], label %[[LOADBB15:.*]]
-; CHECK: [[LOADBB15]]:
+; CHECK-NEXT: [[TMP133:%.*]] = xor i8 [[TMP71]], [[TMP72]]
; CHECK-NEXT: [[TMP74:%.*]] = getelementptr i8, ptr [[A]], i64 15
; CHECK-NEXT: [[TMP75:%.*]] = getelementptr i8, ptr [[B]], i64 15
; CHECK-NEXT: [[TMP76:%.*]] = load i8, ptr [[TMP74]], align 1
; CHECK-NEXT: [[TMP77:%.*]] = load i8, ptr [[TMP75]], align 1
-; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i8 [[TMP76]], [[TMP77]]
+; CHECK-NEXT: [[TMP143:%.*]] = xor i8 [[TMP76]], [[TMP77]]
+; CHECK-NEXT: [[TMP148:%.*]] = or i8 [[TMP98]], [[TMP103]]
+; CHECK-NEXT: [[TMP88:%.*]] = or i8 [[TMP108]], [[TMP113]]
+; CHECK-NEXT: [[TMP153:%.*]] = or i8 [[TMP123]], [[TMP128]]
+; CHECK-NEXT: [[TMP159:%.*]] = or i8 [[TMP133]], [[TMP143]]
+; CHECK-NEXT: [[TMP160:%.*]] = or i8 [[TMP148]], [[TMP88]]
+; CHECK-NEXT: [[TMP161:%.*]] = or i8 [[TMP153]], [[TMP159]]
+; CHECK-NEXT: [[TMP93:%.*]] = or i8 [[TMP160]], [[TMP161]]
+; CHECK-NEXT: [[TMP78:%.*]] = icmp ne i8 [[TMP93]], 0
; CHECK-NEXT: br i1 [[TMP78]], label %[[RES_BLOCK]], label %[[LOADBB16:.*]]
; CHECK: [[LOADBB16]]:
; CHECK-NEXT: [[TMP79:%.*]] = getelementptr i8, ptr [[A]], i64 16
; CHECK-NEXT: [[TMP80:%.*]] = getelementptr i8, ptr [[B]], i64 16
; CHECK-NEXT: [[TMP81:%.*]] = load i8, ptr [[TMP79]], align 1
; CHECK-NEXT: [[TMP82:%.*]] = load i8, ptr [[TMP80]], align 1
-; CHECK-NEXT: [[TMP83:%.*]] = icmp ne i8 [[TMP81]], [[TMP82]]
-; CHECK-NEXT: br i1 [[TMP83]], label %[[RES_BLOCK]], label %[[LOADBB17:.*]]
-; CHECK: [[LOADBB17]]:
+; CHECK-NEXT: [[TMP163:%.*]] = xor i8 [[TMP81]], [[TMP82]]
; CHECK-NEXT: [[TMP84:%.*]] = getelementptr i8, ptr [[A]], i64 17
; CHECK-NEXT: [[TMP85:%.*]] = getelementptr i8, ptr [[B]], i64 17
; CHECK-NEXT: [[TMP86:%.*]] = load i8, ptr [[TMP84]], align 1
; CHECK-NEXT: [[TMP87:%.*]] = load i8, ptr [[TMP85]], align 1
-; CHECK-NEXT: [[TMP88:%.*]] = icmp ne i8 [[TMP86]], [[TMP87]]
-; CHECK-NEXT: br i1 [[TMP88]], label %[[RES_BLOCK]], label %[[LOADBB18:.*]]
-; CHECK: [[LOADBB18]]:
+; CHECK-NEXT: [[TMP164:%.*]] = xor i8 [[TMP86]], [[TMP87]]
; CHECK-NEXT: [[TMP89:%.*]] = getelementptr i8, ptr [[A]], i64 18
; CHECK-NEXT: [[TMP90:%.*]] = getelementptr i8, ptr [[B]], i64 18
; CHECK-NEXT: [[TMP91:%.*]] = load i8, ptr [[TMP89]], align 1
; CHECK-NEXT: [[TMP92:%.*]] = load i8, ptr [[TMP90]], align 1
-; CHECK-NEXT: [[TMP93:%.*]] = icmp ne i8 [[TMP91]], [[TMP92]]
-; CHECK-NEXT: br i1 [[TMP93]], label %[[RES_BLOCK]], label %[[LOADBB19:.*]]
-; CHECK: [[LOADBB19]]:
+; CHECK-NEXT: [[TMP165:%.*]] = xor i8 [[TMP91]], [[TMP92]]
; CHECK-NEXT: [[TMP94:%.*]] = getelementptr i8, ptr [[A]], i64 19
; CHECK-NEXT: [[TMP95:%.*]] = getelementptr i8, ptr [[B]], i64 19
; CHECK-NEXT: [[TMP96:%.*]] = load i8, ptr [[TMP94]], align 1
; CHECK-NEXT: [[TMP97:%.*]] = load i8, ptr [[TMP95]], align 1
-; CHECK-NEXT: [[TMP98:%.*]] = icmp ne i8 [[TMP96]], [[TMP97]]
-; CHECK-NEXT: br i1 [[TMP98]], label %[[RES_BLOCK]], label %[[LOADBB20:.*]]
-; CHECK: [[LOADBB20]]:
+; CHECK-NEXT: [[TMP166:%.*]] = xor i8 [[TMP96]], [[TMP97]]
; CHECK-NEXT: [[TMP99:%.*]] = getelementptr i8, ptr [[A]], i64 20
; CHECK-NEXT: [[TMP100:%.*]] = getelementptr i8, ptr [[B]], i64 20
; CHECK-NEXT: [[TMP101:%.*]] = load i8, ptr [[TMP99]], align 1
; CHECK-NEXT: [[TMP102:%.*]] = load i8, ptr [[TMP100]], align 1
-; CHECK-NEXT: [[TMP103:%.*]] = icmp ne i8 [[TMP101]], [[TMP102]]
-; CHECK-NEXT: br i1 [[TMP103]], label %[[RES_BLOCK]], label %[[LOADBB21:.*]]
-; CHECK: [[LOADBB21]]:
+; CHECK-NEXT: [[TMP168:%.*]] = xor i8 [[TMP101]], [[TMP102]]
; CHECK-NEXT: [[TMP104:%.*]] = getelementptr i8, ptr [[A]], i64 21
; CHECK-NEXT: [[TMP105:%.*]] = getelementptr i8, ptr [[B]], i64 21
; CHECK-NEXT: [[TMP106:%.*]] = load i8, ptr [[TMP104]], align 1
; CHECK-NEXT: [[TMP107:%.*]] = load i8, ptr [[TMP105]], align 1
-; CHECK-NEXT: [[TMP108:%.*]] = icmp ne i8 [[TMP106]], [[TMP107]]
-; CHECK-NEXT: br i1 [[TMP108]], label %[[RES_BLOCK]], label %[[LOADBB22:.*]]
-; CHECK: [[LOADBB22]]:
+; CHECK-NEXT: [[TMP169:%.*]] = xor i8 [[TMP106]], [[TMP107]]
; CHECK-NEXT: [[TMP109:%.*]] = getelementptr i8, ptr [[A]], i64 22
; CHECK-NEXT: [[TMP110:%.*]] = getelementptr i8, ptr [[B]], i64 22
; CHECK-NEXT: [[TMP111:%.*]] = load i8, ptr [[TMP109]], align 1
; CHECK-NEXT: [[TMP112:%.*]] = load i8, ptr [[TMP110]], align 1
-; CHECK-NEXT: [[TMP113:%.*]] = icmp ne i8 [[TMP111]], [[TMP112]]
-; CHECK-NEXT: br i1 [[TMP113]], label %[[RES_BLOCK]], label %[[LOADBB23:.*]]
-; CHECK: [[LOADBB23]]:
+; CHECK-NEXT: [[TMP170:%.*]] = xor i8 [[TMP111]], [[TMP112]]
; CHECK-NEXT: [[TMP114:%.*]] = getelementptr i8, ptr [[A]], i64 23
; CHECK-NEXT: [[TMP115:%.*]] = getelementptr i8, ptr [[B]], i64 23
; CHECK-NEXT: [[TMP116:%.*]] = load i8, ptr [[TMP114]], align 1
; CHECK-NEXT: [[TMP117:%.*]] = load i8, ptr [[TMP115]], align 1
-; CHECK-NEXT: [[TMP118:%.*]] = icmp ne i8 [[TMP116]], [[TMP117]]
+; CHECK-NEXT: [[TMP171:%.*]] = xor i8 [[TMP116]], [[TMP117]]
+; CHECK-NEXT: [[TMP173:%.*]] = or i8 [[TMP163]], [[TMP164]]
+; CHECK-NEXT: [[TMP174:%.*]] = or i8 [[TMP165]], [[TMP166]]
+; CHECK-NEXT: [[TMP175:%.*]] = or i8 [[TMP168]], [[TMP169]]
+; CHECK-NEXT: [[TMP138:%.*]] = or i8 [[TMP170]], [[TMP171]]
+; CHECK-NEXT: [[TMP176:%.*]] = or i8 [[TMP173]], [[TMP174]]
+; CHECK-NEXT: [[TMP178:%.*]] = or i8 [[TMP175]], [[TMP138]]
+; CHECK-NEXT: [[TMP179:%.*]] = or i8 [[TMP176]], [[TMP178]]
+; CHECK-NEXT: [[TMP118:%.*]] = icmp ne i8 [[TMP179]], 0
; CHECK-NEXT: br i1 [[TMP118]], label %[[RES_BLOCK]], label %[[LOADBB24:.*]]
; CHECK: [[LOADBB24]]:
; CHECK-NEXT: [[TMP119:%.*]] = getelementptr i8, ptr [[A]], i64 24
; CHECK-NEXT: [[TMP120:%.*]] = getelementptr i8, ptr [[B]], i64 24
; CHECK-NEXT: [[TMP121:%.*]] = load i8, ptr [[TMP119]], align 1
; CHECK-NEXT: [[TMP122:%.*]] = load i8, ptr [[TMP120]], align 1
-; CHECK-NEXT: [[TMP123:%.*]] = icmp ne i8 [[TMP121]], [[TMP122]]
-; CHECK-NEXT: br i1 [[TMP123]], label %[[RES_BLOCK]], label %[[LOADBB25:.*]]
-; CHECK: [[LOADBB25]]:
+; CHECK-NEXT: [[TMP180:%.*]] = xor i8 [[TMP121]], [[TMP122]]
; CHECK-NEXT: [[TMP124:%.*]] = getelementptr i8, ptr [[A]], i64 25
; CHECK-NEXT: [[TMP125:%.*]] = getelementptr i8, ptr [[B]], i64 25
; CHECK-NEXT: [[TMP126:%.*]] = load i8, ptr [[TMP124]], align 1
; CHECK-NEXT: [[TMP127:%.*]] = load i8, ptr [[TMP125]], align 1
-; CHECK-NEXT: [[TMP128:%.*]] = icmp ne i8 [[TMP126]], [[TMP127]]
-; CHECK-NEXT: br i1 [[TMP128]], label %[[RES_BLOCK]], label %[[LOADBB26:.*]]
-; CHECK: [[LOADBB26]]:
+; CHECK-NEXT: [[TMP181:%.*]] = xor i8 [[TMP126]], [[TMP127]]
; CHECK-NEXT: [[TMP129:%.*]] = getelementptr i8, ptr [[A]], i64 26
; CHECK-NEXT: [[TMP130:%.*]] = getelementptr i8, ptr [[B]], i64 26
; CHECK-NEXT: [[TMP131:%.*]] = load i8, ptr [[TMP129]], align 1
; CHECK-NEXT: [[TMP132:%.*]] = load i8, ptr [[TMP130]], align 1
-; CHECK-NEXT: [[TMP133:%.*]] = icmp ne i8 [[TMP131]], [[TMP132]]
-; CHECK-NEXT: br i1 [[TMP133]], label %[[RES_BLOCK]], label %[[LOADBB27:.*]]
-; CHECK: [[LOADBB27]]:
+; CHECK-NEXT: [[TMP190:%.*]] = xor i8 [[TMP131]], [[TMP132]]
; CHECK-NEXT: [[TMP134:%.*]] = getelementptr i8, ptr [[A]], i64 27
; CHECK-NEXT: [[TMP135:%.*]] = getelementptr i8, ptr [[B]], i64 27
; CHECK-NEXT: [[TMP136:%.*]] = load i8, ptr [[TMP134]], align 1
; CHECK-NEXT: [[TMP137:%.*]] = load i8, ptr [[TMP135]], align 1
-; CHECK-NEXT: [[TMP138:%.*]] = icmp ne i8 [[TMP136]], [[TMP137]]
-; CHECK-NEXT: br i1 [[TMP138]], label %[[RES_BLOCK]], label %[[LOADBB28:.*]]
-; CHECK: [[LOADBB28]]:
+; CHECK-NEXT: [[TMP162:%.*]] = xor i8 [[TMP136]], [[TMP137]]
; CHECK-NEXT: [[TMP139:%.*]] = getelementptr i8, ptr [[A]], i64 28
; CHECK-NEXT: [[TMP140:%.*]] = getelementptr i8, ptr [[B]], i64 28
; CHECK-NEXT: [[TMP141:%.*]] = load i8, ptr [[TMP139]], align 1
; CHECK-NEXT: [[TMP142:%.*]] = load i8, ptr [[TMP140]], align 1
-; CHECK-NEXT: [[TMP143:%.*]] = icmp ne i8 [[TMP141]], [[TMP142]]
-; CHECK-NEXT: br i1 [[TMP143]], label %[[RES_BLOCK]], label %[[LOADBB29:.*]]
-; CHECK: [[LOADBB29]]:
+; CHECK-NEXT: [[TMP167:%.*]] = xor i8 [[TMP141]], [[TMP142]]
; CHECK-NEXT: [[TMP144:%.*]] = getelementptr i8, ptr [[A]], i64 29
; CHECK-NEXT: [[TMP145:%.*]] = getelementptr i8, ptr [[B]], i64 29
; CHECK-NEXT: [[TMP146:%.*]] = load i8, ptr [[TMP144]], align 1
; CHECK-NEXT: [[TMP147:%.*]] = load i8, ptr [[TMP145]], align 1
-; CHECK-NEXT: [[TMP148:%.*]] = icmp ne i8 [[TMP146]], [[TMP147]]
-; CHECK-NEXT: br i1 [[TMP148]], label %[[RES_BLOCK]], label %[[LOADBB30:.*]]
-; CHECK: [[LOADBB30]]:
+; CHECK-NEXT: [[TMP172:%.*]] = xor i8 [[TMP146]], [[TMP147]]
; CHECK-NEXT: [[TMP149:%.*]] = getelementptr i8, ptr [[A]], i64 30
; CHECK-NEXT: [[TMP150:%.*]] = getelementptr i8, ptr [[B]], i64 30
; CHECK-NEXT: [[TMP151:%.*]] = load i8, ptr [[TMP149]], align 1
; CHECK-NEXT: [[TMP152:%.*]] = load i8, ptr [[TMP150]], align 1
-; CHECK-NEXT: [[TMP153:%.*]] = icmp ne i8 [[TMP151]], [[TMP152]]
-; CHECK-NEXT: br i1 [[TMP153]], label %[[RES_BLOCK]], label %[[LOADBB31:.*]]
-; CHECK: [[LOADBB31]]:
+; CHECK-NEXT: [[TMP177:%.*]] = xor i8 [[TMP151]], [[TMP152]]
; CHECK-NEXT: [[TMP154:%.*]] = getelementptr i8, ptr [[A]], i64 31
; CHECK-NEXT: [[TMP155:%.*]] = getelementptr i8, ptr [[B]], i64 31
; CHECK-NEXT: [[TMP156:%.*]] = load i8, ptr [[TMP154]], align 1
; CHECK-NEXT: [[TMP157:%.*]] = load i8, ptr [[TMP155]], align 1
-; CHECK-NEXT: [[TMP158:%.*]] = icmp ne i8 [[TMP156]], [[TMP157]]
+; CHECK-NEXT: [[TMP182:%.*]] = xor i8 [[TMP156]], [[TMP157]]
+; CHECK-NEXT: [[TMP183:%.*]] = or i8 [[TMP180]], [[TMP181]]
+; CHECK-NEXT: [[TMP184:%.*]] = or i8 [[TMP190]], [[TMP162]]
+; CHECK-NEXT: [[TMP185:%.*]] = or i8 [[TMP167]], [[TMP172]]
+; CHECK-NEXT: [[TMP186:%.*]] = or i8 [[TMP177]], [[TMP182]]
+; CHECK-NEXT: [[TMP187:%.*]] = or i8 [[TMP183]], [[TMP184]]
+; CHECK-NEXT: [[TMP188:%.*]] = or i8 [[TMP185]], [[TMP186]]
+; CHECK-NEXT: [[TMP189:%.*]] = or i8 [[TMP187]], [[TMP188]]
+; CHECK-NEXT: [[TMP158:%.*]] = icmp ne i8 [[TMP189]], 0
; CHECK-NEXT: br i1 [[TMP158]], label %[[RES_BLOCK]], label %[[ENDBLOCK]]
; CHECK: [[ENDBLOCK]]:
-; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, %[[LOADBB31]] ], [ 1, %[[RES_BLOCK]] ]
+; CHECK-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, %[[LOADBB24]] ], [ 1, %[[RES_BLOCK]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
diff --git a/llvm/test/Transforms/ExpandMemCmp/X86/memcmp.ll b/llvm/test/Transforms/ExpandMemCmp/X86/memcmp.ll
index f0b9da9622736..c7a276ea7b60e 100644
--- a/llvm/test/Transforms/ExpandMemCmp/X86/memcmp.ll
+++ b/llvm/test/Transforms/ExpandMemCmp/X86/memcmp.ll
@@ -35,31 +35,51 @@ define i32 @cmp2_align2(ptr nocapture readonly align 2 %x, ptr nocapture readonl
}
define i32 @cmp3(ptr nocapture readonly %x, ptr nocapture readonly %y) !prof !0 {
-; X64-LABEL: @cmp3(
-; X64-NEXT: br label [[LOADBB:%.*]]
-; X64: res_block:
-; X64-NEXT: [[TMP1:%.*]] = icmp ult i16 [[TMP7:%.*]], [[TMP8:%.*]]
-; X64-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1, !prof [[PROF1:![0-9]+]]
-; X64-NEXT: br label [[ENDBLOCK:%.*]]
-; X64: loadbb:
-; X64-NEXT: [[TMP5:%.*]] = load i16, ptr [[X:%.*]], align 1
-; X64-NEXT: [[TMP6:%.*]] = load i16, ptr [[Y:%.*]], align 1
-; X64-NEXT: [[TMP7]] = call i16 @llvm.bswap.i16(i16 [[TMP5]])
-; X64-NEXT: [[TMP8]] = call i16 @llvm.bswap.i16(i16 [[TMP6]])
-; X64-NEXT: [[TMP9:%.*]] = icmp eq i16 [[TMP7]], [[TMP8]]
-; X64-NEXT: br i1 [[TMP9]], label [[LOADBB1:%.*]], label [[RES_BLOCK:%.*]], !prof [[PROF1]]
-; X64: loadbb1:
-; X64-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[X]], i64 2
-; X64-NEXT: [[TMP11:%.*]] = getelementptr i8, ptr [[Y]], i64 2
-; X64-NEXT: [[TMP12:%.*]] = load i8, ptr [[TMP10]], align 1
-; X64-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP11]], align 1
-; X64-NEXT: [[TMP14:%.*]] = zext i8 [[TMP12]] to i32
-; X64-NEXT: [[TMP15:%.*]] = zext i8 [[TMP13]] to i32
-; X64-NEXT: [[TMP16:%.*]] = sub i32 [[TMP14]], [[TMP15]]
-; X64-NEXT: br label [[ENDBLOCK]]
-; X64: endblock:
-; X64-NEXT: [[PHI_RES:%.*]] = phi i32 [ [[TMP16]], [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
-; X64-NEXT: ret i32 [[PHI_RES]]
+; X64_1LD-LABEL: @cmp3(
+; X64_1LD-NEXT: br label [[LOADBB:%.*]]
+; X64_1LD: res_block:
+; X64_1LD-NEXT: [[TMP1:%.*]] = icmp ult i16 [[TMP5:%.*]], [[TMP6:%.*]]
+; X64_1LD-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1, !prof [[PROF1:![0-9]+]]
+; X64_1LD-NEXT: br label [[ENDBLOCK:%.*]]
+; X64_1LD: loadbb:
+; X64_1LD-NEXT: [[TMP3:%.*]] = load i16, ptr [[X:%.*]], align 1
+; X64_1LD-NEXT: [[TMP4:%.*]] = load i16, ptr [[Y:%.*]], align 1
+; X64_1LD-NEXT: [[TMP5]] = call i16 @llvm.bswap.i16(i16 [[TMP3]])
+; X64_1LD-NEXT: [[TMP6]] = call i16 @llvm.bswap.i16(i16 [[TMP4]])
+; X64_1LD-NEXT: [[TMP7:%.*]] = icmp eq i16 [[TMP5]], [[TMP6]]
+; X64_1LD-NEXT: br i1 [[TMP7]], label [[LOADBB1:%.*]], label [[RES_BLOCK:%.*]], !prof [[PROF1]]
+; X64_1LD: loadbb1:
+; X64_1LD-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[X]], i64 2
+; X64_1LD-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[Y]], i64 2
+; X64_1LD-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP8]], align 1
+; X64_1LD-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP9]], align 1
+; X64_1LD-NEXT: [[TMP12:%.*]] = zext i8 [[TMP10]] to i32
+; X64_1LD-NEXT: [[TMP13:%.*]] = zext i8 [[TMP11]] to i32
+; X64_1LD-NEXT: [[TMP14:%.*]] = sub i32 [[TMP12]], [[TMP13]]
+; X64_1LD-NEXT: br label [[ENDBLOCK]]
+; X64_1LD: endblock:
+; X64_1LD-NEXT: [[PHI_RES:%.*]] = phi i32 [ [[TMP14]], [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X64_1LD-NEXT: ret i32 [[PHI_RES]]
+;
+; X64_2LD-LABEL: @cmp3(
+; X64_2LD-NEXT: [[TMP1:%.*]] = load i16, ptr [[X:%.*]], align 1
+; X64_2LD-NEXT: [[TMP2:%.*]] = load i16, ptr [[Y:%.*]], align 1
+; X64_2LD-NEXT: [[TMP3:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP1]])
+; X64_2LD-NEXT: [[TMP4:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP2]])
+; X64_2LD-NEXT: [[TMP5:%.*]] = zext i16 [[TMP3]] to i32
+; X64_2LD-NEXT: [[TMP6:%.*]] = zext i16 [[TMP4]] to i32
+; X64_2LD-NEXT: [[TMP7:%.*]] = shl i32 [[TMP5]], 8
+; X64_2LD-NEXT: [[TMP8:%.*]] = shl i32 [[TMP6]], 8
+; X64_2LD-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[X]], i64 2
+; X64_2LD-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[Y]], i64 2
+; X64_2LD-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP9]], align 1
+; X64_2LD-NEXT: [[TMP12:%.*]] = load i8, ptr [[TMP10]], align 1
+; X64_2LD-NEXT: [[TMP13:%.*]] = zext i8 [[TMP11]] to i32
+; X64_2LD-NEXT: [[TMP14:%.*]] = zext i8 [[TMP12]] to i32
+; X64_2LD-NEXT: [[TMP15:%.*]] = or i32 [[TMP7]], [[TMP13]]
+; X64_2LD-NEXT: [[TMP16:%.*]] = or i32 [[TMP8]], [[TMP14]]
+; X64_2LD-NEXT: [[TMP17:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[TMP15]], i32 [[TMP16]])
+; X64_2LD-NEXT: ret i32 [[TMP17]]
;
%call = tail call i32 @memcmp(ptr %x, ptr %y, i64 3)
ret i32 %call
@@ -79,99 +99,163 @@ define i32 @cmp4(ptr nocapture readonly %x, ptr nocapture readonly %y) {
}
define i32 @cmp5(ptr nocapture readonly %x, ptr nocapture readonly %y) {
-; X64-LABEL: @cmp5(
-; X64-NEXT: br label [[LOADBB:%.*]]
-; X64: res_block:
-; X64-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP7:%.*]], [[TMP8:%.*]]
-; X64-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
-; X64-NEXT: br label [[ENDBLOCK:%.*]]
-; X64: loadbb:
-; X64-NEXT: [[TMP5:%.*]] = load i32, ptr [[X:%.*]], align 1
-; X64-NEXT: [[TMP6:%.*]] = load i32, ptr [[Y:%.*]], align 1
-; X64-NEXT: [[TMP7]] = call i32 @llvm.bswap.i32(i32 [[TMP5]])
-; X64-NEXT: [[TMP8]] = call i32 @llvm.bswap.i32(i32 [[TMP6]])
-; X64-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP7]], [[TMP8]]
-; X64-NEXT: br i1 [[TMP9]], label [[LOADBB1:%.*]], label [[RES_BLOCK:%.*]]
-; X64: loadbb1:
-; X64-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[X]], i64 4
-; X64-NEXT: [[TMP11:%.*]] = getelementptr i8, ptr [[Y]], i64 4
-; X64-NEXT: [[TMP12:%.*]] = load i8, ptr [[TMP10]], align 1
-; X64-NEXT: [[TMP13:%.*]] = load i8, ptr [[TMP11]], align 1
-; X64-NEXT: [[TMP14:%.*]] = zext i8 [[TMP12]] to i32
-; X64-NEXT: [[TMP15:%.*]] = zext i8 [[TMP13]] to i32
-; X64-NEXT: [[TMP16:%.*]] = sub i32 [[TMP14]], [[TMP15]]
-; X64-NEXT: br label [[ENDBLOCK]]
-; X64: endblock:
-; X64-NEXT: [[PHI_RES:%.*]] = phi i32 [ [[TMP16]], [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
-; X64-NEXT: ret i32 [[PHI_RES]]
+; X64_1LD-LABEL: @cmp5(
+; X64_1LD-NEXT: br label [[LOADBB:%.*]]
+; X64_1LD: res_block:
+; X64_1LD-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP5:%.*]], [[TMP6:%.*]]
+; X64_1LD-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; X64_1LD-NEXT: br label [[ENDBLOCK:%.*]]
+; X64_1LD: loadbb:
+; X64_1LD-NEXT: [[TMP3:%.*]] = load i32, ptr [[X:%.*]], align 1
+; X64_1LD-NEXT: [[TMP4:%.*]] = load i32, ptr [[Y:%.*]], align 1
+; X64_1LD-NEXT: [[TMP5]] = call i32 @llvm.bswap.i32(i32 [[TMP3]])
+; X64_1LD-NEXT: [[TMP6]] = call i32 @llvm.bswap.i32(i32 [[TMP4]])
+; X64_1LD-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP5]], [[TMP6]]
+; X64_1LD-NEXT: br i1 [[TMP7]], label [[LOADBB1:%.*]], label [[RES_BLOCK:%.*]]
+; X64_1LD: loadbb1:
+; X64_1LD-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[X]], i64 4
+; X64_1LD-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[Y]], i64 4
+; X64_1LD-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP8]], align 1
+; X64_1LD-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP9]], align 1
+; X64_1LD-NEXT: [[TMP12:%.*]] = zext i8 [[TMP10]] to i32
+; X64_1LD-NEXT: [[TMP13:%.*]] = zext i8 [[TMP11]] to i32
+; X64_1LD-NEXT: [[TMP14:%.*]] = sub i32 [[TMP12]], [[TMP13]]
+; X64_1LD-NEXT: br label [[ENDBLOCK]]
+; X64_1LD: endblock:
+; X64_1LD-NEXT: [[PHI_RES:%.*]] = phi i32 [ [[TMP14]], [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X64_1LD-NEXT: ret i32 [[PHI_RES]]
+;
+; X64_2LD-LABEL: @cmp5(
+; X64_2LD-NEXT: [[TMP1:%.*]] = load i32, ptr [[X:%.*]], align 1
+; X64_2LD-NEXT: [[TMP2:%.*]] = load i32, ptr [[Y:%.*]], align 1
+; X64_2LD-NEXT: [[TMP3:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP1]])
+; X64_2LD-NEXT: [[TMP4:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP2]])
+; X64_2LD-NEXT: [[TMP5:%.*]] = zext i32 [[TMP3]] to i64
+; X64_2LD-NEXT: [[TMP6:%.*]] = zext i32 [[TMP4]] to i64
+; X64_2LD-NEXT: [[TMP7:%.*]] = shl i64 [[TMP5]], 8
+; X64_2LD-NEXT: [[TMP8:%.*]] = shl i64 [[TMP6]], 8
+; X64_2LD-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[X]], i64 4
+; X64_2LD-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[Y]], i64 4
+; X64_2LD-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP9]], align 1
+; X64_2LD-NEXT: [[TMP12:%.*]] = load i8, ptr [[TMP10]], align 1
+; X64_2LD-NEXT: [[TMP13:%.*]] = zext i8 [[TMP11]] to i64
+; X64_2LD-NEXT: [[TMP14:%.*]] = zext i8 [[TMP12]] to i64
+; X64_2LD-NEXT: [[TMP15:%.*]] = or i64 [[TMP7]], [[TMP13]]
+; X64_2LD-NEXT: [[TMP16:%.*]] = or i64 [[TMP8]], [[TMP14]]
+; X64_2LD-NEXT: [[TMP17:%.*]] = call i32 @llvm.ucmp.i32.i64(i64 [[TMP15]], i64 [[TMP16]])
+; X64_2LD-NEXT: ret i32 [[TMP17]]
;
%call = tail call i32 @memcmp(ptr %x, ptr %y, i64 5)
ret i32 %call
}
define i32 @cmp6(ptr nocapture readonly %x, ptr nocapture readonly %y) {
-; X64-LABEL: @cmp6(
-; X64-NEXT: br label [[LOADBB:%.*]]
-; X64: res_block:
-; X64-NEXT: [[PHI_SRC1:%.*]] = phi i32 [ [[TMP7:%.*]], [[LOADBB]] ], [ [[TMP18:%.*]], [[LOADBB1:%.*]] ]
-; X64-NEXT: [[PHI_SRC2:%.*]] = phi i32 [ [[TMP8:%.*]], [[LOADBB]] ], [ [[TMP19:%.*]], [[LOADBB1]] ]
-; X64-NEXT: [[TMP1:%.*]] = icmp ult i32 [[PHI_SRC1]], [[PHI_SRC2]]
-; X64-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
-; X64-NEXT: br label [[ENDBLOCK:%.*]]
-; X64: loadbb:
-; X64-NEXT: [[TMP5:%.*]] = load i32, ptr [[X:%.*]], align 1
-; X64-NEXT: [[TMP6:%.*]] = load i32, ptr [[Y:%.*]], align 1
-; X64-NEXT: [[TMP7]] = call i32 @llvm.bswap.i32(i32 [[TMP5]])
-; X64-NEXT: [[TMP8]] = call i32 @llvm.bswap.i32(i32 [[TMP6]])
-; X64-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP7]], [[TMP8]]
-; X64-NEXT: br i1 [[TMP9]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
-; X64: loadbb1:
-; X64-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[X]], i64 4
-; X64-NEXT: [[TMP11:%.*]] = getelementptr i8, ptr [[Y]], i64 4
-; X64-NEXT: [[TMP14:%.*]] = load i16, ptr [[TMP10]], align 1
-; X64-NEXT: [[TMP15:%.*]] = load i16, ptr [[TMP11]], align 1
-; X64-NEXT: [[TMP16:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP14]])
-; X64-NEXT: [[TMP17:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP15]])
-; X64-NEXT: [[TMP18]] = zext i16 [[TMP16]] to i32
-; X64-NEXT: [[TMP19]] = zext i16 [[TMP17]] to i32
-; X64-NEXT: [[TMP20:%.*]] = icmp eq i32 [[TMP18]], [[TMP19]]
-; X64-NEXT: br i1 [[TMP20]], label [[ENDBLOCK]], label [[RES_BLOCK]]
-; X64: endblock:
-; X64-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
-; X64-NEXT: ret i32 [[PHI_RES]]
+; X64_1LD-LABEL: @cmp6(
+; X64_1LD-NEXT: br label [[LOADBB:%.*]]
+; X64_1LD: res_block:
+; X64_1LD-NEXT: [[PHI_SRC1:%.*]] = phi i32 [ [[TMP5:%.*]], [[LOADBB]] ], [ [[TMP14:%.*]], [[LOADBB1:%.*]] ]
+; X64_1LD-NEXT: [[PHI_SRC2:%.*]] = phi i32 [ [[TMP6:%.*]], [[LOADBB]] ], [ [[TMP15:%.*]], [[LOADBB1]] ]
+; X64_1LD-NEXT: [[TMP1:%.*]] = icmp ult i32 [[PHI_SRC1]], [[PHI_SRC2]]
+; X64_1LD-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; X64_1LD-NEXT: br label [[ENDBLOCK:%.*]]
+; X64_1LD: loadbb:
+; X64_1LD-NEXT: [[TMP3:%.*]] = load i32, ptr [[X:%.*]], align 1
+; X64_1LD-NEXT: [[TMP4:%.*]] = load i32, ptr [[Y:%.*]], align 1
+; X64_1LD-NEXT: [[TMP5]] = call i32 @llvm.bswap.i32(i32 [[TMP3]])
+; X64_1LD-NEXT: [[TMP6]] = call i32 @llvm.bswap.i32(i32 [[TMP4]])
+; X64_1LD-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP5]], [[TMP6]]
+; X64_1LD-NEXT: br i1 [[TMP7]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
+; X64_1LD: loadbb1:
+; X64_1LD-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[X]], i64 4
+; X64_1LD-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[Y]], i64 4
+; X64_1LD-NEXT: [[TMP10:%.*]] = load i16, ptr [[TMP8]], align 1
+; X64_1LD-NEXT: [[TMP11:%.*]] = load i16, ptr [[TMP9]], align 1
+; X64_1LD-NEXT: [[TMP12:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP10]])
+; X64_1LD-NEXT: [[TMP13:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP11]])
+; X64_1LD-NEXT: [[TMP14]] = zext i16 [[TMP12]] to i32
+; X64_1LD-NEXT: [[TMP15]] = zext i16 [[TMP13]] to i32
+; X64_1LD-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP14]], [[TMP15]]
+; X64_1LD-NEXT: br i1 [[TMP16]], label [[ENDBLOCK]], label [[RES_BLOCK]]
+; X64_1LD: endblock:
+; X64_1LD-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X64_1LD-NEXT: ret i32 [[PHI_RES]]
+;
+; X64_2LD-LABEL: @cmp6(
+; X64_2LD-NEXT: [[TMP1:%.*]] = load i32, ptr [[X:%.*]], align 1
+; X64_2LD-NEXT: [[TMP2:%.*]] = load i32, ptr [[Y:%.*]], align 1
+; X64_2LD-NEXT: [[TMP3:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP1]])
+; X64_2LD-NEXT: [[TMP4:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP2]])
+; X64_2LD-NEXT: [[TMP5:%.*]] = zext i32 [[TMP3]] to i64
+; X64_2LD-NEXT: [[TMP6:%.*]] = zext i32 [[TMP4]] to i64
+; X64_2LD-NEXT: [[TMP7:%.*]] = shl i64 [[TMP5]], 16
+; X64_2LD-NEXT: [[TMP8:%.*]] = shl i64 [[TMP6]], 16
+; X64_2LD-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[X]], i64 4
+; X64_2LD-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[Y]], i64 4
+; X64_2LD-NEXT: [[TMP11:%.*]] = load i16, ptr [[TMP9]], align 1
+; X64_2LD-NEXT: [[TMP12:%.*]] = load i16, ptr [[TMP10]], align 1
+; X64_2LD-NEXT: [[TMP13:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP11]])
+; X64_2LD-NEXT: [[TMP14:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP12]])
+; X64_2LD-NEXT: [[TMP15:%.*]] = zext i16 [[TMP13]] to i64
+; X64_2LD-NEXT: [[TMP16:%.*]] = zext i16 [[TMP14]] to i64
+; X64_2LD-NEXT: [[TMP17:%.*]] = or i64 [[TMP7]], [[TMP15]]
+; X64_2LD-NEXT: [[TMP18:%.*]] = or i64 [[TMP8]], [[TMP16]]
+; X64_2LD-NEXT: [[TMP19:%.*]] = call i32 @llvm.ucmp.i32.i64(i64 [[TMP17]], i64 [[TMP18]])
+; X64_2LD-NEXT: ret i32 [[TMP19]]
;
%call = tail call i32 @memcmp(ptr %x, ptr %y, i64 6)
ret i32 %call
}
define i32 @cmp7(ptr nocapture readonly %x, ptr nocapture readonly %y) {
-; X64-LABEL: @cmp7(
-; X64-NEXT: br label [[LOADBB:%.*]]
-; X64: res_block:
-; X64-NEXT: [[PHI_SRC1:%.*]] = phi i32 [ [[TMP7:%.*]], [[LOADBB]] ], [ [[TMP16:%.*]], [[LOADBB1:%.*]] ]
-; X64-NEXT: [[PHI_SRC2:%.*]] = phi i32 [ [[TMP8:%.*]], [[LOADBB]] ], [ [[TMP17:%.*]], [[LOADBB1]] ]
-; X64-NEXT: [[TMP1:%.*]] = icmp ult i32 [[PHI_SRC1]], [[PHI_SRC2]]
-; X64-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
-; X64-NEXT: br label [[ENDBLOCK:%.*]]
-; X64: loadbb:
-; X64-NEXT: [[TMP5:%.*]] = load i32, ptr [[X:%.*]], align 1
-; X64-NEXT: [[TMP6:%.*]] = load i32, ptr [[Y:%.*]], align 1
-; X64-NEXT: [[TMP7]] = call i32 @llvm.bswap.i32(i32 [[TMP5]])
-; X64-NEXT: [[TMP8]] = call i32 @llvm.bswap.i32(i32 [[TMP6]])
-; X64-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP7]], [[TMP8]]
-; X64-NEXT: br i1 [[TMP9]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
-; X64: loadbb1:
-; X64-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[X]], i64 3
-; X64-NEXT: [[TMP11:%.*]] = getelementptr i8, ptr [[Y]], i64 3
-; X64-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP10]], align 1
-; X64-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP11]], align 1
-; X64-NEXT: [[TMP16]] = call i32 @llvm.bswap.i32(i32 [[TMP14]])
-; X64-NEXT: [[TMP17]] = call i32 @llvm.bswap.i32(i32 [[TMP15]])
-; X64-NEXT: [[TMP18:%.*]] = icmp eq i32 [[TMP16]], [[TMP17]]
-; X64-NEXT: br i1 [[TMP18]], label [[ENDBLOCK]], label [[RES_BLOCK]]
-; X64: endblock:
-; X64-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
-; X64-NEXT: ret i32 [[PHI_RES]]
+; X64_1LD-LABEL: @cmp7(
+; X64_1LD-NEXT: br label [[LOADBB:%.*]]
+; X64_1LD: res_block:
+; X64_1LD-NEXT: [[PHI_SRC1:%.*]] = phi i32 [ [[TMP5:%.*]], [[LOADBB]] ], [ [[TMP12:%.*]], [[LOADBB1:%.*]] ]
+; X64_1LD-NEXT: [[PHI_SRC2:%.*]] = phi i32 [ [[TMP6:%.*]], [[LOADBB]] ], [ [[TMP13:%.*]], [[LOADBB1]] ]
+; X64_1LD-NEXT: [[TMP1:%.*]] = icmp ult i32 [[PHI_SRC1]], [[PHI_SRC2]]
+; X64_1LD-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; X64_1LD-NEXT: br label [[ENDBLOCK:%.*]]
+; X64_1LD: loadbb:
+; X64_1LD-NEXT: [[TMP3:%.*]] = load i32, ptr [[X:%.*]], align 1
+; X64_1LD-NEXT: [[TMP4:%.*]] = load i32, ptr [[Y:%.*]], align 1
+; X64_1LD-NEXT: [[TMP5]] = call i32 @llvm.bswap.i32(i32 [[TMP3]])
+; X64_1LD-NEXT: [[TMP6]] = call i32 @llvm.bswap.i32(i32 [[TMP4]])
+; X64_1LD-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP5]], [[TMP6]]
+; X64_1LD-NEXT: br i1 [[TMP7]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
+; X64_1LD: loadbb1:
+; X64_1LD-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[X]], i64 3
+; X64_1LD-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[Y]], i64 3
+; X64_1LD-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP8]], align 1
+; X64_1LD-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP9]], align 1
+; X64_1LD-NEXT: [[TMP12]] = call i32 @llvm.bswap.i32(i32 [[TMP10]])
+; X64_1LD-NEXT: [[TMP13]] = call i32 @llvm.bswap.i32(i32 [[TMP11]])
+; X64_1LD-NEXT: [[TMP14:%.*]] = icmp eq i32 [[TMP12]], [[TMP13]]
+; X64_1LD-NEXT: br i1 [[TMP14]], label [[ENDBLOCK]], label [[RES_BLOCK]]
+; X64_1LD: endblock:
+; X64_1LD-NEXT: [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X64_1LD-NEXT: ret i32 [[PHI_RES]]
+;
+; X64_2LD-LABEL: @cmp7(
+; X64_2LD-NEXT: [[TMP1:%.*]] = load i32, ptr [[X:%.*]], align 1
+; X64_2LD-NEXT: [[TMP2:%.*]] = load i32, ptr [[Y:%.*]], align 1
+; X64_2LD-NEXT: [[TMP3:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP1]])
+; X64_2LD-NEXT: [[TMP4:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP2]])
+; X64_2LD-NEXT: [[TMP5:%.*]] = zext i32 [[TMP3]] to i64
+; X64_2LD-NEXT: [[TMP6:%.*]] = zext i32 [[TMP4]] to i64
+; X64_2LD-NEXT: [[TMP7:%.*]] = shl i64 [[TMP5]], 32
+; X64_2LD-NEXT: [[TMP8:%.*]] = shl i64 [[TMP6]], 32
+; X64_2LD-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[X]], i64 3
+; X64_2LD-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[Y]], i64 3
+; X64_2LD-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP9]], align 1
+; X64_2LD-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP10]], align 1
+; X64_2LD-NEXT: [[TMP13:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP11]])
+; X64_2LD-NEXT: [[TMP14:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP12]])
+; X64_2LD-NEXT: [[TMP15:%.*]] = zext i32 [[TMP13]] to i64
+; X64_2LD-NEXT: [[TMP16:%.*]] = zext i32 [[TMP14]] to i64
+; X64_2LD-NEXT: [[TMP17:%.*]] = or i64 [[TMP7]], [[TMP15]]
+; X64_2LD-NEXT: [[TMP18:%.*]] = or i64 [[TMP8]], [[TMP16]]
+; X64_2LD-NEXT: [[TMP19:%.*]] = call i32 @llvm.ucmp.i32.i64(i64 [[TMP17]], i64 [[TMP18]])
+; X64_2LD-NEXT: ret i32 [[TMP19]]
;
%call = tail call i32 @memcmp(ptr %x, ptr %y, i64 7)
ret i32 %call
@@ -1084,5 +1168,4 @@ define i32 @cmp_eq16(ptr nocapture readonly %x, ptr nocapture readonly %y) {
; X64_1LD: [[PROF1]] = !{!"unknown", !"expand-memcmp"}
;.
; X64_2LD: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
-; X64_2LD: [[PROF1]] = !{!"unknown", !"expand-memcmp"}
;.
More information about the llvm-commits
mailing list