xref: /netbsd-src/external/gpl3/gcc.old/dist/contrib/gen_autofdo_event.py (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
13ad841b2Smrg#!/usr/bin/python
23ad841b2Smrg# Generate Intel taken branches Linux perf event script for autofdo profiling.
33ad841b2Smrg
43ad841b2Smrg# Copyright (C) 2016 Free Software Foundation, Inc.
53ad841b2Smrg#
63ad841b2Smrg# GCC is free software; you can redistribute it and/or modify it under
73ad841b2Smrg# the terms of the GNU General Public License as published by the Free
83ad841b2Smrg# Software Foundation; either version 3, or (at your option) any later
93ad841b2Smrg# version.
103ad841b2Smrg#
113ad841b2Smrg# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
123ad841b2Smrg# WARRANTY; without even the implied warranty of MERCHANTABILITY or
133ad841b2Smrg# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
143ad841b2Smrg# for more details.
153ad841b2Smrg#
163ad841b2Smrg# You should have received a copy of the GNU General Public License
173ad841b2Smrg# along with GCC; see the file COPYING3.  If not see
183ad841b2Smrg# <http://www.gnu.org/licenses/>.  */
193ad841b2Smrg
203ad841b2Smrg# Run it with perf record -b -e EVENT program ...
213ad841b2Smrg# The Linux Kernel needs to support the PMU of the current CPU, and
223ad841b2Smrg# It will likely not work in VMs.
233ad841b2Smrg# Add --all to print for all cpus, otherwise for current cpu.
243ad841b2Smrg# Add --script to generate shell script to run correct event.
253ad841b2Smrg#
263ad841b2Smrg# Requires internet (https) access. This may require setting up a proxy
273ad841b2Smrg# with export https_proxy=...
283ad841b2Smrg#
293ad841b2Smrgimport urllib2
303ad841b2Smrgimport sys
313ad841b2Smrgimport json
323ad841b2Smrgimport argparse
333ad841b2Smrgimport collections
343ad841b2Smrg
353ad841b2Smrgbaseurl = "https://download.01.org/perfmon"
363ad841b2Smrg
373ad841b2Smrgtarget_events = (u'BR_INST_RETIRED.NEAR_TAKEN',
383ad841b2Smrg                 u'BR_INST_EXEC.TAKEN',
393ad841b2Smrg                 u'BR_INST_RETIRED.TAKEN_JCC',
403ad841b2Smrg                 u'BR_INST_TYPE_RETIRED.COND_TAKEN')
413ad841b2Smrg
423ad841b2Smrgap = argparse.ArgumentParser()
433ad841b2Smrgap.add_argument('--all', '-a', help='Print for all CPUs', action='store_true')
443ad841b2Smrgap.add_argument('--script', help='Generate shell script', action='store_true')
453ad841b2Smrgargs = ap.parse_args()
463ad841b2Smrg
473ad841b2Smrgeventmap = collections.defaultdict(list)
483ad841b2Smrg
493ad841b2Smrgdef get_cpu_str():
503ad841b2Smrg    with open('/proc/cpuinfo', 'r') as c:
513ad841b2Smrg        vendor, fam, model = None, None, None
523ad841b2Smrg        for j in c:
533ad841b2Smrg            n = j.split()
543ad841b2Smrg            if n[0] == 'vendor_id':
553ad841b2Smrg                vendor = n[2]
563ad841b2Smrg            elif n[0] == 'model' and n[1] == ':':
573ad841b2Smrg                model = int(n[2])
583ad841b2Smrg            elif n[0] == 'cpu' and n[1] == 'family':
593ad841b2Smrg                fam = int(n[3])
603ad841b2Smrg            if vendor and fam and model:
613ad841b2Smrg                return "%s-%d-%X" % (vendor, fam, model), model
623ad841b2Smrg    return None, None
633ad841b2Smrg
643ad841b2Smrgdef find_event(eventurl, model):
653ad841b2Smrg    print >>sys.stderr, "Downloading", eventurl
663ad841b2Smrg    u = urllib2.urlopen(eventurl)
673ad841b2Smrg    events = json.loads(u.read())
683ad841b2Smrg    u.close()
693ad841b2Smrg
703ad841b2Smrg    found = 0
713ad841b2Smrg    for j in events:
723ad841b2Smrg        if j[u'EventName'] in target_events:
733ad841b2Smrg            event = "cpu/event=%s,umask=%s/" % (j[u'EventCode'], j[u'UMask'])
743ad841b2Smrg            if u'PEBS' in j and j[u'PEBS'] > 0:
753ad841b2Smrg                event += "p"
763ad841b2Smrg            if args.script:
773ad841b2Smrg                eventmap[event].append(model)
783ad841b2Smrg            else:
793ad841b2Smrg                print j[u'EventName'], "event for model", model, "is", event
803ad841b2Smrg            found += 1
813ad841b2Smrg    return found
823ad841b2Smrg
833ad841b2Smrgif not args.all:
843ad841b2Smrg    cpu, model = get_cpu_str()
853ad841b2Smrg    if not cpu:
863ad841b2Smrg        sys.exit("Unknown CPU type")
873ad841b2Smrg
883ad841b2Smrgurl = baseurl + "/mapfile.csv"
893ad841b2Smrgprint >>sys.stderr, "Downloading", url
903ad841b2Smrgu = urllib2.urlopen(url)
913ad841b2Smrgfound = 0
923ad841b2Smrgcpufound = 0
933ad841b2Smrgfor j in u:
943ad841b2Smrg    n = j.rstrip().split(',')
953ad841b2Smrg    if len(n) >= 4 and (args.all or n[0] == cpu) and n[3] == "core":
963ad841b2Smrg        if args.all:
973ad841b2Smrg            vendor, fam, model = n[0].split("-")
983ad841b2Smrg            model = int(model, 16)
993ad841b2Smrg        cpufound += 1
1003ad841b2Smrg        found += find_event(baseurl + n[2], model)
1013ad841b2Smrgu.close()
1023ad841b2Smrg
1033ad841b2Smrgif args.script:
1043ad841b2Smrg    print '''#!/bin/sh
1053ad841b2Smrg# Profile workload for gcc profile feedback (autofdo) using Linux perf.
1063ad841b2Smrg# Auto generated. To regenerate for new CPUs run
107*cef8759bSmrg# contrib/gen_autofdo_event.py --script --all in gcc source
1083ad841b2Smrg
1093ad841b2Smrg# usages:
1103ad841b2Smrg# gcc-auto-profile program             (profile program and children)
1113ad841b2Smrg# gcc-auto-profile -a sleep X          (profile all for X secs, may need root)
1123ad841b2Smrg# gcc-auto-profile -p PID sleep X      (profile PID)
1133ad841b2Smrg# gcc-auto-profile --kernel -a sleep X (profile kernel)
1143ad841b2Smrg# gcc-auto-profile --all -a sleep X    (profile kernel and user space)
1153ad841b2Smrg
1163ad841b2Smrg# Identify branches taken event for CPU.
1173ad841b2Smrg#
1183ad841b2Smrg
1193ad841b2SmrgFLAGS=u
1203ad841b2Smrg
1213ad841b2Smrgif [ "$1" = "--kernel" ] ; then
1223ad841b2Smrg  FLAGS=k
1233ad841b2Smrg  shift
1243ad841b2Smrgfi
1253ad841b2Smrgif [ "$1" = "--all" ] ; then
1263ad841b2Smrg  FLAGS=uk
1273ad841b2Smrg  shift
1283ad841b2Smrgfi
1293ad841b2Smrg
1303ad841b2Smrgif ! grep -q Intel /proc/cpuinfo ; then
1313ad841b2Smrg  echo >&2 "Only Intel CPUs supported"
1323ad841b2Smrg  exit 1
1333ad841b2Smrgfi
1343ad841b2Smrg
1353ad841b2Smrgif grep -q hypervisor /proc/cpuinfo ; then
1363ad841b2Smrg  echo >&2 "Warning: branch profiling may not be functional in VMs"
1373ad841b2Smrgfi
1383ad841b2Smrg
1393ad841b2Smrgcase `egrep -q "^cpu family\s*: 6" /proc/cpuinfo &&
1403ad841b2Smrg  egrep "^model\s*:" /proc/cpuinfo | head -n1` in'''
1413ad841b2Smrg    for event, mod in eventmap.iteritems():
1423ad841b2Smrg        for m in mod[:-1]:
1433ad841b2Smrg            print "model*:\ %s|\\" % m
1443ad841b2Smrg        print 'model*:\ %s) E="%s$FLAGS" ;;' % (mod[-1], event)
1453ad841b2Smrg    print '''*)
1463ad841b2Smrgecho >&2 "Unknown CPU. Run contrib/gen_autofdo_event.py --all --script to update script."
1473ad841b2Smrg	exit 1 ;;'''
1483ad841b2Smrg    print "esac"
1493ad841b2Smrg    print 'exec perf record -e $E -b "$@"'
1503ad841b2Smrg
1513ad841b2Smrgif cpufound == 0 and not args.all:
1523ad841b2Smrg    sys.exit('CPU %s not found' % cpu)
1533ad841b2Smrg
1543ad841b2Smrgif found == 0:
1553ad841b2Smrg    sys.exit('Branch event not found')
156