Skip to content

Commit 75f7832

Browse files
committed
feat: A2
1 parent 878fcf8 commit 75f7832

File tree

3 files changed

+208
-16
lines changed

3 files changed

+208
-16
lines changed

A2/tai-e/src/main/java/pascal/taie/analysis/dataflow/analysis/constprop/ConstantPropagation.java

Lines changed: 170 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,12 @@
2525
import pascal.taie.analysis.dataflow.analysis.AbstractDataflowAnalysis;
2626
import pascal.taie.analysis.graph.cfg.CFG;
2727
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.*;
3829
import pascal.taie.ir.stmt.Stmt;
3930
import pascal.taie.language.type.PrimitiveType;
4031
import pascal.taie.language.type.Type;
41-
import pascal.taie.util.AnalysisException;
32+
33+
import java.util.List;
4234

4335
public class ConstantPropagation extends
4436
AbstractDataflowAnalysis<Stmt, CPFact> {
@@ -57,32 +49,102 @@ public boolean isForward() {
5749
@Override
5850
public CPFact newBoundaryFact(CFG<Stmt> cfg) {
5951
// 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;
6160
}
6261

6362
@Override
6463
public CPFact newInitialFact() {
6564
// TODO - finish me
66-
return null;
65+
return new CPFact();
6766
}
6867

6968
@Override
7069
public void meetInto(CPFact fact, CPFact target) {
7170
// TODO - finish me
71+
target.forEach((k, v) -> {
72+
fact.update(k, this.meetValue(fact.get(k), v));
73+
});
7274
}
7375

7476
/**
7577
* Meets two Values.
7678
*/
7779
public Value meetValue(Value v1, Value v2) {
7880
// 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));
80106
}
81107

82108
@Override
83109
public boolean transferNode(Stmt stmt, CPFact in, CPFact out) {
84110
// 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);
86148
}
87149

88150
/**
@@ -103,6 +165,14 @@ public static boolean canHoldInt(Var var) {
103165
return false;
104166
}
105167

168+
public static int booleanToInt(boolean bool) {
169+
if (bool) {
170+
return 1;
171+
} else {
172+
return 0;
173+
}
174+
}
175+
106176
/**
107177
* Evaluates the {@link Value} of given expression.
108178
*
@@ -112,6 +182,90 @@ public static boolean canHoldInt(Var var) {
112182
*/
113183
public static Value evaluate(Exp exp, CPFact in) {
114184
// 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");
116270
}
117271
}

A2/tai-e/src/main/java/pascal/taie/analysis/dataflow/solver/Solver.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ private DataflowResult<Node, Fact> initialize(CFG<Node> cfg) {
7878

7979
protected void initializeForward(CFG<Node> cfg, DataflowResult<Node, Fact> result) {
8080
// TODO - finish me
81+
Node entry = cfg.getEntry();
82+
result.setOutFact(entry, analysis.newBoundaryFact(cfg));
83+
84+
for (Node node : cfg) {
85+
if (!node.equals(entry)) {
86+
result.setInFact(node, analysis.newInitialFact());
87+
result.setOutFact(node, analysis.newInitialFact());
88+
}
89+
}
8190
}
8291

8392
protected void initializeBackward(CFG<Node> cfg, DataflowResult<Node, Fact> result) {

A2/tai-e/src/main/java/pascal/taie/analysis/dataflow/solver/WorkListSolver.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@
2323
package pascal.taie.analysis.dataflow.solver;
2424

2525
import pascal.taie.analysis.dataflow.analysis.DataflowAnalysis;
26+
import pascal.taie.analysis.dataflow.analysis.constprop.CPFact;
2627
import pascal.taie.analysis.dataflow.fact.DataflowResult;
2728
import pascal.taie.analysis.graph.cfg.CFG;
2829

30+
import java.util.HashSet;
31+
import java.util.Set;
32+
import java.util.TreeSet;
33+
2934
class WorkListSolver<Node, Fact> extends Solver<Node, Fact> {
3035

3136
WorkListSolver(DataflowAnalysis<Node, Fact> analysis) {
@@ -35,6 +40,30 @@ class WorkListSolver<Node, Fact> extends Solver<Node, Fact> {
3540
@Override
3641
protected void doSolveForward(CFG<Node> cfg, DataflowResult<Node, Fact> result) {
3742
// TODO - finish me
43+
HashSet<Node> workList = new HashSet<>();
44+
Node entry = cfg.getEntry();
45+
46+
for (Node node : cfg) {
47+
if (!node.equals(entry)) {
48+
workList.add(node);
49+
}
50+
}
51+
52+
while (!workList.isEmpty()) {
53+
Node current = workList.iterator().next();
54+
workList.remove(current);
55+
56+
Fact inFact = result.getInFact(current);
57+
58+
cfg.getPredsOf(current).forEach(node -> {
59+
this.analysis.meetInto(inFact, result.getOutFact(node));
60+
});
61+
62+
Fact outFact = result.getOutFact(current);
63+
if (this.analysis.transferNode(current, inFact, outFact)) {
64+
workList.addAll(cfg.getSuccsOf(current));
65+
}
66+
}
3867
}
3968

4069
@Override

0 commit comments

Comments
 (0)