12
12
* of the License, or (at your option) any later version.
13
13
*
14
14
* Tai-e is distributed in the hope that it will be useful,but WITHOUT
15
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
+ * ANY WARRANTY; without even the implied warrant of MERCHANTABILITY
16
16
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
17
17
* Public License for more details.
18
18
*
25
25
import pascal .taie .analysis .dataflow .analysis .AbstractDataflowAnalysis ;
26
26
import pascal .taie .analysis .graph .cfg .CFG ;
27
27
import pascal .taie .config .AnalysisConfig ;
28
- import pascal .taie .ir .IR ;
29
- import pascal .taie .ir .exp .ArithmeticExp ;
30
- import pascal .taie .ir .exp .BinaryExp ;
31
- import pascal .taie .ir .exp .BitwiseExp ;
32
- import pascal .taie .ir .exp .ConditionExp ;
33
- import pascal .taie .ir .exp .Exp ;
34
- import pascal .taie .ir .exp .IntLiteral ;
35
- import pascal .taie .ir .exp .ShiftExp ;
36
- import pascal .taie .ir .exp .Var ;
28
+ import pascal .taie .ir .exp .*;
37
29
import pascal .taie .ir .stmt .DefinitionStmt ;
38
30
import pascal .taie .ir .stmt .Stmt ;
39
31
import pascal .taie .language .type .PrimitiveType ;
40
32
import pascal .taie .language .type .Type ;
41
- import pascal .taie .util .AnalysisException ;
42
33
43
34
public class ConstantPropagation extends
44
35
AbstractDataflowAnalysis <Stmt , CPFact > {
@@ -57,32 +48,57 @@ public boolean isForward() {
57
48
@ Override
58
49
public CPFact newBoundaryFact (CFG <Stmt > cfg ) {
59
50
// TODO - finish me
60
- return null ;
51
+ var fact = new CPFact ();
52
+ cfg .getIR ().getParams ().forEach (param -> {
53
+ if (canHoldInt (param ))
54
+ fact .update (param , Value .getNAC ());
55
+ });
56
+ return fact ;
61
57
}
62
58
63
59
@ Override
64
60
public CPFact newInitialFact () {
65
61
// TODO - finish me
66
- return null ;
62
+ return new CPFact () ;
67
63
}
68
64
69
65
@ Override
70
66
public void meetInto (CPFact fact , CPFact target ) {
71
67
// TODO - finish me
68
+ for (var key : fact .keySet ()) {
69
+ var value1 = fact .get (key );
70
+ var value2 = target .get (key );
71
+ target .update (key , meetValue (value1 , value2 ));
72
+ }
72
73
}
73
74
74
75
/**
75
76
* Meets two Values.
76
77
*/
77
78
public Value meetValue (Value v1 , Value v2 ) {
78
79
// TODO - finish me
79
- return null ;
80
+ if (v1 .isNAC () || v2 .isNAC ()) return Value .getNAC ();
81
+ if (v1 .isUndef () && v2 .isUndef ()) return Value .getUndef ();
82
+ if (v1 .isUndef () || v2 .isUndef ()) return v1 .isConstant () ?
83
+ Value .makeConstant (v1 .getConstant ()) : Value .makeConstant (v2 .getConstant ());
84
+ return v1 .getConstant () == v2 .getConstant () ?
85
+ Value .makeConstant (v1 .getConstant ()) : Value .getNAC ();
80
86
}
81
87
82
88
@ Override
83
89
public boolean transferNode (Stmt stmt , CPFact in , CPFact out ) {
84
90
// TODO - finish me
85
- return false ;
91
+ // make sure def can hold int
92
+ var oldOut = out .copy ();
93
+ out .clear (); out .copyFrom (in );
94
+ if (stmt instanceof DefinitionStmt <?,?>) {
95
+ var lv = ((DefinitionStmt <?, ?>) stmt ).getLValue ();
96
+ var rv = ((DefinitionStmt <?, ?>) stmt ).getRValue ();
97
+ if (lv == null || !canHoldInt ((Var ) lv )) return false ;
98
+ out .remove ((Var ) lv );
99
+ out .update ((Var ) lv , evaluate (rv , in ));
100
+ }
101
+ return !oldOut .equals (out );
86
102
}
87
103
88
104
/**
@@ -112,6 +128,86 @@ public static boolean canHoldInt(Var var) {
112
128
*/
113
129
public static Value evaluate (Exp exp , CPFact in ) {
114
130
// TODO - finish me
115
- return null ;
131
+ if (exp instanceof Var ) {
132
+ return in .get ((Var ) exp ).isConstant () ?
133
+ Value .makeConstant (in .get ((Var )exp ).getConstant ()) : in .get ((Var )exp );
134
+ }
135
+ if (exp instanceof IntLiteral ) return Value .makeConstant (((IntLiteral ) exp ).getValue ());
136
+ if (!(exp instanceof BinaryExp )) return Value .getNAC ();
137
+ var o1 = evaluate (((BinaryExp ) exp ).getOperand1 (), in );
138
+ var o2 = evaluate (((BinaryExp ) exp ).getOperand2 (), in );
139
+ if (o1 .isNAC () || o2 .isNAC ()) return Value .getNAC ();
140
+ if (o1 .isUndef () || o2 .isUndef ()) return Value .getUndef ();
141
+ if (exp instanceof BitwiseExp ) {
142
+ var op = ((BitwiseExp ) exp ).getOperator ();
143
+ switch (op ) {
144
+ case OR -> {
145
+ return Value .makeConstant (o1 .getConstant () | o2 .getConstant ());
146
+ }
147
+ case XOR -> {
148
+ return Value .makeConstant (o1 .getConstant () ^ o2 .getConstant ());
149
+ }
150
+ case AND -> {
151
+ return Value .makeConstant (o1 .getConstant () & o2 .getConstant ());
152
+ }
153
+ }
154
+ }
155
+ if (exp instanceof ArithmeticExp ) {
156
+ var op = ((ArithmeticExp ) exp ).getOperator ();
157
+ switch (op ) {
158
+ case ADD -> {
159
+ return Value .makeConstant (o1 .getConstant () + o2 .getConstant ());
160
+ }
161
+ case SUB -> {
162
+ return Value .makeConstant (o1 .getConstant () - o2 .getConstant ());
163
+ }
164
+ case MUL -> {
165
+ return Value .makeConstant (o1 .getConstant () * o2 .getConstant ());
166
+ }
167
+ case DIV -> {
168
+ if (o2 .getConstant () == 0 ) return Value .getUndef ();
169
+ return Value .makeConstant (o1 .getConstant () / o2 .getConstant ());
170
+ }
171
+ case REM -> {
172
+ if (o2 .getConstant () == 0 ) return Value .getUndef ();
173
+ return Value .makeConstant (o1 .getConstant () % o2 .getConstant ());
174
+ }
175
+ }
176
+ }
177
+ if (exp instanceof ConditionExp ) {
178
+ var op = ((ConditionExp ) exp ).getOperator ();
179
+ switch (op ) {
180
+ case EQ -> {
181
+ return Value .makeConstant (o1 .getConstant () == o2 .getConstant () ? 1 : 0 );
182
+ }
183
+ case GE -> {
184
+ return Value .makeConstant (o1 .getConstant () >= o2 .getConstant () ? 1 : 0 );
185
+ }
186
+ case GT -> {
187
+ return Value .makeConstant (o1 .getConstant () > o2 .getConstant () ? 1 : 0 );
188
+ }
189
+ case LE -> {
190
+ return Value .makeConstant (o1 .getConstant () <= o2 .getConstant () ? 1 : 0 );
191
+ }
192
+ case LT -> {
193
+ return Value .makeConstant (o1 .getConstant () < o2 .getConstant () ? 1 : 0 );
194
+ }
195
+ }
196
+ }
197
+ if (exp instanceof ShiftExp ) {
198
+ var op = ((ShiftExp ) exp ).getOperator ();
199
+ switch (op ) {
200
+ case SHL -> {
201
+ return Value .makeConstant (o1 .getConstant () << o2 .getConstant ());
202
+ }
203
+ case SHR -> {
204
+ return Value .makeConstant (o1 .getConstant () >> o2 .getConstant ());
205
+ }
206
+ case USHR -> {
207
+ return Value .makeConstant (o1 .getConstant () >>> o2 .getConstant ());
208
+ }
209
+ }
210
+ }
211
+ return Value .getUndef ();
116
212
}
117
213
}
0 commit comments