@@ -133,21 +133,41 @@ private predicate boundCondition(ComparisonExpr comp, SsaVariable v, Expr e, int
133133 )
134134}
135135
136+ private predicate gcdInput ( int x , int y ) {
137+ exists ( ComparisonExpr comp , Bound b |
138+ exprModulus ( comp .getLesserOperand ( ) , b , _, x ) and
139+ exprModulus ( comp .getGreaterOperand ( ) , b , _, y )
140+ ) or
141+ exists ( int x0 , int y0 |
142+ gcdInput ( x0 , y0 ) and
143+ x = y0 and
144+ y = x0 % y0
145+ )
146+ }
147+
148+ private int gcd ( int x , int y ) {
149+ result = x .abs ( ) and y = 0 and gcdInput ( x , y )
150+ or
151+ result = gcd ( y , x % y ) and y != 0 and gcdInput ( x , y )
152+ }
153+
136154/**
137155 * Holds if `comp` is a comparison between `x` and `y` for which `y - x` has a
138156 * fixed value modulo some `mod > 1`, such that the comparison can be
139157 * strengthened by `strengthen` when evaluating to `testIsTrue`.
140158 */
141159private predicate modulusComparison ( ComparisonExpr comp , boolean testIsTrue , int strengthen ) {
142- exists ( Bound b , int v1 , int v2 , int mod , boolean resultIsStrict , int d , int k |
160+ exists ( Bound b , int v1 , int v2 , int mod1 , int mod2 , int mod , boolean resultIsStrict , int d , int k |
143161 // If `x <= y` and `x =(mod) b + v1` and `y =(mod) b + v2` then
144162 // `0 <= y - x =(mod) v2 - v1`. By choosing `k =(mod) v2 - v1` with
145163 // `0 <= k < mod` we get `k <= y - x`. If the resulting comparison is
146164 // strict then the strengthening amount is instead `k - 1` modulo `mod`:
147165 // `x < y` means `0 <= y - x - 1 =(mod) k - 1` so `k - 1 <= y - x - 1` and
148166 // thus `k - 1 < y - x` with `0 <= k - 1 < mod`.
149- exprModulus ( comp .getLesserOperand ( ) , b , v1 , mod ) and
150- exprModulus ( comp .getGreaterOperand ( ) , b , v2 , mod ) and
167+ exprModulus ( comp .getLesserOperand ( ) , b , v1 , mod1 ) and
168+ exprModulus ( comp .getGreaterOperand ( ) , b , v2 , mod2 ) and
169+ mod = gcd ( mod1 , mod2 ) and
170+ mod != 1 and
151171 ( testIsTrue = true or testIsTrue = false ) and
152172 ( if comp .isStrict ( ) then resultIsStrict = testIsTrue else resultIsStrict = testIsTrue .booleanNot ( ) ) and
153173 ( resultIsStrict = true and d = 1 or resultIsStrict = false and d = 0 ) and
0 commit comments