@@ -131,6 +131,54 @@ module InstructionSanity {
131131 blockCount = count ( instr .getBlock ( ) ) and
132132 blockCount != 1
133133 }
134+
135+ private predicate forwardEdge ( IRBlock b1 , IRBlock b2 ) {
136+ b1 .getASuccessor ( ) = b2 and
137+ not b1 .getBackEdgeSuccessor ( _) = b2
138+ }
139+
140+ /**
141+ * Holds if `f` contains a loop in which no edge is a back edge.
142+ *
143+ * This check ensures we don't have too _few_ back edges.
144+ */
145+ query predicate containsLoopOfForwardEdges ( FunctionIR f ) {
146+ exists ( IRBlock block |
147+ forwardEdge + ( block , block ) and
148+ block .getFunctionIR ( ) = f
149+ )
150+ }
151+
152+ /**
153+ * Holds if `block` is reachable from its function entry point but would not
154+ * be reachable by traversing only forward edges. This check is skipped for
155+ * functions containing `goto` statements as the property does not generally
156+ * hold there.
157+ *
158+ * This check ensures we don't have too _many_ back edges.
159+ */
160+ query predicate lostReachability ( IRBlock block ) {
161+ exists ( FunctionIR f , IRBlock entry |
162+ entry = f .getEntryBlock ( ) and
163+ entry .getASuccessor + ( ) = block and
164+ not forwardEdge + ( entry , block ) and
165+ not exists ( GotoStmt s | s .getEnclosingFunction ( ) = f .getFunction ( ) )
166+ )
167+ }
168+
169+ /**
170+ * Holds if the number of back edges differs between the `Instruction` graph
171+ * and the `IRBlock` graph.
172+ */
173+ query predicate backEdgeCountMismatch ( Function f , int fromInstr , int fromBlock ) {
174+ fromInstr = count ( Instruction i1 , Instruction i2 |
175+ i1 .getFunction ( ) = f and i1 .getBackEdgeSuccessor ( _) = i2
176+ ) and
177+ fromBlock = count ( IRBlock b1 , IRBlock b2 |
178+ b1 .getFunction ( ) = f and b1 .getBackEdgeSuccessor ( _) = b2
179+ ) and
180+ fromInstr != fromBlock
181+ }
134182}
135183
136184/**
0 commit comments