diff --git a/openmp/tools/analyzer/llvm-openmp-analyzer b/openmp/tools/analyzer/llvm-openmp-analyzer new file mode 100755 --- /dev/null +++ b/openmp/tools/analyzer/llvm-openmp-analyzer @@ -0,0 +1,76 @@ +#!/usr/bin/env python + +import io +import argparse +import subprocess +import os.path +import sys +import re +import yaml + +demangler = ["c++filt"] +desc = '''OpenMP Analysis passes''' + +default_args = ["-fopenmp", "-Rpass=openmp-opt", "-Rpass-missed=openmp-opt", "-Rpass-analysis=openmp-opt"] + +def getLine(fn): + expr = re.compile("__omp_offloading_[a-zA-Z0-9]*_[a-zA-Z0-9]*__Z.*__l([0-9]*)$") + match = expr.search(fn) + return match.group(1) if match else 0 + +def demangle(fn): + expr = re.compile("__omp_offloading_[a-zA-Z0-9]*_[a-zA-Z0-9]*_(_Z.*_)_l[0-9]*$") + match = expr.search(fn) + + function = match.group(1) if match else fn + output = subprocess.run(demangler + ["-p"] + [function], stdout=subprocess.PIPE) + return output.stdout.decode('utf-8').strip() + +def getRegisters(usages): + match = re.search(r"[Uu]sed ([0-9]+) registers", usages) + return match.group(1) if match else None + +def getSharedMem(usages): + match = re.search(r"([0-9]+) bytes smem", usages) + return match.group(1) if match else None + +def getKernelMem(usages): + match = re.search(r"([0-9]+) bytes cmem\[0\]", usages) + return match.group(1) if match else None + + +def parseKernelUsages(usageStr, usageDict): + expr = re.compile("Function properties for \'?([a-zA-Z0-9_]*)\'?\n(.*,.*)\n") + for (fn, usages) in expr.findall(usageStr): + info = usageDict[fn] if fn in usageDict else dict() + info["Name"] = demangle(fn) + info["DebugLoc"] = {"File" : "unknown", "Line": getLine(fn), "Column" : 0} + info["Usage"] = {"Registers" : getRegisters(usages), "Shared" : getSharedMem(usages), "Kernel" : getKernelMem(usages)} + usageDict[fn] = info + +def main(): + parser = argparse.ArgumentParser(description=desc) + args, forward_args = parser.parse_known_args() + + subprocess.run(["clang"] + default_args + forward_args, check=True) + output = subprocess.run(["clang"] + default_args + forward_args + ["-v"], stderr=subprocess.PIPE) + stderr = output.stderr.decode('utf-8') + + remarks = [line for line in stderr.split('\n') if re.search(r"^remark:", line)] + ptxas = '\n'.join([line.split(':')[1].strip() for line in stderr.split('\n') if re.search(r"^ptxas info *:", line)]) + nvlink = '\n'.join([line.split(':')[1].strip() for line in stderr.split('\n') if re.search(r"^nvlink info *:", line)]) + + if os.path.exists("usage.yaml"): + with io.open("usage.yaml", 'r', encoding = 'utf-8') as f: + usage = yaml.load(f, Loader=yaml.Loader) + else: + usage = dict() + + parseKernelUsages(ptxas, usage) + parseKernelUsages(nvlink, usage) + + with io.open("usage.yaml", 'w', encoding = 'utf-8') as f: + yaml.dump(usage, f) + +if __name__ == '__main__': + main() diff --git a/openmp/tools/analyzer/llvm-openmp-analyzer++ b/openmp/tools/analyzer/llvm-openmp-analyzer++ new file mode 100755 --- /dev/null +++ b/openmp/tools/analyzer/llvm-openmp-analyzer++ @@ -0,0 +1,76 @@ +#!/usr/bin/env python + +import io +import argparse +import subprocess +import os.path +import sys +import re +import yaml + +demangler = ["c++filt"] +desc = '''OpenMP Analysis passes''' + +default_args = ["-fopenmp", "-Rpass=openmp-opt", "-Rpass-missed=openmp-opt", "-Rpass-analysis=openmp-opt"] + +def getLine(fn): + expr = re.compile("__omp_offloading_[a-zA-Z0-9]*_[a-zA-Z0-9]*__Z.*__l([0-9]*)$") + match = expr.search(fn) + return match.group(1) if match else 0 + +def demangle(fn): + expr = re.compile("__omp_offloading_[a-zA-Z0-9]*_[a-zA-Z0-9]*_(_Z.*_)_l[0-9]*$") + match = expr.search(fn) + + function = match.group(1) if match else fn + output = subprocess.run(demangler + ["-p"] + [function], stdout=subprocess.PIPE) + return output.stdout.decode('utf-8').strip() + +def getRegisters(usages): + match = re.search(r"[Uu]sed ([0-9]+) registers", usages) + return match.group(1) if match else None + +def getSharedMem(usages): + match = re.search(r"([0-9]+) bytes smem", usages) + return match.group(1) if match else None + +def getKernelMem(usages): + match = re.search(r"([0-9]+) bytes cmem\[0\]", usages) + return match.group(1) if match else None + + +def parseKernelUsages(usageStr, usageDict): + expr = re.compile("Function properties for \'?([a-zA-Z0-9_]*)\'?\n(.*,.*)\n") + for (fn, usages) in expr.findall(usageStr): + info = usageDict[fn] if fn in usageDict else dict() + info["Name"] = demangle(fn) + info["DebugLoc"] = {"File" : "unknown", "Line": getLine(fn), "Column" : 0} + info["Usage"] = {"Registers" : getRegisters(usages), "Shared" : getSharedMem(usages), "Kernel" : getKernelMem(usages)} + usageDict[fn] = info + +def main(): + parser = argparse.ArgumentParser(description=desc) + args, forward_args = parser.parse_known_args() + + subprocess.run(["clang++"] + default_args + forward_args, check=True) + output = subprocess.run(["clang++"] + default_args + forward_args + ["-v"], stderr=subprocess.PIPE) + stderr = output.stderr.decode('utf-8') + + remarks = [line for line in stderr.split('\n') if re.search(r"^remark:", line)] + ptxas = '\n'.join([line.split(':')[1].strip() for line in stderr.split('\n') if re.search(r"^ptxas info *:", line)]) + nvlink = '\n'.join([line.split(':')[1].strip() for line in stderr.split('\n') if re.search(r"^nvlink info *:", line)]) + + if os.path.exists("usage.yaml"): + with io.open("usage.yaml", 'r', encoding = 'utf-8') as f: + usage = yaml.load(f, Loader=yaml.Loader) + else: + usage = dict() + + parseKernelUsages(ptxas, usage) + parseKernelUsages(nvlink, usage) + + with io.open("usage.yaml", 'w', encoding = 'utf-8') as f: + yaml.dump(usage, f) + +if __name__ == '__main__': + main()