Skip to content

Instantly share code, notes, and snippets.

@nikic
Last active January 12, 2023 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikic/ce69a66fdc0985d1af7a56bf024bc860 to your computer and use it in GitHub Desktop.
Save nikic/ce69a66fdc0985d1af7a56bf024bc860 to your computer and use it in GitHub Desktop.
commit a837a1a0a4b4d8ecdc0276abcf4082582546de7a
Author: Nikita Popov <npopov@redhat.com>
Date: Thu Jan 12 14:10:50 2023 +0100
rebase
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index c8226ce2816a..292bfc536811 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -261,7 +261,7 @@ class PointerReplacer {
public:
PointerReplacer(InstCombinerImpl &IC) : IC(IC) {}
- bool collectUsers(Instruction &I);
+ bool collectUsers(Instruction &I, MemTransferInst *Copy);
void replacePointer(Instruction &I, Value *V);
private:
@@ -274,16 +274,31 @@ private:
};
} // end anonymous namespace
-bool PointerReplacer::collectUsers(Instruction &I) {
+bool PointerReplacer::collectUsers(Instruction &I, MemTransferInst *Copy) {
for (auto *U : I.users()) {
auto *Inst = cast<Instruction>(&*U);
if (auto *Load = dyn_cast<LoadInst>(Inst)) {
if (Load->isVolatile())
return false;
Worklist.insert(Load);
- } else if (isa<GetElementPtrInst>(Inst) || isa<BitCastInst>(Inst)) {
+ } else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
+ // Check if any of the incoming values of PHI is the destination of Copy
+ unsigned CopySrcAddrSpace = Copy->getSourceAddressSpace();
+ unsigned PHIAddrSpace = PHI->getType()->getPointerAddressSpace();
+ for (unsigned Idx = 0; Idx < PHI->getNumIncomingValues(); ++Idx) {
+ auto *V = PHI->getIncomingValue(Idx);
+ if (CopySrcAddrSpace != PHIAddrSpace && V == Copy->getDest())
+ return false;
+ if (auto *Inst = dyn_cast<Instruction>(V))
+ Worklist.insert(Inst);
+ }
+
+ Worklist.insert(PHI);
+ if (!collectUsers(*PHI, Copy))
+ return false;
+ } else if (isa<GetElementPtrInst, BitCastInst>(Inst)) {
Worklist.insert(Inst);
- if (!collectUsers(*Inst))
+ if (!collectUsers(*Inst, Copy))
return false;
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
if (MI->isVolatile())
@@ -318,6 +333,14 @@ void PointerReplacer::replace(Instruction *I) {
IC.InsertNewInstWith(NewI, *LT);
IC.replaceInstUsesWith(*LT, NewI);
WorkMap[LT] = NewI;
+ } else if (auto *PHI = dyn_cast<PHINode>(I)) {
+ Type *NewTy = getReplacement(PHI->getIncomingValue(0))->getType();
+ auto *NewPHI = PHINode::Create(NewTy, PHI->getNumIncomingValues(),
+ PHI->getName(), PHI);
+ for (unsigned int I = 0; I < PHI->getNumIncomingValues(); ++I)
+ NewPHI->addIncoming(getReplacement(PHI->getIncomingValue(I)),
+ PHI->getIncomingBlock(I));
+ WorkMap[PHI] = NewPHI;
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
auto *V = getReplacement(GEP->getPointerOperand());
assert(V && "Operand not replaced");
@@ -452,10 +475,9 @@ Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) {
}
PointerReplacer PtrReplacer(*this);
- if (PtrReplacer.collectUsers(AI)) {
+ if (PtrReplacer.collectUsers(AI, Copy)) {
for (Instruction *Delete : ToDelete)
eraseInstFromFunction(*Delete);
-
Value *Cast = Builder.CreateBitCast(TheSrc, DestTy);
PtrReplacer.replacePointer(AI, Cast);
++NumGlobalCopies;
diff --git a/llvm/test/Transforms/InstCombine/replace-alloca-phi.ll b/llvm/test/Transforms/InstCombine/replace-alloca-phi.ll
index ea9391717ce7..01dbd0dfeeb4 100644
--- a/llvm/test/Transforms/InstCombine/replace-alloca-phi.ll
+++ b/llvm/test/Transforms/InstCombine/replace-alloca-phi.ll
@@ -9,18 +9,14 @@ target datalayout="p5:32:32-A5"
define i8 @remove_alloca_use_arg(i1 %cond) {
; CHECK-LABEL: @remove_alloca_use_arg(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1)
-; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 4 dereferenceable(256) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(256) @g1, i64 256, i1 false)
; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
-; CHECK-NEXT: [[VAL_IF:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 2
; CHECK-NEXT: br label [[SINK:%.*]]
; CHECK: else:
-; CHECK-NEXT: [[VAL_ELSE:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 1
; CHECK-NEXT: br label [[SINK]]
; CHECK: sink:
-; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL_IF]], [[IF]] ], [ [[VAL_ELSE]], [[ELSE]] ]
-; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(1) [[PTR]], align 1
+; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[IF]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ELSE]] ]
+; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
; CHECK-NEXT: ret i8 [[LOAD]]
;
entry:
@@ -116,18 +112,14 @@ sink:
define i8 @loop_phi_remove_alloca(i1 %cond) {
; CHECK-LABEL: @loop_phi_remove_alloca(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1)
-; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 4 dereferenceable(256) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(256) @g1, i64 256, i1 false)
-; CHECK-NEXT: [[VAL1:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 1
; CHECK-NEXT: br label [[BB_0:%.*]]
; CHECK: bb.0:
-; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL1]], [[ENTRY:%.*]] ], [ [[VAL2:%.*]], [[BB_1:%.*]] ]
+; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[BB_1:%.*]] ]
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]]
; CHECK: bb.1:
-; CHECK-NEXT: [[VAL2]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 2
; CHECK-NEXT: br label [[BB_0]]
; CHECK: exit:
-; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(1) [[PTR]], align 1
+; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
; CHECK-NEXT: ret i8 [[LOAD]]
;
entry:
@@ -177,18 +169,14 @@ join:
define i8 @loop_phi_late_memtransfer(i1 %cond) {
; CHECK-LABEL: @loop_phi_late_memtransfer(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1)
-; CHECK-NEXT: [[VAL1:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 1
; CHECK-NEXT: br label [[BB_0:%.*]]
; CHECK: bb.0:
-; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL1]], [[ENTRY:%.*]] ], [ [[VAL2:%.*]], [[BB_1:%.*]] ]
+; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[BB_1:%.*]] ]
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]]
; CHECK: bb.1:
-; CHECK-NEXT: [[VAL2]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 2
-; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 4 dereferenceable(256) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(256) @g1, i64 256, i1 false)
; CHECK-NEXT: br label [[BB_0]]
; CHECK: exit:
-; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(1) [[PTR]], align 1
+; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
; CHECK-NEXT: ret i8 [[LOAD]]
;
entry:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment