xref: /llvm-project/llvm/utils/pipeline.py (revision b71edfaa4ec3c998aadb35255ce2f60bba2940b0)
191d15aa0SMarkus Lavin# Automatically formatted with yapf (https://github.com/google/yapf)
291d15aa0SMarkus Lavin"""Utility functions for creating and manipulating LLVM 'opt' NPM pipeline objects."""
391d15aa0SMarkus Lavin
491d15aa0SMarkus Lavin
591d15aa0SMarkus Lavindef fromStr(pipeStr):
691d15aa0SMarkus Lavin    """Create pipeline object from string representation."""
791d15aa0SMarkus Lavin    stack = []
891d15aa0SMarkus Lavin    curr = []
9*b71edfaaSTobias Hieta    tok = ""
10*b71edfaaSTobias Hieta    kind = ""
1191d15aa0SMarkus Lavin    for c in pipeStr:
12*b71edfaaSTobias Hieta        if c == ",":
13*b71edfaaSTobias Hieta            if tok != "":
1491d15aa0SMarkus Lavin                curr.append([None, tok])
15*b71edfaaSTobias Hieta            tok = ""
16*b71edfaaSTobias Hieta        elif c == "(":
1791d15aa0SMarkus Lavin            stack.append([kind, curr])
1891d15aa0SMarkus Lavin            kind = tok
1991d15aa0SMarkus Lavin            curr = []
20*b71edfaaSTobias Hieta            tok = ""
21*b71edfaaSTobias Hieta        elif c == ")":
22*b71edfaaSTobias Hieta            if tok != "":
2391d15aa0SMarkus Lavin                curr.append([None, tok])
24*b71edfaaSTobias Hieta            tok = ""
2591d15aa0SMarkus Lavin            oldKind = kind
2691d15aa0SMarkus Lavin            oldCurr = curr
2791d15aa0SMarkus Lavin            [kind, curr] = stack.pop()
2891d15aa0SMarkus Lavin            curr.append([oldKind, oldCurr])
2991d15aa0SMarkus Lavin        else:
3091d15aa0SMarkus Lavin            tok += c
31*b71edfaaSTobias Hieta    if tok != "":
3291d15aa0SMarkus Lavin        curr.append([None, tok])
3391d15aa0SMarkus Lavin    return curr
3491d15aa0SMarkus Lavin
3591d15aa0SMarkus Lavin
3691d15aa0SMarkus Lavindef toStr(pipeObj):
3791d15aa0SMarkus Lavin    """Create string representation of pipeline object."""
38*b71edfaaSTobias Hieta    res = ""
3991d15aa0SMarkus Lavin    lastIdx = len(pipeObj) - 1
4091d15aa0SMarkus Lavin    for i, c in enumerate(pipeObj):
4191d15aa0SMarkus Lavin        if c[0]:
42*b71edfaaSTobias Hieta            res += c[0] + "("
4391d15aa0SMarkus Lavin            res += toStr(c[1])
44*b71edfaaSTobias Hieta            res += ")"
4591d15aa0SMarkus Lavin        else:
4691d15aa0SMarkus Lavin            res += c[1]
4791d15aa0SMarkus Lavin        if i != lastIdx:
48*b71edfaaSTobias Hieta            res += ","
4991d15aa0SMarkus Lavin    return res
5091d15aa0SMarkus Lavin
5191d15aa0SMarkus Lavin
5291d15aa0SMarkus Lavindef count(pipeObj):
5391d15aa0SMarkus Lavin    """Count number of passes (pass-managers excluded) in pipeline object."""
5491d15aa0SMarkus Lavin    cnt = 0
5591d15aa0SMarkus Lavin    for c in pipeObj:
5691d15aa0SMarkus Lavin        if c[0]:
5791d15aa0SMarkus Lavin            cnt += count(c[1])
5891d15aa0SMarkus Lavin        else:
5991d15aa0SMarkus Lavin            cnt += 1
6091d15aa0SMarkus Lavin    return cnt
6191d15aa0SMarkus Lavin
6291d15aa0SMarkus Lavin
6391d15aa0SMarkus Lavindef split(pipeObj, splitIndex):
6491d15aa0SMarkus Lavin    """Create two new pipeline objects by splitting pipeObj in two directly after pass with index splitIndex."""
65*b71edfaaSTobias Hieta
6691d15aa0SMarkus Lavin    def splitInt(src, splitIndex, dstA, dstB, idx):
6791d15aa0SMarkus Lavin        for s in src:
6891d15aa0SMarkus Lavin            if s[0]:
6991d15aa0SMarkus Lavin                dstA2 = []
7091d15aa0SMarkus Lavin                dstB2 = []
7191d15aa0SMarkus Lavin                idx = splitInt(s[1], splitIndex, dstA2, dstB2, idx)
7291d15aa0SMarkus Lavin                dstA.append([s[0], dstA2])
7391d15aa0SMarkus Lavin                dstB.append([s[0], dstB2])
7491d15aa0SMarkus Lavin            else:
7591d15aa0SMarkus Lavin                if idx <= splitIndex:
7691d15aa0SMarkus Lavin                    dstA.append([None, s[1]])
7791d15aa0SMarkus Lavin                else:
7891d15aa0SMarkus Lavin                    dstB.append([None, s[1]])
7991d15aa0SMarkus Lavin                idx += 1
8091d15aa0SMarkus Lavin        return idx
8191d15aa0SMarkus Lavin
8291d15aa0SMarkus Lavin    listA = []
8391d15aa0SMarkus Lavin    listB = []
8491d15aa0SMarkus Lavin    splitInt(pipeObj, splitIndex, listA, listB, 0)
8591d15aa0SMarkus Lavin    return [listA, listB]
8691d15aa0SMarkus Lavin
8791d15aa0SMarkus Lavin
8891d15aa0SMarkus Lavindef remove(pipeObj, removeIndex):
8991d15aa0SMarkus Lavin    """Create new pipeline object by removing pass with index removeIndex from pipeObj."""
90*b71edfaaSTobias Hieta
9191d15aa0SMarkus Lavin    def removeInt(src, removeIndex, dst, idx):
9291d15aa0SMarkus Lavin        for s in src:
9391d15aa0SMarkus Lavin            if s[0]:
9491d15aa0SMarkus Lavin                dst2 = []
9591d15aa0SMarkus Lavin                idx = removeInt(s[1], removeIndex, dst2, idx)
9691d15aa0SMarkus Lavin                dst.append([s[0], dst2])
9791d15aa0SMarkus Lavin            else:
9891d15aa0SMarkus Lavin                if idx != removeIndex:
9991d15aa0SMarkus Lavin                    dst.append([None, s[1]])
10091d15aa0SMarkus Lavin                idx += 1
10191d15aa0SMarkus Lavin        return idx
10291d15aa0SMarkus Lavin
10391d15aa0SMarkus Lavin    dst = []
10491d15aa0SMarkus Lavin    removeInt(pipeObj, removeIndex, dst, 0)
10591d15aa0SMarkus Lavin    return dst
10691d15aa0SMarkus Lavin
10791d15aa0SMarkus Lavin
10891d15aa0SMarkus Lavindef copy(srcPipeObj):
10991d15aa0SMarkus Lavin    """Create copy of pipeline object srcPipeObj."""
110*b71edfaaSTobias Hieta
11191d15aa0SMarkus Lavin    def copyInt(dst, src):
11291d15aa0SMarkus Lavin        for s in src:
11391d15aa0SMarkus Lavin            if s[0]:
11491d15aa0SMarkus Lavin                dst2 = []
11591d15aa0SMarkus Lavin                copyInt(dst2, s[1])
11691d15aa0SMarkus Lavin                dst.append([s[0], dst2])
11791d15aa0SMarkus Lavin            else:
11891d15aa0SMarkus Lavin                dst.append([None, s[1]])
11991d15aa0SMarkus Lavin
12091d15aa0SMarkus Lavin    dstPipeObj = []
12191d15aa0SMarkus Lavin    copyInt(dstPipeObj, srcPipeObj)
12291d15aa0SMarkus Lavin    return dstPipeObj
12391d15aa0SMarkus Lavin
12491d15aa0SMarkus Lavin
12591d15aa0SMarkus Lavindef prune(srcPipeObj):
12691d15aa0SMarkus Lavin    """Create new pipeline object by removing empty pass-managers (those with count = 0) from srcPipeObj."""
127*b71edfaaSTobias Hieta
12891d15aa0SMarkus Lavin    def pruneInt(dst, src):
12991d15aa0SMarkus Lavin        for s in src:
13091d15aa0SMarkus Lavin            if s[0]:
13191d15aa0SMarkus Lavin                if count(s[1]):
13291d15aa0SMarkus Lavin                    dst2 = []
13391d15aa0SMarkus Lavin                    pruneInt(dst2, s[1])
13491d15aa0SMarkus Lavin                    dst.append([s[0], dst2])
13591d15aa0SMarkus Lavin            else:
13691d15aa0SMarkus Lavin                dst.append([None, s[1]])
13791d15aa0SMarkus Lavin
13891d15aa0SMarkus Lavin    dstPipeObj = []
13991d15aa0SMarkus Lavin    pruneInt(dstPipeObj, srcPipeObj)
14091d15aa0SMarkus Lavin    return dstPipeObj
14191d15aa0SMarkus Lavin
14291d15aa0SMarkus Lavin
14391d15aa0SMarkus Lavinif __name__ == "__main__":
14491d15aa0SMarkus Lavin    import unittest
14591d15aa0SMarkus Lavin
14691d15aa0SMarkus Lavin    class Test(unittest.TestCase):
14791d15aa0SMarkus Lavin        def test_0(self):
148*b71edfaaSTobias Hieta            pipeStr = "a,b,A(c,B(d,e),f),g"
14991d15aa0SMarkus Lavin            pipeObj = fromStr(pipeStr)
15091d15aa0SMarkus Lavin
15191d15aa0SMarkus Lavin            self.assertEqual(7, count(pipeObj))
15291d15aa0SMarkus Lavin
15391d15aa0SMarkus Lavin            self.assertEqual(pipeObj, pipeObj)
15491d15aa0SMarkus Lavin            self.assertEqual(pipeObj, prune(pipeObj))
15591d15aa0SMarkus Lavin            self.assertEqual(pipeObj, copy(pipeObj))
15691d15aa0SMarkus Lavin
15791d15aa0SMarkus Lavin            self.assertEqual(pipeStr, toStr(pipeObj))
15891d15aa0SMarkus Lavin            self.assertEqual(pipeStr, toStr(prune(pipeObj)))
15991d15aa0SMarkus Lavin            self.assertEqual(pipeStr, toStr(copy(pipeObj)))
16091d15aa0SMarkus Lavin
16191d15aa0SMarkus Lavin            [pipeObjA, pipeObjB] = split(pipeObj, 3)
162*b71edfaaSTobias Hieta            self.assertEqual("a,b,A(c,B(d))", toStr(pipeObjA))
163*b71edfaaSTobias Hieta            self.assertEqual("A(B(e),f),g", toStr(pipeObjB))
16491d15aa0SMarkus Lavin
165*b71edfaaSTobias Hieta            self.assertEqual("b,A(c,B(d,e),f),g", toStr(remove(pipeObj, 0)))
166*b71edfaaSTobias Hieta            self.assertEqual("a,b,A(c,B(d,e),f)", toStr(remove(pipeObj, 6)))
16791d15aa0SMarkus Lavin
16891d15aa0SMarkus Lavin            pipeObjC = remove(pipeObj, 4)
169*b71edfaaSTobias Hieta            self.assertEqual("a,b,A(c,B(d),f),g", toStr(pipeObjC))
17091d15aa0SMarkus Lavin            pipeObjC = remove(pipeObjC, 3)
171*b71edfaaSTobias Hieta            self.assertEqual("a,b,A(c,B(),f),g", toStr(pipeObjC))
17291d15aa0SMarkus Lavin            pipeObjC = prune(pipeObjC)
173*b71edfaaSTobias Hieta            self.assertEqual("a,b,A(c,f),g", toStr(pipeObjC))
17491d15aa0SMarkus Lavin
17591d15aa0SMarkus Lavin    unittest.main()
17691d15aa0SMarkus Lavin    exit(0)
177