@@ -299,12 +299,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
299299 v = TValue ( TValueConstant ( c .asConstantValue ( ) ) , true )
300300 }
301301
302- private predicate exprHasValue ( Expr e , GuardValue v ) {
303- constantHasValue ( e , v )
304- or
305- e instanceof NonNullExpr and v = TValue ( TValueNull ( ) , false )
306- }
307-
308302 private predicate exceptionBranchPoint ( BasicBlock bb1 , BasicBlock normalSucc , BasicBlock excSucc ) {
309303 exists ( SuccessorType norm , ExceptionSuccessor exc |
310304 bb1 .getASuccessor ( norm ) = normalSucc and
@@ -426,30 +420,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
426420 branch = false and result = cond .getElse ( )
427421 }
428422
429- bindingset [ g1, v1]
430- pragma [ inline_late]
431- private predicate unboundBaseImpliesStep ( PreGuard g1 , GuardValue v1 , PreGuard g2 , GuardValue v2 ) {
432- g1 .( IdExpr ) .getEqualChildExpr ( ) = g2 and v1 = v2 and not v1 instanceof TException
433- or
434- exists ( ConditionalExpr cond , boolean branch , Expr e , GuardValue ev |
435- cond = g1 and
436- e = getBranchExpr ( cond , branch ) and
437- exprHasValue ( e , ev ) and
438- disjointValues ( v1 , ev )
439- |
440- // g1 === g2 ? e : ...;
441- // g1 === g2 ? ... : e;
442- g2 = cond .getCondition ( ) and
443- v2 = TValue ( TValueTrue ( ) , branch .booleanNot ( ) )
444- or
445- // g1 === ... ? g2 : e
446- // g1 === ... ? e : g2
447- g2 = getBranchExpr ( cond , branch .booleanNot ( ) ) and
448- v2 = v1 and
449- not exprHasValue ( g2 , v2 ) // disregard trivial guard
450- )
451- }
452-
453423 private predicate baseImpliesStep ( PreGuard g1 , GuardValue v1 , PreGuard g2 , GuardValue v2 ) {
454424 g1 .( AndExpr ) .getAnOperand ( ) = g2 and v1 = TValue ( TValueTrue ( ) , true ) and v2 = v1
455425 or
@@ -532,15 +502,17 @@ module Make<LocationSig Location, InputSig<Location> Input> {
532502 private import LogicInput
533503
534504 private predicate guardControlsPhiBranch (
535- Guard guard , GuardValue v , SsaPhiNode phi , Expr input , BasicBlock bbInput , BasicBlock bbPhi
505+ Guard guard , GuardValue v , SsaPhiNode phi , SsaDefinition inp
536506 ) {
537- exists ( SsaWriteDefinition inp |
538- phi .hasInputFromBlock ( inp , bbInput ) and
507+ exists ( BasicBlock bbPhi |
508+ phi .hasInputFromBlock ( inp , _ ) and
539509 phi .getBasicBlock ( ) = bbPhi and
540- inp .getDefinition ( ) = input and
541- guard .directlyValueControls ( bbInput , v ) and
542510 guard .getBasicBlock ( ) .strictlyDominates ( bbPhi ) and
543- not guard .directlyValueControls ( bbPhi , _)
511+ not guard .directlyValueControls ( bbPhi , _) and
512+ forex ( BasicBlock bbInput | phi .hasInputFromBlock ( inp , bbInput ) |
513+ guard .directlyValueControls ( bbInput , v ) or
514+ guard .hasValueBranchEdge ( bbInput , bbPhi , v )
515+ )
544516 )
545517 }
546518
@@ -552,13 +524,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
552524 * This makes `phi` similar to the conditional `phi = guard==v ? input : ...`.
553525 */
554526 private predicate guardDeterminesPhiInput ( Guard guard , GuardValue v , SsaPhiNode phi , Expr input ) {
555- exists ( GuardValue dv , BasicBlock bbInput , BasicBlock bbPhi |
556- guardControlsPhiBranch ( guard , v , phi , input , bbInput , bbPhi ) and
527+ exists ( GuardValue dv , SsaWriteDefinition inp |
528+ guardControlsPhiBranch ( guard , v , phi , inp ) and
529+ inp .getDefinition ( ) = input and
557530 dv = v .getDualValue ( ) and
558- forall ( BasicBlock other | phi .hasInputFromBlock ( _, other ) and other != bbInput |
559- guard .directlyValueControls ( other , dv )
560- or
561- guard .hasValueBranchEdge ( other , bbPhi , dv )
531+ forall ( SsaDefinition other | phi .hasInputFromBlock ( other , _) and other != inp |
532+ guardControlsPhiBranch ( guard , dv , phi , other )
562533 )
563534 )
564535 }
@@ -702,14 +673,67 @@ module Make<LocationSig Location, InputSig<Location> Input> {
702673 or
703674 exists ( boolean isNull |
704675 additionalNullCheck ( g1 , v1 , g2 , isNull ) and
705- v2 = TValue ( TValueNull ( ) , isNull )
676+ v2 = TValue ( TValueNull ( ) , isNull ) and
677+ not ( g2 instanceof NonNullExpr and isNull = false ) // disregard trivial guard
678+ )
679+ }
680+
681+ /**
682+ * Holds if `g` evaluating to `v` implies that `def` evaluates to `ssaVal`.
683+ * The included set of implications is somewhat restricted to avoid a
684+ * recursive dependency on `exprHasValue`.
685+ */
686+ private predicate baseSsaValueCheck ( SsaDefinition def , GuardValue ssaVal , Guard g , GuardValue v ) {
687+ exists ( Guard g0 , GuardValue v0 |
688+ guardReadsSsaVar ( g0 , def ) and v0 = ssaVal
689+ or
690+ baseSsaValueCheck ( def , ssaVal , g0 , v0 )
691+ |
692+ impliesStep ( g , v , g0 , v0 )
693+ )
694+ }
695+
696+ private predicate exprHasValue ( Expr e , GuardValue v ) {
697+ constantHasValue ( e , v )
698+ or
699+ e instanceof NonNullExpr and v = TValue ( TValueNull ( ) , false )
700+ or
701+ exprHasValue ( e .( IdExpr ) .getEqualChildExpr ( ) , v )
702+ or
703+ exists ( SsaDefinition def , Guard g , GuardValue gv |
704+ e = def .getARead ( ) and
705+ g .directlyValueControls ( e .getBasicBlock ( ) , gv ) and
706+ baseSsaValueCheck ( def , v , g , gv )
707+ )
708+ or
709+ exists ( SsaWriteDefinition def |
710+ exprHasValue ( def .getDefinition ( ) , v ) and
711+ e = def .getARead ( )
706712 )
707713 }
708714
709715 bindingset [ g1, v1]
710716 pragma [ inline_late]
711717 private predicate unboundImpliesStep ( Guard g1 , GuardValue v1 , Guard g2 , GuardValue v2 ) {
712- unboundBaseImpliesStep ( g1 , v1 , g2 , v2 )
718+ g1 .( IdExpr ) .getEqualChildExpr ( ) = g2 and v1 = v2 and not v1 instanceof TException
719+ or
720+ exists ( ConditionalExpr cond , boolean branch , Expr e , GuardValue ev |
721+ cond = g1 and
722+ e = getBranchExpr ( cond , branch ) and
723+ exprHasValue ( e , ev ) and
724+ disjointValues ( v1 , ev )
725+ |
726+ // g1 === g2 ? e : ...;
727+ // g1 === g2 ? ... : e;
728+ g2 = cond .getCondition ( ) and
729+ v2 = TValue ( TValueTrue ( ) , branch .booleanNot ( ) )
730+ or
731+ // g1 === ... ? g2 : e
732+ // g1 === ... ? e : g2
733+ g2 = getBranchExpr ( cond , branch .booleanNot ( ) ) and
734+ v2 = v1 and
735+ not exprHasValue ( g2 , v2 ) // disregard trivial guard
736+ )
713737 }
714738
715739 bindingset [ def1, v1]
@@ -742,7 +766,11 @@ module Make<LocationSig Location, InputSig<Location> Input> {
742766 * Calculates the transitive closure of all the guard implication steps
743767 * starting from a given set of base cases.
744768 */
745- private module ImpliesTC< baseGuardValueSig / 2 baseGuardValue> {
769+ module ImpliesTC< baseGuardValueSig / 2 baseGuardValue> {
770+ /**
771+ * Holds if `tgtGuard` evaluating to `tgtVal` implies that `guard`
772+ * evaluates to `v`.
773+ */
746774 pragma [ nomagic]
747775 predicate guardControls ( Guard guard , GuardValue v , Guard tgtGuard , GuardValue tgtVal ) {
748776 baseGuardValue ( tgtGuard , tgtVal ) and
@@ -770,6 +798,10 @@ module Make<LocationSig Location, InputSig<Location> Input> {
770798 )
771799 }
772800
801+ /**
802+ * Holds if `tgtGuard` evaluating to `tgtVal` implies that `def`
803+ * evaluates to `v`.
804+ */
773805 pragma [ nomagic]
774806 predicate ssaControls ( SsaDefinition def , GuardValue v , Guard tgtGuard , GuardValue tgtVal ) {
775807 exists ( Guard g0 |
0 commit comments