source: proto/Compiler/pablo_optimizer.py @ 4619

Last change on this file since 4619 was 3571, checked in by nmedfort, 6 years ago

start of error rewriting work. some clean up done to pablo.py; a few classes in it were moved to pablo_util.py.

File size: 4.4 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4import ast
5import mkast
6from carryInfo import *
7       
8# look into how viable it would be to transform the AST into a form thats readable by "Espresso"
9# and allow it to minimize the expressions then transform it back into AST form?
10       
11class Optimize(ast.NodeTransformer):
12   
13    def __init__(self):
14        self.modified = True
15   
16    def xfrm(self, root):       
17        while self.modified:
18            self.modified = False
19            self.generic_visit(root)
20           
21    def visit_If(self, node):
22        self.generic_visit(node)
23        return self.eliminateUnnecessaryTest(node)
24       
25    def visit_While(self, node):
26        self.generic_visit(node)       
27        return self.eliminateUnnecessaryTest(node)
28       
29    # transform if/while any/all 0 or if any 1 blocks to return nothing or the node.body respectively
30    def eliminateUnnecessaryTest(self, node):
31        test = self.functionNameOf(node.test)
32        if test == 'bitblock::any' or test == 'bitblock::all':
33            if self.isConstant0(node.test.args[0]):
34                return None
35            elif self.isConstant1(node.test.args[0]):
36                return node.body
37        return node
38       
39    def visit_Assign(self, node):
40        self.generic_visit(node)
41        # if we're assigning a value to itself, eliminate the node from the tree
42        if node.targets[0] == node.value:
43            return None
44        return node
45   
46    def visit_Call(self, node):
47        node = self.generic_visit(node)
48        name = self.functionNameOf(node)
49        if name == 'simd_or':
50            return self.simplify_or(node, node.args[0], node.args[1])
51        elif name == 'simd_and':
52            return self.simplify_and(node, node.args[0], node.args[1]) 
53        elif name == 'simd_andc':
54            return self.simplify_andc(node, node.args[0], node.args[1]) 
55        elif name == 'simd_not':
56            return self.simplify_not(node, node.args[0]) 
57        return node
58                 
59    def functionNameOf(self, x):     
60        if isinstance(x, ast.Call) and isinstance(x.func, ast.Name):
61            return x.func.id
62        return None
63                 
64    def isConstant0(self, x):
65        return self.functionNameOf(x) == 'simd<1>::constant<0>'
66
67    def isConstant1(self, x):
68        return self.functionNameOf(x) == 'simd<1>::constant<1>'
69               
70    def simplify_or(self, node, x, y):
71        # apply the annihilator, identity, and idempotence and absorption laws for x | y           
72        if self.isConstant0(x):
73            self.modified = True
74            return y
75        elif self.isConstant0(y) or x == y:
76            self.modified = True
77            return x
78        elif self.isConstant1(x) or self.isConstant1(y):
79            self.modified = True
80            return mkast.call('simd<1>::constant<1>', [])
81        return node       
82       
83    def simplify_and(self, node, x, y):
84        # apply the annihilator, identity, and idempotence and absorption laws for x & y   
85        if self.isConstant1(x):
86            self.modified = True
87            return y
88        elif self.isConstant1(y) or x == y:
89            self.modified = True
90            return x
91        elif self.isConstant0(x) or self.isConstant0(y):
92            self.modified = True
93            return mkast.call('simd<1>::constant<0>', [])
94        return node           
95         
96    def simplify_andc(self, node, x, y):
97        # apply the annihilator, identity, and idempotence and absorption laws for x & ~y   
98        if self.isConstant1(x):
99            self.modified = True
100            return mkast.call('simd_not', [y])           
101        elif self.isConstant0(x) or self.isConstant1(y) or x == y:
102            self.modified = True
103            return mkast.call('simd<1>::constant<0>', [])       
104        elif self.functionNameOf(y) == 'simd_not':
105            self.modified = True
106            return mkast.call('simd_and', x, y.args[0])
107        return node
108       
109    def simplify_not(self, node, x):
110        # apply the annihilator, identity, and idempotence and absorption laws for x & y   
111        if self.isConstant0(x):
112            self.modified = True
113            return mkast.call('simd<1>::constant<1>', [])
114        elif self.isConstant1(x):
115            self.modified = True
116            return mkast.call('simd<1>::constant<0>', [])
117        elif self.functionNameOf(x) == 'simd_not':
118            self.modified = True
119            return x.args[0]
120        return node         
Note: See TracBrowser for help on using the repository browser.