Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -39,6 +39,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/FPEnv.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" @@ -1285,22 +1286,6 @@ EmitBlock(SkipCountBB); } -/// Tries to mark the given function nounwind based on the -/// non-existence of any throwing calls within it. We believe this is -/// lightweight enough to do at -O0. -static void TryMarkNoThrow(llvm::Function *F) { - // LLVM treats 'nounwind' on a function as part of the type, so we - // can't do this on functions that can be overwritten. - if (F->isInterposable()) return; - - for (llvm::BasicBlock &BB : *F) - for (llvm::Instruction &I : BB) - if (I.mayThrow()) - return; - - F->setDoesNotThrow(); -} - QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args) { const FunctionDecl *FD = cast(GD.getDecl()); @@ -1498,7 +1483,7 @@ // If we haven't marked the function nothrow through other means, do // a quick pass now to see if we can. if (!CurFn->doesNotThrow()) - TryMarkNoThrow(CurFn); + llvm::IRBuilderBase::TryMarkNoThrow(CurFn); } /// ContainsLabel - Return true if the statement contains a label in it. If Index: llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h =================================================================== --- llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -2181,6 +2181,9 @@ /// \param AttributeValue Value of the attribute void addAttributeToModuleFunctions(StringRef AttributeName, StringRef AttributeValue); + + /// Try to add nounwind attribute to the generated functions + void tryMarkNoThrowModuleFunctions(); }; /// Class to represented the control flow structure of an OpenMP canonical loop. Index: llvm/include/llvm/IR/IRBuilder.h =================================================================== --- llvm/include/llvm/IR/IRBuilder.h +++ llvm/include/llvm/IR/IRBuilder.h @@ -2543,6 +2543,11 @@ CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, Value *Alignment, Value *OffsetValue = nullptr); + + /// Tries to mark the given function nounwind based on the + /// non-existence of any throwing calls within it. We believe this is + /// lightweight enough to do at -O0. + static void TryMarkNoThrow(llvm::Function *F); }; /// This provides a uniform API for creating instructions and inserting Index: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp =================================================================== --- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -5052,6 +5052,16 @@ } } +void OpenMPIRBuilder::tryMarkNoThrowModuleFunctions() { + for (Function &f : M.functions()) { + if (f.isDeclaration()) + continue; + if (f.hasFnAttribute(Attribute::NoUnwind)) + continue; + IRBuilderBase::TryMarkNoThrow(&f); + } +} + void TargetRegionEntryInfo::getTargetRegionEntryFnName( SmallVectorImpl &Name, StringRef ParentName, unsigned DeviceID, unsigned FileID, unsigned Line, unsigned Count) { Index: llvm/lib/IR/IRBuilder.cpp =================================================================== --- llvm/lib/IR/IRBuilder.cpp +++ llvm/lib/IR/IRBuilder.cpp @@ -1410,6 +1410,20 @@ return CreateAlignmentAssumptionHelper(DL, PtrValue, Alignment, OffsetValue); } +void IRBuilderBase::TryMarkNoThrow(llvm::Function *F) { + // LLVM treats 'nounwind' on a function as part of the type, so we + // can't do this on functions that can be overwritten. + if (F->isInterposable()) + return; + + for (llvm::BasicBlock &BB : *F) + for (llvm::Instruction &I : BB) + if (I.mayThrow()) + return; + + F->setDoesNotThrow(); +} + IRBuilderDefaultInserter::~IRBuilderDefaultInserter() = default; IRBuilderCallbackInserter::~IRBuilderCallbackInserter() = default; IRBuilderFolder::~IRBuilderFolder() = default; 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 @@ -1615,6 +1615,9 @@ Operation *op, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const { + llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); + ompBuilder->tryMarkNoThrowModuleFunctions(); + return llvm::TypeSwitch(attribute.getValue()) .Case([&](mlir::omp::FlagsAttr rtlAttr) { return convertFlagsAttr(op, rtlAttr, moduleTranslation); Index: mlir/test/Target/LLVMIR/openmp-llvm.mlir =================================================================== --- mlir/test/Target/LLVMIR/openmp-llvm.mlir +++ mlir/test/Target/LLVMIR/openmp-llvm.mlir @@ -2547,7 +2547,7 @@ } } -// CHECK: attributes #0 = { "target-cpu"="gfx908" +// CHECK: attributes #0 = { nounwind "target-cpu"="gfx908" // CHECK-SAME: "target-features"="+dot3-insts,+dot4-insts,+s-memtime-inst, // CHECK-SAME: +16-bit-insts,+s-memrealtime,+dot6-insts,+dl-insts, // CHECK-SAME: +wavefrontsize64,+gfx9-insts,+gfx8-insts,+ci-insts,+dot10-insts, @@ -2567,7 +2567,7 @@ llvm.return } } -// CHECK: attributes #0 = { "target-cpu"="gfx908" +// CHECK: attributes #0 = { nounwind "target-cpu"="gfx908" // CHECK-SAME: "target-features"="+dot3-insts,+dot4-insts,+s-memtime-inst, // CHECK-SAME: +16-bit-insts,+s-memrealtime,+dot6-insts,+dl-insts, // CHECK-SAME: +wavefrontsize64,+gfx9-insts,+gfx8-insts,+ci-insts,+dot10-insts,