@@ -302,15 +302,87 @@ module RangeAnalysis {
302302 )
303303 }
304304
305+ /**
306+ * Holds if `node` is a phi node with `left` and `right` has the only two inputs.
307+ *
308+ * Note that this predicate is symmetric: when it holds for (left, right) it also holds for (right, left).
309+ */
310+ predicate binaryPhiNode ( DataFlow:: Node node , DataFlow:: Node left , DataFlow:: Node right ) {
311+ exists ( SsaPhiNode phi | node = DataFlow:: ssaDefinitionNode ( phi ) |
312+ strictcount ( phi .getAnInput ( ) ) = 2 and
313+ left = DataFlow:: ssaDefinitionNode ( phi .getAnInput ( ) ) and
314+ right = DataFlow:: ssaDefinitionNode ( phi .getAnInput ( ) ) and
315+ left != right )
316+ }
317+
318+ /**
319+ * Holds if `A <= B + c` can be determined based on a phi node.
320+ */
321+ predicate phiEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
322+ exists ( DataFlow:: Node phi , DataFlow:: Node left , DataFlow:: Node right |
323+ binaryPhiNode ( phi , left , right ) and
324+ cfg = phi .getBasicBlock ( )
325+ |
326+ // Both inputs are defined in terms of the same root:
327+ // phi = PHI(root + bias1, root + bias2)
328+ exists ( DataFlow:: Node root , int sign , int bias1 , int bias2 |
329+ linearDefinition ( left , root , sign , bias1 ) and
330+ linearDefinition ( right , root , sign , bias2 ) and
331+ bias1 < bias2 and
332+ // root + bias1 <= phi <= root + bias2
333+ (
334+ // root <= phi - bias1
335+ a = root and asign = 1 and
336+ b = phi and bsign = 1 and
337+ c = - bias1
338+ or
339+ // phi <= root + bias2
340+ a = phi and asign = 1 and
341+ b = root and bsign = 1 and
342+ c = bias2
343+ )
344+ )
345+ or
346+ // One input is defined in terms of the phi node itself:
347+ // phi = PHI(phi + increment, x)
348+ exists ( int increment , DataFlow:: Node root , int sign , int bias |
349+ linearDefinition ( left , phi , 1 , increment ) and
350+ linearDefinition ( right , root , sign , bias ) and
351+ (
352+ // If increment is positive (or zero):
353+ // phi >= right' + bias
354+ increment >= 0 and
355+ a = root and asign = sign and
356+ b = phi and bsign = 1 and
357+ c = - bias
358+ or
359+ // If increment is negative (or zero):
360+ // phi <= right' + bias
361+ increment <= 0 and
362+ a = phi and asign = 1 and
363+ b = root and bsign = sign and
364+ c = bias
365+ )
366+ )
367+ )
368+ }
369+
305370 /**
306371 * The set of initial edges including those from dual constraints.
307372 */
308373 private predicate seedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
309374 // A <= B + c
310375 comparisonEdge ( cfg , a , asign , b , bsign , c )
311376 or
377+ phiEdge ( cfg , a , asign , b , bsign , c )
378+ }
379+
380+ private predicate seedEdgeWithDual ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
381+ // A <= B + c
382+ seedEdge ( cfg , a , asign , b , bsign , c )
383+ or
312384 // -B <= -A + c (dual constraint)
313- comparisonEdge ( cfg , b , - bsign , a , - asign , c )
385+ seedEdge ( cfg , b , - bsign , a , - asign , c )
314386 }
315387
316388 /**
@@ -339,7 +411,7 @@ module RangeAnalysis {
339411 * This means negative-weight cycles (contradictions) can be detected using simple cycle detection.
340412 */
341413 private predicate extendedEdge ( ControlFlowNode cfg , DataFlow:: Node a , int asign , DataFlow:: Node b , int bsign , int c ) {
342- seedEdge ( cfg , a , asign , b , bsign , c )
414+ seedEdgeWithDual ( cfg , a , asign , b , bsign , c )
343415 or
344416 exists ( DataFlow:: Node mid , int midx , ControlFlowNode cfg1 , int c1 , ControlFlowNode cfg2 , int c2 |
345417 extendedEdge ( cfg1 , a , asign , mid , midx , c1 ) and
0 commit comments