Skip to content

Commit 73b0e35

Browse files
committed
add prop for base+offset
1 parent e2524ae commit 73b0e35

File tree

1 file changed

+134
-10
lines changed

1 file changed

+134
-10
lines changed

src/main/scala/ir/transforms/Simp.scala

Lines changed: 134 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -553,16 +553,8 @@ def copypropTransform(
553553
// SimplifyLogger.info(s"${p.name} ExprComplexity ${ExprComplexity()(p)}")
554554
// val result = solver.solveProc(p, true).withDefaultValue(dom.bot)
555555

556-
MinCopyProp.transform(p)
556+
OffsetProp.transform(p)
557557

558-
val result = CopyProp.DSACopyProp(p, procFrames, funcEntries, constRead)
559-
val solve = t.checkPoint("Solve CopyProp")
560-
561-
if (result.nonEmpty) {
562-
val vis = Simplify(CopyProp.toResult(result))
563-
visit_proc(vis, p)
564-
}
565-
// visit_proc(CopyProp.BlockyProp(), p)
566558
val gvis = GuardVisitor()
567559
visit_proc(gvis, p)
568560

@@ -1015,6 +1007,139 @@ object getProcFrame {
10151007

10161008
}
10171009

1010+
object OffsetProp {
1011+
1012+
/*
1013+
* Copyprop for any expression of fitting into the structure
1014+
* bvadd(variable, constant)
1015+
*
1016+
* This is sufficient to propagate branch conditions through.
1017+
*/
1018+
1019+
// None, None -> Top
1020+
// Some(v), None -> v
1021+
// Some(v), Some(Lit) -> v + Lit
1022+
// None, Some(Lit) -> Lit
1023+
type Value = (Option[Variable], Option[BitVecLiteral])
1024+
1025+
def joinValue(l: Value, r: Value) = {
1026+
(l, r) match {
1027+
case ((None, None), _) => (None, None)
1028+
case (_, (None, None)) => (None, None)
1029+
case (l, r) if l != r => (None, None)
1030+
case (l, r) => l
1031+
}
1032+
}
1033+
1034+
class CopyProp() {
1035+
val st = mutable.Map[Variable, Value]()
1036+
var giveUp = false
1037+
1038+
def findOff(v: Variable, c: BitVecLiteral): BitVecLiteral | Variable | BinaryExpr = find(v) match {
1039+
case lc: BitVecLiteral => ir.eval.BitVectorEval.smt_bvadd(lc, c)
1040+
case lv: Variable => BinaryExpr(BVADD, lv, c)
1041+
case BinaryExpr(BVADD, l: Variable, r: BitVecLiteral) =>
1042+
BinaryExpr(BVADD, l, ir.eval.BitVectorEval.smt_bvadd(r, c))
1043+
case _ => throw Exception("Unexpected expression structure created by find() at some point")
1044+
}
1045+
1046+
def find(v: Variable): BitVecLiteral | Variable | BinaryExpr = {
1047+
st.get(v) match {
1048+
case None => v
1049+
case Some((None, None)) => v
1050+
case Some((None, Some(c))) => c
1051+
case Some((Some(v), None)) => find(v)
1052+
case Some((Some(v), Some(c))) => findOff(v, c)
1053+
}
1054+
}
1055+
1056+
def joinState(lhs: Variable, rhs: Expr) = {
1057+
specJoinState(lhs, rhs) match {
1058+
case Some((l, r)) => st(l) = r
1059+
case _ => ()
1060+
}
1061+
}
1062+
1063+
def specJoinState(lhs: Variable, rhs: Expr): Option[(Variable, Value)] = {
1064+
rhs match {
1065+
case e @ BinaryExpr(BVADD, l: Variable, r: BitVecLiteral) if (!st.contains(lhs)) =>
1066+
Some(lhs -> (Some(l), Some(r)))
1067+
case e @ BinaryExpr(BVADD, l: Variable, r: BitVecLiteral) if findOff(l, r) == find(lhs) => None
1068+
case v: Variable if (!st.contains(lhs)) => Some(lhs -> (Some(v), None))
1069+
case v: BitVecLiteral if (!st.contains(lhs)) => Some(lhs -> (None, Some(v)))
1070+
case v: Variable if (find(lhs) == find(v)) => None
1071+
case c: BitVecLiteral if (find(lhs) != c) => Some(lhs -> (None, None))
1072+
case _ => Some(lhs -> (None, None))
1073+
}
1074+
}
1075+
1076+
def clob(v: Variable) = {
1077+
st(v) = (None, None)
1078+
}
1079+
1080+
def transfer(s: Statement) = s match {
1081+
case LocalAssign(l: Variable, r: Variable, _) => joinState(l, r)
1082+
case LocalAssign(l: Variable, r: Literal, _) => joinState(l, r)
1083+
case LocalAssign(l: Variable, r @ BinaryExpr(BVADD, _: Variable, _: BitVecLiteral), _) => joinState(l, r)
1084+
case LocalAssign(l: Variable, _, _) => clob(l)
1085+
// case s: SimulAssign => s.assignments.flatMap {
1086+
// case (l: Variable, r: Variable) => specJoinState(l, r).toSeq
1087+
// case (l: Variable, r) => Seq(l -> None)
1088+
// }.foreach {
1089+
// case (l, r) => st(l) = r
1090+
// }
1091+
case a: Assign => {
1092+
// memoryload and DirectCall
1093+
a.assignees.foreach(clob)
1094+
}
1095+
case _: MemoryStore => ()
1096+
case _: NOP => ()
1097+
case _: Assert => ()
1098+
case _: Assume => ()
1099+
case i: IndirectCall => giveUp = true
1100+
}
1101+
1102+
def analyse(p: Procedure): Map[Variable, Expr] = {
1103+
reversePostOrder(p)
1104+
val worklist = mutable.PriorityQueue[Block]()(Ordering.by(_.rpoOrder))
1105+
worklist.addAll(p.blocks)
1106+
while (worklist.nonEmpty && !giveUp) {
1107+
val b = worklist.dequeue()
1108+
b.statements.foreach(transfer)
1109+
}
1110+
1111+
val res: Map[Variable, Variable | Literal | BinaryExpr] =
1112+
if giveUp then Map()
1113+
else
1114+
st.collect {
1115+
case (v, (Some(v2), None)) => v -> find(v2)
1116+
case (v, (None, Some(c))) => v -> c
1117+
case (v, (Some(v2), Some(c))) => v -> findOff(v2, c)
1118+
}.toMap
1119+
1120+
res
1121+
}
1122+
1123+
}
1124+
1125+
def transform(p: Procedure) = {
1126+
val solver = CopyProp()
1127+
val res = solver.analyse(p)
1128+
1129+
class SubstExprs(subst: Map[Variable, Expr]) extends CILVisitor {
1130+
override def vexpr(e: Expr) = {
1131+
Substitute(subst.get)(e) match {
1132+
case Some(n) => ChangeTo(n)
1133+
case _ => SkipChildren()
1134+
}
1135+
}
1136+
}
1137+
if (res.nonEmpty) {
1138+
visit_proc(SubstExprs(res), p)
1139+
}
1140+
}
1141+
}
1142+
10181143
object MinCopyProp {
10191144

10201145
// None -> Top
@@ -1101,7 +1226,6 @@ object MinCopyProp {
11011226

11021227
res
11031228
}
1104-
11051229
}
11061230

11071231
def transform(p: Procedure) = {

0 commit comments

Comments
 (0)