@@ -936,6 +936,16 @@ private module Cached {
936936 ValueNumber getUnary ( ) { result .getAnInstruction ( ) = instr .getUnary ( ) }
937937 }
938938
939+ private class ConvertBoolToIntOrPointerInstruction extends ConvertInstruction {
940+ ConvertBoolToIntOrPointerInstruction ( ) {
941+ this .getUnary ( ) .getResultIRType ( ) instanceof IRBooleanType and
942+ (
943+ this .getResultIRType ( ) instanceof IRIntegerType or
944+ this .getResultIRType ( ) instanceof IRAddressType
945+ )
946+ }
947+ }
948+
939949 /**
940950 * Holds if `left == right + k` is `areEqual` given that test is `testIsTrue`.
941951 *
@@ -966,6 +976,26 @@ private module Cached {
966976 )
967977 or
968978 compares_eq ( test .( BuiltinExpectCallValueNumber ) .getCondition ( ) , left , right , k , areEqual , value )
979+ or
980+ // If we have e.g.:
981+ // ```
982+ // x = (a == b)
983+ // if(x != c) { ... }
984+ // ```
985+ // then `x != c` is true implies that `a == b` is true.
986+ // ```
987+ exists ( Operand l , Operand r , ValueNumber vn , int c , AbstractValue v |
988+ test .( CompareValueNumber ) .hasOperands ( l , r ) and
989+ int_value ( r .getDef ( ) ) = c and
990+ vn .getAnInstruction ( ) = getBooleanInstruction ( l .getDef ( ) ) and
991+ compares_eq ( vn , left , right , k , areEqual , v )
992+ |
993+ test instanceof CompareNEValueNumber and
994+ if c = 0 then value = v else value = v .getDualValue ( )
995+ or
996+ test instanceof CompareEQValueNumber and
997+ if c = 0 then value = v .getDualValue ( ) else value = v
998+ )
969999 }
9701000
9711001 private predicate isConvertedBool ( Instruction instr ) {
@@ -1006,19 +1036,24 @@ private module Cached {
10061036 k = k1 + k2
10071037 )
10081038 or
1009- exists ( CompareValueNumber cmp , Operand left , Operand right , AbstractValue v |
1010- test = cmp and
1011- pragma [ only_bind_into ] ( cmp )
1012- .hasOperands ( pragma [ only_bind_into ] ( left ) , pragma [ only_bind_into ] ( right ) ) and
1013- isConvertedBool ( left .getDef ( ) ) and
1014- int_value ( right .getDef ( ) ) = 0 and
1015- unary_compares_eq ( valueNumberOfOperand ( left ) , op , k , areEqual , v )
1039+ // If we have e.g.:
1040+ // ```
1041+ // x = (a == 10)
1042+ // if(x != c) { ... }
1043+ // ```
1044+ // then `x != c` is true implies that `a == 10` is true.
1045+ // ```
1046+ exists ( Operand l , Operand r , ValueNumber vn , int c , AbstractValue v |
1047+ test .( CompareValueNumber ) .hasOperands ( l , r ) and
1048+ int_value ( r .getDef ( ) ) = c and
1049+ vn .getAnInstruction ( ) = getBooleanInstruction ( l .getDef ( ) ) and
1050+ compares_lt ( vn , op , k , areEqual , v )
10161051 |
1017- cmp instanceof CompareNEValueNumber and
1018- v = value
1052+ test instanceof CompareNEValueNumber and
1053+ if c = 0 then value = v else value = v . getDualValue ( )
10191054 or
1020- cmp instanceof CompareEQValueNumber and
1021- v .getDualValue ( ) = value
1055+ test instanceof CompareEQValueNumber and
1056+ if c = 0 then value = v .getDualValue ( ) else value = v
10221057 )
10231058 or
10241059 unary_compares_eq ( test .( BuiltinExpectCallValueNumber ) .getCondition ( ) , op , k , areEqual , value )
@@ -1192,6 +1227,12 @@ private module Cached {
11921227 unary_builtin_expect_eq ( test , op , k , areEqual , value )
11931228 }
11941229
1230+ private Instruction getBooleanInstruction ( Instruction instr ) {
1231+ result = instr .( ConvertBoolToIntOrPointerInstruction ) .getUnary ( )
1232+ or
1233+ result = getBooleanInstruction ( instr .( CopyInstruction ) .getSourceValue ( ) )
1234+ }
1235+
11951236 /*
11961237 * Simplification of inequality expressions
11971238 * Simplify conditions in the source to the canonical form l < r + k.
@@ -1215,6 +1256,26 @@ private module Cached {
12151256 exists ( AbstractValue dual | value = dual .getDualValue ( ) |
12161257 compares_lt ( test .( LogicalNotValueNumber ) .getUnary ( ) , left , right , k , isLt , dual )
12171258 )
1259+ or
1260+ // If we have e.g.:
1261+ // ```
1262+ // x = (a < b)
1263+ // if(x != c) { ... }
1264+ // ```
1265+ // then `x != c` is true implies that `a < b` is true.
1266+ // ```
1267+ exists ( Operand l , Operand r , ValueNumber vn , int c , AbstractValue v |
1268+ test .( CompareValueNumber ) .hasOperands ( l , r ) and
1269+ int_value ( r .getDef ( ) ) = c and
1270+ vn .getAnInstruction ( ) = getBooleanInstruction ( l .getDef ( ) ) and
1271+ compares_lt ( vn , left , right , k , isLt , v )
1272+ |
1273+ test instanceof CompareNEValueNumber and
1274+ if c = 0 then value = v else value = v .getDualValue ( )
1275+ or
1276+ test instanceof CompareEQValueNumber and
1277+ if c = 0 then value = v .getDualValue ( ) else value = v
1278+ )
12181279 }
12191280
12201281 /** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
@@ -1234,6 +1295,26 @@ private module Cached {
12341295 int_value ( const ) = k1 and
12351296 k = k1 + k2
12361297 )
1298+ or
1299+ // If we have e.g.:
1300+ // ```
1301+ // x = (a < 10)
1302+ // if(x != c) { ... }
1303+ // ```
1304+ // then `x != c` is true implies that `a < 10` is true.
1305+ // ```
1306+ exists ( Operand l , Operand r , ValueNumber vn , int c , AbstractValue v |
1307+ test .( CompareValueNumber ) .hasOperands ( l , r ) and
1308+ int_value ( r .getDef ( ) ) = c and
1309+ vn .getAnInstruction ( ) = getBooleanInstruction ( l .getDef ( ) ) and
1310+ compares_lt ( vn , op , k , isLt , v )
1311+ |
1312+ test instanceof CompareNEValueNumber and
1313+ if c = 0 then value = v else value = v .getDualValue ( )
1314+ or
1315+ test instanceof CompareEQValueNumber and
1316+ if c = 0 then value = v .getDualValue ( ) else value = v
1317+ )
12371318 }
12381319
12391320 /** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
0 commit comments