18 changes: 18 additions & 0 deletions clang/test/Preprocessor/riscv-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,10 @@

// Experimental extensions

// CHECK-NOT: __riscv_smctr{{.*$}}
// CHECK-NOT: __riscv_smmpm{{.*$}}
// CHECK-NOT: __riscv_smnpm{{.*$}}
// CHECK-NOT: __riscv_ssctr{{.*$}}
// CHECK-NOT: __riscv_ssnpm{{.*$}}
// CHECK-NOT: __riscv_sspm{{.*$}}
// CHECK-NOT: __riscv_supm{{.*$}}
Expand Down Expand Up @@ -1748,6 +1750,22 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-SUPM-EXT %s
// CHECK-SUPM-EXT: __riscv_supm 1000000{{$}}

// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_smctr1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SMCTR-EXT %s
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_smctr1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SMCTR-EXT %s
// CHECK-SMCTR-EXT: __riscv_smctr 1000000{{$}}

// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_ssctr1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCTR-EXT %s
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_ssctr1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-SSCTR-EXT %s
// CHECK-SSCTR-EXT: __riscv_ssctr 1000000{{$}}

// Misaligned

// RUN: %clang --target=riscv32-unknown-linux-gnu -march=rv32i -E -dM %s \
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Sema/bpf-attr-bpf-fastcall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// REQUIRES: bpf-registered-target
// RUN: %clang_cc1 %s -triple bpf -verify

__attribute__((bpf_fastcall)) int var; // expected-warning {{'bpf_fastcall' attribute only applies to functions and function pointers}}

__attribute__((bpf_fastcall)) void func();
__attribute__((bpf_fastcall(1))) void func_invalid(); // expected-error {{'bpf_fastcall' attribute takes no arguments}}

void (*ptr1)(void) __attribute__((bpf_fastcall));
void (*ptr2)(void);
void foo(void) {
ptr2 = ptr1; // not an error
ptr1 = ptr2; // not an error
}
8 changes: 4 additions & 4 deletions clang/tools/clang-format/clang-format-diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def main():
if line_count != 0:
end_line += line_count - 1
lines_by_file.setdefault(filename, []).extend(
["-lines", str(start_line) + ":" + str(end_line)]
["--lines", str(start_line) + ":" + str(end_line)]
)

# Reformat files containing changes in place.
Expand All @@ -146,12 +146,12 @@ def main():
if args.i:
command.append("-i")
if args.sort_includes:
command.append("-sort-includes")
command.append("--sort-includes")
command.extend(lines)
if args.style:
command.extend(["-style", args.style])
command.extend(["--style", args.style])
if args.fallback_style:
command.extend(["-fallback-style", args.fallback_style])
command.extend(["--fallback-style", args.fallback_style])

