[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