domada updated this revision to Diff 465332. domada added a comment. Patch rebased.
CHANGES SINCE LAST ACTION https://reviews.llvm.org/D133578/new/ https://reviews.llvm.org/D133578 Files: clang/lib/CodeGen/CGStmtOpenMP.cpp llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
Index: mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp =================================================================== --- mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -996,8 +996,9 @@ if (llvm::Optional<uint64_t> safelenVar = loop.getSafelen()) safelen = builder.getInt64(safelenVar.value()); + llvm::DenseMap<llvm::Value *, llvm::Value *> alignedVars; ompBuilder->applySimd( - loopInfo, + loopInfo, alignedVars, loop.getIfExpr() ? moduleTranslation.lookupValue(loop.getIfExpr()) : nullptr, llvm::omp::OrderKind::OMP_ORDER_unknown, simdlen, safelen); Index: llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp =================================================================== --- llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp +++ llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp @@ -1767,11 +1767,12 @@ TEST_F(OpenMPIRBuilderTest, ApplySimd) { OpenMPIRBuilder OMPBuilder(*M); - + DenseMap<Value *, Value *> AlignedVars; CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder, 32); // Simd-ize the loop. - OMPBuilder.applySimd(CLI, /* IfCond */ nullptr, OrderKind::OMP_ORDER_unknown, + OMPBuilder.applySimd(CLI, AlignedVars, /* IfCond */ nullptr, + OrderKind::OMP_ORDER_unknown, /* Simdlen */ nullptr, /* Safelen */ nullptr); @@ -1798,13 +1799,84 @@ })); } -TEST_F(OpenMPIRBuilderTest, ApplySimdlen) { +TEST_F(OpenMPIRBuilderTest, ApplySimdCustomAligned) { OpenMPIRBuilder OMPBuilder(*M); + IRBuilder<> Builder(BB); + const int AlignmentValue = 32; + AllocaInst *Alloc1 = + Builder.CreateAlloca(Builder.getInt8PtrTy(), Builder.getInt64(1)); + AllocaInst *Alloc2 = Builder.CreateAlloca( + ArrayType::get(Builder.getInt32Ty(), 10), Builder.getInt64(1)); + DenseMap<Value *, Value *> AlignedVars; + auto Int8Ty = Builder.getInt8Ty(); + Instruction *MallocInstr = CallInst::CreateMalloc( + Alloc2, Builder.getInt64Ty(), Int8Ty, ConstantExpr::getSizeOf(Int8Ty), + Builder.getInt64(400), nullptr, ""); + Builder.CreateStore(MallocInstr, Alloc1); + + AlignedVars.insert({Alloc1, Builder.getInt64(AlignmentValue)}); + AlignedVars.insert({Alloc2, Builder.getInt64(AlignmentValue)}); CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder, 32); // Simd-ize the loop. - OMPBuilder.applySimd(CLI, /* IfCond */ nullptr, OrderKind::OMP_ORDER_unknown, + OMPBuilder.applySimd(CLI, AlignedVars, /* IfCond */ nullptr, + OrderKind::OMP_ORDER_unknown, + /* Simdlen */ nullptr, + /* Safelen */ nullptr); + + OMPBuilder.finalize(); + EXPECT_FALSE(verifyModule(*M, &errs())); + + PassBuilder PB; + FunctionAnalysisManager FAM; + PB.registerFunctionAnalyses(FAM); + LoopInfo &LI = FAM.getResult<LoopAnalysis>(*F); + + const std::vector<Loop *> &TopLvl = LI.getTopLevelLoops(); + EXPECT_EQ(TopLvl.size(), 1u); + + Loop *L = TopLvl.front(); + EXPECT_TRUE(findStringMetadataForLoop(L, "llvm.loop.parallel_accesses")); + EXPECT_TRUE(getBooleanLoopAttribute(L, "llvm.loop.vectorize.enable")); + + // Check for llvm.access.group metadata attached to the printf + // function in the loop body. + BasicBlock *LoopBody = CLI->getBody(); + EXPECT_TRUE(any_of(*LoopBody, [](Instruction &I) { + return I.getMetadata("llvm.access.group") != nullptr; + })); + + // Check if number of assumption instructions is equal to number of aligned + // variables + BasicBlock *LoopPreheader = CLI->getPreheader(); + size_t NumAssummptionCallsInPreheader = count_if( + *LoopPreheader, [](Instruction &I) { return isa<AssumeInst>(I); }); + EXPECT_EQ(NumAssummptionCallsInPreheader, AlignedVars.size()); + + // Check if variables are correctly aligned + for (auto &Instr : LoopPreheader->getInstList()) { + if (isa<AssumeInst>(Instr)) { + auto AssumeInstruction = dyn_cast<AssumeInst>(&Instr); + if (AssumeInstruction->getNumTotalBundleOperands()) { + auto Bundle = AssumeInstruction->getOperandBundleAt(0); + if (Bundle.getTagName() == "align") { + EXPECT_TRUE(isa<ConstantInt>(Bundle.Inputs[1])); + auto ConstIntVal = dyn_cast<ConstantInt>(Bundle.Inputs[1]); + EXPECT_EQ(ConstIntVal->getSExtValue(), AlignmentValue); + } + } + } + } +} +TEST_F(OpenMPIRBuilderTest, ApplySimdlen) { + OpenMPIRBuilder OMPBuilder(*M); + DenseMap<Value *, Value *> AlignedVars; + CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder, 32); + + // Simd-ize the loop. + OMPBuilder.applySimd(CLI, AlignedVars, + /* IfCond */ nullptr, OrderKind::OMP_ORDER_unknown, ConstantInt::get(Type::getInt32Ty(Ctx), 3), /* Safelen */ nullptr); @@ -1834,12 +1906,13 @@ TEST_F(OpenMPIRBuilderTest, ApplySafelenOrderConcurrent) { OpenMPIRBuilder OMPBuilder(*M); + DenseMap<Value *, Value *> AlignedVars; CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder, 32); // Simd-ize the loop. OMPBuilder.applySimd( - CLI, /* IfCond */ nullptr, OrderKind::OMP_ORDER_concurrent, + CLI, AlignedVars, /* IfCond */ nullptr, OrderKind::OMP_ORDER_concurrent, /* Simdlen */ nullptr, ConstantInt::get(Type::getInt32Ty(Ctx), 3)); OMPBuilder.finalize(); @@ -1870,13 +1943,13 @@ TEST_F(OpenMPIRBuilderTest, ApplySafelen) { OpenMPIRBuilder OMPBuilder(*M); + DenseMap<Value *, Value *> AlignedVars; CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder, 32); - // Simd-ize the loop. - OMPBuilder.applySimd(CLI, /* IfCond */ nullptr, OrderKind::OMP_ORDER_unknown, - /* Simdlen */ nullptr, - ConstantInt::get(Type::getInt32Ty(Ctx), 3)); + OMPBuilder.applySimd( + CLI, AlignedVars, /* IfCond */ nullptr, OrderKind::OMP_ORDER_unknown, + /* Simdlen */ nullptr, ConstantInt::get(Type::getInt32Ty(Ctx), 3)); OMPBuilder.finalize(); EXPECT_FALSE(verifyModule(*M, &errs())); @@ -1904,11 +1977,12 @@ TEST_F(OpenMPIRBuilderTest, ApplySimdlenSafelen) { OpenMPIRBuilder OMPBuilder(*M); + DenseMap<Value *, Value *> AlignedVars; CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder, 32); - // Simd-ize the loop. - OMPBuilder.applySimd(CLI, /* IfCond */ nullptr, OrderKind::OMP_ORDER_unknown, + OMPBuilder.applySimd(CLI, AlignedVars, /* IfCond */ nullptr, + OrderKind::OMP_ORDER_unknown, ConstantInt::get(Type::getInt32Ty(Ctx), 2), ConstantInt::get(Type::getInt32Ty(Ctx), 3)); @@ -1939,6 +2013,7 @@ TEST_F(OpenMPIRBuilderTest, ApplySimdLoopIf) { OpenMPIRBuilder OMPBuilder(*M); IRBuilder<> Builder(BB); + DenseMap<Value *, Value *> AlignedVars; AllocaInst *Alloc1 = Builder.CreateAlloca(Builder.getInt32Ty()); AllocaInst *Alloc2 = Builder.CreateAlloca(Builder.getInt32Ty()); @@ -1953,7 +2028,7 @@ CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder, 32); // Simd-ize the loop with if condition - OMPBuilder.applySimd(CLI, IfCmp, OrderKind::OMP_ORDER_unknown, + OMPBuilder.applySimd(CLI, AlignedVars, IfCmp, OrderKind::OMP_ORDER_unknown, ConstantInt::get(Type::getInt32Ty(Ctx), 3), /* Safelen */ nullptr); Index: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp =================================================================== --- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -3005,9 +3005,10 @@ Builder.CreateBr(NewBlocks.front()); } -void OpenMPIRBuilder::applySimd(CanonicalLoopInfo *CanonicalLoop, Value *IfCond, - OrderKind Order, ConstantInt *Simdlen, - ConstantInt *Safelen) { +void OpenMPIRBuilder::applySimd(CanonicalLoopInfo *CanonicalLoop, + DenseMap<Value *, Value *> AlignedVars, + Value *IfCond, OrderKind Order, + ConstantInt *Simdlen, ConstantInt *Safelen) { LLVMContext &Ctx = Builder.getContext(); Function *F = CanonicalLoop->getFunction(); @@ -3026,6 +3027,31 @@ Loop *L = LI.getLoopFor(CanonicalLoop->getHeader()); + for (auto &AlignedItem : AlignedVars) { + assert(isa<AllocaInst>(AlignedItem.first) && + "Value which needs to be aligned must represented by alloca " + "instruction"); + assert(AlignedItem.second && + "Alignment should be specified for all aligned variables"); + Value *AlignPtrInstruction = nullptr; + AllocaInst *AllocaInstruction = dyn_cast<AllocaInst>(AlignedItem.first); + Builder.SetInsertPoint(CanonicalLoop->getPreheader()->getTerminator()); + Type *AllocatedVarType = AllocaInstruction->getAllocatedType(); + if (isa<ArrayType>(AllocatedVarType)) + AlignPtrInstruction = Builder.CreateInBoundsGEP( + AllocaInstruction->getAllocatedType(), AllocaInstruction, + SmallVector<Value *>{Builder.getInt64(0), Builder.getInt64(0)}, + "arraydecay"); + else if (isa<PointerType>(AllocatedVarType)) + AlignPtrInstruction = Builder.CreateLoad( + AllocaInstruction->getAllocatedType(), AllocaInstruction); + assert(AlignPtrInstruction && + "Aligned variables must be either pointer or array type"); + + Builder.CreateAlignmentAssumption(F->getParent()->getDataLayout(), + AlignPtrInstruction, AlignedItem.second); + } + if (IfCond) { ValueToValueMapTy VMap; createIfVersion(CanonicalLoop, IfCond, VMap, "simd"); Index: llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h =================================================================== --- llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -617,13 +617,17 @@ /// to the cloned loop. The cloned loop is executed when ifCond is evaluated /// to false. /// - /// \param Loop The loop to simd-ize. - /// \param IfCond The value which corresponds to the if clause condition. - /// \param Order The enum to map order clause - /// \param Simdlen The Simdlen length to apply to the simd loop. - /// \param Safelen The Safelen length to apply to the simd loop. - void applySimd(CanonicalLoopInfo *Loop, Value *IfCond, omp::OrderKind Order, - ConstantInt *Simdlen, ConstantInt *Safelen); + /// \param Loop The loop to simd-ize. + /// \param AlignedVars The map of the variables which need to aligned with. + /// \param IfCond The value which corresponds to the if clause + /// condition. + /// \param Order The enum to map order clause. + /// \param Simdlen The Simdlen length to apply to the simd loop. + /// \param Safelen The Safelen length to apply to the simd loop. + void applySimd(CanonicalLoopInfo *Loop, + llvm::DenseMap<llvm::Value *, llvm::Value *> AlignedVars, + Value *IfCond, omp::OrderKind Order, ConstantInt *Simdlen, + ConstantInt *Safelen); /// Generator for '#omp flush' /// Index: clang/lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- clang/lib/CodeGen/CGStmtOpenMP.cpp +++ clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2637,6 +2637,7 @@ PrePostActionTy &) { // Use the OpenMPIRBuilder if enabled. if (UseOMPIRBuilder) { + llvm::DenseMap<llvm::Value *, llvm::Value *> AlignedVars; // Emit the associated statement and get its loop representation. const Stmt *Inner = S.getRawStmt(); llvm::CanonicalLoopInfo *CLI = @@ -2669,7 +2670,8 @@ } // Add simd metadata to the collapsed loop. Do not generate // another loop for if clause. Support for if clause is done earlier. - OMPBuilder.applySimd(CLI, /*IfCond*/ nullptr, Order, Simdlen, Safelen); + OMPBuilder.applySimd(CLI, AlignedVars, + /*IfCond*/ nullptr, Order, Simdlen, Safelen); return; } };
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits