diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -12,6 +12,7 @@ #include "InstCombineInternal.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -53,7 +54,8 @@ const bool IsOffset = ValuePair.second; for (auto &U : ValuePair.first->uses()) { auto *I = cast(U.getUser()); - + if (isa(I)) + continue; if (auto *LI = dyn_cast(I)) { // Ignore non-volatile loads, they are always ok. if (!LI->isSimple()) return false; @@ -256,6 +258,9 @@ if (Load->isVolatile()) return false; Worklist.insert(Load); + } else if (auto *PHI = dyn_cast(Inst)) { + append_range(Worklist, PHI->incoming_values()); + Worklist.insert(PHI); } else if (isa(Inst) || isa(Inst)) { Worklist.insert(Inst); if (!collectUsers(*Inst)) @@ -293,6 +298,18 @@ IC.InsertNewInstWith(NewI, *LT); IC.replaceInstUsesWith(*LT, NewI); WorkMap[LT] = NewI; + } else if (auto *PHI = dyn_cast(I)) { + SmallVector ReplacedOperands; + for (unsigned int I = 0; I < PHI->getNumOperands(); ++I) { + ReplacedOperands.push_back(getReplacement(PHI->getOperand(I))); + assert(ReplacedOperands.back() && "Operand not replaced"); + } + auto *NewPHI = PHINode::Create(PHI->getType(), PHI->getNumIncomingValues(), + PHI->getName()); + NewPHI->takeName(PHI); + IC.InsertNewInstWith(NewPHI, *PHI); + IC.replaceInstUsesWith(*PHI, NewPHI); + WorkMap[PHI] = NewPHI; } else if (auto *GEP = dyn_cast(I)) { auto *V = getReplacement(GEP->getPointerOperand()); assert(V && "Operand not replaced"); @@ -430,7 +447,6 @@ if (PtrReplacer.collectUsers(AI)) { 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 new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/replace-alloca-phi.ll @@ -0,0 +1,69 @@ +; RUN: opt -passes=instcombine -S -o - %s | FileCheck %s + +target triple="amdgcn-amd-amdhsa" + +%struct.ghost = type <{ i32, [4 x i8], [4 x i8], [4 x i32], i32, i32, [4 x i32], i32, i32, [4 x i32], [4 x i32], [4 x i32], [4 x i8] }> + +; CHECK-LABEL: @remove_alloca +define void @remove_alloca(ptr addrspace(4) byref(%struct.ghost) align 8 %0, i32 %add.i, i1 %or.cond.i) { +; CHECK-LABEL: entry: +; CHECK-NEXT: br i1 %or.cond.i, label %if.else.i.i.i, label %exit +entry: + %coerce = alloca %struct.ghost, align 8, addrspace(5) + call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) align 8 %coerce, ptr addrspace(4) align 8 %0, i64 1360, i1 false) + %y.i = getelementptr inbounds [3 x i32], ptr addrspace(5) %coerce, i64 0, i32 1 + %z.i = getelementptr inbounds [3 x i32], ptr addrspace(5) %coerce, i64 0, i32 2 + br i1 %or.cond.i, label %if.else.i.i.i, label %exit + +if.else.i.i.i: ; preds = %while.body.i +; CHECK-LABEL: if.else.i.i.i: +; CHECK-NEXT: %arrayidx2.i.i.i = getelementptr %struct.ghost, ptr addrspace(4) %0, i64 0, i32 12, i64 1 +; CHECK-NEXT: %.37 = load i32, ptr addrspace(4) %arrayidx2.i.i.i, align 8 +; CHECK-NEXT: %cmp3.i.i.i = icmp sgt i32 %.37, %add.i +; CHECK-NEXT: br i1 %cmp3.i.i.i, label %if.then4.i.i.i, label %if.else6.i.i.i + %arrayidx2.i.i.i = getelementptr inbounds %struct.ghost, ptr addrspace(5) %coerce, i64 0, i32 12, i64 1 + %.37 = load i32, ptr addrspace(5) %arrayidx2.i.i.i, align 8 + %cmp3.i.i.i = icmp sgt i32 %.37, %add.i + br i1 %cmp3.i.i.i, label %if.then4.i.i.i, label %if.else6.i.i.i + +if.then4.i.i.i: ; preds = %if.else.i.i.i +; CHECK-LABEL: if.then4.i.i.i: +; CHECK-NEXT: br label %return.sink.split.i.i.i + %arrayidx5.i.i.i = getelementptr inbounds %struct.ghost, ptr addrspace(5) %coerce, i64 0, i32 11, i64 1 + br label %return.sink.split.i.i.i + +if.else6.i.i.i: ; preds = %if.else.i.i.i +; CHECK-LABEL: if.else6.i.i.i: +; CHECK-NEXT: %arrayidx8.i.i.i = getelementptr %struct.ghost, ptr addrspace(4) %0, i64 0, i32 12, i64 2 +; CHECK-NEXT: %.38 = load i32, ptr addrspace(4) %arrayidx8.i.i.i, align 4 +; CHECK-NEXT: %cmp9.i.i.i = icmp sgt i32 %.38, %add.i +; CHECK-NEXT: br i1 %cmp9.i.i.i, label %if.then10.i.i.i, label %if.else14.i.i.i + %arrayidx8.i.i.i = getelementptr inbounds %struct.ghost, ptr addrspace(5) %coerce, i64 0, i32 12, i64 2 + %.38 = load i32, ptr addrspace(5) %arrayidx8.i.i.i, align 4 + %cmp9.i.i.i = icmp sgt i32 %.38, %add.i + br i1 %cmp9.i.i.i, label %if.then10.i.i.i, label %if.else14.i.i.i + +if.then10.i.i.i: ; preds = %if.else6.i.i.i +; CHECK-LABEL: if.then10.i.i.i: +; CHECK-NEXT: br label %return.sink.split.i.i.i + %arrayidx12.i.i.i = getelementptr inbounds %struct.ghost, ptr addrspace(5) %coerce, i64 0, i32 11, i64 2 + br label %return.sink.split.i.i.i + +if.else14.i.i.i: ; preds = %if.else6.i.i.i +; CHECK-LABEL: if.else14.i.i.i: +; CHECK-NEXT: br label %return.sink.split.i.i.i + %arrayidx16.i.i.i = getelementptr inbounds %struct.ghost, ptr addrspace(5) %coerce, i64 0, i32 11, i64 3 + br label %return.sink.split.i.i.i + +return.sink.split.i.i.i: ; preds = %if.else14.i.i.i, %if.then10.i.i.i, %if.then4.i.i.i +; CHECK-LABEL: return.sink.split.i.i.i: +; CHECK-NEXT: br label %exit + %.sink.in.i.i.i = phi ptr addrspace(5) [ %arrayidx16.i.i.i, %if.else14.i.i.i ], [ %arrayidx12.i.i.i, %if.then10.i.i.i ], [ %arrayidx5.i.i.i, %if.then4.i.i.i ] + %.sink.i.i.i = load i32, ptr addrspace(5) %.sink.in.i.i.i, align 4 + br label %exit + +exit: + ret void +} + +declare void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) noalias nocapture writeonly, ptr addrspace(4) noalias nocapture readonly, i64, i1 immarg) #3