Skip to content

Commit

Permalink
xcfa oc checker optimization fix
Browse files Browse the repository at this point in the history
  • Loading branch information
csanadtelbisz committed Nov 13, 2024
1 parent f7bdc13 commit 89b72aa
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 40 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ buildscript {

allprojects {
group = "hu.bme.mit.theta"
version = "6.8.3"
version = "6.8.4"

apply(from = rootDir.resolve("gradle/shared-with-buildSrc/mirrors.gradle.kts"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import hu.bme.mit.theta.analysis.algorithm.oc.OcChecker
import hu.bme.mit.theta.analysis.algorithm.oc.Relation
import hu.bme.mit.theta.analysis.algorithm.oc.RelationType
import hu.bme.mit.theta.analysis.unit.UnitPrec
import hu.bme.mit.theta.common.exception.NotSolvableException
import hu.bme.mit.theta.common.logging.Logger
import hu.bme.mit.theta.core.decl.ConstDecl
import hu.bme.mit.theta.core.decl.Decls
Expand All @@ -50,21 +51,25 @@ import hu.bme.mit.theta.solver.SolverStatus
import hu.bme.mit.theta.xcfa.*
import hu.bme.mit.theta.xcfa.analysis.XcfaPrec
import hu.bme.mit.theta.xcfa.model.*
import hu.bme.mit.theta.xcfa.passes.*
import kotlin.time.measureTime

private val Expr<*>.vars
get() = ExprUtils.getVars(this)

class XcfaOcChecker(
private val xcfa: XCFA,
xcfa: XCFA,
decisionProcedure: OcDecisionProcedureType,
private val logger: Logger,
conflictInput: String?,
private val outputConflictClauses: Boolean,
nonPermissiveValidation: Boolean,
private val autoConflictConfig: AutoConflictFinderConfig,
private val acceptUnreliableSafe: Boolean = false,
) : SafetyChecker<EmptyProof, Cex, XcfaPrec<UnitPrec>> {

private val xcfa = xcfa.optimizeFurther(OcExtraPasses())

private var indexing = VarIndexingFactory.indexing(0)
private val localVars = mutableMapOf<VarDecl<*>, MutableMap<Int, VarDecl<*>>>()
private val memoryDecl = Decls.Var("__oc_checker_memory_declaration__", Int())
Expand Down Expand Up @@ -147,7 +152,16 @@ class XcfaOcChecker(
else -> SafetyResult.unknown()
}
}
.also { logger.writeln(Logger.Level.MAINSTEP, "OC checker result: $it") }
.also {
logger.writeln(Logger.Level.MAINSTEP, "OC checker result: $it")
if (xcfa.unsafeUnrollUsed && !acceptUnreliableSafe) {
logger.writeln(
Logger.Level.MAINSTEP,
"Incomplete loop unroll used: safe result is unreliable.",
)
throw NotSolvableException()
}
}

private inner class ThreadProcessor(private val thread: Thread) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ fun getOcChecker(
ocConfig.outputConflictClauses,
ocConfig.nonPermissiveValidation,
ocConfig.autoConflict,
config.outputConfig.acceptUnreliableSafe
)
return SafetyChecker { ocChecker.check() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,20 +124,9 @@ fun complexPortfolio25(
debugConfig = portfolioConfig.debugConfig,
)

val forceUnrolledXcfa =
xcfa.optimizeFurther(
listOf(
AssumeFalseRemovalPass(),
MutexToVarPass(),
AtomicReadsOneWritePass(),
LoopUnrollPass(2),
)
)

val ocConfig = { inProcess: Boolean ->
XcfaConfig(
inputConfig =
baseConfig.inputConfig.copy(xcfaWCtx = Triple(forceUnrolledXcfa, mcm, parseContext)),
inputConfig = baseConfig.inputConfig.copy(xcfaWCtx = Triple(xcfa, mcm, parseContext)),
frontendConfig = baseConfig.frontendConfig,
backendConfig =
BackendConfig(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class XcfaAdapter(val gsonSupplier: () -> Gson) : TypeAdapter<XCFA>() {
lateinit var vars: Set<XcfaGlobalVar>
lateinit var xcfaProcedures: Map<String, XcfaProcedure>
lateinit var initProcedures: List<Pair<XcfaProcedure, List<Expr<*>>>>
var unsafeUnrollUsed: Boolean = false
var unsafeUnrollUsed = false

val varsType = object : TypeToken<Set<XcfaGlobalVar>>() {}.type

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ constructor(
private val procedures: MutableSet<XcfaProcedureBuilder> = LinkedHashSet(),
private val initProcedures: MutableList<Pair<XcfaProcedureBuilder, List<Expr<*>>>> = ArrayList(),
val metaData: MutableMap<String, Any> = LinkedHashMap(),
var unsafeUnrollUsed: Boolean = false,
) {

fun getVars(): Set<XcfaGlobalVar> = vars
Expand All @@ -49,7 +48,6 @@ constructor(
globalVars = vars,
procedureBuilders = procedures,
initProcedureBuilders = initProcedures,
unsafeUnrollUsed = unsafeUnrollUsed,
)
}

Expand Down Expand Up @@ -80,6 +78,7 @@ constructor(
private val locs: MutableSet<XcfaLocation> = LinkedHashSet(),
private val edges: MutableSet<XcfaEdge> = LinkedHashSet(),
val metaData: MutableMap<String, Any> = LinkedHashMap(),
unsafeUnrollUsed: Boolean = false,
) {

lateinit var initLoc: XcfaLocation
Expand All @@ -91,6 +90,9 @@ constructor(
var errorLoc: Optional<XcfaLocation> = Optional.empty()
private set

var unsafeUnrollUsed: Boolean = unsafeUnrollUsed
private set

lateinit var parent: XcfaBuilder
private lateinit var built: XcfaProcedure
private lateinit var optimized: XcfaProcedureBuilder
Expand Down Expand Up @@ -322,6 +324,6 @@ constructor(
}

fun setUnsafeUnroll() {
parent.unsafeUnrollUsed = true
unsafeUnrollUsed = true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ class XCFA(
val globalVars: Set<XcfaGlobalVar>, // global variables
val procedureBuilders: Set<XcfaProcedureBuilder> = emptySet(),
val initProcedureBuilders: List<Pair<XcfaProcedureBuilder, List<Expr<*>>>> = emptyList(),
val unsafeUnrollUsed: Boolean = false,
var unsafeUnrollUsed: Boolean = false
) {

val pointsToGraph by this.lazyPointsToGraph
private var cachedHash: Int? = null

var cachedHash: Int? = null
val pointsToGraph by this.lazyPointsToGraph

var procedures: Set<XcfaProcedure> // procedure definitions
private set
Expand All @@ -51,6 +51,7 @@ class XCFA(

procedures = procedureBuilders.map { it.build(this) }.toSet()
initProcedures = initProcedureBuilders.map { Pair(it.first.build(this), it.second) }
unsafeUnrollUsed = (procedureBuilders + initProcedureBuilders.map { it.first }).any { it.unsafeUnrollUsed }
}

/** Recreate an existing XCFA by substituting the procedures and initProcedures fields. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,20 @@
*/
package hu.bme.mit.theta.xcfa.model

import hu.bme.mit.theta.xcfa.passes.ProcedurePass
import hu.bme.mit.theta.xcfa.passes.ProcedurePassManager

fun XCFA.optimizeFurther(passes: List<ProcedurePass>): XCFA {
if (passes.isEmpty()) return this
val passManager = ProcedurePassManager(passes)
val copy: XcfaProcedureBuilder.() -> XcfaProcedureBuilder = {
val newLocs = getLocs().associateWith { it.copy() }
fun XCFA.optimizeFurther(passManager: ProcedurePassManager): XCFA {
if (passManager.passes.isEmpty()) return this
val deepCopy: XcfaProcedure.() -> XcfaProcedureBuilder = {
val newLocs = locs.associateWith { it.copy() }
XcfaProcedureBuilder(
name = name,
manager = passManager,
params = getParams().toMutableList(),
vars = getVars().toMutableSet(),
locs = getLocs().map { newLocs[it]!! }.toMutableSet(),
params = params.toMutableList(),
vars = vars.toMutableSet(),
locs = locs.map { newLocs[it]!! }.toMutableSet(),
edges =
getEdges()
edges
.map {
val source = newLocs[it.source]!!
val target = newLocs[it.target]!!
Expand All @@ -40,10 +38,11 @@ fun XCFA.optimizeFurther(passes: List<ProcedurePass>): XCFA {
edge
}
.toMutableSet(),
metaData = metaData.toMutableMap(),
metaData = mutableMapOf(),
unsafeUnrollUsed = unsafeUnrollUsed,
)
.also {
it.copyMetaLocs(
.also { proc ->
proc.copyMetaLocs(
newLocs[initLoc]!!,
finalLoc.map { newLocs[it] },
errorLoc.map { newLocs[it] },
Expand All @@ -52,9 +51,9 @@ fun XCFA.optimizeFurther(passes: List<ProcedurePass>): XCFA {
}

val builder = XcfaBuilder(name, globalVars.toMutableSet())
procedureBuilders.forEach { builder.addProcedure(it.copy()) }
initProcedureBuilders.forEach { (proc, params) ->
val initProc = builder.getProcedures().find { it.name == proc.name } ?: proc.copy()
procedures.forEach { builder.addProcedure(it.deepCopy()) }
initProcedures.forEach { (proc, params) ->
val initProc = builder.getProcedures().find { it.name == proc.name } ?: proc.deepCopy()
builder.addEntryPoint(initProc, params)
}
return builder.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ package hu.bme.mit.theta.xcfa.passes
import hu.bme.mit.theta.common.logging.Logger
import hu.bme.mit.theta.frontend.ParseContext

open class ProcedurePassManager(vararg passes: List<ProcedurePass>) {
open class ProcedurePassManager(val passes: List<List<ProcedurePass>>) {

val passes: List<List<ProcedurePass>> = passes.toList()
constructor(vararg passes: List<ProcedurePass>) : this(passes.toList())
}

class CPasses(checkOverflow: Boolean, parseContext: ParseContext, uniqueWarningLogger: Logger) :
Expand Down Expand Up @@ -99,3 +99,13 @@ class ChcPasses(parseContext: ParseContext, uniqueWarningLogger: Logger) :
)

class LitmusPasses : ProcedurePassManager()

class OcExtraPasses :
ProcedurePassManager(
listOf(
AssumeFalseRemovalPass(),
MutexToVarPass(),
AtomicReadsOneWritePass(),
LoopUnrollPass(2), // force loop unroll for BMC
)
)

0 comments on commit 89b72aa

Please sign in to comment.