@@ -936,6 +936,16 @@ private module Cached {
936
936
ValueNumber getUnary ( ) { result .getAnInstruction ( ) = instr .getUnary ( ) }
937
937
}
938
938
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
+
939
949
/**
940
950
* Holds if `left == right + k` is `areEqual` given that test is `testIsTrue`.
941
951
*
@@ -966,6 +976,26 @@ private module Cached {
966
976
)
967
977
or
968
978
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
+ )
969
999
}
970
1000
971
1001
private predicate isConvertedBool ( Instruction instr ) {
@@ -1006,19 +1036,24 @@ private module Cached {
1006
1036
k = k1 + k2
1007
1037
)
1008
1038
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 )
1016
1051
|
1017
- cmp instanceof CompareNEValueNumber and
1018
- v = value
1052
+ test instanceof CompareNEValueNumber and
1053
+ if c = 0 then value = v else value = v . getDualValue ( )
1019
1054
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
1022
1057
)
1023
1058
or
1024
1059
unary_compares_eq ( test .( BuiltinExpectCallValueNumber ) .getCondition ( ) , op , k , areEqual , value )
@@ -1192,6 +1227,12 @@ private module Cached {
1192
1227
unary_builtin_expect_eq ( test , op , k , areEqual , value )
1193
1228
}
1194
1229
1230
+ private Instruction getBooleanInstruction ( Instruction instr ) {
1231
+ result = instr .( ConvertBoolToIntOrPointerInstruction ) .getUnary ( )
1232
+ or
1233
+ result = getBooleanInstruction ( instr .( CopyInstruction ) .getSourceValue ( ) )
1234
+ }
1235
+
1195
1236
/*
1196
1237
* Simplification of inequality expressions
1197
1238
* Simplify conditions in the source to the canonical form l < r + k.
@@ -1215,6 +1256,26 @@ private module Cached {
1215
1256
exists ( AbstractValue dual | value = dual .getDualValue ( ) |
1216
1257
compares_lt ( test .( LogicalNotValueNumber ) .getUnary ( ) , left , right , k , isLt , dual )
1217
1258
)
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
+ )
1218
1279
}
1219
1280
1220
1281
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
@@ -1234,6 +1295,26 @@ private module Cached {
1234
1295
int_value ( const ) = k1 and
1235
1296
k = k1 + k2
1236
1297
)
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
+ )
1237
1318
}
1238
1319
1239
1320
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
0 commit comments