[llvm] Add `visitGEPOfAlloc` to restore the `visitGEPOfBitcast` part of the behavior of non-opaque pointers. (PR #65764)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 8 07:32:18 PDT 2023
https://github.com/DianQK created https://github.com/llvm/llvm-project/pull/65764:
Closes #65763.
>From a64dfb1f569f3c039e7e1dd99a1b61c5f9c756fa Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Thu, 7 Sep 2023 23:07:04 +0800
Subject: [PATCH 1/2] [InstCombine][NFC] Pre-commit for restoring gep original
struct
---
.../restore-gep-original-struct.ll | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/restore-gep-original-struct.ll
diff --git a/llvm/test/Transforms/InstCombine/restore-gep-original-struct.ll b/llvm/test/Transforms/InstCombine/restore-gep-original-struct.ll
new file mode 100644
index 000000000000000..8c71c742c2498b0
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/restore-gep-original-struct.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+%Zip = type { i64, i64, [1 x i8] }
+
+define i64 @foo(i64 %idx, ptr %v) {
+; CHECK-LABEL: define i64 @foo(
+; CHECK-SAME: i64 [[IDX:%.*]], ptr [[V:%.*]]) {
+; CHECK-NEXT: [[Z1:%.*]] = alloca [[ZIP:%.*]], align 8
+; CHECK-NEXT: [[SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[Z1]], i64 8
+; CHECK-NEXT: store i64 32, ptr [[SROA_IDX]], align 8
+; CHECK-NEXT: [[OFFSET:%.*]] = getelementptr inbounds [[ZIP]], ptr [[Z1]], i64 0, i32 1
+; CHECK-NEXT: [[AF:%.*]] = getelementptr inbounds [[ZIP]], ptr [[Z1]], i64 0, i32 2, i64 [[IDX]]
+; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[AF]], align 8
+; CHECK-NEXT: store i8 [[A]], ptr [[V]], align 8
+; CHECK-NEXT: [[LEN:%.*]] = load i64, ptr [[OFFSET]], align 8
+; CHECK-NEXT: ret i64 [[LEN]]
+;
+ %z1 = alloca %Zip, align 8
+ %sroa_idx = getelementptr inbounds i8, ptr %z1, i64 8
+ store i64 32, ptr %sroa_idx, align 8
+ %offset = getelementptr inbounds %Zip, ptr %z1, i64 0, i32 1
+ %af = getelementptr inbounds %Zip, ptr %z1, i64 0, i32 2, i64 %idx
+ %a = load i8, ptr %af, align 8
+ store i8 %a, ptr %v, align 8
+ %len = load i64, ptr %offset, align 8
+ ret i64 %len
+}
+
>From 35d0b5aff0d2ecaf34d5daec4bf372dfe096bd76 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Thu, 7 Sep 2023 23:09:12 +0800
Subject: [PATCH 2/2] [InstCombine] Simplify GEP into a GEP of the original
struct.
Use the alloc instruction to add back a transform that similar to
https://github.com/llvm/llvm-project/commit/b7179d92799c7a375b7f8fa1a2a91c5fda713423.
---
.../InstCombine/InstCombineInternal.h | 1 +
.../InstCombine/InstructionCombining.cpp | 46 +++++++++++++++++++
.../InstCombine/2009-01-08-AlignAlloca.ll | 2 +-
.../restore-gep-original-struct.ll | 6 +--
4 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index e9e8e90d4802bec..4efc4ca0ce53674 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -155,6 +155,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
Instruction *visitPHINode(PHINode &PN);
Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP);
Instruction *visitGEPOfGEP(GetElementPtrInst &GEP, GEPOperator *Src);
+ Instruction *visitGEPOfAlloc(GetElementPtrInst &GEP, AllocaInst *AI);
Instruction *visitAllocaInst(AllocaInst &AI);
Instruction *visitAllocSite(Instruction &FI);
Instruction *visitFree(CallInst &FI, Value *FreedOp);
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index ed8709ea4c051f7..37d6321c35c0926 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1975,6 +1975,48 @@ static Instruction *foldSelectGEP(GetElementPtrInst &GEP,
return SelectInst::Create(Cond, NewTrueC, NewFalseC, "", nullptr, Sel);
}
+static Type *findElementAtOffset(Type *PtrTy, Type *Ty, int64_t IntOffset,
+ SmallVectorImpl<Value *> &NewIndices,
+ const DataLayout &DL) {
+ if (!Ty->isSized())
+ return nullptr;
+ APInt Offset(DL.getIndexTypeSizeInBits(PtrTy), IntOffset);
+ SmallVector<APInt> Indices = DL.getGEPIndicesForOffset(Ty, Offset);
+ if (!Offset.isZero())
+ return nullptr;
+
+ for (const APInt &Index : Indices)
+ NewIndices.push_back(ConstantInt::get(Ty->getContext(), Index));
+ return Ty;
+}
+
+// See if we can simplify:
+// X = alloc %Type
+// Y = gep X, <...constant indices...>
+// into a gep of the original struct. This is important for SROA and alias
+// analysis of unions.
+Instruction *InstCombinerImpl::visitGEPOfAlloc(GetElementPtrInst &GEP,
+ AllocaInst *AI) {
+ Type *SrcType = AI->getAllocatedType();
+ if (SrcType->isArrayTy() || GEP.getSourceElementType() == SrcType)
+ return nullptr;
+ unsigned OffsetBits = DL.getIndexTypeSizeInBits(GEP.getType());
+ APInt Offset(OffsetBits, 0);
+ if (GEP.accumulateConstantOffset(DL, Offset)) {
+ if (!Offset)
+ return nullptr;
+ // we need to find out if there is a field at Offset in 'A's type.
+ SmallVector<Value *, 8> NewIndices;
+ if (findElementAtOffset(GEP.getType(), SrcType, Offset.getSExtValue(),
+ NewIndices, DL)) {
+ Value *NGEP = Builder.CreateGEP(SrcType, GEP.getOperand(0), NewIndices,
+ "", GEP.isInBounds());
+ return replaceInstUsesWith(GEP, NGEP);
+ }
+ }
+ return nullptr;
+}
+
Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
GEPOperator *Src) {
// Combine Indices - If the source pointer to this getelementptr instruction
@@ -2334,6 +2376,10 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
if (GEPType->isVectorTy())
return nullptr;
+ if (auto *AI = dyn_cast<AllocaInst>(PtrOp))
+ if (Instruction *I = visitGEPOfAlloc(GEP, AI))
+ return I;
+
if (!GEP.isInBounds()) {
unsigned IdxWidth =
DL.getIndexSizeInBits(PtrOp->getType()->getPointerAddressSpace());
diff --git a/llvm/test/Transforms/InstCombine/2009-01-08-AlignAlloca.ll b/llvm/test/Transforms/InstCombine/2009-01-08-AlignAlloca.ll
index 00bce165efa2ae3..f39c451b3af5e6c 100644
--- a/llvm/test/Transforms/InstCombine/2009-01-08-AlignAlloca.ll
+++ b/llvm/test/Transforms/InstCombine/2009-01-08-AlignAlloca.ll
@@ -13,7 +13,7 @@ define i32 @bar(i64 %key_token2) nounwind {
; CHECK-NEXT: [[IOSPEC:%.*]] = alloca [[STRUCT_KEY:%.*]], align 8
; CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4
; CHECK-NEXT: store i32 0, ptr [[IOSPEC]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds { i32, i32 }, ptr [[IOSPEC]], i32 0, i32 1
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_KEY]], ptr [[IOSPEC]], i32 0, i32 0, i32 1
; CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4
; CHECK-NEXT: store i64 [[KEY_TOKEN2:%.*]], ptr [[IOSPEC]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = call i32 (...) @foo(ptr nonnull byval([[STRUCT_KEY]]) align 4 [[IOSPEC]], ptr nonnull [[RET]]) #[[ATTR0:[0-9]+]]
diff --git a/llvm/test/Transforms/InstCombine/restore-gep-original-struct.ll b/llvm/test/Transforms/InstCombine/restore-gep-original-struct.ll
index 8c71c742c2498b0..f0efaacbf4dd696 100644
--- a/llvm/test/Transforms/InstCombine/restore-gep-original-struct.ll
+++ b/llvm/test/Transforms/InstCombine/restore-gep-original-struct.ll
@@ -6,14 +6,12 @@ define i64 @foo(i64 %idx, ptr %v) {
; CHECK-LABEL: define i64 @foo(
; CHECK-SAME: i64 [[IDX:%.*]], ptr [[V:%.*]]) {
; CHECK-NEXT: [[Z1:%.*]] = alloca [[ZIP:%.*]], align 8
-; CHECK-NEXT: [[SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[Z1]], i64 8
+; CHECK-NEXT: [[SROA_IDX:%.*]] = getelementptr inbounds [[ZIP]], ptr [[Z1]], i64 0, i32 1
; CHECK-NEXT: store i64 32, ptr [[SROA_IDX]], align 8
-; CHECK-NEXT: [[OFFSET:%.*]] = getelementptr inbounds [[ZIP]], ptr [[Z1]], i64 0, i32 1
; CHECK-NEXT: [[AF:%.*]] = getelementptr inbounds [[ZIP]], ptr [[Z1]], i64 0, i32 2, i64 [[IDX]]
; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[AF]], align 8
; CHECK-NEXT: store i8 [[A]], ptr [[V]], align 8
-; CHECK-NEXT: [[LEN:%.*]] = load i64, ptr [[OFFSET]], align 8
-; CHECK-NEXT: ret i64 [[LEN]]
+; CHECK-NEXT: ret i64 32
;
%z1 = alloca %Zip, align 8
%sroa_idx = getelementptr inbounds i8, ptr %z1, i64 8
More information about the llvm-commits
mailing list