23
23
package pascal .taie .analysis .dataflow .analysis .constprop ;
24
24
25
25
import pascal .taie .analysis .dataflow .analysis .AbstractDataflowAnalysis ;
26
+ import pascal .taie .analysis .dataflow .fact .MapFact ;
26
27
import pascal .taie .analysis .graph .cfg .CFG ;
27
28
import pascal .taie .config .AnalysisConfig ;
28
29
import pascal .taie .ir .IR ;
40
41
import pascal .taie .language .type .Type ;
41
42
import pascal .taie .util .AnalysisException ;
42
43
44
+ import java .util .HashMap ;
45
+ import java .util .HashSet ;
46
+ import java .util .Map ;
47
+
43
48
public class ConstantPropagation extends
44
49
AbstractDataflowAnalysis <Stmt , CPFact > {
45
50
@@ -57,32 +62,65 @@ public boolean isForward() {
57
62
@ Override
58
63
public CPFact newBoundaryFact (CFG <Stmt > cfg ) {
59
64
// TODO - finish me
60
- return null ;
65
+ CPFact cpFact = new CPFact ();
66
+ for (Var param : cfg .getIR ().getParams () ){
67
+ if (canHoldInt (param )){
68
+ cpFact .update (param , Value .getNAC ());
69
+ // Actually, absence means "UNDEF", i.e. TOP.
70
+ }
71
+ }
72
+ return cpFact ;
61
73
}
62
74
63
75
@ Override
64
76
public CPFact newInitialFact () {
65
77
// TODO - finish me
66
- return null ;
78
+ return new CPFact () ;
67
79
}
68
80
69
81
@ Override
70
82
public void meetInto (CPFact fact , CPFact target ) {
71
83
// TODO - finish me
84
+ fact .forEach ((Var var , Value value ) -> {
85
+ target .update (var , meetValue (target .get (var ), value ));
86
+ });
72
87
}
73
88
74
89
/**
75
90
* Meets two Values.
76
91
*/
77
92
public Value meetValue (Value v1 , Value v2 ) {
78
93
// TODO - finish me
79
- return null ;
94
+ if (v1 .isNAC () || v2 .isNAC ()){
95
+ return Value .getNAC ();
96
+ }
97
+ if (v1 .isUndef ()) return v2 ;
98
+ if (v2 .isUndef ()) return v1 ;
99
+ if (v1 .getConstant () == v2 .getConstant ()){
100
+ return v1 ;
101
+ } else {
102
+ return Value .getNAC ();
103
+ }
80
104
}
81
105
82
106
@ Override
83
107
public boolean transferNode (Stmt stmt , CPFact in , CPFact out ) {
84
108
// TODO - finish me
85
- return false ;
109
+ var gen = stmt .getDef ();
110
+ CPFact old_out = out .copy ();
111
+ out .copyFrom (in );
112
+ if (gen .isPresent () && gen .get () instanceof Var def ) {
113
+ if (!(stmt instanceof DefinitionStmt <?,?> definitionStmt ) || !canHoldInt (def )){
114
+ return true ;
115
+ }
116
+ var rValue = definitionStmt .getRValue ();
117
+ if (rValue != null ) {
118
+ out .update (def , evaluate (rValue , in ));
119
+ } else {
120
+ out .update (def , Value .getNAC ());
121
+ }
122
+ }
123
+ return out .equals (old_out );
86
124
}
87
125
88
126
/**
@@ -112,6 +150,112 @@ public static boolean canHoldInt(Var var) {
112
150
*/
113
151
public static Value evaluate (Exp exp , CPFact in ) {
114
152
// TODO - finish me
115
- return null ;
153
+ if (exp instanceof Var ){
154
+ if (canHoldInt ((Var ) exp )) {
155
+ return in .get ((Var ) exp );
156
+ } else {
157
+ return Value .getNAC ();
158
+ }
159
+ } else if (exp instanceof IntLiteral ){
160
+ return Value .makeConstant (((IntLiteral )exp ).getValue ());
161
+ } else if (exp instanceof BinaryExp ){
162
+ Value op1 = evaluate (((BinaryExp ) exp ).getOperand1 (), in );
163
+ Value op2 = evaluate (((BinaryExp ) exp ).getOperand2 (), in );
164
+ // By issue: https://github.com/pascal-lab/Tai-e-assignments/issues/2
165
+ // judge '/0' and '%0' at first.
166
+ BinaryExp .Op op = ((BinaryExp ) exp ).getOperator ();
167
+ if ( op2 .isConstant () && op2 .getConstant () == 0 && (op == ArithmeticExp .Op .DIV || op == ArithmeticExp .Op .REM ) ){
168
+ return Value .getUndef ();
169
+ }
170
+ if ( op1 .isNAC () || op2 .isNAC ()){
171
+ return Value .getNAC ();
172
+ }
173
+ if ( !op1 .isConstant () || !op2 .isConstant ()){
174
+ return Value .getUndef ();
175
+ }
176
+ if (op instanceof ArithmeticExp .Op ) {
177
+ switch ((ArithmeticExp .Op )op ) {
178
+ case ADD -> {
179
+ return Value .makeConstant (op1 .getConstant () + op2 .getConstant ());
180
+ }
181
+ case SUB -> {
182
+ return Value .makeConstant (op1 .getConstant () - op2 .getConstant ());
183
+ }
184
+ case MUL -> {
185
+ return Value .makeConstant (op1 .getConstant () * op2 .getConstant ());
186
+ }
187
+ case DIV -> {
188
+ if (op2 .getConstant () == 0 ) {
189
+ return Value .getUndef ();
190
+ }
191
+ return Value .makeConstant (op1 .getConstant () / op2 .getConstant ());
192
+ }
193
+ case REM -> {
194
+ if (op2 .getConstant () == 0 ) {
195
+ return Value .getUndef ();
196
+ }
197
+ return Value .makeConstant (op1 .getConstant () % op2 .getConstant ());
198
+ }
199
+ }
200
+ }
201
+ if (op instanceof ConditionExp .Op ){
202
+ switch ((ConditionExp .Op )op ){
203
+ case EQ -> {
204
+ return Value .makeConstant (op1 .getConstant () == op2 .getConstant ()? 1 : 0 );
205
+ }
206
+ case GE -> {
207
+ return Value .makeConstant (op1 .getConstant () >= op2 .getConstant ()? 1 : 0 );
208
+ }
209
+ case GT -> {
210
+ return Value .makeConstant (op1 .getConstant () > op2 .getConstant ()? 1 : 0 );
211
+ }
212
+ case LE -> {
213
+ return Value .makeConstant (op1 .getConstant () <= op2 .getConstant ()? 1 : 0 );
214
+ }
215
+ case LT -> {
216
+ return Value .makeConstant (op1 .getConstant () < op2 .getConstant ()? 1 : 0 );
217
+ }
218
+ case NE -> {
219
+ return Value .makeConstant (op1 .getConstant () != op2 .getConstant ()? 1 : 0 );
220
+ }
221
+ }
222
+ }
223
+ if (op instanceof ShiftExp .Op ){
224
+ switch ((ShiftExp .Op )op ){
225
+ case SHL -> {
226
+ return Value .makeConstant (op1 .getConstant () << op2 .getConstant ());
227
+ }
228
+ case SHR -> {
229
+ return Value .makeConstant (op1 .getConstant () >> op2 .getConstant ());
230
+ }
231
+ case USHR -> {
232
+ return Value .makeConstant (op1 .getConstant () >>> op2 .getConstant ());
233
+ }
234
+ }
235
+ }
236
+ if (op instanceof BitwiseExp .Op ) {
237
+ // maybe no need to process it? NO!!! logic rather than bitwise.
238
+ switch ((BitwiseExp .Op )op ){
239
+ case OR -> {
240
+ return Value .makeConstant (op1 .getConstant () | op2 .getConstant ());
241
+ }
242
+ case AND -> {
243
+ return Value .makeConstant (op1 .getConstant () & op2 .getConstant ());
244
+ }
245
+ case XOR -> {
246
+ return Value .makeConstant (op1 .getConstant () ^ op2 .getConstant ());
247
+ }
248
+ }
249
+ }
250
+ return Value .getUndef ();
251
+ }
252
+ /*
253
+ f(y,z) =
254
+ val(y) op val(z) // if val(y) and val(z) are constants
255
+ NAC // if val(y) or val(z) is NAC
256
+ UNDEF // otherwise
257
+ 对于其它情况,该方法会像我们在第 2.1 节提到的那样返回 NAC。
258
+ */
259
+ return Value .getNAC ();
116
260
}
117
261
}
0 commit comments