Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -58,6 +58,9 @@ /// Initialize all passes linked into the CodeGen library. void initializeTarget(PassRegistry&); +/// Initialize all passes linked into the PIR library. +void initializePIROpts(PassRegistry&); + void initializeAAEvalLegacyPassPass(PassRegistry&); void initializeAAResultsWrapperPassPass(PassRegistry &); void initializeADCELegacyPassPass(PassRegistry&); @@ -318,6 +321,7 @@ void initializeScalarizerPass(PassRegistry&); void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&); void initializeSeparateConstOffsetFromGEPPass(PassRegistry &); +void initializeSequentializePIRPass(PassRegistry&); void initializeShadowStackGCLoweringPass(PassRegistry&); void initializeShrinkWrapPass(PassRegistry &); void initializeSimpleInlinerPass(PassRegistry&); Index: lib/Passes/LLVMBuild.txt =================================================================== --- lib/Passes/LLVMBuild.txt +++ lib/Passes/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = Passes parent = Libraries -required_libraries = Analysis CodeGen Core IPO InstCombine Scalar Support TransformUtils Vectorize Instrumentation +required_libraries = Analysis CodeGen Core IPO InstCombine Scalar Support TransformUtils Vectorize Instrumentation PIR Index: lib/Transforms/CMakeLists.txt =================================================================== --- lib/Transforms/CMakeLists.txt +++ lib/Transforms/CMakeLists.txt @@ -5,5 +5,6 @@ add_subdirectory(IPO) add_subdirectory(Vectorize) add_subdirectory(Hello) +add_subdirectory(PIR) add_subdirectory(ObjCARC) add_subdirectory(Coroutines) Index: lib/Transforms/LLVMBuild.txt =================================================================== --- lib/Transforms/LLVMBuild.txt +++ lib/Transforms/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = Coroutines IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC +subdirectories = Coroutines IPO InstCombine Instrumentation Scalar Utils Vectorize ObjCARC PIR [component_0] type = Group Index: lib/Transforms/PIR/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Transforms/PIR/CMakeLists.txt @@ -0,0 +1,10 @@ +add_llvm_library(LLVMPIR + SequentializePIR.cpp + PIR.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms + + DEPENDS + intrinsics_gen + ) Index: lib/Transforms/PIR/LLVMBuild.txt =================================================================== --- lib/Transforms/PIR/LLVMBuild.txt +++ lib/Transforms/PIR/LLVMBuild.txt @@ -1,4 +1,4 @@ -;===- ./lib/Passes/LLVMBuild.txt -------------------------------*- Conf -*--===; +;===- ./lib/Transforms/PIR/LLVMBuild.txt -----------------------*- Conf -*--===; ; ; The LLVM Compiler Infrastructure ; @@ -17,6 +17,6 @@ [component_0] type = Library -name = Passes -parent = Libraries -required_libraries = Analysis CodeGen Core IPO InstCombine Scalar Support TransformUtils Vectorize Instrumentation +name = PIR +parent = Transforms +required_libraries = Analysis BitWriter Core InstCombine IRReader Linker Object ProfileData Scalar Support TransformUtils Vectorize Instrumentation Index: lib/Transforms/PIR/PIR.cpp =================================================================== --- /dev/null +++ lib/Transforms/PIR/PIR.cpp @@ -0,0 +1,16 @@ +//===-- PIR.cpp -----------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/InitializePasses.h" + +using namespace llvm; + +void llvm::initializePIROpts(PassRegistry &Registry) { + initializeSequentializePIRPass(Registry); +} Index: lib/Transforms/PIR/SequentializePIR.cpp =================================================================== --- /dev/null +++ lib/Transforms/PIR/SequentializePIR.cpp @@ -0,0 +1,64 @@ +//===-- PIR/SequentializePIR.cpp - Sequentialize parallel regions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass will lower all parallel regions to sequential IR. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { + +/// This pass will lower all parallel regions to sequential IR. It replaces +/// PIR instruction by unconditional branch instructions as follows: +/// - fork is replaced with a branch to the forked block. +/// - halt is replaced with a branch to the sibling continuation block. +/// - join is replaced with a branch to its destination block. +struct SequentializePIR : public FunctionPass { + static char ID; + + SequentializePIR() : FunctionPass(ID) { + initializeSequentializePIRPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + bool Changed = false; + + for (auto BB = F.begin(); BB != F.end(); ++BB) { + auto I = BB->getTerminator(); + + if (ForkInst *FI = dyn_cast(I)) { + BranchInst::Create(FI->getForked(), I); + I->eraseFromParent(); + Changed = true; + } else if (HaltInst *HI = dyn_cast(I)) { + BranchInst::Create(HI->getForkContinue(), I); + I->eraseFromParent(); + Changed = true; + } else if (JoinInst *JI = dyn_cast(I)) { + BranchInst::Create(JI->getContinue(), I); + I->eraseFromParent(); + Changed = true; + } + } + + return Changed; + } +}; +} + +char SequentializePIR::ID = 0; +INITIALIZE_PASS(SequentializePIR, "sequentialize-pir", + "Lower parallel regions to sequential IR", false, false) Index: test/PIR/lower.ll =================================================================== --- /dev/null +++ test/PIR/lower.ll @@ -0,0 +1,78 @@ +; RUN: opt -sequentialize-pir -S < %s | FileCheck %s + +declare void @foo(); + +define void @simple() { +entry: + fork label %forked, label %cont +; CHECK: entry +; CHECK-NEXT: br label %forked + +forked: + call void @foo() + halt label %cont +; CHECK: forked +; CHECK-NEXT: call void @foo +; CHECK-NEXT: br label %cont + +cont: + call void @foo() + join label %join +; CHECK: cont +; CHECK-NEXT: call void @foo +; CHECK-NEXT: br label %join + +join: + ret void +} + + +define void @nested() { +entry: + fork label %forked.outer, label %cont.outer +; CHECK: entry +; CHECK-NEXT: br label %forked.outer + +forked.outer: + call void @foo() + fork label %forked.inner, label %cont.inner +; CHECK: forked.outer +; CHECK-NEXT: call void @foo +; CHECK-NEXT: br label %forked.inner + +forked.inner: + call void @foo() + br label %forked.inner.body +; CHECK: forked.inner +; CHECK-NEXT: call void @foo +; CHECK-NEXT: br label %forked.inner.body + +forked.inner.body: + call void @foo() + halt label %cont.inner +; CHECK: forked.inner.body +; CHECK-NEXT: call void @foo +; CHECK-NEXT: br label %cont.inner + +cont.inner: + call void @foo() + join label %forked.outer.end +; CHECK: cont.inner +; CHECK-NEXT: call void @foo +; CHECK-NEXT: br label %forked.outer.end + +forked.outer.end: + halt label %cont.outer +; CHECK: forked.outer.end +; CHECK-NEXT: br label %cont.outer + +cont.outer: + call void @foo() + join label %join +; CHECK: cont +; CHECK-NEXT: call void @foo +; CHECK-NEXT: br label %join + +join: + ret void +} Index: tools/opt/CMakeLists.txt =================================================================== --- tools/opt/CMakeLists.txt +++ tools/opt/CMakeLists.txt @@ -6,6 +6,7 @@ Core Coroutines IPO + PIR IRReader InstCombine Instrumentation Index: tools/opt/opt.cpp =================================================================== --- tools/opt/opt.cpp +++ tools/opt/opt.cpp @@ -378,6 +378,7 @@ initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); + initializePIROpts(Registry); // For codegen passes, only passes that do IR to IR transformation are // supported. initializeCodeGenPreparePass(Registry);