[llvm] dd48c0b - Add Load merge tests to AggressiveInstCombine

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 22 13:59:15 PDT 2022


Author: bipmis
Date: 2022-09-22T21:55:54+01:00
New Revision: dd48c0be55d69ec8ffd0c780d01c0478a81ddb88

URL: https://github.com/llvm/llvm-project/commit/dd48c0be55d69ec8ffd0c780d01c0478a81ddb88
DIFF: https://github.com/llvm/llvm-project/commit/dd48c0be55d69ec8ffd0c780d01c0478a81ddb88.diff

LOG: Add Load merge tests to AggressiveInstCombine

Added: 
    llvm/test/Transforms/AggressiveInstCombine/AArch64/or-load.ll
    llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/AggressiveInstCombine/AArch64/or-load.ll b/llvm/test/Transforms/AggressiveInstCombine/AArch64/or-load.ll
new file mode 100644
index 0000000000000..59a459e8243a0
--- /dev/null
+++ b/llvm/test/Transforms/AggressiveInstCombine/AArch64/or-load.ll
@@ -0,0 +1,1153 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=aggressive-instcombine -S -mtriple aarch64 -data-layout="e-n64" | FileCheck %s --check-prefixes=ALL
+; RUN: opt < %s -passes=aggressive-instcombine -S -mtriple aarch64 -data-layout="E-n64" | FileCheck %s --check-prefixes=ALL
+
+define i16 @loadCombine_2consecutive(ptr %p) {
+;
+; ALL-LABEL: @loadCombine_2consecutive(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i16 @loadCombine_2consecutive_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_2consecutive_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S1:%.*]] = shl i16 [[E1]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[S1]], [[E2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s1 = shl i16 %e1, 8
+  %o1 = or i16 %s1, %e2
+  ret i16 %o1
+}
+
+define i32 @loadCombine_4consecutive(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S1:%.*]] = shl i32 [[E1]], 24
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[E4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s1 = shl i32 %e1, 24
+  %s2 = shl i32 %e2, 16
+  %s3 = shl i32 %e3, 8
+
+  %o1 = or i32 %s1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %e4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_alias(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    store i8 10, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  store i8 10, i8* %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_alias_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    store i8 10, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S1:%.*]] = shl i32 [[E1]], 24
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[E4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  store i8 10, i8* %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s1 = shl i32 %e1, 24
+  %s2 = shl i32 %e2, 16
+  %s3 = shl i32 %e3, 8
+
+  %o1 = or i32 %s1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %e4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias2(ptr %p, ptr %pstr) {
+; ALL-LABEL: @loadCombine_4consecutive_alias2(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PSTR:%.*]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %pstr
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias2_BE(ptr %p, ptr %pstr) {
+; ALL-LABEL: @loadCombine_4consecutive_alias2_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PSTR:%.*]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S1:%.*]] = shl i32 [[E1]], 24
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[E4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %pstr
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s1 = shl i32 %e1, 24
+  %s2 = shl i32 %e2, 16
+  %s3 = shl i32 %e3, 8
+
+  %o1 = or i32 %s1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %e4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias3(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_alias3(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[P3]], align 1
+; ALL-NEXT:    store i8 5, ptr [[P]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %p3
+  store i8 5, i8* %p
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias3_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_alias3_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[P3]], align 1
+; ALL-NEXT:    store i8 5, ptr [[P]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S1:%.*]] = shl i32 [[E1]], 24
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[E4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %p3
+  store i8 5, i8* %p
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s1 = shl i32 %e1, 24
+  %s2 = shl i32 %e2, 16
+  %s3 = shl i32 %e3, 8
+
+  %o1 = or i32 %s1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %e4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_with_alias4(ptr %p, ptr %ps) {
+; ALL-LABEL: @loadCombine_4consecutive_with_alias4(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[PS1:%.*]] = getelementptr i8, ptr [[PS:%.*]], i32 1
+; ALL-NEXT:    [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i32 2
+; ALL-NEXT:    [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PS]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PS1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PS2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PS3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %ps1 = getelementptr i8, ptr %ps, i32 1
+  %ps2 = getelementptr i8, ptr %ps, i32 2
+  %ps3 = getelementptr i8, ptr %ps, i32 3
+  %l1 = load i8, ptr %p
+  store i8 10, i8* %ps
+  %l2 = load i8, ptr %p1
+  store i8 10, i8* %ps1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %ps2
+  %l4 = load i8, ptr %p3
+  store i8 10, i8* %ps3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+declare void @use(i8)
+declare void @use2(i32)
+
+define i32 @loadCombine_4consecutive_hasOneUse1(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_hasOneUse1(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    call void @use(i8 [[L1]])
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    call void @use(i8 [[L2]])
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    call void @use(i8 [[L3]])
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    call void @use(i8 [[L4]])
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  call void @use(i8 %l1)
+  %l2 = load i8, ptr %p1
+  call void @use(i8 %l2)
+  %l3 = load i8, ptr %p2
+  call void @use(i8 %l3)
+  %l4 = load i8, ptr %p3
+  call void @use(i8 %l4)
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_hasOneUse2(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_hasOneUse2(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    call void @use(i32 [[E1]])
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    call void @use(i32 [[E2]])
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    call void @use(i32 [[E3]])
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    call void @use(i32 [[E4]])
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  call void @use(i32 %e1)
+  %e2 = zext i8 %l2 to i32
+  call void @use(i32 %e2)
+  %e3 = zext i8 %l3 to i32
+  call void @use(i32 %e3)
+  %e4 = zext i8 %l4 to i32
+  call void @use(i32 %e4)
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_hasOneUse3(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_hasOneUse3(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    call void @use(i32 [[S2]])
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    call void @use(i32 [[S3]])
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    call void @use(i32 [[S4]])
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  call void @use(i32 %s2)
+  %s3 = shl i32 %e3, 16
+  call void @use(i32 %s3)
+  %s4 = shl i32 %e4, 24
+  call void @use(i32 %s4)
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_hasOneUse4(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_hasOneUse4(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    call void @use(i32 [[O1]])
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    call void @use(i32 [[O2]])
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  call void @use(i32 %o1)
+  %o2 = or i32 %o1, %s3
+  call void @use(i32 %o2)
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_parLoad1(ptr %p) {
+; ALL-LABEL: @loadCombine_parLoad1(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    ret i32 [[O2]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  ret i32 %o2
+}
+
+define i128 @loadCombine_i128(ptr %p) {
+; ALL-LABEL: @loadCombine_i128(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i32, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i32, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i32, ptr [[P]], align 4
+; ALL-NEXT:    [[L2:%.*]] = load i32, ptr [[P1]], align 4
+; ALL-NEXT:    [[L3:%.*]] = load i32, ptr [[P2]], align 4
+; ALL-NEXT:    [[L4:%.*]] = load i32, ptr [[P3]], align 4
+; ALL-NEXT:    [[E1:%.*]] = zext i32 [[L1]] to i128
+; ALL-NEXT:    [[E2:%.*]] = zext i32 [[L2]] to i128
+; ALL-NEXT:    [[E3:%.*]] = zext i32 [[L3]] to i128
+; ALL-NEXT:    [[E4:%.*]] = zext i32 [[L4]] to i128
+; ALL-NEXT:    [[S2:%.*]] = shl i128 [[E2]], 32
+; ALL-NEXT:    [[S3:%.*]] = shl i128 [[E3]], 64
+; ALL-NEXT:    [[S4:%.*]] = shl i128 [[E4]], 96
+; ALL-NEXT:    [[O1:%.*]] = or i128 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i128 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i128 [[O2]], [[S4]]
+; ALL-NEXT:    ret i128 [[O3]]
+;
+  %p1 = getelementptr i32, ptr %p, i32 1
+  %p2 = getelementptr i32, ptr %p, i32 2
+  %p3 = getelementptr i32, ptr %p, i32 3
+  %l1 = load i32, ptr %p
+  %l2 = load i32, ptr %p1
+  %l3 = load i32, ptr %p2
+  %l4 = load i32, ptr %p3
+
+  %e1 = zext i32 %l1 to i128
+  %e2 = zext i32 %l2 to i128
+  %e3 = zext i32 %l3 to i128
+  %e4 = zext i32 %l4 to i128
+
+  %s2 = shl i128 %e2, 32
+  %s3 = shl i128 %e3, 64
+  %s4 = shl i128 %e4, 96
+
+  %o1 = or i128 %e1, %s2
+  %o2 = or i128 %o1, %s3
+  %o3 = or i128 %o2, %s4
+  ret i128 %o3
+}
+
+define i128 @loadCombine_i128_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_i128_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i32, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i32, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i32, ptr [[P]], align 4
+; ALL-NEXT:    [[L2:%.*]] = load i32, ptr [[P1]], align 4
+; ALL-NEXT:    [[L3:%.*]] = load i32, ptr [[P2]], align 4
+; ALL-NEXT:    [[L4:%.*]] = load i32, ptr [[P3]], align 4
+; ALL-NEXT:    [[E1:%.*]] = zext i32 [[L1]] to i128
+; ALL-NEXT:    [[E2:%.*]] = zext i32 [[L2]] to i128
+; ALL-NEXT:    [[E3:%.*]] = zext i32 [[L3]] to i128
+; ALL-NEXT:    [[E4:%.*]] = zext i32 [[L4]] to i128
+; ALL-NEXT:    [[S1:%.*]] = shl i128 [[E1]], 96
+; ALL-NEXT:    [[S2:%.*]] = shl i128 [[E2]], 64
+; ALL-NEXT:    [[S3:%.*]] = shl i128 [[E3]], 32
+; ALL-NEXT:    [[O1:%.*]] = or i128 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i128 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i128 [[O2]], [[E4]]
+; ALL-NEXT:    ret i128 [[O3]]
+;
+  %p1 = getelementptr i32, ptr %p, i32 1
+  %p2 = getelementptr i32, ptr %p, i32 2
+  %p3 = getelementptr i32, ptr %p, i32 3
+  %l1 = load i32, ptr %p
+  %l2 = load i32, ptr %p1
+  %l3 = load i32, ptr %p2
+  %l4 = load i32, ptr %p3
+
+  %e1 = zext i32 %l1 to i128
+  %e2 = zext i32 %l2 to i128
+  %e3 = zext i32 %l3 to i128
+  %e4 = zext i32 %l4 to i128
+
+  %s1 = shl i128 %e1, 96
+  %s2 = shl i128 %e2, 64
+  %s3 = shl i128 %e3, 32
+
+  %o1 = or i128 %s1, %s2
+  %o2 = or i128 %o1, %s3
+  %o3 = or i128 %o2, %e4
+  ret i128 %o3
+}
+
+define i64 @loadCombine_i64(ptr %p) {
+; ALL-LABEL: @loadCombine_i64(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i16, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i16, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i16, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i16, ptr [[P]], align 2
+; ALL-NEXT:    [[L2:%.*]] = load i16, ptr [[P1]], align 2
+; ALL-NEXT:    [[L3:%.*]] = load i16, ptr [[P2]], align 2
+; ALL-NEXT:    [[L4:%.*]] = load i16, ptr [[P3]], align 2
+; ALL-NEXT:    [[E1:%.*]] = zext i16 [[L1]] to i64
+; ALL-NEXT:    [[E2:%.*]] = zext i16 [[L2]] to i64
+; ALL-NEXT:    [[E3:%.*]] = zext i16 [[L3]] to i64
+; ALL-NEXT:    [[E4:%.*]] = zext i16 [[L4]] to i64
+; ALL-NEXT:    [[S2:%.*]] = shl i64 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i64 [[E3]], 32
+; ALL-NEXT:    [[S4:%.*]] = shl i64 [[E4]], 48
+; ALL-NEXT:    [[O1:%.*]] = or i64 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i64 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i64 [[O2]], [[S4]]
+; ALL-NEXT:    ret i64 [[O3]]
+;
+  %p1 = getelementptr i16, ptr %p, i32 1
+  %p2 = getelementptr i16, ptr %p, i32 2
+  %p3 = getelementptr i16, ptr %p, i32 3
+  %l1 = load i16, ptr %p
+  %l2 = load i16, ptr %p1
+  %l3 = load i16, ptr %p2
+  %l4 = load i16, ptr %p3
+
+  %e1 = zext i16 %l1 to i64
+  %e2 = zext i16 %l2 to i64
+  %e3 = zext i16 %l3 to i64
+  %e4 = zext i16 %l4 to i64
+
+  %s2 = shl i64 %e2, 16
+  %s3 = shl i64 %e3, 32
+  %s4 = shl i64 %e4, 48
+
+  %o1 = or i64 %e1, %s2
+  %o2 = or i64 %o1, %s3
+  %o3 = or i64 %o2, %s4
+  ret i64 %o3
+}
+
+define i64 @loadCombine_i64_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_i64_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i16, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i16, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i16, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i16, ptr [[P]], align 2
+; ALL-NEXT:    [[L2:%.*]] = load i16, ptr [[P1]], align 2
+; ALL-NEXT:    [[L3:%.*]] = load i16, ptr [[P2]], align 2
+; ALL-NEXT:    [[L4:%.*]] = load i16, ptr [[P3]], align 2
+; ALL-NEXT:    [[E1:%.*]] = zext i16 [[L1]] to i64
+; ALL-NEXT:    [[E2:%.*]] = zext i16 [[L2]] to i64
+; ALL-NEXT:    [[E3:%.*]] = zext i16 [[L3]] to i64
+; ALL-NEXT:    [[E4:%.*]] = zext i16 [[L4]] to i64
+; ALL-NEXT:    [[S1:%.*]] = shl i64 [[E1]], 48
+; ALL-NEXT:    [[S2:%.*]] = shl i64 [[E2]], 32
+; ALL-NEXT:    [[S3:%.*]] = shl i64 [[E3]], 16
+; ALL-NEXT:    [[O1:%.*]] = or i64 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i64 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i64 [[O2]], [[E4]]
+; ALL-NEXT:    ret i64 [[O3]]
+;
+  %p1 = getelementptr i16, ptr %p, i32 1
+  %p2 = getelementptr i16, ptr %p, i32 2
+  %p3 = getelementptr i16, ptr %p, i32 3
+  %l1 = load i16, ptr %p
+  %l2 = load i16, ptr %p1
+  %l3 = load i16, ptr %p2
+  %l4 = load i16, ptr %p3
+
+  %e1 = zext i16 %l1 to i64
+  %e2 = zext i16 %l2 to i64
+  %e3 = zext i16 %l3 to i64
+  %e4 = zext i16 %l4 to i64
+
+  %s1 = shl i64 %e1, 48
+  %s2 = shl i64 %e2, 32
+  %s3 = shl i64 %e3, 16
+
+  %o1 = or i64 %s1, %s2
+  %o2 = or i64 %o1, %s3
+  %o3 = or i64 %o2, %e4
+  ret i64 %o3
+}
+
+define i16 @loadCombine_2consecutive_atomic(ptr %p) {
+; ALL-LABEL: @loadCombine_2consecutive_atomic(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load atomic i8, ptr [[P]] monotonic, align 1
+; ALL-NEXT:    [[L2:%.*]] = load atomic i8, ptr [[P1]] monotonic, align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load atomic i8, ptr %p monotonic, align 1
+  %l2 = load atomic i8, ptr %p1 monotonic, align 1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i16 @loadCombine_2consecutive_volatile(ptr %p) {
+; ALL-LABEL: @loadCombine_2consecutive_volatile(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load volatile i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load volatile i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load volatile i8, ptr %p, align 1
+  %l2 = load volatile i8, ptr %p1, align 1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i16 @loadCombine_2consecutive_separateBB(ptr %p) {
+; ALL-LABEL: @loadCombine_2consecutive_separateBB(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    br label [[BB2:%.*]]
+; ALL:       bb2:
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load i8, ptr %p, align 1
+  br label %bb2
+bb2:
+  %l2 = load i8, ptr %p1, align 1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i16 @loadCombine_2consecutive_separateptr(ptr %p, ptr %p2) {
+; ALL-LABEL: @loadCombine_2consecutive_separateptr(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P2:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P:%.*]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p2, i32 1
+  %l1 = load i8, ptr %p, align 1
+  %l2 = load i8, ptr %p1, align 1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i64 @load64_farLoads(ptr %ptr) {
+; ALL-LABEL: @load64_farLoads(
+; ALL-NEXT:  entry:
+; ALL-NEXT:    [[TMP0:%.*]] = load i8, ptr [[PTR:%.*]], align 1
+; ALL-NEXT:    [[CONV:%.*]] = zext i8 [[TMP0]] to i64
+; ALL-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1
+; ALL-NEXT:    [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
+; ALL-NEXT:    [[CONV2:%.*]] = zext i8 [[TMP1]] to i64
+; ALL-NEXT:    [[SHL:%.*]] = shl i64 [[CONV2]], 8
+; ALL-NEXT:    [[OR:%.*]] = or i64 [[CONV]], [[SHL]]
+; ALL-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 2
+; ALL-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ARRAYIDX3]], align 1
+; ALL-NEXT:    [[CONV4:%.*]] = zext i8 [[TMP2]] to i64
+; ALL-NEXT:    [[SHL5:%.*]] = shl i64 [[CONV4]], 16
+; ALL-NEXT:    [[OR6:%.*]] = or i64 [[OR]], [[SHL5]]
+; ALL-NEXT:    [[ARRAYIDX7:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 3
+; ALL-NEXT:    [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX7]], align 1
+; ALL-NEXT:    [[CONV8:%.*]] = zext i8 [[TMP3]] to i64
+; ALL-NEXT:    [[SHL9:%.*]] = shl i64 [[CONV8]], 24
+; ALL-NEXT:    [[OR10:%.*]] = or i64 [[OR6]], [[SHL9]]
+; ALL-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 4
+; ALL-NEXT:    [[TMP4:%.*]] = load i8, ptr [[ARRAYIDX11]], align 1
+; ALL-NEXT:    [[CONV12:%.*]] = zext i8 [[TMP4]] to i64
+; ALL-NEXT:    [[SHL13:%.*]] = shl i64 [[CONV12]], 32
+; ALL-NEXT:    [[OR14:%.*]] = or i64 [[OR10]], [[SHL13]]
+; ALL-NEXT:    [[ARRAYIDX15:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 5
+; ALL-NEXT:    [[TMP5:%.*]] = load i8, ptr [[ARRAYIDX15]], align 1
+; ALL-NEXT:    [[CONV16:%.*]] = zext i8 [[TMP5]] to i64
+; ALL-NEXT:    [[SHL17:%.*]] = shl i64 [[CONV16]], 40
+; ALL-NEXT:    [[OR18:%.*]] = or i64 [[OR14]], [[SHL17]]
+; ALL-NEXT:    [[ARRAYIDX19:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 6
+; ALL-NEXT:    [[TMP6:%.*]] = load i8, ptr [[ARRAYIDX19]], align 1
+; ALL-NEXT:    [[CONV20:%.*]] = zext i8 [[TMP6]] to i64
+; ALL-NEXT:    [[SHL21:%.*]] = shl i64 [[CONV20]], 48
+; ALL-NEXT:    [[OR22:%.*]] = or i64 [[OR18]], [[SHL21]]
+; ALL-NEXT:    [[ARRAYIDX23:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 7
+; ALL-NEXT:    [[TMP7:%.*]] = load i8, ptr [[ARRAYIDX23]], align 1
+; ALL-NEXT:    [[CONV24:%.*]] = zext i8 [[TMP7]] to i64
+; ALL-NEXT:    [[SHL25:%.*]] = shl i64 [[CONV24]], 56
+; ALL-NEXT:    [[OR26:%.*]] = or i64 [[OR22]], [[SHL25]]
+; ALL-NEXT:    ret i64 [[OR26]]
+;
+entry:
+  %0 = load i8, ptr %ptr, align 1
+  %conv = zext i8 %0 to i64
+  %arrayidx1 = getelementptr inbounds i8, ptr %ptr, i64 1
+  %1 = load i8, ptr %arrayidx1, align 1
+  %conv2 = zext i8 %1 to i64
+  %shl = shl i64 %conv2, 8
+  %or = or i64 %conv, %shl
+  %arrayidx3 = getelementptr inbounds i8, ptr %ptr, i64 2
+  %2 = load i8, ptr %arrayidx3, align 1
+  %conv4 = zext i8 %2 to i64
+  %shl5 = shl i64 %conv4, 16
+  %or6 = or i64 %or, %shl5
+  %arrayidx7 = getelementptr inbounds i8, ptr %ptr, i64 3
+  %3 = load i8, ptr %arrayidx7, align 1
+  %conv8 = zext i8 %3 to i64
+  %shl9 = shl i64 %conv8, 24
+  %or10 = or i64 %or6, %shl9
+  %arrayidx11 = getelementptr inbounds i8, ptr %ptr, i64 4
+  %4 = load i8, ptr %arrayidx11, align 1
+  %conv12 = zext i8 %4 to i64
+  %shl13 = shl i64 %conv12, 32
+  %or14 = or i64 %or10, %shl13
+  %arrayidx15 = getelementptr inbounds i8, ptr %ptr, i64 5
+  %5 = load i8, ptr %arrayidx15, align 1
+  %conv16 = zext i8 %5 to i64
+  %shl17 = shl i64 %conv16, 40
+  %or18 = or i64 %or14, %shl17
+  %arrayidx19 = getelementptr inbounds i8, ptr %ptr, i64 6
+  %6 = load i8, ptr %arrayidx19, align 1
+  %conv20 = zext i8 %6 to i64
+  %shl21 = shl i64 %conv20, 48
+  %or22 = or i64 %or18, %shl21
+  %arrayidx23 = getelementptr inbounds i8, ptr %ptr, i64 7
+  %7 = load i8, ptr %arrayidx23, align 1
+  %conv24 = zext i8 %7 to i64
+  %shl25 = shl i64 %conv24, 56
+  %or26 = or i64 %or22, %shl25
+  ret i64 %or26
+}
+
+define i32 @loadCombine_4consecutive_metadata(ptr %p, ptr %pstr) {
+; ALL-LABEL: @loadCombine_4consecutive_metadata(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1, !alias.scope !0
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1, !alias.scope !0
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1, !alias.scope !0
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1, !alias.scope !0
+; ALL-NEXT:    store i32 25, ptr [[PSTR:%.*]], align 4, !noalias !0
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p, !alias.scope !2
+  %l2 = load i8, ptr %p1, !alias.scope !2
+  %l3 = load i8, ptr %p2, !alias.scope !2
+  %l4 = load i8, ptr %p3, !alias.scope !2
+  store i32 25, ptr %pstr, !noalias !2
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+!0 = distinct !{!0}
+!1 = distinct !{!1, !0}
+!2 = !{!1}
+
+; CHECK: !0 = !{!1}
+; CHECK: !1 = distinct !{!1, !2}
+; CHECK: !2 = distinct !{!2}
+
+define i16 @loadCombine_4consecutive_4bit(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_4bit(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i4, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i4, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i4, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i4, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i4, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i4, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i4, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i4 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i4 [[L2]] to i16
+; ALL-NEXT:    [[E3:%.*]] = zext i4 [[L3]] to i16
+; ALL-NEXT:    [[E4:%.*]] = zext i4 [[L4]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 4
+; ALL-NEXT:    [[S3:%.*]] = shl i16 [[E3]], 8
+; ALL-NEXT:    [[S4:%.*]] = shl i16 [[E4]], 12
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i16 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i16 [[O2]], [[S4]]
+; ALL-NEXT:    ret i16 [[O3]]
+;
+  %p1 = getelementptr i4, ptr %p, i32 1
+  %p2 = getelementptr i4, ptr %p, i32 2
+  %p3 = getelementptr i4, ptr %p, i32 3
+  %l1 = load i4, ptr %p
+  %l2 = load i4, ptr %p1
+  %l3 = load i4, ptr %p2
+  %l4 = load i4, ptr %p3
+  %e1 = zext i4 %l1 to i16
+  %e2 = zext i4 %l2 to i16
+  %e3 = zext i4 %l3 to i16
+  %e4 = zext i4 %l4 to i16
+  %s2 = shl i16 %e2, 4
+  %s3 = shl i16 %e3, 8
+  %s4 = shl i16 %e4, 12
+  %o1 = or i16 %e1, %s2
+  %o2 = or i16 %o1, %s3
+  %o3 = or i16 %o2, %s4
+  ret i16 %o3
+}

diff  --git a/llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll b/llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll
new file mode 100644
index 0000000000000..9258fa4f59e82
--- /dev/null
+++ b/llvm/test/Transforms/AggressiveInstCombine/X86/or-load.ll
@@ -0,0 +1,1154 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=aggressive-instcombine -mtriple x86_64-none-eabi -mattr=avx2 -data-layout="e-n64" -S | FileCheck %s --check-prefixes=ALL
+; RUN: opt < %s -passes=aggressive-instcombine -mtriple x86_64-none-eabi -mattr=avx2 -data-layout="E-n64" -S | FileCheck %s --check-prefixes=ALL
+
+define i16 @loadCombine_2consecutive(ptr %p) {
+;
+; ALL-LABEL: @loadCombine_2consecutive(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i16 @loadCombine_2consecutive_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_2consecutive_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S1:%.*]] = shl i16 [[E1]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[S1]], [[E2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s1 = shl i16 %e1, 8
+  %o1 = or i16 %s1, %e2
+  ret i16 %o1
+}
+
+define i32 @loadCombine_4consecutive(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S1:%.*]] = shl i32 [[E1]], 24
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[E4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s1 = shl i32 %e1, 24
+  %s2 = shl i32 %e2, 16
+  %s3 = shl i32 %e3, 8
+
+  %o1 = or i32 %s1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %e4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_alias(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    store i8 10, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  store i8 10, i8* %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_alias_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    store i8 10, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S1:%.*]] = shl i32 [[E1]], 24
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[E4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  store i8 10, i8* %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s1 = shl i32 %e1, 24
+  %s2 = shl i32 %e2, 16
+  %s3 = shl i32 %e3, 8
+
+  %o1 = or i32 %s1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %e4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias2(ptr %p, ptr %pstr) {
+; ALL-LABEL: @loadCombine_4consecutive_alias2(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PSTR:%.*]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %pstr
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias2_BE(ptr %p, ptr %pstr) {
+; ALL-LABEL: @loadCombine_4consecutive_alias2_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PSTR:%.*]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S1:%.*]] = shl i32 [[E1]], 24
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[E4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %pstr
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s1 = shl i32 %e1, 24
+  %s2 = shl i32 %e2, 16
+  %s3 = shl i32 %e3, 8
+
+  %o1 = or i32 %s1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %e4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias3(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_alias3(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[P3]], align 1
+; ALL-NEXT:    store i8 5, ptr [[P]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %p3
+  store i8 5, i8* %p
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_alias3_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_alias3_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[P3]], align 1
+; ALL-NEXT:    store i8 5, ptr [[P]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S1:%.*]] = shl i32 [[E1]], 24
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[E4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %p3
+  store i8 5, i8* %p
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s1 = shl i32 %e1, 24
+  %s2 = shl i32 %e2, 16
+  %s3 = shl i32 %e3, 8
+
+  %o1 = or i32 %s1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %e4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_with_alias4(ptr %p, ptr %ps) {
+; ALL-LABEL: @loadCombine_4consecutive_with_alias4(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[PS1:%.*]] = getelementptr i8, ptr [[PS:%.*]], i32 1
+; ALL-NEXT:    [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i32 2
+; ALL-NEXT:    [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PS]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PS1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PS2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    store i8 10, ptr [[PS3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %ps1 = getelementptr i8, ptr %ps, i32 1
+  %ps2 = getelementptr i8, ptr %ps, i32 2
+  %ps3 = getelementptr i8, ptr %ps, i32 3
+  %l1 = load i8, ptr %p
+  store i8 10, i8* %ps
+  %l2 = load i8, ptr %p1
+  store i8 10, i8* %ps1
+  %l3 = load i8, ptr %p2
+  store i8 10, i8* %ps2
+  %l4 = load i8, ptr %p3
+  store i8 10, i8* %ps3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+declare void @use(i8)
+declare void @use2(i32)
+
+define i32 @loadCombine_4consecutive_hasOneUse1(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_hasOneUse1(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    call void @use(i8 [[L1]])
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    call void @use(i8 [[L2]])
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    call void @use(i8 [[L3]])
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    call void @use(i8 [[L4]])
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  call void @use(i8 %l1)
+  %l2 = load i8, ptr %p1
+  call void @use(i8 %l2)
+  %l3 = load i8, ptr %p2
+  call void @use(i8 %l3)
+  %l4 = load i8, ptr %p3
+  call void @use(i8 %l4)
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_hasOneUse2(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_hasOneUse2(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    call void @use(i32 [[E1]])
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    call void @use(i32 [[E2]])
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    call void @use(i32 [[E3]])
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    call void @use(i32 [[E4]])
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  call void @use(i32 %e1)
+  %e2 = zext i8 %l2 to i32
+  call void @use(i32 %e2)
+  %e3 = zext i8 %l3 to i32
+  call void @use(i32 %e3)
+  %e4 = zext i8 %l4 to i32
+  call void @use(i32 %e4)
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_hasOneUse3(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_hasOneUse3(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    call void @use(i32 [[S2]])
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    call void @use(i32 [[S3]])
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    call void @use(i32 [[S4]])
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  call void @use(i32 %s2)
+  %s3 = shl i32 %e3, 16
+  call void @use(i32 %s3)
+  %s4 = shl i32 %e4, 24
+  call void @use(i32 %s4)
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_4consecutive_hasOneUse4(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_hasOneUse4(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    call void @use(i32 [[O1]])
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    call void @use(i32 [[O2]])
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+  %l4 = load i8, ptr %p3
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  call void @use(i32 %o1)
+  %o2 = or i32 %o1, %s3
+  call void @use(i32 %o2)
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+define i32 @loadCombine_parLoad1(ptr %p) {
+; ALL-LABEL: @loadCombine_parLoad1(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    ret i32 [[O2]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %l1 = load i8, ptr %p
+  %l2 = load i8, ptr %p1
+  %l3 = load i8, ptr %p2
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  ret i32 %o2
+}
+
+define i128 @loadCombine_i128(ptr %p) {
+; ALL-LABEL: @loadCombine_i128(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i32, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i32, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i32, ptr [[P]], align 4
+; ALL-NEXT:    [[L2:%.*]] = load i32, ptr [[P1]], align 4
+; ALL-NEXT:    [[L3:%.*]] = load i32, ptr [[P2]], align 4
+; ALL-NEXT:    [[L4:%.*]] = load i32, ptr [[P3]], align 4
+; ALL-NEXT:    [[E1:%.*]] = zext i32 [[L1]] to i128
+; ALL-NEXT:    [[E2:%.*]] = zext i32 [[L2]] to i128
+; ALL-NEXT:    [[E3:%.*]] = zext i32 [[L3]] to i128
+; ALL-NEXT:    [[E4:%.*]] = zext i32 [[L4]] to i128
+; ALL-NEXT:    [[S2:%.*]] = shl i128 [[E2]], 32
+; ALL-NEXT:    [[S3:%.*]] = shl i128 [[E3]], 64
+; ALL-NEXT:    [[S4:%.*]] = shl i128 [[E4]], 96
+; ALL-NEXT:    [[O1:%.*]] = or i128 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i128 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i128 [[O2]], [[S4]]
+; ALL-NEXT:    ret i128 [[O3]]
+;
+  %p1 = getelementptr i32, ptr %p, i32 1
+  %p2 = getelementptr i32, ptr %p, i32 2
+  %p3 = getelementptr i32, ptr %p, i32 3
+  %l1 = load i32, ptr %p
+  %l2 = load i32, ptr %p1
+  %l3 = load i32, ptr %p2
+  %l4 = load i32, ptr %p3
+
+  %e1 = zext i32 %l1 to i128
+  %e2 = zext i32 %l2 to i128
+  %e3 = zext i32 %l3 to i128
+  %e4 = zext i32 %l4 to i128
+
+  %s2 = shl i128 %e2, 32
+  %s3 = shl i128 %e3, 64
+  %s4 = shl i128 %e4, 96
+
+  %o1 = or i128 %e1, %s2
+  %o2 = or i128 %o1, %s3
+  %o3 = or i128 %o2, %s4
+  ret i128 %o3
+}
+
+define i128 @loadCombine_i128_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_i128_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i32, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i32, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i32, ptr [[P]], align 4
+; ALL-NEXT:    [[L2:%.*]] = load i32, ptr [[P1]], align 4
+; ALL-NEXT:    [[L3:%.*]] = load i32, ptr [[P2]], align 4
+; ALL-NEXT:    [[L4:%.*]] = load i32, ptr [[P3]], align 4
+; ALL-NEXT:    [[E1:%.*]] = zext i32 [[L1]] to i128
+; ALL-NEXT:    [[E2:%.*]] = zext i32 [[L2]] to i128
+; ALL-NEXT:    [[E3:%.*]] = zext i32 [[L3]] to i128
+; ALL-NEXT:    [[E4:%.*]] = zext i32 [[L4]] to i128
+; ALL-NEXT:    [[S1:%.*]] = shl i128 [[E1]], 96
+; ALL-NEXT:    [[S2:%.*]] = shl i128 [[E2]], 64
+; ALL-NEXT:    [[S3:%.*]] = shl i128 [[E3]], 32
+; ALL-NEXT:    [[O1:%.*]] = or i128 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i128 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i128 [[O2]], [[E4]]
+; ALL-NEXT:    ret i128 [[O3]]
+;
+  %p1 = getelementptr i32, ptr %p, i32 1
+  %p2 = getelementptr i32, ptr %p, i32 2
+  %p3 = getelementptr i32, ptr %p, i32 3
+  %l1 = load i32, ptr %p
+  %l2 = load i32, ptr %p1
+  %l3 = load i32, ptr %p2
+  %l4 = load i32, ptr %p3
+
+  %e1 = zext i32 %l1 to i128
+  %e2 = zext i32 %l2 to i128
+  %e3 = zext i32 %l3 to i128
+  %e4 = zext i32 %l4 to i128
+
+  %s1 = shl i128 %e1, 96
+  %s2 = shl i128 %e2, 64
+  %s3 = shl i128 %e3, 32
+
+  %o1 = or i128 %s1, %s2
+  %o2 = or i128 %o1, %s3
+  %o3 = or i128 %o2, %e4
+  ret i128 %o3
+}
+
+define i64 @loadCombine_i64(ptr %p) {
+; ALL-LABEL: @loadCombine_i64(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i16, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i16, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i16, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i16, ptr [[P]], align 2
+; ALL-NEXT:    [[L2:%.*]] = load i16, ptr [[P1]], align 2
+; ALL-NEXT:    [[L3:%.*]] = load i16, ptr [[P2]], align 2
+; ALL-NEXT:    [[L4:%.*]] = load i16, ptr [[P3]], align 2
+; ALL-NEXT:    [[E1:%.*]] = zext i16 [[L1]] to i64
+; ALL-NEXT:    [[E2:%.*]] = zext i16 [[L2]] to i64
+; ALL-NEXT:    [[E3:%.*]] = zext i16 [[L3]] to i64
+; ALL-NEXT:    [[E4:%.*]] = zext i16 [[L4]] to i64
+; ALL-NEXT:    [[S2:%.*]] = shl i64 [[E2]], 16
+; ALL-NEXT:    [[S3:%.*]] = shl i64 [[E3]], 32
+; ALL-NEXT:    [[S4:%.*]] = shl i64 [[E4]], 48
+; ALL-NEXT:    [[O1:%.*]] = or i64 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i64 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i64 [[O2]], [[S4]]
+; ALL-NEXT:    ret i64 [[O3]]
+;
+  %p1 = getelementptr i16, ptr %p, i32 1
+  %p2 = getelementptr i16, ptr %p, i32 2
+  %p3 = getelementptr i16, ptr %p, i32 3
+  %l1 = load i16, ptr %p
+  %l2 = load i16, ptr %p1
+  %l3 = load i16, ptr %p2
+  %l4 = load i16, ptr %p3
+
+  %e1 = zext i16 %l1 to i64
+  %e2 = zext i16 %l2 to i64
+  %e3 = zext i16 %l3 to i64
+  %e4 = zext i16 %l4 to i64
+
+  %s2 = shl i64 %e2, 16
+  %s3 = shl i64 %e3, 32
+  %s4 = shl i64 %e4, 48
+
+  %o1 = or i64 %e1, %s2
+  %o2 = or i64 %o1, %s3
+  %o3 = or i64 %o2, %s4
+  ret i64 %o3
+}
+
+define i64 @loadCombine_i64_BE(ptr %p) {
+; ALL-LABEL: @loadCombine_i64_BE(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i16, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i16, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i16, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i16, ptr [[P]], align 2
+; ALL-NEXT:    [[L2:%.*]] = load i16, ptr [[P1]], align 2
+; ALL-NEXT:    [[L3:%.*]] = load i16, ptr [[P2]], align 2
+; ALL-NEXT:    [[L4:%.*]] = load i16, ptr [[P3]], align 2
+; ALL-NEXT:    [[E1:%.*]] = zext i16 [[L1]] to i64
+; ALL-NEXT:    [[E2:%.*]] = zext i16 [[L2]] to i64
+; ALL-NEXT:    [[E3:%.*]] = zext i16 [[L3]] to i64
+; ALL-NEXT:    [[E4:%.*]] = zext i16 [[L4]] to i64
+; ALL-NEXT:    [[S1:%.*]] = shl i64 [[E1]], 48
+; ALL-NEXT:    [[S2:%.*]] = shl i64 [[E2]], 32
+; ALL-NEXT:    [[S3:%.*]] = shl i64 [[E3]], 16
+; ALL-NEXT:    [[O1:%.*]] = or i64 [[S1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i64 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i64 [[O2]], [[E4]]
+; ALL-NEXT:    ret i64 [[O3]]
+;
+  %p1 = getelementptr i16, ptr %p, i32 1
+  %p2 = getelementptr i16, ptr %p, i32 2
+  %p3 = getelementptr i16, ptr %p, i32 3
+  %l1 = load i16, ptr %p
+  %l2 = load i16, ptr %p1
+  %l3 = load i16, ptr %p2
+  %l4 = load i16, ptr %p3
+
+  %e1 = zext i16 %l1 to i64
+  %e2 = zext i16 %l2 to i64
+  %e3 = zext i16 %l3 to i64
+  %e4 = zext i16 %l4 to i64
+
+  %s1 = shl i64 %e1, 48
+  %s2 = shl i64 %e2, 32
+  %s3 = shl i64 %e3, 16
+
+  %o1 = or i64 %s1, %s2
+  %o2 = or i64 %o1, %s3
+  %o3 = or i64 %o2, %e4
+  ret i64 %o3
+}
+
+define i16 @loadCombine_2consecutive_atomic(ptr %p) {
+; ALL-LABEL: @loadCombine_2consecutive_atomic(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load atomic i8, ptr [[P]] monotonic, align 1
+; ALL-NEXT:    [[L2:%.*]] = load atomic i8, ptr [[P1]] monotonic, align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load atomic i8, ptr %p monotonic, align 1
+  %l2 = load atomic i8, ptr %p1 monotonic, align 1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i16 @loadCombine_2consecutive_volatile(ptr %p) {
+; ALL-LABEL: @loadCombine_2consecutive_volatile(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load volatile i8, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load volatile i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load volatile i8, ptr %p, align 1
+  %l2 = load volatile i8, ptr %p1, align 1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i16 @loadCombine_2consecutive_separateBB(ptr %p) {
+; ALL-LABEL: @loadCombine_2consecutive_separateBB(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1
+; ALL-NEXT:    br label [[BB2:%.*]]
+; ALL:       bb2:
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %l1 = load i8, ptr %p, align 1
+  br label %bb2
+
+bb2:
+  %l2 = load i8, ptr %p1, align 1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i16 @loadCombine_2consecutive_separateptr(ptr %p, ptr %p2) {
+; ALL-LABEL: @loadCombine_2consecutive_separateptr(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P2:%.*]], i32 1
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P:%.*]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 8
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    ret i16 [[O1]]
+;
+  %p1 = getelementptr i8, ptr %p2, i32 1
+  %l1 = load i8, ptr %p, align 1
+  %l2 = load i8, ptr %p1, align 1
+  %e1 = zext i8 %l1 to i16
+  %e2 = zext i8 %l2 to i16
+  %s2 = shl i16 %e2, 8
+  %o1 = or i16 %e1, %s2
+  ret i16 %o1
+}
+
+define i64 @load64_farLoads(ptr %ptr) {
+; ALL-LABEL: @load64_farLoads(
+; ALL-NEXT:  entry:
+; ALL-NEXT:    [[TMP0:%.*]] = load i8, ptr [[PTR:%.*]], align 1
+; ALL-NEXT:    [[CONV:%.*]] = zext i8 [[TMP0]] to i64
+; ALL-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1
+; ALL-NEXT:    [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
+; ALL-NEXT:    [[CONV2:%.*]] = zext i8 [[TMP1]] to i64
+; ALL-NEXT:    [[SHL:%.*]] = shl i64 [[CONV2]], 8
+; ALL-NEXT:    [[OR:%.*]] = or i64 [[CONV]], [[SHL]]
+; ALL-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 2
+; ALL-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ARRAYIDX3]], align 1
+; ALL-NEXT:    [[CONV4:%.*]] = zext i8 [[TMP2]] to i64
+; ALL-NEXT:    [[SHL5:%.*]] = shl i64 [[CONV4]], 16
+; ALL-NEXT:    [[OR6:%.*]] = or i64 [[OR]], [[SHL5]]
+; ALL-NEXT:    [[ARRAYIDX7:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 3
+; ALL-NEXT:    [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX7]], align 1
+; ALL-NEXT:    [[CONV8:%.*]] = zext i8 [[TMP3]] to i64
+; ALL-NEXT:    [[SHL9:%.*]] = shl i64 [[CONV8]], 24
+; ALL-NEXT:    [[OR10:%.*]] = or i64 [[OR6]], [[SHL9]]
+; ALL-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 4
+; ALL-NEXT:    [[TMP4:%.*]] = load i8, ptr [[ARRAYIDX11]], align 1
+; ALL-NEXT:    [[CONV12:%.*]] = zext i8 [[TMP4]] to i64
+; ALL-NEXT:    [[SHL13:%.*]] = shl i64 [[CONV12]], 32
+; ALL-NEXT:    [[OR14:%.*]] = or i64 [[OR10]], [[SHL13]]
+; ALL-NEXT:    [[ARRAYIDX15:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 5
+; ALL-NEXT:    [[TMP5:%.*]] = load i8, ptr [[ARRAYIDX15]], align 1
+; ALL-NEXT:    [[CONV16:%.*]] = zext i8 [[TMP5]] to i64
+; ALL-NEXT:    [[SHL17:%.*]] = shl i64 [[CONV16]], 40
+; ALL-NEXT:    [[OR18:%.*]] = or i64 [[OR14]], [[SHL17]]
+; ALL-NEXT:    [[ARRAYIDX19:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 6
+; ALL-NEXT:    [[TMP6:%.*]] = load i8, ptr [[ARRAYIDX19]], align 1
+; ALL-NEXT:    [[CONV20:%.*]] = zext i8 [[TMP6]] to i64
+; ALL-NEXT:    [[SHL21:%.*]] = shl i64 [[CONV20]], 48
+; ALL-NEXT:    [[OR22:%.*]] = or i64 [[OR18]], [[SHL21]]
+; ALL-NEXT:    [[ARRAYIDX23:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 7
+; ALL-NEXT:    [[TMP7:%.*]] = load i8, ptr [[ARRAYIDX23]], align 1
+; ALL-NEXT:    [[CONV24:%.*]] = zext i8 [[TMP7]] to i64
+; ALL-NEXT:    [[SHL25:%.*]] = shl i64 [[CONV24]], 56
+; ALL-NEXT:    [[OR26:%.*]] = or i64 [[OR22]], [[SHL25]]
+; ALL-NEXT:    ret i64 [[OR26]]
+;
+entry:
+  %0 = load i8, ptr %ptr, align 1
+  %conv = zext i8 %0 to i64
+  %arrayidx1 = getelementptr inbounds i8, ptr %ptr, i64 1
+  %1 = load i8, ptr %arrayidx1, align 1
+  %conv2 = zext i8 %1 to i64
+  %shl = shl i64 %conv2, 8
+  %or = or i64 %conv, %shl
+  %arrayidx3 = getelementptr inbounds i8, ptr %ptr, i64 2
+  %2 = load i8, ptr %arrayidx3, align 1
+  %conv4 = zext i8 %2 to i64
+  %shl5 = shl i64 %conv4, 16
+  %or6 = or i64 %or, %shl5
+  %arrayidx7 = getelementptr inbounds i8, ptr %ptr, i64 3
+  %3 = load i8, ptr %arrayidx7, align 1
+  %conv8 = zext i8 %3 to i64
+  %shl9 = shl i64 %conv8, 24
+  %or10 = or i64 %or6, %shl9
+  %arrayidx11 = getelementptr inbounds i8, ptr %ptr, i64 4
+  %4 = load i8, ptr %arrayidx11, align 1
+  %conv12 = zext i8 %4 to i64
+  %shl13 = shl i64 %conv12, 32
+  %or14 = or i64 %or10, %shl13
+  %arrayidx15 = getelementptr inbounds i8, ptr %ptr, i64 5
+  %5 = load i8, ptr %arrayidx15, align 1
+  %conv16 = zext i8 %5 to i64
+  %shl17 = shl i64 %conv16, 40
+  %or18 = or i64 %or14, %shl17
+  %arrayidx19 = getelementptr inbounds i8, ptr %ptr, i64 6
+  %6 = load i8, ptr %arrayidx19, align 1
+  %conv20 = zext i8 %6 to i64
+  %shl21 = shl i64 %conv20, 48
+  %or22 = or i64 %or18, %shl21
+  %arrayidx23 = getelementptr inbounds i8, ptr %ptr, i64 7
+  %7 = load i8, ptr %arrayidx23, align 1
+  %conv24 = zext i8 %7 to i64
+  %shl25 = shl i64 %conv24, 56
+  %or26 = or i64 %or22, %shl25
+  ret i64 %or26
+}
+
+define i32 @loadCombine_4consecutive_metadata(ptr %p, ptr %pstr) {
+; ALL-LABEL: @loadCombine_4consecutive_metadata(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i8, ptr [[P]], align 1, !alias.scope !0
+; ALL-NEXT:    [[L2:%.*]] = load i8, ptr [[P1]], align 1, !alias.scope !0
+; ALL-NEXT:    [[L3:%.*]] = load i8, ptr [[P2]], align 1, !alias.scope !0
+; ALL-NEXT:    [[L4:%.*]] = load i8, ptr [[P3]], align 1, !alias.scope !0
+; ALL-NEXT:    store i32 25, ptr [[PSTR:%.*]], align 4, !noalias !0
+; ALL-NEXT:    [[E1:%.*]] = zext i8 [[L1]] to i32
+; ALL-NEXT:    [[E2:%.*]] = zext i8 [[L2]] to i32
+; ALL-NEXT:    [[E3:%.*]] = zext i8 [[L3]] to i32
+; ALL-NEXT:    [[E4:%.*]] = zext i8 [[L4]] to i32
+; ALL-NEXT:    [[S2:%.*]] = shl i32 [[E2]], 8
+; ALL-NEXT:    [[S3:%.*]] = shl i32 [[E3]], 16
+; ALL-NEXT:    [[S4:%.*]] = shl i32 [[E4]], 24
+; ALL-NEXT:    [[O1:%.*]] = or i32 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i32 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i32 [[O2]], [[S4]]
+; ALL-NEXT:    ret i32 [[O3]]
+;
+  %p1 = getelementptr i8, ptr %p, i32 1
+  %p2 = getelementptr i8, ptr %p, i32 2
+  %p3 = getelementptr i8, ptr %p, i32 3
+  %l1 = load i8, ptr %p, !alias.scope !2
+  %l2 = load i8, ptr %p1, !alias.scope !2
+  %l3 = load i8, ptr %p2, !alias.scope !2
+  %l4 = load i8, ptr %p3, !alias.scope !2
+  store i32 25, ptr %pstr, !noalias !2
+
+  %e1 = zext i8 %l1 to i32
+  %e2 = zext i8 %l2 to i32
+  %e3 = zext i8 %l3 to i32
+  %e4 = zext i8 %l4 to i32
+
+  %s2 = shl i32 %e2, 8
+  %s3 = shl i32 %e3, 16
+  %s4 = shl i32 %e4, 24
+
+  %o1 = or i32 %e1, %s2
+  %o2 = or i32 %o1, %s3
+  %o3 = or i32 %o2, %s4
+  ret i32 %o3
+}
+
+!0 = distinct !{!0}
+!1 = distinct !{!1, !0}
+!2 = !{!1}
+
+; CHECK: !0 = !{!1}
+; CHECK: !1 = distinct !{!1, !2}
+; CHECK: !2 = distinct !{!2}
+
+define i16 @loadCombine_4consecutive_4bit(ptr %p) {
+; ALL-LABEL: @loadCombine_4consecutive_4bit(
+; ALL-NEXT:    [[P1:%.*]] = getelementptr i4, ptr [[P:%.*]], i32 1
+; ALL-NEXT:    [[P2:%.*]] = getelementptr i4, ptr [[P]], i32 2
+; ALL-NEXT:    [[P3:%.*]] = getelementptr i4, ptr [[P]], i32 3
+; ALL-NEXT:    [[L1:%.*]] = load i4, ptr [[P]], align 1
+; ALL-NEXT:    [[L2:%.*]] = load i4, ptr [[P1]], align 1
+; ALL-NEXT:    [[L3:%.*]] = load i4, ptr [[P2]], align 1
+; ALL-NEXT:    [[L4:%.*]] = load i4, ptr [[P3]], align 1
+; ALL-NEXT:    [[E1:%.*]] = zext i4 [[L1]] to i16
+; ALL-NEXT:    [[E2:%.*]] = zext i4 [[L2]] to i16
+; ALL-NEXT:    [[E3:%.*]] = zext i4 [[L3]] to i16
+; ALL-NEXT:    [[E4:%.*]] = zext i4 [[L4]] to i16
+; ALL-NEXT:    [[S2:%.*]] = shl i16 [[E2]], 4
+; ALL-NEXT:    [[S3:%.*]] = shl i16 [[E3]], 8
+; ALL-NEXT:    [[S4:%.*]] = shl i16 [[E4]], 12
+; ALL-NEXT:    [[O1:%.*]] = or i16 [[E1]], [[S2]]
+; ALL-NEXT:    [[O2:%.*]] = or i16 [[O1]], [[S3]]
+; ALL-NEXT:    [[O3:%.*]] = or i16 [[O2]], [[S4]]
+; ALL-NEXT:    ret i16 [[O3]]
+;
+  %p1 = getelementptr i4, ptr %p, i32 1
+  %p2 = getelementptr i4, ptr %p, i32 2
+  %p3 = getelementptr i4, ptr %p, i32 3
+  %l1 = load i4, ptr %p
+  %l2 = load i4, ptr %p1
+  %l3 = load i4, ptr %p2
+  %l4 = load i4, ptr %p3
+  %e1 = zext i4 %l1 to i16
+  %e2 = zext i4 %l2 to i16
+  %e3 = zext i4 %l3 to i16
+  %e4 = zext i4 %l4 to i16
+  %s2 = shl i16 %e2, 4
+  %s3 = shl i16 %e3, 8
+  %s4 = shl i16 %e4, 12
+  %o1 = or i16 %e1, %s2
+  %o2 = or i16 %o1, %s3
+  %o3 = or i16 %o2, %s4
+  ret i16 %o3
+}


        


More information about the llvm-commits mailing list