try:
p = subprocess.Popen(
Expand Down
8 changes: 4 additions & 4 deletions clang/tools/clang-format/clang-format-sublime.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,18 @@ def run(self, edit):
regions = []
command = [binary]
if style:
command.extend(["-style", style])
command.extend(["--style", style])
for region in self.view.sel():
regions.append(region)
region_offset = min(region.a, region.b)
region_length = abs(region.b - region.a)
command.extend(
[
"-offset",
"--offset",
str(region_offset),
"-length",
"--length",
str(region_length),
"-assume-filename",
"--assume-filename",
str(self.view.file_name()),
]
)
Expand Down
14 changes: 7 additions & 7 deletions clang/tools/clang-format/clang-format.el
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,19 @@ uses the function `buffer-file-name'."
(let ((status (apply #'call-process-region
nil nil clang-format-executable
nil `(,temp-buffer ,temp-file) nil
`("-output-replacements-xml"
`("--output-replacements-xml"
;; Guard against a nil assume-file-name.
;; If the clang-format option -assume-filename
;; is given a blank string it will crash as per
;; the following bug report
;; https://bugs.llvm.org/show_bug.cgi?id=34667
,@(and assume-file-name
(list "-assume-filename" assume-file-name))
,@(and style (list "-style" style))
"-fallback-style" ,clang-format-fallback-style
"-offset" ,(number-to-string file-start)
"-length" ,(number-to-string (- file-end file-start))
"-cursor" ,(number-to-string cursor))))
(list "--assume-filename" assume-file-name))
,@(and style (list "--style" style))
"--fallback-style" ,clang-format-fallback-style
"--offset" ,(number-to-string file-start)
"--length" ,(number-to-string (- file-end file-start))
"--cursor" ,(number-to-string cursor))))
(stderr (with-temp-buffer
(unless (zerop (cadr (insert-file-contents temp-file)))
(insert ": "))
Expand Down
16 changes: 8 additions & 8 deletions clang/tools/clang-format/clang-format.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def main():

# Determine range to format.
if vim.eval('exists("l:lines")') == "1":
lines = ["-lines", vim.eval("l:lines")]
lines = ["--lines", vim.eval("l:lines")]
elif vim.eval('exists("l:formatdiff")') == "1" and os.path.exists(
vim.current.buffer.name
):
Expand All @@ -88,12 +88,12 @@ def main():
lines = []
for op in reversed(sequence.get_opcodes()):
if op[0] not in ["equal", "delete"]:
lines += ["-lines", "%s:%s" % (op[3] + 1, op[4])]
lines += ["--lines", "%s:%s" % (op[3] + 1, op[4])]
if lines == []:
return
else:
lines = [
"-lines",
"--lines",
"%s:%s" % (vim.current.range.start + 1, vim.current.range.end + 1),
]

Expand All @@ -116,15 +116,15 @@ def main():
startupinfo.wShowWindow = subprocess.SW_HIDE

# Call formatter.
command = [binary, "-cursor", str(cursor_byte)]
if lines != ["-lines", "all"]:
command = [binary, "--cursor", str(cursor_byte)]
if lines != ["--lines", "all"]:
command += lines
if style:
command.extend(["-style", style])
command.extend(["--style", style])
if fallback_style:
command.extend(["-fallback-style", fallback_style])
command.extend(["--fallback-style", fallback_style])
if vim.current.buffer.name:
command.extend(["-assume-filename", vim.current.buffer.name])
command.extend(["--assume-filename", vim.current.buffer.name])
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
Expand Down
6 changes: 3 additions & 3 deletions clang/tools/clang-format/git-clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -510,12 +510,12 @@ def clang_format_to_blob(filename, line_ranges, revision=None,
Returns the object ID (SHA-1) of the created blob."""
clang_format_cmd = [binary]
if style:
clang_format_cmd.extend(['-style='+style])
clang_format_cmd.extend(['--style='+style])
clang_format_cmd.extend([
'-lines=%s:%s' % (start_line, start_line+line_count-1)
'--lines=%s:%s' % (start_line, start_line+line_count-1)
for start_line, line_count in line_ranges])
if revision is not None:
clang_format_cmd.extend(['-assume-filename='+filename])
clang_format_cmd.extend(['--assume-filename='+filename])
git_show_cmd = ['git', 'cat-file', 'blob', '%s:%s' % (revision, filename)]
git_show = subprocess.Popen(git_show_cmd, env=env, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/fuzzer/features_dir.test
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Tests -features_dir=F
# REQUIRES: linux
# REQUIRES: linux, shell
RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
RUN: rm -rf %t-C %t-F
RUN: mkdir %t-C %t-F
Expand Down
12 changes: 7 additions & 5 deletions flang/include/flang/Optimizer/Builder/HLFIRTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,20 +357,22 @@ hlfir::ElementalOp genElementalOp(

/// Structure to describe a loop nest.
struct LoopNest {
fir::DoLoopOp outerLoop;
fir::DoLoopOp innerLoop;
mlir::Operation *outerOp = nullptr;
mlir::Block *body = nullptr;
llvm::SmallVector<mlir::Value> oneBasedIndices;
};

/// Generate a fir.do_loop nest looping from 1 to extents[i].
/// \p isUnordered specifies whether the loops in the loop nest
/// are unordered.
LoopNest genLoopNest(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::ValueRange extents, bool isUnordered = false);
mlir::ValueRange extents, bool isUnordered = false,
bool emitWorkshareLoop = false);
inline LoopNest genLoopNest(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::Value shape, bool isUnordered = false) {
mlir::Value shape, bool isUnordered = false,
bool emitWorkshareLoop = false) {
return genLoopNest(loc, builder, getIndexExtents(loc, builder, shape),
isUnordered);
isUnordered, emitWorkshareLoop);
}

/// Inline the body of an hlfir.elemental at the current insertion point
Expand Down
6 changes: 5 additions & 1 deletion flang/include/flang/Optimizer/CodeGen/CGPasses.td
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ def FIRToLLVMLowering : Pass<"fir-to-llvm-ir", "mlir::ModuleOp"> {
Option<"forcedTargetFeatures", "target-features", "std::string",
/*default=*/"", "Override module's target features.">,
Option<"applyTBAA", "apply-tbaa", "bool", /*default=*/"false",
"Attach TBAA tags to memory accessing operations.">
"Attach TBAA tags to memory accessing operations.">,
Option<"typeDescriptorsRenamedForAssembly",
"type-descriptors-renamed-for-assembly", "bool", /*default=*/"false",
"Global variables created to describe derived types "
"have been renamed to avoid special symbols in their names.">
];
}

Expand Down
10 changes: 10 additions & 0 deletions flang/include/flang/Optimizer/CodeGen/CodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ struct FIRToLLVMPassOptions {

// Force the usage of a unified tbaa tree in TBAABuilder.
bool forceUnifiedTBAATree = false;

// If set to true, then the global variables created
// for the derived types have been renamed to avoid usage
// of special symbols that may not be supported by all targets.
// The renaming is done by the CompilerGeneratedNamesConversion pass.
// If it is true, FIR-to-LLVM pass has to use
// fir::NameUniquer::getTypeDescriptorAssemblyName() to take
// the name of the global variable corresponding to a derived
// type's descriptor.
bool typeDescriptorsRenamedForAssembly = false;
};

/// Convert FIR to the LLVM IR dialect with default options.
Expand Down
5 changes: 5 additions & 0 deletions flang/include/flang/Optimizer/OpenMP/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ namespace flangomp {
#define GEN_PASS_REGISTRATION
#include "flang/Optimizer/OpenMP/Passes.h.inc"

/// Impelements the logic specified in the 2.8.3 workshare Construct section of
/// the OpenMP standard which specifies what statements or constructs shall be
/// divided into units of work.
bool shouldUseWorkshareLowering(mlir::Operation *op);

} // namespace flangomp

#endif // FORTRAN_OPTIMIZER_OPENMP_PASSES_H
5 changes: 5 additions & 0 deletions flang/include/flang/Optimizer/OpenMP/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ def FunctionFiltering : Pass<"omp-function-filtering"> {
];
}

// Needs to be scheduled on Module as we create functions in it
def LowerWorkshare : Pass<"lower-workshare", "::mlir::ModuleOp"> {
let summary = "Lower workshare construct";
}

#endif //FORTRAN_OPTIMIZER_OPENMP_PASSES
25 changes: 20 additions & 5 deletions flang/include/flang/Optimizer/Support/InternalNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,23 @@
#include <cstdint>
#include <optional>

static constexpr llvm::StringRef typeDescriptorSeparator = ".dt.";
static constexpr llvm::StringRef componentInitSeparator = ".di.";
static constexpr llvm::StringRef bindingTableSeparator = ".v.";
static constexpr llvm::StringRef boxprocSuffix = "UnboxProc";

namespace fir {

static constexpr llvm::StringRef kNameSeparator = ".";
static constexpr llvm::StringRef kBoundsSeparator = ".b.";
static constexpr llvm::StringRef kComponentSeparator = ".c.";
static constexpr llvm::StringRef kComponentInitSeparator = ".di.";
static constexpr llvm::StringRef kDataPtrInitSeparator = ".dp.";
static constexpr llvm::StringRef kTypeDescriptorSeparator = ".dt.";
static constexpr llvm::StringRef kKindParameterSeparator = ".kp.";
static constexpr llvm::StringRef kLenKindSeparator = ".lpk.";
static constexpr llvm::StringRef kLenParameterSeparator = ".lv.";
static constexpr llvm::StringRef kNameStringSeparator = ".n.";
static constexpr llvm::StringRef kProcPtrSeparator = ".p.";
static constexpr llvm::StringRef kSpecialBindingSeparator = ".s.";
static constexpr llvm::StringRef kBindingTableSeparator = ".v.";
static constexpr llvm::StringRef boxprocSuffix = "UnboxProc";

/// Internal name mangling of identifiers
///
/// In order to generate symbolically referencable artifacts in a ModuleOp,
Expand Down Expand Up @@ -150,6 +160,9 @@ struct NameUniquer {
/// not a valid mangled derived type name.
static std::string getTypeDescriptorName(llvm::StringRef mangledTypeName);

static std::string
getTypeDescriptorAssemblyName(llvm::StringRef mangledTypeName);

/// Given a mangled derived type name, get the name of the related binding
/// table object. Returns an empty string if \p mangledTypeName is not a valid
/// mangled derived type name.
Expand All @@ -169,6 +182,8 @@ struct NameUniquer {
static llvm::StringRef
dropTypeConversionMarkers(llvm::StringRef mangledTypeName);

static std::string replaceSpecialSymbols(const std::string &name);

private:
static std::string intAsString(std::int64_t i);
static std::string doKind(std::int64_t kind);
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Optimizer/Transforms/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ namespace fir {
#define GEN_PASS_DECL_VSCALEATTR
#define GEN_PASS_DECL_FUNCTIONATTR
#define GEN_PASS_DECL_CONSTANTARGUMENTGLOBALISATIONOPT
#define GEN_PASS_DECL_COMPILERGENERATEDNAMESCONVERSION

#include "flang/Optimizer/Transforms/Passes.h.inc"

Expand Down
18 changes: 18 additions & 0 deletions flang/include/flang/Optimizer/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,24 @@ def ExternalNameConversion : Pass<"external-name-interop", "mlir::ModuleOp"> {
];
}

def CompilerGeneratedNamesConversion : Pass<"compiler-generated-names",
"mlir::ModuleOp"> {
let summary = "Convert names of compiler generated globals";
let description = [{
Transforms names of compiler generated globals to avoid
characters that might be unsupported by some target toolchains.
All special symbols are replaced with a predefined 'X' character.
This is only done for uniqued names that are not externally facing.
The uniqued names always use '_Q' prefix, and the user entity names
are always lower cased, so using 'X' instead of the special symbols
will guarantee that the converted name will not conflict with the user
space. This pass does not affect the externally facing names,
because the expectation is that the compiler will not generate
externally facing names on its own, and these names cannot use
special symbols.
}];
}

def MemRefDataFlowOpt : Pass<"fir-memref-dataflow-opt", "::mlir::func::FuncOp"> {
let summary =
"Perform store/load forwarding and potentially removing dead stores.";
Expand Down
16 changes: 14 additions & 2 deletions flang/include/flang/Tools/CLOptions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ DisableOption(ExternalNameConversion, "external-name-interop",
"convert names with external convention");
EnableOption(ConstantArgumentGlobalisation, "constant-argument-globalisation",
"the local constant argument to global constant conversion");
DisableOption(CompilerGeneratedNamesConversion, "compiler-generated-names",
"replace special symbols in compiler generated names");

using PassConstructor = std::unique_ptr<mlir::Pass>();

Expand Down Expand Up @@ -223,6 +225,8 @@ inline void addFIRToLLVMPass(
options.ignoreMissingTypeDescriptors = ignoreMissingTypeDescriptors;
options.applyTBAA = config.AliasAnalysis;
options.forceUnifiedTBAATree = useOldAliasTags;
options.typeDescriptorsRenamedForAssembly =
!disableCompilerGeneratedNamesConversion;
addPassConditionally(pm, disableFirToLlvmIr,
[&]() { return fir::createFIRToLLVMPass(options); });
// The dialect conversion framework may leave dead unrealized_conversion_cast
Expand All @@ -249,6 +253,11 @@ inline void addExternalNameConversionPass(
[&]() { return fir::createExternalNameConversion({appendUnderscore}); });
}

inline void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm) {
addPassConditionally(pm, disableCompilerGeneratedNamesConversion,
[&]() { return fir::createCompilerGeneratedNamesConversion(); });
}

// Use inliner extension point callback to register the default inliner pass.
inline void registerDefaultInlinerPass(MLIRToLLVMPassPipelineConfig &config) {
config.registerFIRInlinerCallback(
Expand Down Expand Up @@ -328,7 +337,7 @@ inline void createDefaultFIROptimizerPassPipeline(
/// \param optLevel - optimization level used for creating FIR optimization
/// passes pipeline
inline void createHLFIRToFIRPassPipeline(
mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel) {
mlir::PassManager &pm, bool enableOpenMP, llvm::OptimizationLevel optLevel = defaultOptLevel) {
if (optLevel.isOptimizingForSpeed()) {
addCanonicalizerPassWithoutRegionSimplification(pm);
addNestedPassToAllTopLevelOperations(
Expand All @@ -345,6 +354,8 @@ inline void createHLFIRToFIRPassPipeline(
pm.addPass(hlfir::createLowerHLFIRIntrinsics());
pm.addPass(hlfir::createBufferizeHLFIR());
pm.addPass(hlfir::createConvertHLFIRtoFIR());
if (enableOpenMP)
pm.addPass(flangomp::createLowerWorkshare());
}

/// Create a pass pipeline for handling certain OpenMP transformations needed
Expand Down Expand Up @@ -380,6 +391,7 @@ inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
fir::addCodeGenRewritePass(
pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo));
fir::addTargetRewritePass(pm);
fir::addCompilerGeneratedNamesConversionPass(pm);
fir::addExternalNameConversionPass(pm, config.Underscoring);
fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename);

Expand Down Expand Up @@ -415,7 +427,7 @@ inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
/// passes pipeline
inline void createMLIRToLLVMPassPipeline(mlir::PassManager &pm,
MLIRToLLVMPassPipelineConfig &config, llvm::StringRef inputFilename = {}) {
fir::createHLFIRToFIRPassPipeline(pm, config.OptLevel);
fir::createHLFIRToFIRPassPipeline(pm, config.EnableOpenMP, config.OptLevel);

// Add default optimizer pass pipeline.
fir::createDefaultFIROptimizerPassPipeline(pm, config);
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Tools/CrossToolHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
false; ///< Set no-signed-zeros-fp-math attribute for functions.
bool UnsafeFPMath = false; ///< Set unsafe-fp-math attribute for functions.
bool NSWOnLoopVarInc = false; ///< Add nsw flag to loop variable increments.
bool EnableOpenMP = false; ///< Enable OpenMP lowering.
};

struct OffloadModuleOpts {
Expand Down
10 changes: 9 additions & 1 deletion flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,11 @@ void CodeGenAction::lowerHLFIRToFIR() {
pm.enableVerifier(/*verifyPasses=*/true);

// Create the pass pipeline
fir::createHLFIRToFIRPassPipeline(pm, level);
fir::createHLFIRToFIRPassPipeline(
pm,
ci.getInvocation().getFrontendOpts().features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP),
level);
(void)mlir::applyPassManagerCLOptions(pm);

if (!mlir::succeeded(pm.run(*mlirModule))) {
Expand Down Expand Up @@ -824,6 +828,10 @@ void CodeGenAction::generateLLVMIR() {
config.VScaleMax = vsr->second;
}

if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP))
config.EnableOpenMP = true;

if (ci.getInvocation().getLoweringOpts().getNSWOnLoopVarInc())
config.NSWOnLoopVarInc = true;

Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Lower/ConvertCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2128,7 +2128,7 @@ class ElementalCallBuilder {
hlfir::genLoopNest(loc, builder, shape, !mustBeOrdered);
mlir::ValueRange oneBasedIndices = loopNest.oneBasedIndices;
auto insPt = builder.saveInsertionPoint();
builder.setInsertionPointToStart(loopNest.innerLoop.getBody());
builder.setInsertionPointToStart(loopNest.body);
callContext.stmtCtx.pushScope();
for (auto &preparedActual : loweredActuals)
if (preparedActual)
Expand Down
30 changes: 6 additions & 24 deletions flang/lib/Lower/OpenMP/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,9 @@ MAKE_EMPTY_CLASS(Full, Full);
MAKE_EMPTY_CLASS(Inbranch, Inbranch);
MAKE_EMPTY_CLASS(Mergeable, Mergeable);
MAKE_EMPTY_CLASS(Nogroup, Nogroup);
// MAKE_EMPTY_CLASS(NoOpenmp, ); // missing-in-parser
// MAKE_EMPTY_CLASS(NoOpenmpRoutines, ); // missing-in-parser
// MAKE_EMPTY_CLASS(NoParallelism, ); // missing-in-parser
MAKE_EMPTY_CLASS(NoOpenmp, NoOpenmp);
MAKE_EMPTY_CLASS(NoOpenmpRoutines, NoOpenmpRoutines);
MAKE_EMPTY_CLASS(NoParallelism, NoParallelism);
MAKE_EMPTY_CLASS(Notinbranch, Notinbranch);
MAKE_EMPTY_CLASS(Nowait, Nowait);
MAKE_EMPTY_CLASS(OmpxAttribute, OmpxAttribute);
Expand Down Expand Up @@ -321,7 +321,6 @@ ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp,
// --------------------------------------------------------------------
// Actual clauses. Each T (where tomp::T exists in ClauseT) has its "make".

// Absent: missing-in-parser
Absent make(const parser::OmpClause::Absent &inp,
semantics::SemanticsContext &semaCtx) {
llvm_unreachable("Unimplemented: absent");
Expand Down Expand Up @@ -450,7 +449,6 @@ Collapse make(const parser::OmpClause::Collapse &inp,

// Compare: empty

// Contains: missing-in-parser
Contains make(const parser::OmpClause::Contains &inp,
semantics::SemanticsContext &semaCtx) {
llvm_unreachable("Unimplemented: contains");
Expand Down Expand Up @@ -714,7 +712,6 @@ Hint make(const parser::OmpClause::Hint &inp,
return Hint{/*HintExpr=*/makeExpr(inp.v, semaCtx)};
}

// Holds: missing-in-parser
Holds make(const parser::OmpClause::Holds &inp,
semantics::SemanticsContext &semaCtx) {
llvm_unreachable("Unimplemented: holds");
Expand Down Expand Up @@ -897,24 +894,9 @@ Nontemporal make(const parser::OmpClause::Nontemporal &inp,
return Nontemporal{/*List=*/makeList(inp.v, makeObjectFn(semaCtx))};
}

// NoOpenmp: missing-in-parser
NoOpenmp make(const parser::OmpClause::NoOpenmp &inp,
semantics::SemanticsContext &semaCtx) {
llvm_unreachable("Unimplemented: no_openmp");
}

// NoOpenmpRoutines: missing-in-parser
NoOpenmpRoutines make(const parser::OmpClause::NoOpenmpRoutines &inp,
semantics::SemanticsContext &semaCtx) {
llvm_unreachable("Unimplemented: no_openmp_routines");
}

// NoParallelism: missing-in-parser
NoParallelism make(const parser::OmpClause::NoParallelism &inp,
semantics::SemanticsContext &semaCtx) {
llvm_unreachable("Unimplemented: no_parallelism");
}

// NoOpenmp: empty
// NoOpenmpRoutines: empty
// NoParallelism: empty
// Notinbranch: empty

Novariants make(const parser::OmpClause::Novariants &inp,
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Lower/OpenMP/Clauses.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>;
using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>;
using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>;
using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>;
using Contains = tomp::clause::ContainsT<TypeTy, IdTy, ExprTy>;
using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>;
using Contains = tomp::clause::ContainsT<TypeTy, IdTy, ExprTy>;
using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>;
using Copyprivate = tomp::clause::CopyprivateT<TypeTy, IdTy, ExprTy>;
using Defaultmap = tomp::clause::DefaultmapT<TypeTy, IdTy, ExprTy>;
Expand Down
30 changes: 26 additions & 4 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,15 @@ static void genTaskwaitClauses(lower::AbstractConverter &converter,
loc, llvm::omp::Directive::OMPD_taskwait);
}

static void genWorkshareClauses(lower::AbstractConverter &converter,
semantics::SemanticsContext &semaCtx,
lower::StatementContext &stmtCtx,
const List<Clause> &clauses, mlir::Location loc,
mlir::omp::WorkshareOperands &clauseOps) {
ClauseProcessor cp(converter, semaCtx, clauses);
cp.processNowait(clauseOps);
}

static void genTeamsClauses(lower::AbstractConverter &converter,
semantics::SemanticsContext &semaCtx,
lower::StatementContext &stmtCtx,
Expand Down Expand Up @@ -1897,6 +1906,22 @@ genTaskyieldOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
return converter.getFirOpBuilder().create<mlir::omp::TaskyieldOp>(loc);
}

static mlir::omp::WorkshareOp
genWorkshareOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
mlir::Location loc, const ConstructQueue &queue,
ConstructQueue::iterator item) {
lower::StatementContext stmtCtx;
mlir::omp::WorkshareOperands clauseOps;
genWorkshareClauses(converter, semaCtx, stmtCtx, item->clauses, loc, clauseOps);

return genOpWithBody<mlir::omp::WorkshareOp>(
OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval,
llvm::omp::Directive::OMPD_workshare)
.setClauses(&item->clauses),
queue, item, clauseOps);
}

static mlir::omp::TeamsOp
genTeamsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
Expand Down Expand Up @@ -2309,10 +2334,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
llvm::omp::getOpenMPDirectiveName(dir) + ")");
// case llvm::omp::Directive::OMPD_workdistribute:
case llvm::omp::Directive::OMPD_workshare:
// FIXME: Workshare is not a commonly used OpenMP construct, an
// implementation for this feature will come later. For the codes
// that use this construct, add a single construct for now.
genSingleOp(converter, symTable, semaCtx, eval, loc, queue, item);
genWorkshareOp(converter, symTable, semaCtx, eval, loc, queue, item);
break;
default:
// Combined and composite constructs should have been split into a sequence
Expand Down
4 changes: 2 additions & 2 deletions flang/lib/Lower/OpenMP/ReductionProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc,
// know this won't miss any opportuinties for clever elemental inlining
hlfir::LoopNest nest = hlfir::genLoopNest(
loc, builder, shapeShift.getExtents(), /*isUnordered=*/true);
builder.setInsertionPointToStart(nest.innerLoop.getBody());
builder.setInsertionPointToStart(nest.body);
mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy());
auto lhsEleAddr = builder.create<fir::ArrayCoorOp>(
loc, refTy, lhs, shapeShift, /*slice=*/mlir::Value{},
Expand All @@ -389,7 +389,7 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc,
builder, loc, redId, refTy, lhsEle, rhsEle);
builder.create<fir::StoreOp>(loc, scalarReduction, lhsEleAddr);

builder.setInsertionPointAfter(nest.outerLoop);
builder.setInsertionPointAfter(nest.outerOp);
builder.create<mlir::omp::YieldOp>(loc, lhsAddr);
}

Expand Down
52 changes: 39 additions & 13 deletions flang/lib/Optimizer/Builder/HLFIRTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "mlir/IR/IRMapping.h"
#include "mlir/Support/LLVM.h"
#include "llvm/ADT/TypeSwitch.h"
#include <mlir/Dialect/OpenMP/OpenMPDialect.h>
#include <optional>

// Return explicit extents. If the base is a fir.box, this won't read it to
Expand Down Expand Up @@ -855,26 +856,51 @@ mlir::Value hlfir::inlineElementalOp(

hlfir::LoopNest hlfir::genLoopNest(mlir::Location loc,
fir::FirOpBuilder &builder,
mlir::ValueRange extents, bool isUnordered) {
mlir::ValueRange extents, bool isUnordered,
bool emitWorkshareLoop) {
emitWorkshareLoop = emitWorkshareLoop && isUnordered;
hlfir::LoopNest loopNest;
assert(!extents.empty() && "must have at least one extent");
auto insPt = builder.saveInsertionPoint();
mlir::OpBuilder::InsertionGuard guard(builder);
loopNest.oneBasedIndices.assign(extents.size(), mlir::Value{});
// Build loop nest from column to row.
auto one = builder.create<mlir::arith::ConstantIndexOp>(loc, 1);
mlir::Type indexType = builder.getIndexType();
unsigned dim = extents.size() - 1;
for (auto extent : llvm::reverse(extents)) {
auto ub = builder.createConvert(loc, indexType, extent);
loopNest.innerLoop =
builder.create<fir::DoLoopOp>(loc, one, ub, one, isUnordered);
builder.setInsertionPointToStart(loopNest.innerLoop.getBody());
// Reverse the indices so they are in column-major order.
loopNest.oneBasedIndices[dim--] = loopNest.innerLoop.getInductionVar();
if (!loopNest.outerLoop)
loopNest.outerLoop = loopNest.innerLoop;
if (emitWorkshareLoop) {
auto wslw = builder.create<mlir::omp::WorkshareLoopWrapperOp>(loc);
loopNest.outerOp = wslw;
builder.createBlock(&wslw.getRegion());
mlir::omp::LoopNestOperands lnops;
lnops.loopInclusive = builder.getUnitAttr();
for (auto extent : llvm::reverse(extents)) {
lnops.loopLowerBounds.push_back(one);
lnops.loopUpperBounds.push_back(extent);
lnops.loopSteps.push_back(one);
}
auto lnOp = builder.create<mlir::omp::LoopNestOp>(loc, lnops);
builder.create<mlir::omp::TerminatorOp>(loc);
mlir::Block *block = builder.createBlock(&lnOp.getRegion());
for (auto extent : llvm::reverse(extents))
block->addArgument(extent.getType(), extent.getLoc());
loopNest.body = block;
builder.create<mlir::omp::YieldOp>(loc);
for (unsigned dim = 0; dim < extents.size(); dim++)
loopNest.oneBasedIndices[extents.size() - dim - 1] =
lnOp.getRegion().front().getArgument(dim);
} else {
unsigned dim = extents.size() - 1;
for (auto extent : llvm::reverse(extents)) {
auto ub = builder.createConvert(loc, indexType, extent);
auto doLoop =
builder.create<fir::DoLoopOp>(loc, one, ub, one, isUnordered);
loopNest.body = doLoop.getBody();
builder.setInsertionPointToStart(loopNest.body);
// Reverse the indices so they are in column-major order.
loopNest.oneBasedIndices[dim--] = doLoop.getInductionVar();
if (!loopNest.outerOp)
loopNest.outerOp = doLoop;
}
}
builder.restoreInsertionPoint(insPt);
return loopNest;
}

Expand Down
13 changes: 11 additions & 2 deletions flang/lib/Optimizer/CodeGen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,9 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
mlir::Location loc,
fir::RecordType recType) const {
std::string name =
fir::NameUniquer::getTypeDescriptorName(recType.getName());
this->options.typeDescriptorsRenamedForAssembly
? fir::NameUniquer::getTypeDescriptorAssemblyName(recType.getName())
: fir::NameUniquer::getTypeDescriptorName(recType.getName());
mlir::Type llvmPtrTy = ::getLlvmPtrType(mod.getContext());
if (auto global = mod.template lookupSymbol<fir::GlobalOp>(name)) {
return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
Expand Down Expand Up @@ -2704,7 +2706,10 @@ struct TypeDescOpConversion : public fir::FIROpConversion<fir::TypeDescOp> {
auto recordType = mlir::dyn_cast<fir::RecordType>(inTy);
auto module = typeDescOp.getOperation()->getParentOfType<mlir::ModuleOp>();
std::string typeDescName =
fir::NameUniquer::getTypeDescriptorName(recordType.getName());
this->options.typeDescriptorsRenamedForAssembly
? fir::NameUniquer::getTypeDescriptorAssemblyName(
recordType.getName())
: fir::NameUniquer::getTypeDescriptorName(recordType.getName());
auto llvmPtrTy = ::getLlvmPtrType(typeDescOp.getContext());
if (auto global = module.lookupSymbol<mlir::LLVM::GlobalOp>(typeDescName)) {
rewriter.replaceOpWithNewOp<mlir::LLVM::AddressOfOp>(
Expand Down Expand Up @@ -3653,6 +3658,10 @@ class FIRToLLVMLowering
if (!forcedTargetFeatures.empty())
fir::setTargetFeatures(mod, forcedTargetFeatures);

if (typeDescriptorsRenamedForAssembly)
options.typeDescriptorsRenamedForAssembly =
typeDescriptorsRenamedForAssembly;

// Run dynamic pass pipeline for converting Math dialect
// operations into other dialects (llvm, func, etc.).
// Some conversions of Math operations cannot be done
Expand Down
7 changes: 5 additions & 2 deletions flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "flang/Optimizer/HLFIR/Passes.h"
#include "flang/Optimizer/OpenMP/Passes.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/IR/Dominance.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
Expand Down Expand Up @@ -791,9 +793,10 @@ struct ElementalOpConversion
// Generate a loop nest looping around the fir.elemental shape and clone
// fir.elemental region inside the inner loop.
hlfir::LoopNest loopNest =
hlfir::genLoopNest(loc, builder, extents, !elemental.isOrdered());
hlfir::genLoopNest(loc, builder, extents, !elemental.isOrdered(),
flangomp::shouldUseWorkshareLowering(elemental));
auto insPt = builder.saveInsertionPoint();
builder.setInsertionPointToStart(loopNest.innerLoop.getBody());
builder.setInsertionPointToStart(loopNest.body);
auto yield = hlfir::inlineElementalOp(loc, builder, elemental,
loopNest.oneBasedIndices);
hlfir::Entity elementValue(yield.getElementValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) {
// if the LHS is not).
mlir::Value shape = hlfir::genShape(loc, builder, lhsEntity);
elementalLoopNest = hlfir::genLoopNest(loc, builder, shape);
builder.setInsertionPointToStart(elementalLoopNest->innerLoop.getBody());
builder.setInsertionPointToStart(elementalLoopNest->body);
lhsEntity = hlfir::getElementAt(loc, builder, lhsEntity,
elementalLoopNest->oneBasedIndices);
rhsEntity = hlfir::getElementAt(loc, builder, rhsEntity,
Expand All @@ -484,7 +484,7 @@ void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) {
for (auto &cleanupConversion : argConversionCleanups)
cleanupConversion();
if (elementalLoopNest)
builder.setInsertionPointAfter(elementalLoopNest->outerLoop);
builder.setInsertionPointAfter(elementalLoopNest->outerOp);
} else {
// TODO: preserve allocatable assignment aspects for forall once
// they are conveyed in hlfir.region_assign.
Expand All @@ -493,7 +493,7 @@ void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) {
generateCleanupIfAny(loweredLhs.elementalCleanup);
if (loweredLhs.vectorSubscriptLoopNest)
builder.setInsertionPointAfter(
loweredLhs.vectorSubscriptLoopNest->outerLoop);
loweredLhs.vectorSubscriptLoopNest->outerOp);
generateCleanupIfAny(oldRhsYield);
generateCleanupIfAny(loweredLhs.nonElementalCleanup);
}
Expand All @@ -518,16 +518,16 @@ void OrderedAssignmentRewriter::pre(hlfir::WhereOp whereOp) {
hlfir::Entity savedMask{maybeSaved->first};
mlir::Value shape = hlfir::genShape(loc, builder, savedMask);
whereLoopNest = hlfir::genLoopNest(loc, builder, shape);
constructStack.push_back(whereLoopNest->outerLoop.getOperation());
builder.setInsertionPointToStart(whereLoopNest->innerLoop.getBody());
constructStack.push_back(whereLoopNest->outerOp);
builder.setInsertionPointToStart(whereLoopNest->body);
mlir::Value cdt = hlfir::getElementAt(loc, builder, savedMask,
whereLoopNest->oneBasedIndices);
generateMaskIfOp(cdt);
if (maybeSaved->second) {
// If this is the same run as the one that saved the value, the clean-up
// was left-over to be done now.
auto insertionPoint = builder.saveInsertionPoint();
builder.setInsertionPointAfter(whereLoopNest->outerLoop);
builder.setInsertionPointAfter(whereLoopNest->outerOp);
generateCleanupIfAny(maybeSaved->second);
builder.restoreInsertionPoint(insertionPoint);
}
Expand All @@ -539,8 +539,8 @@ void OrderedAssignmentRewriter::pre(hlfir::WhereOp whereOp) {
mask.generateNoneElementalPart(builder, mapper);
mlir::Value shape = mask.generateShape(builder, mapper);
whereLoopNest = hlfir::genLoopNest(loc, builder, shape);
constructStack.push_back(whereLoopNest->outerLoop.getOperation());
builder.setInsertionPointToStart(whereLoopNest->innerLoop.getBody());
constructStack.push_back(whereLoopNest->outerOp);
builder.setInsertionPointToStart(whereLoopNest->body);
mlir::Value cdt = generateMaskedEntity(mask);
generateMaskIfOp(cdt);
return;
Expand Down Expand Up @@ -754,7 +754,7 @@ OrderedAssignmentRewriter::generateYieldedLHS(
loweredLhs.vectorSubscriptLoopNest = hlfir::genLoopNest(
loc, builder, loweredLhs.vectorSubscriptShape.value());
builder.setInsertionPointToStart(
loweredLhs.vectorSubscriptLoopNest->innerLoop.getBody());
loweredLhs.vectorSubscriptLoopNest->body);
}
loweredLhs.lhs = temp->second.fetch(loc, builder);
return loweredLhs;
Expand All @@ -772,7 +772,7 @@ OrderedAssignmentRewriter::generateYieldedLHS(
hlfir::genLoopNest(loc, builder, *loweredLhs.vectorSubscriptShape,
!elementalAddrLhs.isOrdered());
builder.setInsertionPointToStart(
loweredLhs.vectorSubscriptLoopNest->innerLoop.getBody());
loweredLhs.vectorSubscriptLoopNest->body);
mapper.map(elementalAddrLhs.getIndices(),
loweredLhs.vectorSubscriptLoopNest->oneBasedIndices);
for (auto &op : elementalAddrLhs.getBody().front().without_terminator())
Expand All @@ -798,11 +798,11 @@ OrderedAssignmentRewriter::generateMaskedEntity(MaskedArrayExpr &maskedExpr) {
if (!maskedExpr.noneElementalPartWasGenerated) {
// Generate none elemental part before the where loops (but inside the
// current forall loops if any).
builder.setInsertionPoint(whereLoopNest->outerLoop);
builder.setInsertionPoint(whereLoopNest->outerOp);
maskedExpr.generateNoneElementalPart(builder, mapper);
}
// Generate the none elemental part cleanup after the where loops.
builder.setInsertionPointAfter(whereLoopNest->outerLoop);
builder.setInsertionPointAfter(whereLoopNest->outerOp);
maskedExpr.generateNoneElementalCleanupIfAny(builder, mapper);
// Generate the value of the current element for the masked expression
// at the current insertion point (inside the where loops, and any fir.if
Expand Down Expand Up @@ -1242,7 +1242,7 @@ void OrderedAssignmentRewriter::saveLeftHandSide(
LhsValueAndCleanUp loweredLhs = generateYieldedLHS(loc, region);
fir::factory::TemporaryStorage *temp = nullptr;
if (loweredLhs.vectorSubscriptLoopNest)
constructStack.push_back(loweredLhs.vectorSubscriptLoopNest->outerLoop);
constructStack.push_back(loweredLhs.vectorSubscriptLoopNest->outerOp);
if (loweredLhs.vectorSubscriptLoopNest && !rhsIsArray(regionAssignOp)) {
// Vector subscripted entity for which the shape must also be saved on top
// of the element addresses (e.g. the shape may change in each forall
Expand All @@ -1265,7 +1265,7 @@ void OrderedAssignmentRewriter::saveLeftHandSide(
// subscripted LHS.
auto &vectorTmp = temp->cast<fir::factory::AnyVectorSubscriptStack>();
auto insertionPoint = builder.saveInsertionPoint();
builder.setInsertionPoint(loweredLhs.vectorSubscriptLoopNest->outerLoop);
builder.setInsertionPoint(loweredLhs.vectorSubscriptLoopNest->outerOp);
vectorTmp.pushShape(loc, builder, shape);
builder.restoreInsertionPoint(insertionPoint);
} else {
Expand All @@ -1291,7 +1291,7 @@ void OrderedAssignmentRewriter::saveLeftHandSide(
if (loweredLhs.vectorSubscriptLoopNest) {
constructStack.pop_back();
builder.setInsertionPointAfter(
loweredLhs.vectorSubscriptLoopNest->outerLoop);
loweredLhs.vectorSubscriptLoopNest->outerOp);
}
}

Expand Down
16 changes: 10 additions & 6 deletions flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "flang/Optimizer/HLFIR/Passes.h"
#include "flang/Optimizer/OpenMP/Passes.h"
#include "flang/Optimizer/Transforms/Utils.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/Dominance.h"
Expand Down Expand Up @@ -482,8 +483,9 @@ llvm::LogicalResult ElementalAssignBufferization::matchAndRewrite(
// Generate a loop nest looping around the hlfir.elemental shape and clone
// hlfir.elemental region inside the inner loop
hlfir::LoopNest loopNest =
hlfir::genLoopNest(loc, builder, extents, !elemental.isOrdered());
builder.setInsertionPointToStart(loopNest.innerLoop.getBody());
hlfir::genLoopNest(loc, builder, extents, !elemental.isOrdered(),
flangomp::shouldUseWorkshareLowering(elemental));
builder.setInsertionPointToStart(loopNest.body);
auto yield = hlfir::inlineElementalOp(loc, builder, elemental,
loopNest.oneBasedIndices);
hlfir::Entity elementValue{yield.getElementValue()};
Expand Down Expand Up @@ -553,8 +555,9 @@ llvm::LogicalResult BroadcastAssignBufferization::matchAndRewrite(
llvm::SmallVector<mlir::Value> extents =
hlfir::getIndexExtents(loc, builder, shape);
hlfir::LoopNest loopNest =
hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true);
builder.setInsertionPointToStart(loopNest.innerLoop.getBody());
hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true,
flangomp::shouldUseWorkshareLowering(assign));
builder.setInsertionPointToStart(loopNest.body);
auto arrayElement =
hlfir::getElementAt(loc, builder, lhs, loopNest.oneBasedIndices);
builder.create<hlfir::AssignOp>(loc, rhs, arrayElement);
Expand Down Expand Up @@ -648,8 +651,9 @@ llvm::LogicalResult VariableAssignBufferization::matchAndRewrite(
llvm::SmallVector<mlir::Value> extents =
hlfir::getIndexExtents(loc, builder, shape);
hlfir::LoopNest loopNest =
hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true);
builder.setInsertionPointToStart(loopNest.innerLoop.getBody());
hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true,
flangomp::shouldUseWorkshareLowering(assign));
builder.setInsertionPointToStart(loopNest.body);
auto rhsArrayElement =
hlfir::getElementAt(loc, builder, rhs, loopNest.oneBasedIndices);
rhsArrayElement = hlfir::loadTrivialScalar(loc, builder, rhsArrayElement);
Expand Down
2 changes: 2 additions & 0 deletions flang/lib/Optimizer/OpenMP/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_flang_library(FlangOpenMPTransforms
FunctionFiltering.cpp
MapInfoFinalization.cpp
MarkDeclareTarget.cpp
LowerWorkshare.cpp

DEPENDS
FIRDialect
Expand All @@ -22,4 +23,5 @@ add_flang_library(FlangOpenMPTransforms
MLIROpenMPDialect
HLFIRDialect
MLIRIR
MLIRPass
)
446 changes: 446 additions & 0 deletions flang/lib/Optimizer/OpenMP/LowerWorkshare.cpp

Large diffs are not rendered by default.

31 changes: 23 additions & 8 deletions flang/lib/Optimizer/Support/InternalNames.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "mlir/IR/Diagnostics.h"
#include "llvm/Support/CommandLine.h"
#include <optional>
#include <regex>

static llvm::cl::opt<std::string> mainEntryName(
"main-entry-name",
Expand Down Expand Up @@ -59,7 +60,11 @@ convertToStringRef(const std::optional<std::string> &from) {

static std::string readName(llvm::StringRef uniq, std::size_t &i,
std::size_t init, std::size_t end) {
for (i = init; i < end && (uniq[i] < 'A' || uniq[i] > 'Z'); ++i) {
// Allow 'X' to be part of the mangled name, which
// can happen after the special symbols are replaced
// in the mangled names by CompilerGeneratedNamesConversionPass.
for (i = init; i < end && (uniq[i] < 'A' || uniq[i] > 'Z' || uniq[i] == 'X');
++i) {
// do nothing
}
return uniq.substr(init, i - init).str();
Expand Down Expand Up @@ -348,7 +353,7 @@ mangleTypeDescriptorKinds(llvm::ArrayRef<std::int64_t> kinds) {
return "";
std::string result;
for (std::int64_t kind : kinds)
result += "." + std::to_string(kind);
result += (fir::kNameSeparator + std::to_string(kind)).str();
return result;
}

Expand All @@ -373,26 +378,36 @@ static std::string getDerivedTypeObjectName(llvm::StringRef mangledTypeName,

std::string
fir::NameUniquer::getTypeDescriptorName(llvm::StringRef mangledTypeName) {
return getDerivedTypeObjectName(mangledTypeName, typeDescriptorSeparator);
return getDerivedTypeObjectName(mangledTypeName,
fir::kTypeDescriptorSeparator);
}

std::string fir::NameUniquer::getTypeDescriptorAssemblyName(
llvm::StringRef mangledTypeName) {
return replaceSpecialSymbols(getTypeDescriptorName(mangledTypeName));
}

std::string fir::NameUniquer::getTypeDescriptorBindingTableName(
llvm::StringRef mangledTypeName) {
return getDerivedTypeObjectName(mangledTypeName, bindingTableSeparator);
return getDerivedTypeObjectName(mangledTypeName, fir::kBindingTableSeparator);
}

std::string
fir::NameUniquer::getComponentInitName(llvm::StringRef mangledTypeName,
llvm::StringRef componentName) {

std::string prefix =
getDerivedTypeObjectName(mangledTypeName, componentInitSeparator);
return prefix + "." + componentName.str();
getDerivedTypeObjectName(mangledTypeName, fir::kComponentInitSeparator);
return (prefix + fir::kNameSeparator + componentName).str();
}

llvm::StringRef
fir::NameUniquer::dropTypeConversionMarkers(llvm::StringRef mangledTypeName) {
if (mangledTypeName.ends_with(boxprocSuffix))
return mangledTypeName.drop_back(boxprocSuffix.size());
if (mangledTypeName.ends_with(fir::boxprocSuffix))
return mangledTypeName.drop_back(fir::boxprocSuffix.size());
return mangledTypeName;
}

std::string fir::NameUniquer::replaceSpecialSymbols(const std::string &name) {
return std::regex_replace(name, std::regex{"\\."}, "X");
}
23 changes: 13 additions & 10 deletions flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {

void handleGlobalOp(fir::GlobalOp glocalOp, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
mlir::SymbolTable *symbolTable);
mlir::SymbolTable *symbolTable,
fir::cg::XDeclareOp declOp);
void handleFuncOp(mlir::func::FuncOp funcOp, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DICompileUnitAttr cuAttr,
mlir::SymbolTable *symbolTable);
Expand Down Expand Up @@ -100,10 +101,9 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,

if (result.first != fir::NameUniquer::NameKind::VARIABLE)
return;

// If this DeclareOp actually represents a global then treat it as such.
if (auto global = symbolTable->lookup<fir::GlobalOp>(declOp.getUniqName())) {
handleGlobalOp(global, fileAttr, scopeAttr, symbolTable);
handleGlobalOp(global, fileAttr, scopeAttr, symbolTable, declOp);
return;
}

Expand All @@ -127,7 +127,7 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
}

auto tyAttr = typeGen.convertType(fir::unwrapRefType(declOp.getType()),
fileAttr, scopeAttr, declOp.getLoc());
fileAttr, scopeAttr, declOp);

auto localVarAttr = mlir::LLVM::DILocalVariableAttr::get(
context, scopeAttr, mlir::StringAttr::get(context, result.second.name),
Expand Down Expand Up @@ -160,7 +160,8 @@ mlir::LLVM::DIModuleAttr AddDebugInfoPass::getOrCreateModuleAttr(
void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
mlir::SymbolTable *symbolTable) {
mlir::SymbolTable *symbolTable,
fir::cg::XDeclareOp declOp) {
if (debugInfoIsAlreadySet(globalOp.getLoc()))
return;
mlir::ModuleOp module = getOperation();
Expand Down Expand Up @@ -200,8 +201,8 @@ void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp,
scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, scope,
line - 1, !globalOp.isInitialized());
}
mlir::LLVM::DITypeAttr diType = typeGen.convertType(
globalOp.getType(), fileAttr, scope, globalOp.getLoc());
mlir::LLVM::DITypeAttr diType =
typeGen.convertType(globalOp.getType(), fileAttr, scope, declOp);
auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get(
context, scope, mlir::StringAttr::get(context, result.second.name),
mlir::StringAttr::get(context, globalOp.getName()), fileAttr, line,
Expand Down Expand Up @@ -246,12 +247,13 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
llvm::SmallVector<mlir::LLVM::DITypeAttr> types;
fir::DebugTypeGenerator typeGen(module);
for (auto resTy : funcOp.getResultTypes()) {
auto tyAttr = typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc());
auto tyAttr =
typeGen.convertType(resTy, fileAttr, cuAttr, /*declOp=*/nullptr);
types.push_back(tyAttr);
}
for (auto inTy : funcOp.getArgumentTypes()) {
auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr,
cuAttr, funcOp.getLoc());
cuAttr, /*declOp=*/nullptr);
types.push_back(tyAttr);
}

Expand Down Expand Up @@ -358,7 +360,8 @@ void AddDebugInfoPass::runOnOperation() {
if (debugLevel == mlir::LLVM::DIEmissionKind::Full) {
// Process 'GlobalOp' only if full debug info is requested.
for (auto globalOp : module.getOps<fir::GlobalOp>())
handleGlobalOp(globalOp, fileAttr, cuAttr, &symbolTable);
handleGlobalOp(globalOp, fileAttr, cuAttr, &symbolTable,
/*declOp=*/nullptr);
}
}

Expand Down
1 change: 1 addition & 0 deletions flang/lib/Optimizer/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_flang_library(FIRTransforms
AnnotateConstant.cpp
AssumedRankOpConversion.cpp
CharacterConversion.cpp
CompilerGeneratedNames.cpp
ConstantArgumentGlobalisation.cpp
ControlFlowConverter.cpp
CufOpConversion.cpp
Expand Down
80 changes: 80 additions & 0 deletions flang/lib/Optimizer/Transforms/CompilerGeneratedNames.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//=== CompilerGeneratedNames.cpp - convert special symbols in global names ===//
//
// 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 "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Pass/Pass.h"

namespace fir {
#define GEN_PASS_DEF_COMPILERGENERATEDNAMESCONVERSION
#include "flang/Optimizer/Transforms/Passes.h.inc"
} // namespace fir

using namespace mlir;

namespace {

class CompilerGeneratedNamesConversionPass
: public fir::impl::CompilerGeneratedNamesConversionBase<
CompilerGeneratedNamesConversionPass> {
public:
using CompilerGeneratedNamesConversionBase<
CompilerGeneratedNamesConversionPass>::
CompilerGeneratedNamesConversionBase;

mlir::ModuleOp getModule() { return getOperation(); }
void runOnOperation() override;
};
} // namespace

void CompilerGeneratedNamesConversionPass::runOnOperation() {
auto op = getOperation();
auto *context = &getContext();

llvm::DenseMap<mlir::StringAttr, mlir::FlatSymbolRefAttr> remappings;
for (auto &funcOrGlobal : op->getRegion(0).front()) {
if (llvm::isa<mlir::func::FuncOp>(funcOrGlobal) ||
llvm::isa<fir::GlobalOp>(funcOrGlobal)) {
auto symName = funcOrGlobal.getAttrOfType<mlir::StringAttr>(
mlir::SymbolTable::getSymbolAttrName());
auto deconstructedName = fir::NameUniquer::deconstruct(symName);
if (deconstructedName.first != fir::NameUniquer::NameKind::NOT_UNIQUED &&
!fir::NameUniquer::isExternalFacingUniquedName(deconstructedName)) {
std::string newName =
fir::NameUniquer::replaceSpecialSymbols(symName.getValue().str());
if (newName != symName) {
auto newAttr = mlir::StringAttr::get(context, newName);
mlir::SymbolTable::setSymbolName(&funcOrGlobal, newAttr);
auto newSymRef = mlir::FlatSymbolRefAttr::get(newAttr);
remappings.try_emplace(symName, newSymRef);
}
}
}
}

if (remappings.empty())
return;

// Update all uses of the functions and globals that have been renamed.
op.walk([&remappings](mlir::Operation *nestedOp) {
llvm::SmallVector<std::pair<mlir::StringAttr, mlir::SymbolRefAttr>> updates;
for (const mlir::NamedAttribute &attr : nestedOp->getAttrDictionary())
if (auto symRef = llvm::dyn_cast<mlir::SymbolRefAttr>(attr.getValue()))
if (auto remap = remappings.find(symRef.getRootReference());
remap != remappings.end())
updates.emplace_back(std::pair<mlir::StringAttr, mlir::SymbolRefAttr>{
attr.getName(), mlir::SymbolRefAttr(remap->second)});
for (auto update : updates)
nestedOp->setAttr(update.first, update.second);
});
}
54 changes: 28 additions & 26 deletions flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) {

mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, mlir::Location loc, bool genAllocated,
bool genAssociated) {
mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp,
bool genAllocated, bool genAssociated) {

mlir::MLIRContext *context = module.getContext();
// FIXME: Assumed rank arrays not supported yet
Expand Down Expand Up @@ -114,7 +114,7 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(

llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
mlir::LLVM::DITypeAttr elemTy =
convertType(seqTy.getEleTy(), fileAttr, scope, loc);
convertType(seqTy.getEleTy(), fileAttr, scope, declOp);
unsigned offset = dimsOffset;
const unsigned indexSize = dimsSize / 3;
for ([[maybe_unused]] auto _ : seqTy.getShape()) {
Expand Down Expand Up @@ -156,13 +156,14 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(

mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType(
fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, mlir::Location loc) {
mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp) {
mlir::MLIRContext *context = module.getContext();

llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
mlir::LLVM::DITypeAttr elemTy =
convertType(seqTy.getEleTy(), fileAttr, scope, loc);
convertType(seqTy.getEleTy(), fileAttr, scope, declOp);

unsigned index = 0;
for (fir::SequenceType::Extent dim : seqTy.getShape()) {
if (dim == seqTy.getUnknownExtent()) {
// FIXME: This path is taken for assumed size arrays but also for arrays
Expand All @@ -174,20 +175,20 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType(
elements.push_back(subrangeTy);
} else {
auto intTy = mlir::IntegerType::get(context, 64);
// FIXME: Only supporting lower bound of 1 at the moment. The
// 'SequenceType' has information about the shape but not the shift. In
// cases where the conversion originated during the processing of
// 'DeclareOp', it may be possible to pass on this information. But the
// type conversion should ideally be based on what information present in
// the type class so that it works from everywhere (e.g. when it is part
// of a module or a derived type.)
int64_t shift = 1;
if (declOp && declOp.getShift().size() > index) {
if (std::optional<std::int64_t> optint =
getIntIfConstant(declOp.getShift()[index]))
shift = *optint;
}
auto countAttr = mlir::IntegerAttr::get(intTy, llvm::APInt(64, dim));
auto lowerAttr = mlir::IntegerAttr::get(intTy, llvm::APInt(64, 1));
auto lowerAttr = mlir::IntegerAttr::get(intTy, llvm::APInt(64, shift));
auto subrangeTy = mlir::LLVM::DISubrangeAttr::get(
context, countAttr, lowerAttr, /*upperBound=*/nullptr,
/*stride=*/nullptr);
elements.push_back(subrangeTy);
}
++index;
}
// Apart from arrays, the `DICompositeTypeAttr` is used for other things like
// structure types. Many of its fields which are not applicable to arrays
Expand All @@ -203,7 +204,8 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType(

mlir::LLVM::DITypeAttr DebugTypeGenerator::convertCharacterType(
fir::CharacterType charTy, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, mlir::Location loc, bool hasDescriptor) {
mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp,
bool hasDescriptor) {
mlir::MLIRContext *context = module.getContext();

// DWARF 5 says the following about the character encoding in 5.1.1.2.
Expand Down Expand Up @@ -250,21 +252,21 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertCharacterType(

mlir::LLVM::DITypeAttr DebugTypeGenerator::convertPointerLikeType(
mlir::Type elTy, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, mlir::Location loc, bool genAllocated,
bool genAssociated) {
mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp,
bool genAllocated, bool genAssociated) {
mlir::MLIRContext *context = module.getContext();

// Arrays and character need different treatment because DWARF have special
// constructs for them to get the location from the descriptor. Rest of
// types are handled like pointer to underlying type.
if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
return convertBoxedSequenceType(seqTy, fileAttr, scope, loc, genAllocated,
genAssociated);
return convertBoxedSequenceType(seqTy, fileAttr, scope, declOp,
genAllocated, genAssociated);
if (auto charTy = mlir::dyn_cast_or_null<fir::CharacterType>(elTy))
return convertCharacterType(charTy, fileAttr, scope, loc,
return convertCharacterType(charTy, fileAttr, scope, declOp,
/*hasDescriptor=*/true);

mlir::LLVM::DITypeAttr elTyAttr = convertType(elTy, fileAttr, scope, loc);
mlir::LLVM::DITypeAttr elTyAttr = convertType(elTy, fileAttr, scope, declOp);

return mlir::LLVM::DIDerivedTypeAttr::get(
context, llvm::dwarf::DW_TAG_pointer_type,
Expand All @@ -276,7 +278,7 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertPointerLikeType(
mlir::LLVM::DITypeAttr
DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
mlir::Location loc) {
fir::cg::XDeclareOp declOp) {
mlir::MLIRContext *context = module.getContext();
if (Ty.isInteger()) {
return genBasicType(context, mlir::StringAttr::get(context, "integer"),
Expand Down Expand Up @@ -306,22 +308,22 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
return genBasicType(context, mlir::StringAttr::get(context, "complex"),
bitWidth * 2, llvm::dwarf::DW_ATE_complex_float);
} else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(Ty)) {
return convertSequenceType(seqTy, fileAttr, scope, loc);
return convertSequenceType(seqTy, fileAttr, scope, declOp);
} else if (auto charTy = mlir::dyn_cast_or_null<fir::CharacterType>(Ty)) {
return convertCharacterType(charTy, fileAttr, scope, loc,
return convertCharacterType(charTy, fileAttr, scope, declOp,
/*hasDescriptor=*/false);
} else if (auto boxTy = mlir::dyn_cast_or_null<fir::BoxType>(Ty)) {
auto elTy = boxTy.getElementType();
if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
return convertBoxedSequenceType(seqTy, fileAttr, scope, loc, false,
return convertBoxedSequenceType(seqTy, fileAttr, scope, declOp, false,
false);
if (auto heapTy = mlir::dyn_cast_or_null<fir::HeapType>(elTy))
return convertPointerLikeType(heapTy.getElementType(), fileAttr, scope,
loc, /*genAllocated=*/true,
declOp, /*genAllocated=*/true,
/*genAssociated=*/false);
if (auto ptrTy = mlir::dyn_cast_or_null<fir::PointerType>(elTy))
return convertPointerLikeType(ptrTy.getElementType(), fileAttr, scope,
loc, /*genAllocated=*/false,
declOp, /*genAllocated=*/false,
/*genAssociated=*/true);
return genPlaceholderType(context);
} else {
Expand Down
26 changes: 14 additions & 12 deletions flang/lib/Optimizer/Transforms/DebugTypeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H
#define FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H

#include "flang/Optimizer/CodeGen/CGOps.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
Expand All @@ -28,33 +29,34 @@ class DebugTypeGenerator {
mlir::LLVM::DITypeAttr convertType(mlir::Type Ty,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
mlir::Location loc);
fir::cg::XDeclareOp declOp);

private:
mlir::LLVM::DITypeAttr convertSequenceType(fir::SequenceType seqTy,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
mlir::Location loc);
fir::cg::XDeclareOp declOp);

/// The 'genAllocated' is true when we want to generate 'allocated' field
/// in the DICompositeType. It is needed for the allocatable arrays.
/// Similarly, 'genAssociated' is used with 'pointer' type to generate
/// 'associated' field.
mlir::LLVM::DITypeAttr
convertBoxedSequenceType(fir::SequenceType seqTy,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, mlir::Location loc,
bool genAllocated, bool genAssociated);
mlir::LLVM::DITypeAttr convertBoxedSequenceType(
fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp,
bool genAllocated, bool genAssociated);
mlir::LLVM::DITypeAttr convertCharacterType(fir::CharacterType charTy,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
mlir::Location loc,
fir::cg::XDeclareOp declOp,
bool hasDescriptor);

mlir::LLVM::DITypeAttr
convertPointerLikeType(mlir::Type elTy, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, mlir::Location loc,
bool genAllocated, bool genAssociated);
mlir::LLVM::DITypeAttr convertPointerLikeType(mlir::Type elTy,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
fir::cg::XDeclareOp declOp,
bool genAllocated,
bool genAssociated);

mlir::ModuleOp module;
KindMapping kindMapping;
Expand Down
69 changes: 44 additions & 25 deletions flang/lib/Semantics/runtime-type-info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "flang/Evaluate/fold.h"
#include "flang/Evaluate/tools.h"
#include "flang/Evaluate/type.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Semantics/scope.h"
#include "flang/Semantics/tools.h"
#include <functional>
Expand Down Expand Up @@ -377,9 +378,12 @@ static std::optional<std::string> GetSuffixIfTypeKindParameters(
if (pv->GetExplicit()) {
if (auto instantiatedValue{evaluate::ToInt64(*pv->GetExplicit())}) {
if (suffix.has_value()) {
*suffix += "."s + std::to_string(*instantiatedValue);
*suffix +=
(fir::kNameSeparator + llvm::Twine(*instantiatedValue))
.str();
} else {
suffix = "."s + std::to_string(*instantiatedValue);
suffix = (fir::kNameSeparator + llvm::Twine(*instantiatedValue))
.str();
}
}
}
Expand Down Expand Up @@ -448,7 +452,7 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
} else if (isPDTDefinitionWithKindParameters) {
return nullptr;
}
std::string dtDescName{".dt."s + distinctName};
std::string dtDescName{(fir::kTypeDescriptorSeparator + distinctName).str()};
Scope *dtSymbolScope{const_cast<Scope *>(dtSymbol->scope())};
Scope &scope{
GetContainingNonDerivedScope(dtSymbolScope ? *dtSymbolScope : dtScope)};
Expand Down Expand Up @@ -518,11 +522,13 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
}
}
AddValue(dtValues, derivedTypeSchema_, "kindparameter"s,
SaveNumericPointerTarget<Int8>(
scope, SaveObjectName(".kp."s + distinctName), std::move(kinds)));
SaveNumericPointerTarget<Int8>(scope,
SaveObjectName((fir::kKindParameterSeparator + distinctName).str()),
std::move(kinds)));
AddValue(dtValues, derivedTypeSchema_, "lenparameterkind"s,
SaveNumericPointerTarget<Int1>(
scope, SaveObjectName(".lpk."s + distinctName), std::move(lenKinds)));
SaveNumericPointerTarget<Int1>(scope,
SaveObjectName((fir::kLenKindSeparator + distinctName).str()),
std::move(lenKinds)));
// Traverse the components of the derived type
if (!isPDTDefinitionWithKindParameters) {
std::vector<const Symbol *> dataComponentSymbols;
Expand Down Expand Up @@ -570,13 +576,15 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
dtScope, distinctName, parameters));
}
AddValue(dtValues, derivedTypeSchema_, "component"s,
SaveDerivedPointerTarget(scope, SaveObjectName(".c."s + distinctName),
SaveDerivedPointerTarget(scope,
SaveObjectName((fir::kComponentSeparator + distinctName).str()),
std::move(dataComponents),
evaluate::ConstantSubscripts{
static_cast<evaluate::ConstantSubscript>(
dataComponents.size())}));
AddValue(dtValues, derivedTypeSchema_, "procptr"s,
SaveDerivedPointerTarget(scope, SaveObjectName(".p."s + distinctName),
SaveDerivedPointerTarget(scope,
SaveObjectName((fir::kProcPtrSeparator + distinctName).str()),
std::move(procPtrComponents),
evaluate::ConstantSubscripts{
static_cast<evaluate::ConstantSubscript>(
Expand All @@ -587,7 +595,9 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
std::vector<evaluate::StructureConstructor> bindings{
DescribeBindings(dtScope, scope)};
AddValue(dtValues, derivedTypeSchema_, bindingDescCompName,
SaveDerivedPointerTarget(scope, SaveObjectName(".v."s + distinctName),
SaveDerivedPointerTarget(scope,
SaveObjectName(
(fir::kBindingTableSeparator + distinctName).str()),
std::move(bindings),
evaluate::ConstantSubscripts{
static_cast<evaluate::ConstantSubscript>(bindings.size())}));
Expand Down Expand Up @@ -623,7 +633,9 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
sortedSpecials.emplace_back(std::move(pair.second));
}
AddValue(dtValues, derivedTypeSchema_, "special"s,
SaveDerivedPointerTarget(scope, SaveObjectName(".s."s + distinctName),
SaveDerivedPointerTarget(scope,
SaveObjectName(
(fir::kSpecialBindingSeparator + distinctName).str()),
std::move(sortedSpecials),
evaluate::ConstantSubscripts{
static_cast<evaluate::ConstantSubscript>(specials.size())}));
Expand Down Expand Up @@ -730,10 +742,12 @@ SomeExpr RuntimeTableBuilder::SaveNameAsPointerTarget(
using evaluate::Ascii;
using AsciiExpr = evaluate::Expr<Ascii>;
object.set_init(evaluate::AsGenericExpr(AsciiExpr{name}));
Symbol &symbol{*scope
.try_emplace(SaveObjectName(".n."s + name),
Attrs{Attr::TARGET, Attr::SAVE}, std::move(object))
.first->second};
Symbol &symbol{
*scope
.try_emplace(
SaveObjectName((fir::kNameStringSeparator + name).str()),
Attrs{Attr::TARGET, Attr::SAVE}, std::move(object))
.first->second};
SetReadOnlyCompilerCreatedFlags(symbol);
return evaluate::AsGenericExpr(
AsciiExpr{evaluate::Designator<Ascii>{symbol}});
Expand Down Expand Up @@ -821,8 +835,9 @@ evaluate::StructureConstructor RuntimeTableBuilder::DescribeComponent(
if (!lenParams.empty()) {
AddValue(values, componentSchema_, "lenvalue"s,
SaveDerivedPointerTarget(scope,
SaveObjectName(
".lv."s + distinctName + "."s + symbol.name().ToString()),
SaveObjectName((fir::kLenParameterSeparator + distinctName +
fir::kNameSeparator + symbol.name().ToString())
.str()),
std::move(lenParams),
evaluate::ConstantSubscripts{
static_cast<evaluate::ConstantSubscript>(lenParams.size())}));
Expand All @@ -845,8 +860,9 @@ evaluate::StructureConstructor RuntimeTableBuilder::DescribeComponent(
}
AddValue(values, componentSchema_, "bounds"s,
SaveDerivedPointerTarget(scope,
SaveObjectName(
".b."s + distinctName + "."s + symbol.name().ToString()),
SaveObjectName((fir::kBoundsSeparator + distinctName +
fir::kNameSeparator + symbol.name().ToString())
.str()),
std::move(bounds), evaluate::ConstantSubscripts{2, rank}));
} else {
AddValue(
Expand All @@ -868,8 +884,9 @@ evaluate::StructureConstructor RuntimeTableBuilder::DescribeComponent(
if (hasDataInit) {
AddValue(values, componentSchema_, "initialization"s,
SaveObjectInit(scope,
SaveObjectName(
".di."s + distinctName + "."s + symbol.name().ToString()),
SaveObjectName((fir::kComponentInitSeparator + distinctName +
fir::kNameSeparator + symbol.name().ToString())
.str()),
object));
}
}
Expand Down Expand Up @@ -918,8 +935,9 @@ bool RuntimeTableBuilder::InitializeDataPointer(
const ObjectEntityDetails &object, Scope &scope, Scope &dtScope,
const std::string &distinctName) {
if (object.init().has_value()) {
SourceName ptrDtName{SaveObjectName(
".dp."s + distinctName + "."s + symbol.name().ToString())};
SourceName ptrDtName{SaveObjectName((fir::kDataPtrInitSeparator +
distinctName + fir::kNameSeparator + symbol.name().ToString())
.str())};
Symbol &ptrDtSym{
*scope.try_emplace(ptrDtName, Attrs{}, UnknownDetails{}).first->second};
SetReadOnlyCompilerCreatedFlags(ptrDtSym);
Expand Down Expand Up @@ -952,8 +970,9 @@ bool RuntimeTableBuilder::InitializeDataPointer(
Structure(ptrDtDeclType, std::move(ptrInitValues))));
AddValue(values, componentSchema_, "initialization"s,
SaveObjectInit(scope,
SaveObjectName(
".di."s + distinctName + "."s + symbol.name().ToString()),
SaveObjectName((fir::kComponentInitSeparator + distinctName +
fir::kNameSeparator + symbol.name().ToString())
.str()),
ptrInitObj));
return true;
} else {
Expand Down
37 changes: 23 additions & 14 deletions flang/runtime/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ inline RT_API_ATTRS CppTypeFor<TypeCategory::Integer, 4> SelectedIntKind(T x) {
return 4;
} else if (x <= 18) {
return 8;
#ifdef __SIZEOF_INT128__
#if defined __SIZEOF_INT128__ && !defined FLANG_RUNTIME_NO_INTEGER_16
} else if (x <= 38) {
return 16;
#endif
Expand Down Expand Up @@ -137,23 +137,35 @@ inline RT_API_ATTRS CppTypeFor<TypeCategory::Integer, 4> SelectedRealKind(
return -5;
}

#ifndef FLANG_RUNTIME_NO_REAL_2
constexpr bool hasReal2{true};
#else
constexpr bool hasReal2{false};
#endif
#if defined LDBL_MANT_DIG == 64 && !defined FLANG_RUNTIME_NO_REAL_10
constexpr bool hasReal10{true};
#else
constexpr bool hasReal10{false};
#endif
#if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && \
!defined FLANG_RUNTIME_NO_REAL_16
constexpr bool hasReal16{true};
#else
constexpr bool hasReal16{false};
#endif

int error{0};
int kind{0};
if (p <= 3) {
if (hasReal2 && p <= 3) {
kind = 2;
} else if (p <= 6) {
kind = 4;
} else if (p <= 15) {
kind = 8;
#if LDBL_MANT_DIG == 64
} else if (p <= 18) {
} else if (hasReal10 && p <= 18) {
kind = 10;
} else if (p <= 33) {
kind = 16;
#elif LDBL_MANT_DIG == 113
} else if (p <= 33) {
} else if (hasReal16 && p <= 33) {
kind = 16;
#endif
} else {
error -= 1;
}
Expand All @@ -164,13 +176,10 @@ inline RT_API_ATTRS CppTypeFor<TypeCategory::Integer, 4> SelectedRealKind(
kind = kind < 3 ? (p == 3 ? 4 : 3) : kind;
} else if (r <= 307) {
kind = kind < 8 ? 8 : kind;
#if LDBL_MANT_DIG == 64
} else if (r <= 4931) {
} else if (hasReal10 && r <= 4931) {
kind = kind < 10 ? 10 : kind;
#elif LDBL_MANT_DIG == 113
} else if (r <= 4931) {
} else if (hasReal16 && r <= 4931) {
kind = kind < 16 ? 16 : kind;
#endif
} else {
error -= 2;
}
Expand Down
1 change: 0 additions & 1 deletion flang/test/Driver/fveclib-codegen.f90
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
! test that -fveclib= is passed to the backend
! -target aarch64 so that ArmPL is available
! RUN: %if aarch64-registered-target %{ %flang -S -Ofast -target aarch64-unknown-linux-gnu -fveclib=LIBMVEC -o - %s | FileCheck %s %}
! RUN: %if x86-registered-target %{ %flang -S -Ofast -target x86_64-unknown-linux-gnu -fveclib=LIBMVEC -o - %s | FileCheck %s %}
! RUN: %flang -S -Ofast -fveclib=NoLibrary -o - %s | FileCheck %s --check-prefix=NOLIB
Expand Down
1 change: 1 addition & 0 deletions flang/test/Driver/mlir-debug-pass-pipeline.f90
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
! ALL-NEXT: CodeGenRewrite
! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated
! ALL-NEXT: TargetRewrite
! ALL-NEXT: CompilerGeneratedNamesConversion
! ALL-NEXT: ExternalNameConversion
! DEBUG-NEXT: AddDebugInfo
! NO-DEBUG-NOT: AddDebugInfo
Expand Down
1 change: 1 addition & 0 deletions flang/test/Driver/mlir-pass-pipeline.f90
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
! ALL-NEXT: CodeGenRewrite
! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated
! ALL-NEXT: TargetRewrite
! ALL-NEXT: CompilerGeneratedNamesConversion
! ALL-NEXT: ExternalNameConversion
! ALL-NEXT: FIRToLLVMLowering
! ALL-NOT: LLVMIRLoweringPass
2 changes: 2 additions & 0 deletions flang/test/Fir/basic-program.fir
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func.func @_QQmain() {
// PASSES-NEXT: LowerHLFIRIntrinsics
// PASSES-NEXT: BufferizeHLFIR
// PASSES-NEXT: ConvertHLFIRtoFIR
// PASSES-NEXT: LowerWorkshare
// PASSES-NEXT: CSE
// PASSES-NEXT: (S) 0 num-cse'd - Number of operations CSE'd
// PASSES-NEXT: (S) 0 num-dce'd - Number of operations DCE'd
Expand Down Expand Up @@ -118,6 +119,7 @@ func.func @_QQmain() {
// PASSES-NEXT: CodeGenRewrite
// PASSES-NEXT: (S) 0 num-dce'd - Number of operations eliminated
// PASSES-NEXT: TargetRewrite
// PASSES-NEXT: CompilerGeneratedNamesConversion
// PASSES-NEXT: FIRToLLVMLowering
// PASSES-NEXT: ReconcileUnrealizedCasts
// PASSES-NEXT: LLVMIRLoweringPass
2 changes: 1 addition & 1 deletion flang/test/Fir/convert-to-llvm.fir
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-pc-win32" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-apple-darwin" %s | FileCheck %s --check-prefixes=CHECK,CHECK-NO-COMDAT,GENERIC
// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=amdgcn-amd-amdhsa, datalayout=e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-P0" %s | FileCheck -check-prefixes=CHECK,AMDGPU %s
Expand Down
29 changes: 29 additions & 0 deletions flang/test/Fir/convert-type-desc-to-llvm.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: fir-opt --split-input-file --compiler-generated-names --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu type-descriptors-renamed-for-assembly=true" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
// RUN: fir-opt --split-input-file --compiler-generated-names --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu type-descriptors-renamed-for-assembly=true" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
// RUN: fir-opt --split-input-file --compiler-generated-names --fir-to-llvm-ir="target=i386-unknown-linux-gnu type-descriptors-renamed-for-assembly=true" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
// RUN: fir-opt --split-input-file --compiler-generated-names --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gnu type-descriptors-renamed-for-assembly=true" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
// RUN: fir-opt --split-input-file --compiler-generated-names --fir-to-llvm-ir="target=x86_64-pc-win32 type-descriptors-renamed-for-assembly=true" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
// RUN: fir-opt --split-input-file --compiler-generated-names --fir-to-llvm-ir="target=aarch64-apple-darwin type-descriptors-renamed-for-assembly=true" %s | FileCheck %s --check-prefixes=CHECK,CHECK-NO-COMDAT
// RUN: fir-opt --split-input-file --compiler-generated-names --fir-to-llvm-ir="target=amdgcn-amd-amdhsa type-descriptors-renamed-for-assembly=1 datalayout=e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-P0" %s | FileCheck -check-prefixes=CHECK %s

// Check descriptor for a derived type. Check that the f18Addendum flag is set
// to 1 meaning the addendum is present (true) and the addendum values are
// inserted.

fir.global linkonce @_QMtest_dinitE.dt.tseq constant : i8

func.func @embox1(%arg0: !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>) {
%0 = fir.embox %arg0() : (!fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>) -> !fir.box<!fir.type<_QMtest_dinitTtseq{i:i32}>>
return
}

// CHECK-COMDAT: llvm.mlir.global linkonce constant @_QMtest_dinitEXdtXtseq() comdat(@__llvm_comdat::@_QMtest_dinitEXdtXtseq) {addr_space = 0 : i32} : i8
// CHECK-NO-COMDAT: llvm.mlir.global linkonce constant @_QMtest_dinitEXdtXtseq() {addr_space = 0 : i32} : i8
// CHECK-LABEL: llvm.func @embox1
// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(42 : i32) : i32
// CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20240719 : i32) : i32
// CHECK: %{{.*}} = llvm.insertvalue %[[VERSION]], %{{.*}}[2] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>)>
// CHECK: %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
// CHECK: %{{.*}} = llvm.insertvalue %[[TYPE_CODE_I8]], %{{.*}}[4] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>
// CHECK: %[[TDESC:.*]] = llvm.mlir.addressof @_QMtest_dinitEXdtXtseq : !llvm.ptr
// CHECK: %{{.*}} = llvm.insertvalue %[[TDESC]], %{{.*}}[7] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>
4 changes: 2 additions & 2 deletions flang/test/Fir/polymorphic.fir
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func.func @_QQmain() {
// CHECK-LABEL: define void @_QQmain(){{.*}}{
// CHECK: %[[CLASS_NONE:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }
// CHECK: %[[DESC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, i64 1
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr @_QMmod1Ea, i64 ptrtoint (ptr getelementptr (%_QMmod1TtK2, ptr null, i32 1) to i64), i32 20240719, i8 0, i8 42, i8 1, i8 1, ptr @_QMmod1E.dt.t.2, [1 x i64] zeroinitializer }, ptr %[[CLASS_NONE]], align 8
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr @_QMmod1Ea, i64 ptrtoint (ptr getelementptr (%_QMmod1TtK2, ptr null, i32 1) to i64), i32 20240719, i8 0, i8 42, i8 1, i8 1, ptr @_QMmod1EXdtXtX2, [1 x i64] zeroinitializer }, ptr %[[CLASS_NONE]], align 8
// CHECK: %[[LOAD:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[CLASS_NONE]]
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOAD]], ptr %[[DESC]]
// CHECK: call void @_QMmod1Psub1(ptr %[[DESC]])
Expand Down Expand Up @@ -197,4 +197,4 @@ func.func @_QQembox_input_type(%arg0 : !fir.ref<!fir.type<_QMmod1Tp2{v:!fir.arra
}

// CHECK-LABEL: define void @_QQembox_input_type
// CHECK: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr undef, i64 ptrtoint (ptr getelementptr (%_QMmod1Tp2, ptr null, i32 1) to i64), i32 20240719, i8 0, i8 42, i8 0, i8 1, ptr @_QMmod1E.dt.p2, [1 x i64] zeroinitializer }, ptr %{{.*}}, 0
// CHECK: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr undef, i64 ptrtoint (ptr getelementptr (%_QMmod1Tp2, ptr null, i32 1) to i64), i32 20240719, i8 0, i8 42, i8 0, i8 1, ptr @_QMmod1EXdtXp2, [1 x i64] zeroinitializer }, ptr %{{.*}}, 0
4 changes: 2 additions & 2 deletions flang/test/Fir/type-descriptor.fir
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fir.global internal @_QFfooEx : !fir.box<!fir.heap<!sometype>> {
}
// CHECK: @_QFfooEx = internal global { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }
// CHECK-SAME: { ptr null, i64 ptrtoint (ptr getelementptr (%_QFfooTsometype, ptr null, i32 1) to i64),
// CHECK-SAME: i32 20240719, i8 0, i8 42, i8 2, i8 1, ptr @_QFfooE.dt.sometype, [1 x i64] zeroinitializer }
// CHECK-SAME: i32 20240719, i8 0, i8 42, i8 2, i8 1, ptr @_QFfooEXdtXsometype, [1 x i64] zeroinitializer }

!some_pdt_type = !fir.type<_QFfooTsome_pdt_typeK42K43{num:i32,values:!fir.box<!fir.ptr<!fir.array<?x?xf32>>>}>
fir.global internal @_QFfooE.dt.some_pdt_type.42.43 constant : i8
Expand All @@ -26,4 +26,4 @@ fir.global internal @_QFfooEx2 : !fir.box<!fir.heap<!some_pdt_type>> {
}
// CHECK: @_QFfooEx2 = internal global { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }
// CHECK-SAME: { ptr null, i64 ptrtoint (ptr getelementptr (%_QFfooTsome_pdt_typeK42K43, ptr null, i32 1) to i64),
// CHECK-SAME: i32 20240719, i8 0, i8 42, i8 2, i8 1, ptr @_QFfooE.dt.some_pdt_type.42.43, [1 x i64] zeroinitializer }
// CHECK-SAME: i32 20240719, i8 0, i8 42, i8 2, i8 1, ptr @_QFfooEXdtXsome_pdt_typeX42X43, [1 x i64] zeroinitializer }
58 changes: 58 additions & 0 deletions flang/test/HLFIR/bufferize-workshare.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// RUN: fir-opt --bufferize-hlfir %s | FileCheck %s

// CHECK-LABEL: func.func @simple(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<42xi32>>) {
// CHECK: omp.parallel {
// CHECK: omp.workshare {
// CHECK: %[[VAL_1:.*]] = arith.constant 42 : index
// CHECK: %[[VAL_2:.*]] = arith.constant 1 : i32
// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "array"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>)
// CHECK: %[[VAL_5:.*]] = fir.allocmem !fir.array<42xi32> {bindc_name = ".tmp.array", uniq_name = ""}
// CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_3]]) {uniq_name = ".tmp.array"} : (!fir.heap<!fir.array<42xi32>>, !fir.shape<1>) -> (!fir.heap<!fir.array<42xi32>>, !fir.heap<!fir.array<42xi32>>)
// CHECK: %[[VAL_7:.*]] = arith.constant true
// CHECK: %[[VAL_8:.*]] = arith.constant 1 : index
// CHECK: omp.workshare_loop_wrapper {
// CHECK: omp.loop_nest (%[[VAL_9:.*]]) : index = (%[[VAL_8]]) to (%[[VAL_1]]) inclusive step (%[[VAL_8]]) {
// CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_9]]) : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
// CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_10]] : !fir.ref<i32>
// CHECK: %[[VAL_12:.*]] = arith.subi %[[VAL_11]], %[[VAL_2]] : i32
// CHECK: %[[VAL_13:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_9]]) : (!fir.heap<!fir.array<42xi32>>, index) -> !fir.ref<i32>
// CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_13]] temporary_lhs : i32, !fir.ref<i32>
// CHECK: omp.yield
// CHECK: }
// CHECK: omp.terminator
// CHECK: }
// CHECK: %[[VAL_14:.*]] = fir.undefined tuple<!fir.heap<!fir.array<42xi32>>, i1>
// CHECK: %[[VAL_15:.*]] = fir.insert_value %[[VAL_14]], %[[VAL_7]], [1 : index] : (tuple<!fir.heap<!fir.array<42xi32>>, i1>, i1) -> tuple<!fir.heap<!fir.array<42xi32>>, i1>
// CHECK: %[[VAL_16:.*]] = fir.insert_value %[[VAL_15]], %[[VAL_6]]#0, [0 : index] : (tuple<!fir.heap<!fir.array<42xi32>>, i1>, !fir.heap<!fir.array<42xi32>>) -> tuple<!fir.heap<!fir.array<42xi32>>, i1>
// CHECK: hlfir.assign %[[VAL_6]]#0 to %[[VAL_4]]#0 : !fir.heap<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>
// CHECK: fir.freemem %[[VAL_6]]#0 : !fir.heap<!fir.array<42xi32>>
// CHECK: omp.terminator
// CHECK: }
// CHECK: omp.terminator
// CHECK: }
// CHECK: return
// CHECK: }
func.func @simple(%arg: !fir.ref<!fir.array<42xi32>>) {
omp.parallel {
omp.workshare {
%c42 = arith.constant 42 : index
%c1_i32 = arith.constant 1 : i32
%shape = fir.shape %c42 : (index) -> !fir.shape<1>
%array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref<!fir.array<42xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<42xi32>>, !fir.ref<!fir.array<42xi32>>)
%elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> {
^bb0(%i: index):
%ref = hlfir.designate %array#0 (%i) : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
%val = fir.load %ref : !fir.ref<i32>
%sub = arith.subi %val, %c1_i32 : i32
hlfir.yield_element %sub : i32
}
hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref<!fir.array<42xi32>>
hlfir.destroy %elemental : !hlfir.expr<42xi32>
omp.terminator
}
omp.terminator
}
return
}
38 changes: 25 additions & 13 deletions flang/test/Integration/debug-fixed-array-type-2.f90
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s

program mn

module test
integer d1(3)
integer d2(2, 5)
real d3(6, 8, 7)
integer d2(1:4, -1:3)
real d3(-2:6, 0:5, 3:7)
end

program mn
use test

i8 = fn1(d1, d2, d3)
contains
function fn1(a1, b1, c1) result (res)
integer a1(3)
integer b1(2, 5)
real c1(6, 8, 7)
integer b1(-1:0, 5:9)
real c1(-2:6, 0:5, 3:7)
integer res
res = a1(1) + b1(1,2) + c1(3, 3, 4)
res = a1(1) + b1(0,6) + c1(3, 3, 4)
end function

end program
Expand All @@ -24,17 +27,26 @@ function fn1(a1, b1, c1) result (res)
! CHECK-DAG: ![[SUB1:.*]] = !{![[R1]]}
! CHECK-DAG: ![[D1TY:.*]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[INT]], elements: ![[SUB1]])

! CHECK-DAG: ![[R21:.*]] = !DISubrange(count: 2, lowerBound: 1)
! CHECK-DAG: ![[R22:.*]] = !DISubrange(count: 5, lowerBound: 1)
! CHECK-DAG: ![[R21:.*]] = !DISubrange(count: 4, lowerBound: 1)
! CHECK-DAG: ![[R22:.*]] = !DISubrange(count: 5, lowerBound: -1)
! CHECK-DAG: ![[SUB2:.*]] = !{![[R21]], ![[R22]]}
! CHECK-DAG: ![[D2TY:.*]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[INT]], elements: ![[SUB2]])

! CHECK-DAG: ![[R31:.*]] = !DISubrange(count: 6, lowerBound: 1)
! CHECK-DAG: ![[R32:.*]] = !DISubrange(count: 8, lowerBound: 1)
! CHECK-DAG: ![[R33:.*]] = !DISubrange(count: 7, lowerBound: 1)
! CHECK-DAG: ![[R31:.*]] = !DISubrange(count: 9, lowerBound: -2)
! CHECK-DAG: ![[R32:.*]] = !DISubrange(count: 6, lowerBound: 0)
! CHECK-DAG: ![[R33:.*]] = !DISubrange(count: 5, lowerBound: 3)
! CHECK-DAG: ![[SUB3:.*]] = !{![[R31]], ![[R32]], ![[R33]]}
! CHECK-DAG: ![[D3TY:.*]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[REAL]], elements: ![[SUB3]])

! CHECK-DAG: ![[B11:.*]] = !DISubrange(count: 2, lowerBound: -1)
! CHECK-DAG: ![[B12:.*]] = !DISubrange(count: 5, lowerBound: 5)
! CHECK-DAG: ![[B1:.*]] = !{![[B11]], ![[B12]]}
! CHECK-DAG: ![[B1TY:.*]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[INT]], elements: ![[B1]])

! CHECK-DAG: {{.*}}!DIGlobalVariable(name: "d1"{{.*}}type: ![[D1TY]]{{.*}})
! CHECK-DAG: {{.*}}!DIGlobalVariable(name: "d2"{{.*}}type: ![[D2TY]]{{.*}})
! CHECK-DAG: {{.*}}!DIGlobalVariable(name: "d3"{{.*}}type: ![[D3TY]]{{.*}})

! CHECK-DAG: !DILocalVariable(name: "a1", arg: 1{{.*}}type: ![[D1TY]])
! CHECK-DAG: !DILocalVariable(name: "b1", arg: 2{{.*}}type: ![[D2TY]])
! CHECK-DAG: !DILocalVariable(name: "b1", arg: 2{{.*}}type: ![[B1TY]])
! CHECK-DAG: !DILocalVariable(name: "c1", arg: 3{{.*}}type: ![[D3TY]])
6 changes: 3 additions & 3 deletions flang/test/Lower/OpenMP/workshare.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ subroutine sb1(arr)
integer :: arr(:)
!CHECK: omp.parallel {
!$omp parallel
!CHECK: omp.single {
!CHECK: omp.workshare {
!$omp workshare
arr = 0
!$omp end workshare
Expand All @@ -20,7 +20,7 @@ subroutine sb2(arr)
integer :: arr(:)
!CHECK: omp.parallel {
!$omp parallel
!CHECK: omp.single nowait {
!CHECK: omp.workshare nowait {
!$omp workshare
arr = 0
!$omp end workshare nowait
Expand All @@ -33,7 +33,7 @@ subroutine sb2(arr)
subroutine sb3(arr)
integer :: arr(:)
!CHECK: omp.parallel {
!CHECK: omp.single {
!CHECK: omp.workshare {
!$omp parallel workshare
arr = 0
!$omp end parallel workshare
Expand Down
14 changes: 7 additions & 7 deletions flang/test/Lower/allocatable-polymorphic.f90
Original file line number Diff line number Diff line change
Expand Up @@ -591,16 +591,16 @@ program test_alloc

! LLVM-LABEL: define void @_QMpolyPtest_allocatable()

! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyE.dt.p1, i32 0, i32 0)
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyEXdtXp1, i32 0, i32 0)
! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQclX{{.*}}, i32 {{.*}})
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyE.dt.p1, i32 0, i32 0)
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyEXdtXp1, i32 0, i32 0)
! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQclX{{.*}}, i32 {{.*}})
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyE.dt.p2, i32 0, i32 0)
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyEXdtXp2, i32 0, i32 0)
! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQclX{{.*}}, i32 {{.*}})
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyE.dt.p1, i32 1, i32 0)
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyEXdtXp1, i32 1, i32 0)
! LLVM: %{{.*}} = call {} @_FortranAAllocatableSetBounds(ptr %{{.*}}, i32 0, i64 1, i64 10)
! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQclX{{.*}}, i32 {{.*}})
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyE.dt.p2, i32 1, i32 0)
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %{{.*}}, ptr @_QMpolyEXdtXp2, i32 1, i32 0)
! LLVM: %{{.*}} = call {} @_FortranAAllocatableSetBounds(ptr %{{.*}}, i32 0, i64 1, i64 20)
! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQclX{{.*}}, i32 {{.*}})
! LLVM-COUNT-2: call void %{{.*}}()
Expand Down Expand Up @@ -685,9 +685,9 @@ program test_alloc
! allocatable.

! LLVM-LABEL: define void @_QMpolyPtest_deallocate()
! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr null, i64 ptrtoint (ptr getelementptr (%_QMpolyTp1, ptr null, i32 1) to i64), i32 20240719, i8 0, i8 42, i8 2, i8 1, ptr @_QMpolyE.dt.p1, [1 x i64] zeroinitializer }, ptr %[[ALLOCA1:[0-9]*]]
! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr null, i64 ptrtoint (ptr getelementptr (%_QMpolyTp1, ptr null, i32 1) to i64), i32 20240719, i8 0, i8 42, i8 2, i8 1, ptr @_QMpolyEXdtXp1, [1 x i64] zeroinitializer }, ptr %[[ALLOCA1:[0-9]*]]
! LLVM: %[[LOAD:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[ALLOCA1]]
! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOAD]], ptr %[[ALLOCA2:[0-9]*]]
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %[[ALLOCA2]], ptr @_QMpolyE.dt.p1, i32 0, i32 0)
! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerivedForAllocate(ptr %[[ALLOCA2]], ptr @_QMpolyEXdtXp1, i32 0, i32 0)
! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %[[ALLOCA2]], i1 false, ptr null, ptr @_QQclX{{.*}}, i32 {{.*}})
! LLVM: %{{.*}} = call i32 @_FortranAAllocatableDeallocatePolymorphic(ptr %[[ALLOCA2]], ptr {{.*}}, i1 false, ptr null, ptr @_QQclX{{.*}}, i32 {{.*}})
6 changes: 3 additions & 3 deletions flang/test/Lower/dense-array-any-rank.f90
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ subroutine test()

! a1 array constructor
! CHECK-FIR: fir.global internal @_QQro.10xi4.{{.*}}(dense<[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]> : tensor<10xi32>) constant : !fir.array<10xi32>
! CHECK-LLVMIR: @_QQro.10xi4.0 = internal constant [10 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10]
! CHECK-LLVMIR: @_QQroX10xi4X0 = internal constant [10 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10]

! a2 array constructor
! CHECK-FIR: fir.global internal @_QQro.3x4xi4.{{.*}}(dense<{{\[\[11, 12, 13], \[21, 22, 23], \[31, 32, 33], \[41, 42, 43]]}}> : tensor<4x3xi32>) constant : !fir.array<3x4xi32>
! CHECK-LLVMIR: @_QQro.3x4xi4.1 = internal constant [4 x [3 x i32]] {{\[\[3 x i32] \[i32 11, i32 12, i32 13], \[3 x i32] \[i32 21, i32 22, i32 23], \[3 x i32] \[i32 31, i32 32, i32 33], \[3 x i32] \[i32 41, i32 42, i32 43]]}}
! CHECK-LLVMIR: @_QQroX3x4xi4X1 = internal constant [4 x [3 x i32]] {{\[\[3 x i32] \[i32 11, i32 12, i32 13], \[3 x i32] \[i32 21, i32 22, i32 23], \[3 x i32] \[i32 31, i32 32, i32 33], \[3 x i32] \[i32 41, i32 42, i32 43]]}}

! a3 array constructor
! CHECK-FIR: fir.global internal @_QQro.2x3x4xi4.{{.*}}(dense<{{\[\[\[111, 112], \[121, 122], \[131, 132]], \[\[211, 212], \[221, 222], \[231, 232]], \[\[311, 312], \[321, 322], \[331, 332]], \[\[411, 412], \[421, 422], \[431, 432]]]}}> : tensor<4x3x2xi32>) constant : !fir.array<2x3x4xi32>
! CHECK-LLVMIR: @_QQro.2x3x4xi4.2 = internal constant [4 x [3 x [2 x i32]]] {{\[\[3 x \[2 x i32]] \[\[2 x i32] \[i32 111, i32 112], \[2 x i32] \[i32 121, i32 122], \[2 x i32] \[i32 131, i32 132]], \[3 x \[2 x i32]] \[\[2 x i32] \[i32 211, i32 212], \[2 x i32] \[i32 221, i32 222], \[2 x i32] \[i32 231, i32 232]], \[3 x \[2 x i32]] \[\[2 x i32] \[i32 311, i32 312], \[2 x i32] \[i32 321, i32 322], \[2 x i32] \[i32 331, i32 332]], \[3 x \[2 x i32]] \[\[2 x i32] \[i32 411, i32 412], \[2 x i32] \[i32 421, i32 422], \[2 x i32] \[i32 431, i32 432]]]}}
! CHECK-LLVMIR: @_QQroX2x3x4xi4X2 = internal constant [4 x [3 x [2 x i32]]] {{\[\[3 x \[2 x i32]] \[\[2 x i32] \[i32 111, i32 112], \[2 x i32] \[i32 121, i32 122], \[2 x i32] \[i32 131, i32 132]], \[3 x \[2 x i32]] \[\[2 x i32] \[i32 211, i32 212], \[2 x i32] \[i32 221, i32 222], \[2 x i32] \[i32 231, i32 232]], \[3 x \[2 x i32]] \[\[2 x i32] \[i32 311, i32 312], \[2 x i32] \[i32 321, i32 322], \[2 x i32] \[i32 331, i32 332]], \[3 x \[2 x i32]] \[\[2 x i32] \[i32 411, i32 412], \[2 x i32] \[i32 421, i32 422], \[2 x i32] \[i32 431, i32 432]]]}}
Loading