@@ -923,6 +923,55 @@ private predicate simple_comparison_eq(
923
923
value .( BooleanValue ) .getValue ( ) = false
924
924
}
925
925
926
+ /**
927
+ * Holds if `op` is an operand that is eventually used in a unary comparison
928
+ * with a constant.
929
+ */
930
+ private predicate isRelevantUnaryComparisonOperand ( Operand op ) {
931
+ // Base case: `op` is an operand of a `CompareEQInstruction` or `CompareNEInstruction`,
932
+ // and the other operand is a constant.
933
+ exists ( CompareInstruction eq , Instruction instr |
934
+ eq .hasOperands ( op , instr .getAUse ( ) ) and
935
+ exists ( int_value ( instr ) )
936
+ |
937
+ eq instanceof CompareEQInstruction
938
+ or
939
+ eq instanceof CompareNEInstruction
940
+ )
941
+ or
942
+ // C doesn't have int-to-bool conversions, so `if(x)` will just generate:
943
+ // r2_1(glval<int>) = VariableAddress[x]
944
+ // r2_2(int) = Load[x] : &:r2_1, m1_6
945
+ // v2_3(void) = ConditionalBranch : r2_2
946
+ exists ( ConditionalBranchInstruction branch | branch .getConditionOperand ( ) = op )
947
+ or
948
+ // If `!x` is a relevant unary comparison then so is `x`.
949
+ exists ( LogicalNotInstruction logicalNot |
950
+ isRelevantUnaryComparisonOperand ( unique( | | logicalNot .getAUse ( ) ) ) and
951
+ logicalNot .getUnaryOperand ( ) = op
952
+ )
953
+ or
954
+ // If `y` is a relevant unary comparison and `y = x` then so is `x`.
955
+ not op .isDefinitionInexact ( ) and
956
+ exists ( CopyInstruction copy |
957
+ isRelevantUnaryComparisonOperand ( unique( | | copy .getAUse ( ) ) ) and
958
+ op = copy .getSourceValueOperand ( )
959
+ )
960
+ or
961
+ // If phi(x1, x2) is a relevant unary comparison then so is `x1` and `x2`.
962
+ not op .isDefinitionInexact ( ) and
963
+ exists ( PhiInstruction phi |
964
+ isRelevantUnaryComparisonOperand ( unique( | | phi .getAUse ( ) ) ) and
965
+ op = phi .getAnInputOperand ( )
966
+ )
967
+ or
968
+ // If `__builtin_expect(x)` is a relevant unary comparison then so is `x`.
969
+ exists ( BuiltinExpectCallInstruction call |
970
+ isRelevantUnaryComparisonOperand ( unique( | | call .getAUse ( ) ) ) and
971
+ op = call .getConditionOperand ( )
972
+ )
973
+ }
974
+
926
975
/** Rearrange various simple comparisons into `op == k` form. */
927
976
private predicate unary_simple_comparison_eq (
928
977
ValueNumber test , Operand op , int k , boolean inNonZeroCase , AbstractValue value
@@ -936,41 +985,8 @@ private predicate unary_simple_comparison_eq(
936
985
inNonZeroCase = false
937
986
)
938
987
or
939
- // Any instruction with an integral type could potentially be part of a
940
- // check for nullness when used in a guard. So we include all integral
941
- // typed instructions here. However, since some of these instructions are
942
- // already included as guards in other cases, we exclude those here.
943
- // These are instructions that compute a binary equality or inequality
944
- // relation. For example, the following:
945
- // ```cpp
946
- // if(a == b + 42) { ... }
947
- // ```
948
- // generates the following IR:
949
- // ```
950
- // r1(glval<int>) = VariableAddress[a] :
951
- // r2(int) = Load[a] : &:r1, m1
952
- // r3(glval<int>) = VariableAddress[b] :
953
- // r4(int) = Load[b] : &:r3, m2
954
- // r5(int) = Constant[42] :
955
- // r6(int) = Add : r4, r5
956
- // r7(bool) = CompareEQ : r2, r6
957
- // v1(void) = ConditionalBranch : r7
958
- // ```
959
- // and since `r7` is an integral typed instruction this predicate could
960
- // include a case for when `r7` evaluates to true (in which case we would
961
- // infer that `r6` was non-zero, and a case for when `r7` evaluates to false
962
- // (in which case we would infer that `r6` was zero).
963
- // However, since `a == b + 42` is already supported when reasoning about
964
- // binary equalities we exclude those cases here.
965
- not test .isGLValue ( ) and
966
- not simple_comparison_eq ( test , _, _, _, _) and
967
- not simple_comparison_lt ( test , _, _, _) and
968
- op = test .getExpressionOperand ( ) and
969
- (
970
- test .getResultIRType ( ) instanceof IRAddressType or
971
- test .getResultIRType ( ) instanceof IRIntegerType or
972
- test .getResultIRType ( ) instanceof IRBooleanType
973
- ) and
988
+ isRelevantUnaryComparisonOperand ( op ) and
989
+ op .getDef ( ) = test .getAnInstruction ( ) and
974
990
(
975
991
k = 1 and
976
992
value .( BooleanValue ) .getValue ( ) = true and
@@ -987,10 +1003,12 @@ private class BuiltinExpectCallInstruction extends CallInstruction {
987
1003
BuiltinExpectCallInstruction ( ) { this .getStaticCallTarget ( ) .hasName ( "__builtin_expect" ) }
988
1004
989
1005
/** Gets the condition of this call. */
990
- Instruction getCondition ( ) {
1006
+ Instruction getCondition ( ) { result = this .getConditionOperand ( ) .getDef ( ) }
1007
+
1008
+ Operand getConditionOperand ( ) {
991
1009
// The first parameter of `__builtin_expect` has type `long`. So we skip
992
1010
// the conversion when inferring guards.
993
- result = this .getArgument ( 0 ) .( ConvertInstruction ) .getUnary ( )
1011
+ result = this .getArgument ( 0 ) .( ConvertInstruction ) .getUnaryOperand ( )
994
1012
}
995
1013
}
996
1014
0 commit comments