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 ;
37
- import pascal .taie .ir .stmt .DefinitionStmt ;
28
+ import pascal .taie .ir .exp .*;
38
29
import pascal .taie .ir .stmt .Stmt ;
39
30
import pascal .taie .language .type .PrimitiveType ;
40
31
import pascal .taie .language .type .Type ;
41
- import pascal .taie .util .AnalysisException ;
32
+
33
+ import java .util .List ;
42
34
43
35
public class ConstantPropagation extends
44
36
AbstractDataflowAnalysis <Stmt , CPFact > {
@@ -57,32 +49,102 @@ public boolean isForward() {
57
49
@ Override
58
50
public CPFact newBoundaryFact (CFG <Stmt > cfg ) {
59
51
// TODO - finish me
60
- return null ;
52
+ CPFact cpFact = new CPFact ();
53
+ List <Var > params = cfg .getIR ().getParams ();
54
+ params .forEach (x -> {
55
+ if (ConstantPropagation .canHoldInt (x )) {
56
+ cpFact .update (x , Value .getNAC ());
57
+ }
58
+ });
59
+ return cpFact ;
61
60
}
62
61
63
62
@ Override
64
63
public CPFact newInitialFact () {
65
64
// TODO - finish me
66
- return null ;
65
+ return new CPFact () ;
67
66
}
68
67
69
68
@ Override
70
69
public void meetInto (CPFact fact , CPFact target ) {
71
70
// TODO - finish me
71
+ fact .forEach ((k , v ) -> {
72
+ target .update (k , this .meetValue (target .get (k ), v ));
73
+ });
72
74
}
73
75
74
76
/**
75
77
* Meets two Values.
76
78
*/
77
79
public Value meetValue (Value v1 , Value v2 ) {
78
80
// TODO - finish me
79
- return null ;
81
+ if (v1 .isConstant () && v2 .isConstant ()) {
82
+ if (v1 .equals (v2 )) {
83
+ return v1 ;
84
+ } else {
85
+ return Value .getNAC ();
86
+ }
87
+ }
88
+
89
+ if (v1 .isConstant () && v2 .isUndef ()) {
90
+ return v1 ;
91
+ }
92
+
93
+ if (v2 .isConstant () && v1 .isUndef ()) {
94
+ return v2 ;
95
+ }
96
+
97
+ if (v1 .isNAC () || v2 .isNAC ()) {
98
+ return Value .getNAC ();
99
+ }
100
+
101
+ if (v1 .isUndef () && v2 .isUndef ()) {
102
+ return Value .getUndef ();
103
+ }
104
+
105
+ throw new RuntimeException (String .format ("Unexpected value of %s and %s" , v1 , v2 ));
80
106
}
81
107
82
108
@ Override
83
109
public boolean transferNode (Stmt stmt , CPFact in , CPFact out ) {
84
110
// TODO - finish me
85
- return false ;
111
+ CPFact oldFact = out .copy ();
112
+
113
+ in .forEach (out ::update );
114
+
115
+ stmt .getDef ().ifPresent (lValue -> {
116
+ if (lValue instanceof Var && ConstantPropagation .canHoldInt ((Var ) lValue )) {
117
+ stmt .getUses ().forEach (rValue -> {
118
+ if (rValue instanceof BinaryExp ) {
119
+ Var left = ((BinaryExp ) rValue ).getOperand1 ();
120
+ Var right = ((BinaryExp ) rValue ).getOperand2 ();
121
+
122
+ if (ConstantPropagation .canHoldInt (left ) && ConstantPropagation .canHoldInt (right )) {
123
+ if (rValue instanceof ArithmeticExp || rValue instanceof ConditionExp || rValue instanceof ShiftExp || rValue instanceof BitwiseExp ) {
124
+ out .update ((Var ) lValue , ConstantPropagation .evaluate (rValue , in ));
125
+ }
126
+ }
127
+ } else if (rValue instanceof Var ) {
128
+ if (ConstantPropagation .canHoldInt ((Var ) rValue )) {
129
+ // is int type
130
+ Var rValueVar = (Var ) rValue ;
131
+ if (rValueVar .isTempConst ()) {
132
+ out .update ((Var ) lValue , Value .makeConstant (((IntLiteral ) rValueVar .getTempConstValue ()).getValue ()));
133
+ } else {
134
+ out .update ((Var ) lValue , in .get (rValueVar ));
135
+ }
136
+ }
137
+ } else if (rValue instanceof IntLiteral ) {
138
+ out .update ((Var ) lValue , Value .makeConstant (((IntLiteral ) rValue ).getValue ()));
139
+ } else {
140
+ out .update ((Var ) lValue , Value .getNAC ());
141
+ }
142
+ });
143
+ }
144
+ });
145
+
146
+ // 不等于 -> 需要重新计算
147
+ return !oldFact .equals (out );
86
148
}
87
149
88
150
/**
@@ -103,6 +165,14 @@ public static boolean canHoldInt(Var var) {
103
165
return false ;
104
166
}
105
167
168
+ public static int booleanToInt (boolean bool ) {
169
+ if (bool ) {
170
+ return 1 ;
171
+ } else {
172
+ return 0 ;
173
+ }
174
+ }
175
+
106
176
/**
107
177
* Evaluates the {@link Value} of given expression.
108
178
*
@@ -112,6 +182,90 @@ public static boolean canHoldInt(Var var) {
112
182
*/
113
183
public static Value evaluate (Exp exp , CPFact in ) {
114
184
// TODO - finish me
115
- return null ;
185
+
186
+ if (exp instanceof BinaryExp ) {
187
+ Var left = ((BinaryExp ) exp ).getOperand1 ();
188
+ Var right = ((BinaryExp ) exp ).getOperand2 ();
189
+
190
+ if ((left .isTempConst () || in .get (left ).isConstant ()) && (right .isTempConst () || in .get (right ).isConstant ())) {
191
+ Integer leftLiteral = null ;
192
+ Integer rightLiteral = null ;
193
+
194
+ if (left .isTempConst ()) {
195
+ leftLiteral = ((IntLiteral ) left .getTempConstValue ()).getValue ();
196
+ } else {
197
+ leftLiteral = in .get (left ).getConstant ();
198
+ }
199
+
200
+ if (right .isTempConst ()) {
201
+ rightLiteral = ((IntLiteral ) right .getTempConstValue ()).getValue ();
202
+ } else {
203
+ rightLiteral = in .get (right ).getConstant ();
204
+ }
205
+ BinaryExp .Op op = ((BinaryExp ) exp ).getOperator ();
206
+ if (op .equals (ArithmeticExp .Op .ADD )) {
207
+ return Value .makeConstant (leftLiteral + rightLiteral );
208
+ } else if (op .equals (ArithmeticExp .Op .SUB )) {
209
+ return Value .makeConstant (leftLiteral - rightLiteral );
210
+ } else if (op .equals (ArithmeticExp .Op .MUL )) {
211
+ return Value .makeConstant (leftLiteral * rightLiteral );
212
+ } else if (op .equals (ArithmeticExp .Op .DIV )) {
213
+ if (rightLiteral == 0 ) {
214
+ return Value .getUndef ();
215
+ } else {
216
+ return Value .makeConstant (leftLiteral / rightLiteral );
217
+ }
218
+ } else if (op .equals (ArithmeticExp .Op .REM )) {
219
+ if (rightLiteral == 0 ) {
220
+ return Value .getUndef ();
221
+ } else {
222
+ return Value .makeConstant (leftLiteral % rightLiteral );
223
+ }
224
+ } else if (op .equals (ShiftExp .Op .SHL )) {
225
+ return Value .makeConstant (leftLiteral << rightLiteral );
226
+ } else if (op .equals (ShiftExp .Op .SHR )) {
227
+ return Value .makeConstant (leftLiteral >> rightLiteral );
228
+ } else if (op .equals (ShiftExp .Op .USHR )) {
229
+ return Value .makeConstant (leftLiteral >>> rightLiteral );
230
+ } else if (op .equals (BitwiseExp .Op .OR )) {
231
+ return Value .makeConstant (leftLiteral | rightLiteral );
232
+ } else if (op .equals (BitwiseExp .Op .AND )) {
233
+ return Value .makeConstant (leftLiteral & rightLiteral );
234
+ } else if (op .equals (BitwiseExp .Op .XOR )) {
235
+ return Value .makeConstant (leftLiteral ^ rightLiteral );
236
+ } else if (op .equals (ConditionExp .Op .EQ )) {
237
+ return Value .makeConstant (booleanToInt (leftLiteral .equals (rightLiteral )));
238
+ } else if (op .equals (ConditionExp .Op .NE )) {
239
+ return Value .makeConstant (booleanToInt (!leftLiteral .equals (rightLiteral )));
240
+ } else if (op .equals (ConditionExp .Op .GE )) {
241
+ return Value .makeConstant (booleanToInt (leftLiteral >= rightLiteral ));
242
+ } else if (op .equals (ConditionExp .Op .GT )) {
243
+ return Value .makeConstant (booleanToInt (leftLiteral > rightLiteral ));
244
+ } else if (op .equals (ConditionExp .Op .LE )) {
245
+ return Value .makeConstant (booleanToInt (leftLiteral <= rightLiteral ));
246
+ } else if (op .equals (ConditionExp .Op .LT )) {
247
+ return Value .makeConstant (booleanToInt (leftLiteral < rightLiteral ));
248
+ }
249
+ }
250
+
251
+ if (in .get (left ).isNAC () || in .get (right ).isNAC ()) {
252
+ if (right .isTempConst () || in .get (right ).isConstant ()) {
253
+ Integer rightLiteral = null ;
254
+
255
+ if (right .isTempConst ()) {
256
+ rightLiteral = ((IntLiteral ) right .getTempConstValue ()).getValue ();
257
+ } else {
258
+ rightLiteral = in .get (right ).getConstant ();
259
+ }
260
+ if (rightLiteral .equals (0 ) && (((BinaryExp ) exp ).getOperator ().equals (ArithmeticExp .Op .REM ) || ((BinaryExp ) exp ).getOperator ().equals (ArithmeticExp .Op .DIV ))) {
261
+ return Value .getUndef ();
262
+ }
263
+ }
264
+ return Value .getNAC ();
265
+ }
266
+
267
+ return Value .getUndef ();
268
+ }
269
+ throw new RuntimeException (exp + "is a expression that can't evaluate" );
116
270
}
117
271
}
0 commit comments