diff --git a/lib/FixupStructuredCFGPass.cpp b/lib/FixupStructuredCFGPass.cpp index 600fe1892..ffdec4bb3 100644 --- a/lib/FixupStructuredCFGPass.cpp +++ b/lib/FixupStructuredCFGPass.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/Constants.h" #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" @@ -28,10 +29,52 @@ clspv::FixupStructuredCFGPass::run(Function &F, FunctionAnalysisManager &FAM) { // Run after isolateContinue since this can invalidate loop info. breakConditionalHeader(F, FAM); + removeUndefPHI(F); + PreservedAnalyses PA; return PA; } +void clspv::FixupStructuredCFGPass::removeUndefPHI(Function &F) { + SmallVector ToBeDeleted; + DenseMap> dict; + for (auto &BB : F) { + for (auto &I : BB) { + if (auto phi = dyn_cast(&I)) { + if (!phi->getType()->isPointerTy()) { + continue; + } + bool phiIsUndef = true; + for (unsigned i = 0; i < phi->getNumIncomingValues(); i++) { + auto Val = phi->getIncomingValue(i); + if (auto phi2 = dyn_cast(Val)) { + for (unsigned j = 0; j < phi2->getNumIncomingValues(); j++) { + auto Val2 = phi2->getIncomingValue(i); + if (auto phi3 = dyn_cast(Val2)) { + if (phi3 != phi) { + phiIsUndef = false; + } + } else if (!isa(Val2)) { + phiIsUndef = false; + } + } + } else if (!isa(Val)) { + phiIsUndef = false; + } + } + if (!phiIsUndef) { + continue; + } + phi->replaceAllUsesWith(UndefValue::get(phi->getType())); + ToBeDeleted.push_back(phi); + } + } + } + for (auto phi : ToBeDeleted) { + phi->eraseFromParent(); + } +} + void clspv::FixupStructuredCFGPass::breakConditionalHeader( Function &F, FunctionAnalysisManager &FAM) { auto &LI = FAM.getResult(F); diff --git a/lib/FixupStructuredCFGPass.h b/lib/FixupStructuredCFGPass.h index 606962585..83ccb65b2 100644 --- a/lib/FixupStructuredCFGPass.h +++ b/lib/FixupStructuredCFGPass.h @@ -24,6 +24,7 @@ struct FixupStructuredCFGPass : llvm::PassInfoMixin { llvm::FunctionAnalysisManager &FAM); private: + void removeUndefPHI(llvm::Function &F); void breakConditionalHeader(llvm::Function &F, llvm::FunctionAnalysisManager &FAM); void isolateContinue(llvm::Function &F, llvm::FunctionAnalysisManager &FAM); diff --git a/test/FixupStructuredCFG/UndefPHI.ll b/test/FixupStructuredCFG/UndefPHI.ll new file mode 100644 index 000000000..4ea630901 --- /dev/null +++ b/test/FixupStructuredCFG/UndefPHI.ll @@ -0,0 +1,30 @@ +; RUN: clspv-opt %s -o %t.ll --passes=fixup-structured-cfg +; RUN: FileCheck %s < %t.ll + +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +target triple = "spir64-unknown-unknown" + +define dso_local spir_kernel void @foo(i1 %cmp1, i1 %cmp2, i1 %cmp3) { +entry: +; CHECK: [[alloca:%[^ ]+]] = alloca i32, align 4 + %alloca = alloca i32, align 4 + br i1 %cmp1, label %b1, label %b2 + +; CHECK: b1: +; CHECK-NEXT: br +b1: + %b1_phi = phi ptr [ undef, %entry ], [ %b2_phi, %b2 ] + br i1 %cmp2, label %b2, label %exit + +; CHECK: b2: +; CHECK-NEXT: br +b2: + %b2_phi = phi ptr [ undef, %entry ], [ %b1_phi, %b1 ] + br i1 %cmp3, label %b1, label %exit + +; CHECK: exit: +; CHECK-NEXT: phi ptr [ undef, %b1 ], [ [[alloca]], %b2 ] +exit: + %exit_phi = phi ptr [ %b1_phi, %b1 ], [ %alloca, %b2 ] + ret void +}