forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			783 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			783 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- llvm/unittest/IR/OpenMPIRBuilderTest.cpp - OpenMPIRBuilder tests ---===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
 | 
						|
#include "llvm/IR/BasicBlock.h"
 | 
						|
#include "llvm/IR/DIBuilder.h"
 | 
						|
#include "llvm/IR/Function.h"
 | 
						|
#include "llvm/IR/LLVMContext.h"
 | 
						|
#include "llvm/IR/Module.h"
 | 
						|
#include "llvm/Frontend/OpenMP/OMPConstants.h"
 | 
						|
#include "llvm/IR/Verifier.h"
 | 
						|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
 | 
						|
#include "gtest/gtest.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
using namespace omp;
 | 
						|
using namespace types;
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
class OpenMPIRBuilderTest : public testing::Test {
 | 
						|
protected:
 | 
						|
  void SetUp() override {
 | 
						|
    M.reset(new Module("MyModule", Ctx));
 | 
						|
    FunctionType *FTy =
 | 
						|
        FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
 | 
						|
                          /*isVarArg=*/false);
 | 
						|
    F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
 | 
						|
    BB = BasicBlock::Create(Ctx, "", F);
 | 
						|
 | 
						|
    DIBuilder DIB(*M);
 | 
						|
    auto File = DIB.createFile("test.dbg", "/");
 | 
						|
    auto CU =
 | 
						|
        DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0);
 | 
						|
    auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
 | 
						|
    auto SP = DIB.createFunction(
 | 
						|
        CU, "foo", "", File, 1, Type, 1, DINode::FlagZero,
 | 
						|
        DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
 | 
						|
    F->setSubprogram(SP);
 | 
						|
    auto Scope = DIB.createLexicalBlockFile(SP, File, 0);
 | 
						|
    DIB.finalize();
 | 
						|
    DL = DebugLoc::get(3, 7, Scope);
 | 
						|
  }
 | 
						|
 | 
						|
  void TearDown() override {
 | 
						|
    BB = nullptr;
 | 
						|
    M.reset();
 | 
						|
    uninitializeTypes();
 | 
						|
  }
 | 
						|
 | 
						|
  LLVMContext Ctx;
 | 
						|
  std::unique_ptr<Module> M;
 | 
						|
  Function *F;
 | 
						|
  BasicBlock *BB;
 | 
						|
  DebugLoc DL;
 | 
						|
};
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, CreateBarrier) {
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OMPBuilder.CreateBarrier({IRBuilder<>::InsertPoint()}, OMPD_for);
 | 
						|
  EXPECT_TRUE(M->global_empty());
 | 
						|
  EXPECT_EQ(M->size(), 1U);
 | 
						|
  EXPECT_EQ(F->size(), 1U);
 | 
						|
  EXPECT_EQ(BB->size(), 0U);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
 | 
						|
  OMPBuilder.CreateBarrier(Loc, OMPD_for);
 | 
						|
  EXPECT_FALSE(M->global_empty());
 | 
						|
  EXPECT_EQ(M->size(), 3U);
 | 
						|
  EXPECT_EQ(F->size(), 1U);
 | 
						|
  EXPECT_EQ(BB->size(), 2U);
 | 
						|
 | 
						|
  CallInst *GTID = dyn_cast<CallInst>(&BB->front());
 | 
						|
  EXPECT_NE(GTID, nullptr);
 | 
						|
  EXPECT_EQ(GTID->getNumArgOperands(), 1U);
 | 
						|
  EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
 | 
						|
  EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
 | 
						|
  EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
 | 
						|
 | 
						|
  CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
 | 
						|
  EXPECT_NE(Barrier, nullptr);
 | 
						|
  EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
 | 
						|
  EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier");
 | 
						|
  EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
 | 
						|
  EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
 | 
						|
 | 
						|
  EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
 | 
						|
 | 
						|
  Builder.CreateUnreachable();
 | 
						|
  EXPECT_FALSE(verifyModule(*M, &errs()));
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, CreateCancel) {
 | 
						|
  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
 | 
						|
  BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
 | 
						|
  new UnreachableInst(Ctx, CBB);
 | 
						|
  auto FiniCB = [&](InsertPointTy IP) {
 | 
						|
    ASSERT_NE(IP.getBlock(), nullptr);
 | 
						|
    ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
 | 
						|
    BranchInst::Create(CBB, IP.getBlock());
 | 
						|
  };
 | 
						|
  OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
 | 
						|
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
 | 
						|
  auto NewIP = OMPBuilder.CreateCancel(Loc, nullptr, OMPD_parallel);
 | 
						|
  Builder.restoreIP(NewIP);
 | 
						|
  EXPECT_FALSE(M->global_empty());
 | 
						|
  EXPECT_EQ(M->size(), 3U);
 | 
						|
  EXPECT_EQ(F->size(), 4U);
 | 
						|
  EXPECT_EQ(BB->size(), 4U);
 | 
						|
 | 
						|
  CallInst *GTID = dyn_cast<CallInst>(&BB->front());
 | 
						|
  EXPECT_NE(GTID, nullptr);
 | 
						|
  EXPECT_EQ(GTID->getNumArgOperands(), 1U);
 | 
						|
  EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
 | 
						|
  EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
 | 
						|
  EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
 | 
						|
 | 
						|
  CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
 | 
						|
  EXPECT_NE(Cancel, nullptr);
 | 
						|
  EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
 | 
						|
  EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
 | 
						|
  EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
 | 
						|
  EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
 | 
						|
  EXPECT_EQ(Cancel->getNumUses(), 1U);
 | 
						|
  Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
 | 
						|
  EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(0), NewIP.getBlock());
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
 | 
						|
            1U);
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
 | 
						|
            CBB);
 | 
						|
 | 
						|
  EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
 | 
						|
 | 
						|
  OMPBuilder.popFinalizationCB();
 | 
						|
 | 
						|
  Builder.CreateUnreachable();
 | 
						|
  EXPECT_FALSE(verifyModule(*M, &errs()));
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) {
 | 
						|
  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
 | 
						|
  BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
 | 
						|
  new UnreachableInst(Ctx, CBB);
 | 
						|
  auto FiniCB = [&](InsertPointTy IP) {
 | 
						|
    ASSERT_NE(IP.getBlock(), nullptr);
 | 
						|
    ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
 | 
						|
    BranchInst::Create(CBB, IP.getBlock());
 | 
						|
  };
 | 
						|
  OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
 | 
						|
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
 | 
						|
  auto NewIP = OMPBuilder.CreateCancel(Loc, Builder.getTrue(), OMPD_parallel);
 | 
						|
  Builder.restoreIP(NewIP);
 | 
						|
  EXPECT_FALSE(M->global_empty());
 | 
						|
  EXPECT_EQ(M->size(), 3U);
 | 
						|
  EXPECT_EQ(F->size(), 7U);
 | 
						|
  EXPECT_EQ(BB->size(), 1U);
 | 
						|
  ASSERT_TRUE(isa<BranchInst>(BB->getTerminator()));
 | 
						|
  ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U);
 | 
						|
  BB = BB->getTerminator()->getSuccessor(0);
 | 
						|
  EXPECT_EQ(BB->size(), 4U);
 | 
						|
 | 
						|
 | 
						|
  CallInst *GTID = dyn_cast<CallInst>(&BB->front());
 | 
						|
  EXPECT_NE(GTID, nullptr);
 | 
						|
  EXPECT_EQ(GTID->getNumArgOperands(), 1U);
 | 
						|
  EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
 | 
						|
  EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
 | 
						|
  EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
 | 
						|
 | 
						|
  CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
 | 
						|
  EXPECT_NE(Cancel, nullptr);
 | 
						|
  EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
 | 
						|
  EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
 | 
						|
  EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
 | 
						|
  EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
 | 
						|
  EXPECT_EQ(Cancel->getNumUses(), 1U);
 | 
						|
  Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
 | 
						|
  EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(0)->size(), 1U);
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(0)->getUniqueSuccessor(), NewIP.getBlock());
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
 | 
						|
            1U);
 | 
						|
  EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
 | 
						|
            CBB);
 | 
						|
 | 
						|
  EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
 | 
						|
 | 
						|
  OMPBuilder.popFinalizationCB();
 | 
						|
 | 
						|
  Builder.CreateUnreachable();
 | 
						|
  EXPECT_FALSE(verifyModule(*M, &errs()));
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
 | 
						|
  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
 | 
						|
  BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
 | 
						|
  new UnreachableInst(Ctx, CBB);
 | 
						|
  auto FiniCB = [&](InsertPointTy IP) {
 | 
						|
    ASSERT_NE(IP.getBlock(), nullptr);
 | 
						|
    ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
 | 
						|
    BranchInst::Create(CBB, IP.getBlock());
 | 
						|
  };
 | 
						|
  OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
 | 
						|
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
 | 
						|
  auto NewIP = OMPBuilder.CreateBarrier(Loc, OMPD_for);
 | 
						|
  Builder.restoreIP(NewIP);
 | 
						|
  EXPECT_FALSE(M->global_empty());
 | 
						|
  EXPECT_EQ(M->size(), 3U);
 | 
						|
  EXPECT_EQ(F->size(), 4U);
 | 
						|
  EXPECT_EQ(BB->size(), 4U);
 | 
						|
 | 
						|
  CallInst *GTID = dyn_cast<CallInst>(&BB->front());
 | 
						|
  EXPECT_NE(GTID, nullptr);
 | 
						|
  EXPECT_EQ(GTID->getNumArgOperands(), 1U);
 | 
						|
  EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
 | 
						|
  EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
 | 
						|
  EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
 | 
						|
 | 
						|
  CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
 | 
						|
  EXPECT_NE(Barrier, nullptr);
 | 
						|
  EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
 | 
						|
  EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
 | 
						|
  EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
 | 
						|
  EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
 | 
						|
  EXPECT_EQ(Barrier->getNumUses(), 1U);
 | 
						|
  Instruction *BarrierBBTI = Barrier->getParent()->getTerminator();
 | 
						|
  EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U);
 | 
						|
  EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock());
 | 
						|
  EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U);
 | 
						|
  EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
 | 
						|
            1U);
 | 
						|
  EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
 | 
						|
            CBB);
 | 
						|
 | 
						|
  EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
 | 
						|
 | 
						|
  OMPBuilder.popFinalizationCB();
 | 
						|
 | 
						|
  Builder.CreateUnreachable();
 | 
						|
  EXPECT_FALSE(verifyModule(*M, &errs()));
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, DbgLoc) {
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
  F->setName("func");
 | 
						|
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
 | 
						|
  OMPBuilder.CreateBarrier(Loc, OMPD_for);
 | 
						|
  CallInst *GTID = dyn_cast<CallInst>(&BB->front());
 | 
						|
  CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
 | 
						|
  EXPECT_EQ(GTID->getDebugLoc(), DL);
 | 
						|
  EXPECT_EQ(Barrier->getDebugLoc(), DL);
 | 
						|
  EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0)));
 | 
						|
  if (!isa<GlobalVariable>(Barrier->getOperand(0)))
 | 
						|
    return;
 | 
						|
  GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0));
 | 
						|
  EXPECT_TRUE(Ident->hasInitializer());
 | 
						|
  if (!Ident->hasInitializer())
 | 
						|
    return;
 | 
						|
  Constant *Initializer = Ident->getInitializer();
 | 
						|
  EXPECT_TRUE(
 | 
						|
      isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()));
 | 
						|
  GlobalVariable *SrcStrGlob =
 | 
						|
      cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts());
 | 
						|
  if (!SrcStrGlob)
 | 
						|
    return;
 | 
						|
  EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer()));
 | 
						|
  ConstantDataArray *SrcSrc =
 | 
						|
      dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer());
 | 
						|
  if (!SrcSrc)
 | 
						|
    return;
 | 
						|
  EXPECT_EQ(SrcSrc->getAsCString(), ";test.dbg;foo;3;7;;");
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, ParallelSimple) {
 | 
						|
  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
  F->setName("func");
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
 | 
						|
 | 
						|
  AllocaInst *PrivAI = nullptr;
 | 
						|
 | 
						|
  unsigned NumBodiesGenerated = 0;
 | 
						|
  unsigned NumPrivatizedVars = 0;
 | 
						|
  unsigned NumFinalizationPoints = 0;
 | 
						|
 | 
						|
  auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
 | 
						|
                       BasicBlock &ContinuationIP) {
 | 
						|
    ++NumBodiesGenerated;
 | 
						|
 | 
						|
    Builder.restoreIP(AllocaIP);
 | 
						|
    PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
 | 
						|
    Builder.CreateStore(F->arg_begin(), PrivAI);
 | 
						|
 | 
						|
    Builder.restoreIP(CodeGenIP);
 | 
						|
    Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
 | 
						|
    Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
 | 
						|
    Instruction *ThenTerm, *ElseTerm;
 | 
						|
    SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
 | 
						|
                                  &ThenTerm, &ElseTerm);
 | 
						|
 | 
						|
    Builder.SetInsertPoint(ThenTerm);
 | 
						|
    Builder.CreateBr(&ContinuationIP);
 | 
						|
    ThenTerm->eraseFromParent();
 | 
						|
  };
 | 
						|
 | 
						|
  auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
 | 
						|
                    Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
 | 
						|
    ++NumPrivatizedVars;
 | 
						|
 | 
						|
    if (!isa<AllocaInst>(VPtr)) {
 | 
						|
      EXPECT_EQ(&VPtr, F->arg_begin());
 | 
						|
      ReplacementValue = &VPtr;
 | 
						|
      return CodeGenIP;
 | 
						|
    }
 | 
						|
 | 
						|
    // Trivial copy (=firstprivate).
 | 
						|
    Builder.restoreIP(AllocaIP);
 | 
						|
    Type *VTy = VPtr.getType()->getPointerElementType();
 | 
						|
    Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
 | 
						|
    ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
 | 
						|
    Builder.restoreIP(CodeGenIP);
 | 
						|
    Builder.CreateStore(V, ReplacementValue);
 | 
						|
    return CodeGenIP;
 | 
						|
  };
 | 
						|
 | 
						|
  auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
 | 
						|
 | 
						|
  IRBuilder<>::InsertPoint AfterIP =
 | 
						|
      OMPBuilder.CreateParallel(Loc, BodyGenCB, PrivCB, FiniCB, nullptr,
 | 
						|
                                nullptr, OMP_PROC_BIND_default, false);
 | 
						|
  EXPECT_EQ(NumBodiesGenerated, 1U);
 | 
						|
  EXPECT_EQ(NumPrivatizedVars, 1U);
 | 
						|
  EXPECT_EQ(NumFinalizationPoints, 1U);
 | 
						|
 | 
						|
  Builder.restoreIP(AfterIP);
 | 
						|
  Builder.CreateRetVoid();
 | 
						|
 | 
						|
  OMPBuilder.finalize();
 | 
						|
 | 
						|
  EXPECT_NE(PrivAI, nullptr);
 | 
						|
  Function *OutlinedFn = PrivAI->getFunction();
 | 
						|
  EXPECT_NE(F, OutlinedFn);
 | 
						|
  EXPECT_FALSE(verifyModule(*M, &errs()));
 | 
						|
  EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
 | 
						|
  EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
 | 
						|
  EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
 | 
						|
  EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
 | 
						|
 | 
						|
  EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
 | 
						|
  EXPECT_EQ(OutlinedFn->arg_size(), 3U);
 | 
						|
 | 
						|
  EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
 | 
						|
  EXPECT_EQ(OutlinedFn->getNumUses(), 1U);
 | 
						|
  User *Usr = OutlinedFn->user_back();
 | 
						|
  ASSERT_TRUE(isa<ConstantExpr>(Usr));
 | 
						|
  CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
 | 
						|
  ASSERT_NE(ForkCI, nullptr);
 | 
						|
 | 
						|
  EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
 | 
						|
  EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
 | 
						|
  EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
 | 
						|
  EXPECT_EQ(ForkCI->getArgOperand(1),
 | 
						|
            ConstantInt::get(Type::getInt32Ty(Ctx), 1U));
 | 
						|
  EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
 | 
						|
  EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin());
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, ParallelIfCond) {
 | 
						|
  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
  F->setName("func");
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
 | 
						|
 | 
						|
  AllocaInst *PrivAI = nullptr;
 | 
						|
 | 
						|
  unsigned NumBodiesGenerated = 0;
 | 
						|
  unsigned NumPrivatizedVars = 0;
 | 
						|
  unsigned NumFinalizationPoints = 0;
 | 
						|
 | 
						|
  auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
 | 
						|
                       BasicBlock &ContinuationIP) {
 | 
						|
    ++NumBodiesGenerated;
 | 
						|
 | 
						|
    Builder.restoreIP(AllocaIP);
 | 
						|
    PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
 | 
						|
    Builder.CreateStore(F->arg_begin(), PrivAI);
 | 
						|
 | 
						|
    Builder.restoreIP(CodeGenIP);
 | 
						|
    Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
 | 
						|
    Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
 | 
						|
    Instruction *ThenTerm, *ElseTerm;
 | 
						|
    SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
 | 
						|
                                  &ThenTerm, &ElseTerm);
 | 
						|
 | 
						|
    Builder.SetInsertPoint(ThenTerm);
 | 
						|
    Builder.CreateBr(&ContinuationIP);
 | 
						|
    ThenTerm->eraseFromParent();
 | 
						|
  };
 | 
						|
 | 
						|
  auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
 | 
						|
                    Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
 | 
						|
    ++NumPrivatizedVars;
 | 
						|
 | 
						|
    if (!isa<AllocaInst>(VPtr)) {
 | 
						|
      EXPECT_EQ(&VPtr, F->arg_begin());
 | 
						|
      ReplacementValue = &VPtr;
 | 
						|
      return CodeGenIP;
 | 
						|
    }
 | 
						|
 | 
						|
    // Trivial copy (=firstprivate).
 | 
						|
    Builder.restoreIP(AllocaIP);
 | 
						|
    Type *VTy = VPtr.getType()->getPointerElementType();
 | 
						|
    Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
 | 
						|
    ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
 | 
						|
    Builder.restoreIP(CodeGenIP);
 | 
						|
    Builder.CreateStore(V, ReplacementValue);
 | 
						|
    return CodeGenIP;
 | 
						|
  };
 | 
						|
 | 
						|
  auto FiniCB = [&](InsertPointTy CodeGenIP) {
 | 
						|
    ++NumFinalizationPoints;
 | 
						|
    // No destructors.
 | 
						|
  };
 | 
						|
 | 
						|
  IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel(
 | 
						|
      Loc, BodyGenCB, PrivCB, FiniCB, Builder.CreateIsNotNull(F->arg_begin()),
 | 
						|
      nullptr, OMP_PROC_BIND_default, false);
 | 
						|
 | 
						|
  EXPECT_EQ(NumBodiesGenerated, 1U);
 | 
						|
  EXPECT_EQ(NumPrivatizedVars, 1U);
 | 
						|
  EXPECT_EQ(NumFinalizationPoints, 1U);
 | 
						|
 | 
						|
  Builder.restoreIP(AfterIP);
 | 
						|
  Builder.CreateRetVoid();
 | 
						|
  OMPBuilder.finalize();
 | 
						|
 | 
						|
  EXPECT_NE(PrivAI, nullptr);
 | 
						|
  Function *OutlinedFn = PrivAI->getFunction();
 | 
						|
  EXPECT_NE(F, OutlinedFn);
 | 
						|
  EXPECT_FALSE(verifyModule(*M, &errs()));
 | 
						|
 | 
						|
  EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
 | 
						|
  EXPECT_EQ(OutlinedFn->arg_size(), 3U);
 | 
						|
 | 
						|
  EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
 | 
						|
  ASSERT_EQ(OutlinedFn->getNumUses(), 2U);
 | 
						|
 | 
						|
  CallInst *DirectCI = nullptr;
 | 
						|
  CallInst *ForkCI = nullptr;
 | 
						|
  for (User *Usr : OutlinedFn->users()) {
 | 
						|
    if (isa<CallInst>(Usr)) {
 | 
						|
      ASSERT_EQ(DirectCI, nullptr);
 | 
						|
      DirectCI = cast<CallInst>(Usr);
 | 
						|
    } else {
 | 
						|
      ASSERT_TRUE(isa<ConstantExpr>(Usr));
 | 
						|
      ASSERT_EQ(Usr->getNumUses(), 1U);
 | 
						|
      ASSERT_TRUE(isa<CallInst>(Usr->user_back()));
 | 
						|
      ForkCI = cast<CallInst>(Usr->user_back());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
 | 
						|
  EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
 | 
						|
  EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
 | 
						|
  EXPECT_EQ(ForkCI->getArgOperand(1),
 | 
						|
            ConstantInt::get(Type::getInt32Ty(Ctx), 1));
 | 
						|
  EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin());
 | 
						|
 | 
						|
  EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn);
 | 
						|
  EXPECT_EQ(DirectCI->getNumArgOperands(), 3U);
 | 
						|
  EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0)));
 | 
						|
  EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1)));
 | 
						|
  EXPECT_EQ(DirectCI->getArgOperand(2), F->arg_begin());
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
 | 
						|
  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
  F->setName("func");
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
 | 
						|
 | 
						|
  unsigned NumBodiesGenerated = 0;
 | 
						|
  unsigned NumPrivatizedVars = 0;
 | 
						|
  unsigned NumFinalizationPoints = 0;
 | 
						|
 | 
						|
  CallInst *CheckedBarrier = nullptr;
 | 
						|
  auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
 | 
						|
                       BasicBlock &ContinuationIP) {
 | 
						|
    ++NumBodiesGenerated;
 | 
						|
 | 
						|
    Builder.restoreIP(CodeGenIP);
 | 
						|
 | 
						|
    // Create three barriers, two cancel barriers but only one checked.
 | 
						|
    Function *CBFn, *BFn;
 | 
						|
 | 
						|
    Builder.restoreIP(
 | 
						|
        OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel));
 | 
						|
 | 
						|
    CBFn = M->getFunction("__kmpc_cancel_barrier");
 | 
						|
    BFn = M->getFunction("__kmpc_barrier");
 | 
						|
    ASSERT_NE(CBFn, nullptr);
 | 
						|
    ASSERT_EQ(BFn, nullptr);
 | 
						|
    ASSERT_EQ(CBFn->getNumUses(), 1U);
 | 
						|
    ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
 | 
						|
    ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U);
 | 
						|
    CheckedBarrier = cast<CallInst>(CBFn->user_back());
 | 
						|
 | 
						|
    Builder.restoreIP(
 | 
						|
        OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel, true));
 | 
						|
    CBFn = M->getFunction("__kmpc_cancel_barrier");
 | 
						|
    BFn = M->getFunction("__kmpc_barrier");
 | 
						|
    ASSERT_NE(CBFn, nullptr);
 | 
						|
    ASSERT_NE(BFn, nullptr);
 | 
						|
    ASSERT_EQ(CBFn->getNumUses(), 1U);
 | 
						|
    ASSERT_EQ(BFn->getNumUses(), 1U);
 | 
						|
    ASSERT_TRUE(isa<CallInst>(BFn->user_back()));
 | 
						|
    ASSERT_EQ(BFn->user_back()->getNumUses(), 0U);
 | 
						|
 | 
						|
    Builder.restoreIP(OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel,
 | 
						|
                                               false, false));
 | 
						|
    ASSERT_EQ(CBFn->getNumUses(), 2U);
 | 
						|
    ASSERT_EQ(BFn->getNumUses(), 1U);
 | 
						|
    ASSERT_TRUE(CBFn->user_back() != CheckedBarrier);
 | 
						|
    ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
 | 
						|
    ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U);
 | 
						|
  };
 | 
						|
 | 
						|
  auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V,
 | 
						|
                    Value *&) -> InsertPointTy {
 | 
						|
    ++NumPrivatizedVars;
 | 
						|
    llvm_unreachable("No privatization callback call expected!");
 | 
						|
  };
 | 
						|
 | 
						|
  FunctionType *FakeDestructorTy =
 | 
						|
      FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
 | 
						|
                        /*isVarArg=*/false);
 | 
						|
  auto *FakeDestructor = Function::Create(
 | 
						|
      FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get());
 | 
						|
 | 
						|
  auto FiniCB = [&](InsertPointTy IP) {
 | 
						|
    ++NumFinalizationPoints;
 | 
						|
    Builder.restoreIP(IP);
 | 
						|
    Builder.CreateCall(FakeDestructor,
 | 
						|
                       {Builder.getInt32(NumFinalizationPoints)});
 | 
						|
  };
 | 
						|
 | 
						|
  IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel(
 | 
						|
      Loc, BodyGenCB, PrivCB, FiniCB, Builder.CreateIsNotNull(F->arg_begin()),
 | 
						|
      nullptr, OMP_PROC_BIND_default, true);
 | 
						|
 | 
						|
  EXPECT_EQ(NumBodiesGenerated, 1U);
 | 
						|
  EXPECT_EQ(NumPrivatizedVars, 0U);
 | 
						|
  EXPECT_EQ(NumFinalizationPoints, 2U);
 | 
						|
  EXPECT_EQ(FakeDestructor->getNumUses(), 2U);
 | 
						|
 | 
						|
  Builder.restoreIP(AfterIP);
 | 
						|
  Builder.CreateRetVoid();
 | 
						|
  OMPBuilder.finalize();
 | 
						|
 | 
						|
  EXPECT_FALSE(verifyModule(*M, &errs()));
 | 
						|
 | 
						|
  BasicBlock *ExitBB = nullptr;
 | 
						|
  for (const User *Usr : FakeDestructor->users()) {
 | 
						|
    const CallInst *CI = dyn_cast<CallInst>(Usr);
 | 
						|
    ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
 | 
						|
    ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
 | 
						|
    ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
 | 
						|
    if (ExitBB)
 | 
						|
      ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
 | 
						|
    else
 | 
						|
      ExitBB = CI->getNextNode()->getSuccessor(0);
 | 
						|
    ASSERT_EQ(ExitBB->size(), 1U);
 | 
						|
    if (!isa<ReturnInst>(ExitBB->front())) {
 | 
						|
      ASSERT_TRUE(isa<BranchInst>(ExitBB->front()));
 | 
						|
      ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U);
 | 
						|
      ASSERT_TRUE(isa<ReturnInst>(
 | 
						|
          cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front()));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, MasterDirective) {
 | 
						|
  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
  F->setName("func");
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
 | 
						|
 | 
						|
  AllocaInst *PrivAI = nullptr;
 | 
						|
 | 
						|
  BasicBlock *EntryBB = nullptr;
 | 
						|
  BasicBlock *ExitBB = nullptr;
 | 
						|
  BasicBlock *ThenBB = nullptr;
 | 
						|
 | 
						|
  auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
 | 
						|
                       BasicBlock &FiniBB) {
 | 
						|
    if (AllocaIP.isSet())
 | 
						|
      Builder.restoreIP(AllocaIP);
 | 
						|
    else
 | 
						|
      Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
 | 
						|
    PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
 | 
						|
    Builder.CreateStore(F->arg_begin(), PrivAI);
 | 
						|
 | 
						|
    llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
 | 
						|
    llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
 | 
						|
    EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
 | 
						|
 | 
						|
    Builder.restoreIP(CodeGenIP);
 | 
						|
 | 
						|
    // collect some info for checks later
 | 
						|
    ExitBB = FiniBB.getUniqueSuccessor();
 | 
						|
    ThenBB = Builder.GetInsertBlock();
 | 
						|
    EntryBB = ThenBB->getUniquePredecessor();
 | 
						|
 | 
						|
    // simple instructions for body
 | 
						|
    Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
 | 
						|
    Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
 | 
						|
  };
 | 
						|
 | 
						|
  auto FiniCB = [&](InsertPointTy IP) {
 | 
						|
    BasicBlock *IPBB = IP.getBlock();
 | 
						|
    EXPECT_NE(IPBB->end(), IP.getPoint());
 | 
						|
  };
 | 
						|
 | 
						|
  Builder.restoreIP(OMPBuilder.CreateMaster(Builder, BodyGenCB, FiniCB));
 | 
						|
  Value *EntryBBTI = EntryBB->getTerminator();
 | 
						|
  EXPECT_NE(EntryBBTI, nullptr);
 | 
						|
  EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
 | 
						|
  BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
 | 
						|
  EXPECT_TRUE(EntryBr->isConditional());
 | 
						|
  EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
 | 
						|
  EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
 | 
						|
  EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
 | 
						|
 | 
						|
  CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
 | 
						|
  EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
 | 
						|
 | 
						|
  CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
 | 
						|
  EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U);
 | 
						|
  EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master");
 | 
						|
  EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
 | 
						|
 | 
						|
  CallInst *MasterEndCI = nullptr;
 | 
						|
  for (auto &FI : *ThenBB) {
 | 
						|
    Instruction *cur = &FI;
 | 
						|
    if (isa<CallInst>(cur)) {
 | 
						|
      MasterEndCI = cast<CallInst>(cur);
 | 
						|
      if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master")
 | 
						|
        break;
 | 
						|
      MasterEndCI = nullptr;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  EXPECT_NE(MasterEndCI, nullptr);
 | 
						|
  EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U);
 | 
						|
  EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
 | 
						|
  EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
 | 
						|
  using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
 | 
						|
  OpenMPIRBuilder OMPBuilder(*M);
 | 
						|
  OMPBuilder.initialize();
 | 
						|
  F->setName("func");
 | 
						|
  IRBuilder<> Builder(BB);
 | 
						|
 | 
						|
  OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
 | 
						|
 | 
						|
  AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
 | 
						|
 | 
						|
  BasicBlock *EntryBB = nullptr;
 | 
						|
 | 
						|
  auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
 | 
						|
                       BasicBlock &FiniBB) {
 | 
						|
    // collect some info for checks later
 | 
						|
    EntryBB = FiniBB.getUniquePredecessor();
 | 
						|
 | 
						|
    // actual start for bodyCB
 | 
						|
    llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
 | 
						|
    llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
 | 
						|
    EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
 | 
						|
    EXPECT_EQ(EntryBB, CodeGenIPBB);
 | 
						|
 | 
						|
    // body begin
 | 
						|
    Builder.restoreIP(CodeGenIP);
 | 
						|
    Builder.CreateStore(F->arg_begin(), PrivAI);
 | 
						|
    Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
 | 
						|
    Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
 | 
						|
  };
 | 
						|
 | 
						|
  auto FiniCB = [&](InsertPointTy IP) {
 | 
						|
    BasicBlock *IPBB = IP.getBlock();
 | 
						|
    EXPECT_NE(IPBB->end(), IP.getPoint());
 | 
						|
  };
 | 
						|
 | 
						|
  Builder.restoreIP(OMPBuilder.CreateCritical(Builder, BodyGenCB, FiniCB,
 | 
						|
                                              "testCRT", nullptr));
 | 
						|
 | 
						|
  Value *EntryBBTI = EntryBB->getTerminator();
 | 
						|
  EXPECT_EQ(EntryBBTI, nullptr);
 | 
						|
 | 
						|
  CallInst *CriticalEntryCI = nullptr;
 | 
						|
  for (auto &EI : *EntryBB) {
 | 
						|
    Instruction *cur = &EI;
 | 
						|
    if (isa<CallInst>(cur)) {
 | 
						|
      CriticalEntryCI = cast<CallInst>(cur);
 | 
						|
      if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical")
 | 
						|
        break;
 | 
						|
      CriticalEntryCI = nullptr;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  EXPECT_NE(CriticalEntryCI, nullptr);
 | 
						|
  EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U);
 | 
						|
  EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical");
 | 
						|
  EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
 | 
						|
 | 
						|
  CallInst *CriticalEndCI = nullptr;
 | 
						|
  for (auto &FI : *EntryBB) {
 | 
						|
    Instruction *cur = &FI;
 | 
						|
    if (isa<CallInst>(cur)) {
 | 
						|
      CriticalEndCI = cast<CallInst>(cur);
 | 
						|
      if (CriticalEndCI->getCalledFunction()->getName() ==
 | 
						|
          "__kmpc_end_critical")
 | 
						|
        break;
 | 
						|
      CriticalEndCI = nullptr;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  EXPECT_NE(CriticalEndCI, nullptr);
 | 
						|
  EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U);
 | 
						|
  EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
 | 
						|
  EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
 | 
						|
  PointerType *CriticalNamePtrTy =
 | 
						|
      PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
 | 
						|
  EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
 | 
						|
  EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace
 |