xref: /aosp_15_r20/external/llvm/examples/Kaleidoscope/MCJIT/complete/genk-timing.py (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker#!/usr/bin/env python
2*9880d681SAndroid Build Coastguard Worker
3*9880d681SAndroid Build Coastguard Workerimport sys
4*9880d681SAndroid Build Coastguard Workerimport random
5*9880d681SAndroid Build Coastguard Worker
6*9880d681SAndroid Build Coastguard Workerclass TimingScriptGenerator:
7*9880d681SAndroid Build Coastguard Worker    """Used to generate a bash script which will invoke the toy and time it"""
8*9880d681SAndroid Build Coastguard Worker    def __init__(self, scriptname, outputname):
9*9880d681SAndroid Build Coastguard Worker        self.timeFile = outputname
10*9880d681SAndroid Build Coastguard Worker        self.shfile = open(scriptname, 'w')
11*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"\" > %s\n" % self.timeFile)
12*9880d681SAndroid Build Coastguard Worker
13*9880d681SAndroid Build Coastguard Worker    def writeTimingCall(self, filename, numFuncs, funcsCalled, totalCalls):
14*9880d681SAndroid Build Coastguard Worker        """Echo some comments and invoke both versions of toy"""
15*9880d681SAndroid Build Coastguard Worker        rootname = filename
16*9880d681SAndroid Build Coastguard Worker        if '.' in filename:
17*9880d681SAndroid Build Coastguard Worker            rootname = filename[:filename.rfind('.')]
18*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"%s: Calls %d of %d functions, %d total\" >> %s\n" % (filename, funcsCalled, numFuncs, totalCalls, self.timeFile))
19*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
20*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"With MCJIT (original)\" >> %s\n" % self.timeFile)
21*9880d681SAndroid Build Coastguard Worker        self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
22*9880d681SAndroid Build Coastguard Worker        self.shfile.write(" -o %s -a " % self.timeFile)
23*9880d681SAndroid Build Coastguard Worker        self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=false < %s > %s-mcjit.out 2> %s-mcjit.err\n" % (filename, rootname, rootname))
24*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
25*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"With MCJIT (lazy)\" >> %s\n" % self.timeFile)
26*9880d681SAndroid Build Coastguard Worker        self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
27*9880d681SAndroid Build Coastguard Worker        self.shfile.write(" -o %s -a " % self.timeFile)
28*9880d681SAndroid Build Coastguard Worker        self.shfile.write("./toy -suppress-prompts -use-mcjit=true -enable-lazy-compilation=true < %s > %s-mcjit-lazy.out 2> %s-mcjit-lazy.err\n" % (filename, rootname, rootname))
29*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
30*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"With JIT\" >> %s\n" % self.timeFile)
31*9880d681SAndroid Build Coastguard Worker        self.shfile.write("/usr/bin/time -f \"Command %C\\n\\tuser time: %U s\\n\\tsytem time: %S s\\n\\tmax set: %M kb\"")
32*9880d681SAndroid Build Coastguard Worker        self.shfile.write(" -o %s -a " % self.timeFile)
33*9880d681SAndroid Build Coastguard Worker        self.shfile.write("./toy -suppress-prompts -use-mcjit=false < %s > %s-jit.out 2> %s-jit.err\n" % (filename, rootname, rootname))
34*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
35*9880d681SAndroid Build Coastguard Worker        self.shfile.write("echo \"\" >> %s\n" % self.timeFile)
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Workerclass KScriptGenerator:
38*9880d681SAndroid Build Coastguard Worker    """Used to generate random Kaleidoscope code"""
39*9880d681SAndroid Build Coastguard Worker    def __init__(self, filename):
40*9880d681SAndroid Build Coastguard Worker        self.kfile = open(filename, 'w')
41*9880d681SAndroid Build Coastguard Worker        self.nextFuncNum = 1
42*9880d681SAndroid Build Coastguard Worker        self.lastFuncNum = None
43*9880d681SAndroid Build Coastguard Worker        self.callWeighting = 0.1
44*9880d681SAndroid Build Coastguard Worker        # A mapping of calls within functions with no duplicates
45*9880d681SAndroid Build Coastguard Worker        self.calledFunctionTable = {}
46*9880d681SAndroid Build Coastguard Worker        # A list of function calls which will actually be executed
47*9880d681SAndroid Build Coastguard Worker        self.calledFunctions = []
48*9880d681SAndroid Build Coastguard Worker        # A comprehensive mapping of calls within functions
49*9880d681SAndroid Build Coastguard Worker        # used for computing the total number of calls
50*9880d681SAndroid Build Coastguard Worker        self.comprehensiveCalledFunctionTable = {}
51*9880d681SAndroid Build Coastguard Worker        self.totalCallsExecuted = 0
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker    def updateTotalCallCount(self, callee):
54*9880d681SAndroid Build Coastguard Worker        # Count this call
55*9880d681SAndroid Build Coastguard Worker        self.totalCallsExecuted += 1
56*9880d681SAndroid Build Coastguard Worker        # Then count all the functions it calls
57*9880d681SAndroid Build Coastguard Worker        if callee in self.comprehensiveCalledFunctionTable:
58*9880d681SAndroid Build Coastguard Worker            for child in self.comprehensiveCalledFunctionTable[callee]:
59*9880d681SAndroid Build Coastguard Worker                self.updateTotalCallCount(child)
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker    def updateFunctionCallMap(self, caller, callee):
62*9880d681SAndroid Build Coastguard Worker        """Maintains a map of functions that are called from other functions"""
63*9880d681SAndroid Build Coastguard Worker        if not caller in self.calledFunctionTable:
64*9880d681SAndroid Build Coastguard Worker            self.calledFunctionTable[caller] = []
65*9880d681SAndroid Build Coastguard Worker        if not callee in self.calledFunctionTable[caller]:
66*9880d681SAndroid Build Coastguard Worker            self.calledFunctionTable[caller].append(callee)
67*9880d681SAndroid Build Coastguard Worker        if not caller in self.comprehensiveCalledFunctionTable:
68*9880d681SAndroid Build Coastguard Worker            self.comprehensiveCalledFunctionTable[caller] = []
69*9880d681SAndroid Build Coastguard Worker        self.comprehensiveCalledFunctionTable[caller].append(callee)
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker    def updateCalledFunctionList(self, callee):
72*9880d681SAndroid Build Coastguard Worker        """Maintains a list of functions that will actually be called"""
73*9880d681SAndroid Build Coastguard Worker        # Update the total call count
74*9880d681SAndroid Build Coastguard Worker        self.updateTotalCallCount(callee)
75*9880d681SAndroid Build Coastguard Worker        # If this function is already in the list, don't do anything else
76*9880d681SAndroid Build Coastguard Worker        if callee in self.calledFunctions:
77*9880d681SAndroid Build Coastguard Worker            return
78*9880d681SAndroid Build Coastguard Worker        # Add this function to the list of those that will be called.
79*9880d681SAndroid Build Coastguard Worker        self.calledFunctions.append(callee)
80*9880d681SAndroid Build Coastguard Worker        # If this function calls other functions, add them too
81*9880d681SAndroid Build Coastguard Worker        if callee in self.calledFunctionTable:
82*9880d681SAndroid Build Coastguard Worker            for subCallee in self.calledFunctionTable[callee]:
83*9880d681SAndroid Build Coastguard Worker                self.updateCalledFunctionList(subCallee)
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker    def setCallWeighting(self, weight):
86*9880d681SAndroid Build Coastguard Worker        """ Sets the probably of generating a function call"""
87*9880d681SAndroid Build Coastguard Worker        self.callWeighting = weight
88*9880d681SAndroid Build Coastguard Worker
89*9880d681SAndroid Build Coastguard Worker    def writeln(self, line):
90*9880d681SAndroid Build Coastguard Worker        self.kfile.write(line + '\n')
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker    def writeComment(self, comment):
93*9880d681SAndroid Build Coastguard Worker        self.writeln('# ' + comment)
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker    def writeEmptyLine(self):
96*9880d681SAndroid Build Coastguard Worker        self.writeln("")
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker    def writePredefinedFunctions(self):
99*9880d681SAndroid Build Coastguard Worker        self.writeComment("Define ':' for sequencing: as a low-precedence operator that ignores operands")
100*9880d681SAndroid Build Coastguard Worker        self.writeComment("and just returns the RHS.")
101*9880d681SAndroid Build Coastguard Worker        self.writeln("def binary : 1 (x y) y;")
102*9880d681SAndroid Build Coastguard Worker        self.writeEmptyLine()
103*9880d681SAndroid Build Coastguard Worker        self.writeComment("Helper functions defined within toy")
104*9880d681SAndroid Build Coastguard Worker        self.writeln("extern putchard(x);")
105*9880d681SAndroid Build Coastguard Worker        self.writeln("extern printd(d);")
106*9880d681SAndroid Build Coastguard Worker        self.writeln("extern printlf();")
107*9880d681SAndroid Build Coastguard Worker        self.writeEmptyLine()
108*9880d681SAndroid Build Coastguard Worker        self.writeComment("Print the result of a function call")
109*9880d681SAndroid Build Coastguard Worker        self.writeln("def printresult(N Result)")
110*9880d681SAndroid Build Coastguard Worker        self.writeln("  # 'result('")
111*9880d681SAndroid Build Coastguard Worker        self.writeln("  putchard(114) : putchard(101) : putchard(115) : putchard(117) : putchard(108) : putchard(116) : putchard(40) :")
112*9880d681SAndroid Build Coastguard Worker        self.writeln("  printd(N) :");
113*9880d681SAndroid Build Coastguard Worker        self.writeln("  # ') = '")
114*9880d681SAndroid Build Coastguard Worker        self.writeln("  putchard(41) : putchard(32) : putchard(61) : putchard(32) :")
115*9880d681SAndroid Build Coastguard Worker        self.writeln("  printd(Result) :");
116*9880d681SAndroid Build Coastguard Worker        self.writeln("  printlf();")
117*9880d681SAndroid Build Coastguard Worker        self.writeEmptyLine()
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker    def writeRandomOperation(self, LValue, LHS, RHS):
120*9880d681SAndroid Build Coastguard Worker        shouldCallFunc = (self.lastFuncNum > 2 and random.random() < self.callWeighting)
121*9880d681SAndroid Build Coastguard Worker        if shouldCallFunc:
122*9880d681SAndroid Build Coastguard Worker            funcToCall = random.randrange(1, self.lastFuncNum - 1)
123*9880d681SAndroid Build Coastguard Worker            self.updateFunctionCallMap(self.lastFuncNum, funcToCall)
124*9880d681SAndroid Build Coastguard Worker            self.writeln("  %s = func%d(%s, %s) :" % (LValue, funcToCall, LHS, RHS))
125*9880d681SAndroid Build Coastguard Worker        else:
126*9880d681SAndroid Build Coastguard Worker            possibleOperations = ["+", "-", "*", "/"]
127*9880d681SAndroid Build Coastguard Worker            operation = random.choice(possibleOperations)
128*9880d681SAndroid Build Coastguard Worker            if operation == "-":
129*9880d681SAndroid Build Coastguard Worker                # Don't let our intermediate value become zero
130*9880d681SAndroid Build Coastguard Worker                # This is complicated by the fact that '<' is our only comparison operator
131*9880d681SAndroid Build Coastguard Worker                self.writeln("  if %s < %s then" % (LHS, RHS))
132*9880d681SAndroid Build Coastguard Worker                self.writeln("    %s = %s %s %s" % (LValue, LHS, operation, RHS))
133*9880d681SAndroid Build Coastguard Worker                self.writeln("  else if %s < %s then" % (RHS, LHS))
134*9880d681SAndroid Build Coastguard Worker                self.writeln("    %s = %s %s %s" % (LValue, LHS, operation, RHS))
135*9880d681SAndroid Build Coastguard Worker                self.writeln("  else")
136*9880d681SAndroid Build Coastguard Worker                self.writeln("    %s = %s %s %f :" % (LValue, LHS, operation, random.uniform(1, 100)))
137*9880d681SAndroid Build Coastguard Worker            else:
138*9880d681SAndroid Build Coastguard Worker                self.writeln("  %s = %s %s %s :" % (LValue, LHS, operation, RHS))
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker    def getNextFuncNum(self):
141*9880d681SAndroid Build Coastguard Worker        result = self.nextFuncNum
142*9880d681SAndroid Build Coastguard Worker        self.nextFuncNum += 1
143*9880d681SAndroid Build Coastguard Worker        self.lastFuncNum = result
144*9880d681SAndroid Build Coastguard Worker        return result
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker    def writeFunction(self, elements):
147*9880d681SAndroid Build Coastguard Worker        funcNum = self.getNextFuncNum()
148*9880d681SAndroid Build Coastguard Worker        self.writeComment("Auto-generated function number %d" % funcNum)
149*9880d681SAndroid Build Coastguard Worker        self.writeln("def func%d(X Y)" % funcNum)
150*9880d681SAndroid Build Coastguard Worker        self.writeln("  var temp1 = X,")
151*9880d681SAndroid Build Coastguard Worker        self.writeln("      temp2 = Y,")
152*9880d681SAndroid Build Coastguard Worker        self.writeln("      temp3 in")
153*9880d681SAndroid Build Coastguard Worker        # Initialize the variable names to be rotated
154*9880d681SAndroid Build Coastguard Worker        first = "temp3"
155*9880d681SAndroid Build Coastguard Worker        second = "temp1"
156*9880d681SAndroid Build Coastguard Worker        third = "temp2"
157*9880d681SAndroid Build Coastguard Worker        # Write some random operations
158*9880d681SAndroid Build Coastguard Worker        for i in range(elements):
159*9880d681SAndroid Build Coastguard Worker            self.writeRandomOperation(first, second, third)
160*9880d681SAndroid Build Coastguard Worker            # Rotate the variables
161*9880d681SAndroid Build Coastguard Worker            temp = first
162*9880d681SAndroid Build Coastguard Worker            first = second
163*9880d681SAndroid Build Coastguard Worker            second = third
164*9880d681SAndroid Build Coastguard Worker            third = temp
165*9880d681SAndroid Build Coastguard Worker        self.writeln("  " + third + ";")
166*9880d681SAndroid Build Coastguard Worker        self.writeEmptyLine()
167*9880d681SAndroid Build Coastguard Worker
168*9880d681SAndroid Build Coastguard Worker    def writeFunctionCall(self):
169*9880d681SAndroid Build Coastguard Worker        self.writeComment("Call the last function")
170*9880d681SAndroid Build Coastguard Worker        arg1 = random.uniform(1, 100)
171*9880d681SAndroid Build Coastguard Worker        arg2 = random.uniform(1, 100)
172*9880d681SAndroid Build Coastguard Worker        self.writeln("printresult(%d, func%d(%f, %f) )" % (self.lastFuncNum, self.lastFuncNum, arg1, arg2))
173*9880d681SAndroid Build Coastguard Worker        self.writeEmptyLine()
174*9880d681SAndroid Build Coastguard Worker        self.updateCalledFunctionList(self.lastFuncNum)
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker    def writeFinalFunctionCounts(self):
177*9880d681SAndroid Build Coastguard Worker        self.writeComment("Called %d of %d functions" % (len(self.calledFunctions), self.lastFuncNum))
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Workerdef generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript):
180*9880d681SAndroid Build Coastguard Worker    """ Generate a random Kaleidoscope script based on the given parameters """
181*9880d681SAndroid Build Coastguard Worker    print "Generating " + filename
182*9880d681SAndroid Build Coastguard Worker    print("  %d functions, %d elements per function, %d functions between execution" %
183*9880d681SAndroid Build Coastguard Worker          (numFuncs, elementsPerFunc, funcsBetweenExec))
184*9880d681SAndroid Build Coastguard Worker    print("  Call weighting = %f" % callWeighting)
185*9880d681SAndroid Build Coastguard Worker    script = KScriptGenerator(filename)
186*9880d681SAndroid Build Coastguard Worker    script.setCallWeighting(callWeighting)
187*9880d681SAndroid Build Coastguard Worker    script.writeComment("===========================================================================")
188*9880d681SAndroid Build Coastguard Worker    script.writeComment("Auto-generated script")
189*9880d681SAndroid Build Coastguard Worker    script.writeComment("  %d functions, %d elements per function, %d functions between execution"
190*9880d681SAndroid Build Coastguard Worker                         % (numFuncs, elementsPerFunc, funcsBetweenExec))
191*9880d681SAndroid Build Coastguard Worker    script.writeComment("  call weighting = %f" % callWeighting)
192*9880d681SAndroid Build Coastguard Worker    script.writeComment("===========================================================================")
193*9880d681SAndroid Build Coastguard Worker    script.writeEmptyLine()
194*9880d681SAndroid Build Coastguard Worker    script.writePredefinedFunctions()
195*9880d681SAndroid Build Coastguard Worker    funcsSinceLastExec = 0
196*9880d681SAndroid Build Coastguard Worker    for i in range(numFuncs):
197*9880d681SAndroid Build Coastguard Worker        script.writeFunction(elementsPerFunc)
198*9880d681SAndroid Build Coastguard Worker        funcsSinceLastExec += 1
199*9880d681SAndroid Build Coastguard Worker        if funcsSinceLastExec == funcsBetweenExec:
200*9880d681SAndroid Build Coastguard Worker            script.writeFunctionCall()
201*9880d681SAndroid Build Coastguard Worker            funcsSinceLastExec = 0
202*9880d681SAndroid Build Coastguard Worker    # Always end with a function call
203*9880d681SAndroid Build Coastguard Worker    if funcsSinceLastExec > 0:
204*9880d681SAndroid Build Coastguard Worker        script.writeFunctionCall()
205*9880d681SAndroid Build Coastguard Worker    script.writeEmptyLine()
206*9880d681SAndroid Build Coastguard Worker    script.writeFinalFunctionCounts()
207*9880d681SAndroid Build Coastguard Worker    funcsCalled = len(script.calledFunctions)
208*9880d681SAndroid Build Coastguard Worker    print "  Called %d of %d functions, %d total" % (funcsCalled, numFuncs, script.totalCallsExecuted)
209*9880d681SAndroid Build Coastguard Worker    timingScript.writeTimingCall(filename, numFuncs, funcsCalled, script.totalCallsExecuted)
210*9880d681SAndroid Build Coastguard Worker
211*9880d681SAndroid Build Coastguard Worker# Execution begins here
212*9880d681SAndroid Build Coastguard Workerrandom.seed()
213*9880d681SAndroid Build Coastguard Worker
214*9880d681SAndroid Build Coastguard WorkertimingScript = TimingScriptGenerator("time-toy.sh", "timing-data.txt")
215*9880d681SAndroid Build Coastguard Worker
216*9880d681SAndroid Build Coastguard WorkerdataSets = [(5000, 3,  50, 0.50), (5000, 10, 100, 0.10), (5000, 10, 5, 0.10), (5000, 10, 1, 0.0),
217*9880d681SAndroid Build Coastguard Worker            (1000, 3,  10, 0.50), (1000, 10, 100, 0.10), (1000, 10, 5, 0.10), (1000, 10, 1, 0.0),
218*9880d681SAndroid Build Coastguard Worker            ( 200, 3,   2, 0.50), ( 200, 10,  40, 0.10), ( 200, 10, 2, 0.10), ( 200, 10, 1, 0.0)]
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker# Generate the code
221*9880d681SAndroid Build Coastguard Workerfor (numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting) in dataSets:
222*9880d681SAndroid Build Coastguard Worker    filename = "test-%d-%d-%d-%d.k" % (numFuncs, elementsPerFunc, funcsBetweenExec, int(callWeighting * 100))
223*9880d681SAndroid Build Coastguard Worker    generateKScript(filename, numFuncs, elementsPerFunc, funcsBetweenExec, callWeighting, timingScript)
224*9880d681SAndroid Build Coastguard Workerprint "All done!"
225