@@ -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+
10181143object 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