[llvm] [InstCombine] Convert load from LUT into a select (PR #98339)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 17 09:01:39 PDT 2024


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/98339

>From a49066220879b7b24d40c8a65fbe5fd1535240a5 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 17 Jul 2024 23:45:44 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.

---
 .../Transforms/InstCombine/load-global.ll     | 241 ++++++++++++++++++
 1 file changed, 241 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/load-global.ll

diff --git a/llvm/test/Transforms/InstCombine/load-global.ll b/llvm/test/Transforms/InstCombine/load-global.ll
new file mode 100644
index 0000000000000..736f04c86f5c8
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/load-global.ll
@@ -0,0 +1,241 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+ at arr2 = constant [2 x i32] [i32 0, i32 1], align 4
+ at arr2_mutable = global [4 x i32] [i32 0, i32 0, i32 1, i32 1], align 4
+ at arr2_external = external constant [4 x i32], align 4
+ at arr2_uniform = constant [2 x i32] [i32 1, i32 1], align 4
+ at arr2_undef = constant [2 x i32] [i32 1, i32 undef], align 4
+ at arr3 = constant [3 x i32] [i32 0, i32 1, i32 1], align 4
+ at arr3_alt = constant [3 x i32] [i32 1, i32 0, i32 1], align 4
+ at arr3_uniform = constant [3 x i32] [i32 1, i32 1, i32 1], align 4
+ at arr3_var = constant [3 x i32] [i32 0, i32 3, i32 4], align 4
+ at arr4_multimap = constant [4 x i32] [i32 0, i32 0, i32 1, i32 1], align 4
+
+define i32 @fold_arr2(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr2_uniform(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_uniform(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2_uniform, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2_uniform, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr3(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr3(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [3 x i32], ptr @arr3, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [3 x i32], ptr @arr3, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr3_alt(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr3_alt(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [3 x i32], ptr @arr3_alt, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [3 x i32], ptr @arr3_alt, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr3_uniform(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr3_uniform(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [3 x i32], ptr @arr3_uniform, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [3 x i32], ptr @arr3_uniform, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+; TODO: Handle ptradd pattern
+define i32 @fold_arr2_i8(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_i8(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[OFFSET:%.*]] = shl nuw nsw i64 [[X]], 2
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr i8, ptr @arr2, i64 [[OFFSET]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %offset = mul nsw nuw i64 %x, 4
+  %arrayidx = getelementptr i8, ptr @arr2, i64 %offset
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+; TODO: can be folded into x < 3 ? 0 : 1
+define i32 @fold_arr4_multimap(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr4_multimap(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [4 x i32], ptr @arr4_multimap, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [4 x i32], ptr @arr4_multimap, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+; negative tests
+
+define i32 @fold_arr2_mutable(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_mutable(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2_mutable, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2_mutable, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr2_external(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_external(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2_external, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2_external, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr2_volatile(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_volatile(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load volatile i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2, i64 0, i64 %x
+  %val = load volatile i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr2_mismatch_type1(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_mismatch_type1(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i8], ptr @arr2, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i8], ptr @arr2, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i8 @fold_arr2_mismatch_type2(i64 %x) {
+; CHECK-LABEL: define i8 @fold_arr2_mismatch_type2(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i8, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i8 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2, i64 0, i64 %x
+  %val = load i8, ptr %arrayidx, align 4
+  ret i8 %val
+}
+
+define i32 @fold_arr2_bad_gep1(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_bad_gep1(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2, i64 1, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2, i64 1, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr2_bad_gep2(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_bad_gep2(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2, i64 0
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr3_var(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr3_var(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [3 x i32], ptr @arr3_var, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [3 x i32], ptr @arr3_var, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}
+
+define i32 @fold_arr2_undef(i64 %x) {
+; CHECK-LABEL: define i32 @fold_arr2_undef(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2_undef, i64 0, i64 [[X]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    ret i32 [[VAL]]
+;
+entry:
+  %arrayidx = getelementptr [2 x i32], ptr @arr2_undef, i64 0, i64 %x
+  %val = load i32, ptr %arrayidx, align 4
+  ret i32 %val
+}

>From de550d309914b8f0bd1d63d5506e0674adf2081c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 17 Jul 2024 23:46:40 +0800
Subject: [PATCH 2/2] [InstCombine] Convert load from LUT into a select

---
 .../InstCombineLoadStoreAlloca.cpp            | 104 ++++++++++++++++++
 llvm/test/Transforms/InstCombine/load-cmp.ll  |  19 +---
 .../Transforms/InstCombine/load-global.ll     |  24 ++--
 .../test/Transforms/InstCombine/opaque-ptr.ll |   5 +-
 4 files changed, 119 insertions(+), 33 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 1661fa564c65c..efb487b272b33 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -1003,6 +1003,106 @@ static bool canSimplifyNullLoadOrGEP(LoadInst &LI, Value *Op) {
   return false;
 }
 
+static Value *foldLoadFromIndexedGlobal(LoadInst &LI, IRBuilderBase &Builder,
+                                        TargetLibraryInfo &TLI) {
+  if (LI.isVolatile())
+    return nullptr;
+
+  auto *GEP = dyn_cast<GetElementPtrInst>(LI.getPointerOperand());
+  if (!GEP)
+    return nullptr;
+
+  auto *GV = dyn_cast<GlobalVariable>(GEP->getPointerOperand());
+  if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer())
+    return nullptr;
+
+  Constant *Init = GV->getInitializer();
+  auto &DL = LI.getDataLayout();
+
+  uint64_t IndexBW = DL.getIndexTypeSizeInBits(GEP->getType());
+  APInt ConstOffset(IndexBW, 0);
+  MapVector<Value *, APInt> VariableOffsets;
+  if (!GEP->collectOffset(DL, IndexBW, VariableOffsets, ConstOffset))
+    return nullptr;
+
+  if (!ConstOffset.isZero() || VariableOffsets.size() != 1)
+    return nullptr;
+
+  auto &Step = VariableOffsets.front().second;
+  if (Step.isNonPositive())
+    return nullptr;
+  uint64_t ArraySize = DL.getTypeAllocSize(Init->getType()).getFixedValue();
+  // Don't blow up on huge arrays.
+  // This threshold is chosen based on statistics on a dataset
+  // which is collected from real-world applications.
+  constexpr uint64_t MaxArraySize = 16;
+  if (ArraySize > MaxArraySize * Step.getZExtValue())
+    return nullptr;
+
+  Value *Index = VariableOffsets.front().first;
+  if (Index->getType()->getScalarSizeInBits() != IndexBW)
+    return nullptr;
+
+  Type *LoadTy = LI.getType();
+  SmallMapVector<Constant *, uint64_t, 2> ValueMap;
+  // MultiMapIdx indicates that this value occurs more than once in the array.
+  constexpr uint64_t MultiMapIdx = static_cast<uint64_t>(-1);
+  uint32_t MultiMapElts = 0;
+  APInt Offset(IndexBW, 0);
+  for (uint64_t I = 0; Offset.getZExtValue() < ArraySize; ++I, Offset += Step) {
+    Constant *Elt = ConstantFoldLoadFromConst(Init, LoadTy, Offset, DL);
+
+    if (!Elt)
+      return nullptr;
+
+    // bail out if the array contains undef values
+    if (isa<UndefValue>(Elt))
+      return nullptr;
+
+    if (auto It = ValueMap.find(Elt); It != ValueMap.end()) {
+      if (It->second == MultiMapIdx)
+        continue;
+      if (++MultiMapElts == 2)
+        return nullptr;
+      It->second = MultiMapIdx;
+    } else {
+      if (ValueMap.size() == 2)
+        return nullptr;
+      ValueMap.insert(std::make_pair(Elt, I));
+    }
+  }
+
+  // Handle load from uniform arrays.
+  if (ValueMap.size() == 1)
+    return ValueMap.begin()->first;
+
+  // Now we have two unique values in the array. And at least one value
+  // only occurs in Array[Index].
+  assert(ValueMap.size() == 2);
+
+  auto [C1, I1] = *ValueMap.begin();
+  auto [C2, I2] = *ValueMap.rbegin();
+  assert((I1 != MultiMapIdx || I2 != MultiMapIdx) &&
+         "Should have a one to one mapping");
+  Value *TrueArm;
+  Value *FalseArm;
+  uint64_t C;
+  if (I1 != MultiMapIdx) {
+    TrueArm = C1;
+    FalseArm = C2;
+    C = I1;
+  } else {
+    TrueArm = C2;
+    FalseArm = C1;
+    C = I2;
+  }
+
+  return Builder.CreateSelect(
+      Builder.CreateICmp(ICmpInst::ICMP_EQ, Index,
+                         ConstantInt::get(Index->getType(), C)),
+      TrueArm, FalseArm);
+}
+
 Instruction *InstCombinerImpl::visitLoadInst(LoadInst &LI) {
   Value *Op = LI.getOperand(0);
   if (Value *Res = simplifyLoadInst(&LI, Op, SQ.getWithInstruction(&LI)))
@@ -1053,6 +1153,10 @@ Instruction *InstCombinerImpl::visitLoadInst(LoadInst &LI) {
     return replaceInstUsesWith(LI, PoisonValue::get(LI.getType()));
   }
 
+  // Convert load from a constant lookup table into select
+  if (auto *V = foldLoadFromIndexedGlobal(LI, Builder, TLI))
+    return replaceInstUsesWith(LI, V);
+
   if (Op->hasOneUse()) {
     // Change select and PHI nodes to select values instead of addresses: this
     // helps alias analysis out a lot, allows many others simplifications, and
diff --git a/llvm/test/Transforms/InstCombine/load-cmp.ll b/llvm/test/Transforms/InstCombine/load-cmp.ll
index b956de29e0b8d..43ffbd48dd8bd 100644
--- a/llvm/test/Transforms/InstCombine/load-cmp.ll
+++ b/llvm/test/Transforms/InstCombine/load-cmp.ll
@@ -215,10 +215,7 @@ define i1 @test10_struct(i32 %x) {
 
 define i1 @test10_struct_noinbounds(i32 %x) {
 ; CHECK-LABEL: @test10_struct_noinbounds(
-; CHECK-NEXT:    [[P:%.*]] = getelementptr [[FOO:%.*]], ptr @GS, i32 [[X:%.*]], i32 0
-; CHECK-NEXT:    [[Q:%.*]] = load i32, ptr [[P]], align 4
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[Q]], 9
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %p = getelementptr %Foo, ptr @GS, i32 %x, i32 0
   %q = load i32, ptr %p
@@ -252,11 +249,7 @@ define i1 @test10_struct_i64(i64 %x){
 
 define i1 @test10_struct_noinbounds_i16(i16 %x) {
 ; CHECK-LABEL: @test10_struct_noinbounds_i16(
-; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32
-; CHECK-NEXT:    [[P:%.*]] = getelementptr [[FOO:%.*]], ptr @GS, i32 [[TMP1]], i32 0
-; CHECK-NEXT:    [[Q:%.*]] = load i32, ptr [[P]], align 4
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[Q]], 0
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %p = getelementptr %Foo, ptr @GS, i16 %x, i32 0
   %q = load i32, ptr %p
@@ -335,16 +328,12 @@ define i1 @test10_struct_arr_noinbounds_i64(i64 %x) {
   ret i1 %r
 }
 
- at table = internal constant [2 x ptr] [ptr @g, ptr getelementptr (i8, ptr @g, i64 4)], align 16
+ at table = internal constant [2 x ptr] [ptr @g, ptr getelementptr inbounds (i8, ptr @g, i64 4)], align 16
 @g = external global [2 x i32]
 
 define i1 @pr93017(i64 %idx) {
 ; CHECK-LABEL: @pr93017(
-; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[IDX:%.*]] to i32
-; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr @table, i32 0, i32 [[TMP1]]
-; CHECK-NEXT:    [[V:%.*]] = load ptr, ptr [[GEP]], align 4
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne ptr [[V]], null
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %gep = getelementptr inbounds [2 x ptr], ptr @table, i64 0, i64 %idx
   %v = load ptr, ptr %gep
diff --git a/llvm/test/Transforms/InstCombine/load-global.ll b/llvm/test/Transforms/InstCombine/load-global.ll
index 736f04c86f5c8..14ac530c42e9e 100644
--- a/llvm/test/Transforms/InstCombine/load-global.ll
+++ b/llvm/test/Transforms/InstCombine/load-global.ll
@@ -16,8 +16,8 @@ define i32 @fold_arr2(i64 %x) {
 ; CHECK-LABEL: define i32 @fold_arr2(
 ; CHECK-SAME: i64 [[X:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2, i64 0, i64 [[X]]
-; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[X]], 0
+; CHECK-NEXT:    [[VAL:%.*]] = zext i1 [[TMP0]] to i32
 ; CHECK-NEXT:    ret i32 [[VAL]]
 ;
 entry:
@@ -30,9 +30,7 @@ define i32 @fold_arr2_uniform(i64 %x) {
 ; CHECK-LABEL: define i32 @fold_arr2_uniform(
 ; CHECK-SAME: i64 [[X:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2_uniform, i64 0, i64 [[X]]
-; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
-; CHECK-NEXT:    ret i32 [[VAL]]
+; CHECK-NEXT:    ret i32 1
 ;
 entry:
   %arrayidx = getelementptr [2 x i32], ptr @arr2_uniform, i64 0, i64 %x
@@ -44,8 +42,8 @@ define i32 @fold_arr3(i64 %x) {
 ; CHECK-LABEL: define i32 @fold_arr3(
 ; CHECK-SAME: i64 [[X:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [3 x i32], ptr @arr3, i64 0, i64 [[X]]
-; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[X]], 0
+; CHECK-NEXT:    [[VAL:%.*]] = zext i1 [[TMP0]] to i32
 ; CHECK-NEXT:    ret i32 [[VAL]]
 ;
 entry:
@@ -58,8 +56,8 @@ define i32 @fold_arr3_alt(i64 %x) {
 ; CHECK-LABEL: define i32 @fold_arr3_alt(
 ; CHECK-SAME: i64 [[X:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [3 x i32], ptr @arr3_alt, i64 0, i64 [[X]]
-; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[X]], 1
+; CHECK-NEXT:    [[VAL:%.*]] = zext i1 [[TMP0]] to i32
 ; CHECK-NEXT:    ret i32 [[VAL]]
 ;
 entry:
@@ -72,9 +70,7 @@ define i32 @fold_arr3_uniform(i64 %x) {
 ; CHECK-LABEL: define i32 @fold_arr3_uniform(
 ; CHECK-SAME: i64 [[X:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [3 x i32], ptr @arr3_uniform, i64 0, i64 [[X]]
-; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
-; CHECK-NEXT:    ret i32 [[VAL]]
+; CHECK-NEXT:    ret i32 1
 ;
 entry:
   %arrayidx = getelementptr [3 x i32], ptr @arr3_uniform, i64 0, i64 %x
@@ -176,8 +172,8 @@ define i8 @fold_arr2_mismatch_type2(i64 %x) {
 ; CHECK-LABEL: define i8 @fold_arr2_mismatch_type2(
 ; CHECK-SAME: i64 [[X:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr [2 x i32], ptr @arr2, i64 0, i64 [[X]]
-; CHECK-NEXT:    [[VAL:%.*]] = load i8, ptr [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[X]], 0
+; CHECK-NEXT:    [[VAL:%.*]] = zext i1 [[TMP0]] to i8
 ; CHECK-NEXT:    ret i8 [[VAL]]
 ;
 entry:
diff --git a/llvm/test/Transforms/InstCombine/opaque-ptr.ll b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
index df85547f56d74..d800bd804028b 100644
--- a/llvm/test/Transforms/InstCombine/opaque-ptr.ll
+++ b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
@@ -504,10 +504,7 @@ define i1 @cmp_load_gep_global_different_load_type(i64 %idx) {
 
 define i1 @cmp_load_gep_global_different_gep_type(i64 %idx) {
 ; CHECK-LABEL: @cmp_load_gep_global_different_gep_type(
-; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [4 x i16], ptr @ary, i64 0, i64 [[IDX:%.*]]
-; CHECK-NEXT:    [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[LOAD]], 3
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %gep = getelementptr [4 x i16], ptr @ary, i64 0, i64 %idx
   %load = load i16, ptr %gep



More information about the llvm-commits mailing list