@@ -664,6 +664,14 @@ private void makeValue(AbstractCopyStmt copy, VersionedLocal ssaL) {
664
664
* the value and value type.
665
665
* */
666
666
Expr e = copy .getExpression ();
667
+
668
+ // Be more conservative with array accesses and loop variables
669
+ if (isInLoop (copy .getBlock ()) && (containsArrayAccess (e ) || isLoopVariable (ssaL ))) {
670
+ LatestValue value = new LatestValue (builder .graph , LatestValue .VAR , ssaL , null );
671
+ latest .put (ssaL , value );
672
+ return ;
673
+ }
674
+
667
675
int opcode = e .getOpcode ();
668
676
if (opcode == Opcode .LOCAL_LOAD ) {
669
677
if (copy .isSynthetic ()) {
@@ -715,6 +723,25 @@ private void makeValue(AbstractCopyStmt copy, VersionedLocal ssaL) {
715
723
716
724
// System.out.println("made val " + ssaL + " -> " + latest.get(ssaL));
717
725
}
726
+
727
+ private boolean containsArrayAccess (Expr e ) {
728
+ for (Expr child : e .enumerateWithSelf ()) {
729
+ if (child .getOpcode () == Opcode .ARRAY_LOAD ||
730
+ child .getOpcode () == Opcode .ARRAY_STORE ) {
731
+ return true ;
732
+ }
733
+ }
734
+ return false ;
735
+ }
736
+
737
+ private boolean isLoopVariable (VersionedLocal local ) {
738
+ // Check if this local is used in loop conditions
739
+ AbstractCopyStmt def = pool .defs .get (local );
740
+ if (def != null && isInLoop (def .getBlock ())) {
741
+ return true ;
742
+ }
743
+ return false ;
744
+ }
718
745
719
746
private void collectUses (Expr e ) {
720
747
for (Expr c : e .enumerateWithSelf ()) {
@@ -757,6 +784,11 @@ private void merge(VersionedLocal vla, VersionedLocal vlb) {
757
784
}
758
785
759
786
private boolean canTransferHandlers (BasicBlock db , BasicBlock ub ) {
787
+ // Add loop check
788
+ if (isInLoop (db ) || isInLoop (ub )) {
789
+ return false ; // Be conservative with transfers in loops
790
+ }
791
+
760
792
List <ExceptionRange <BasicBlock >> dr = db .cfg .getProtectingRanges (db );
761
793
List <ExceptionRange <BasicBlock >> ur = ub .cfg .getProtectingRanges (ub );
762
794
@@ -786,6 +818,32 @@ private boolean canTransferHandlers(BasicBlock db, BasicBlock ub) {
786
818
787
819
return transferable ;
788
820
}
821
+
822
+
823
+ // Add helper method to detect if block is in a loop
824
+ private boolean isInLoop (BasicBlock block ) {
825
+ // Simple loop detection - if block can reach itself
826
+ Set <BasicBlock > visited = new HashSet <>();
827
+ LinkedList <BasicBlock > queue = new LinkedList <>();
828
+ queue .add (block );
829
+
830
+ while (!queue .isEmpty ()) {
831
+ BasicBlock current = queue .poll ();
832
+ if (!visited .add (current )) {
833
+ continue ;
834
+ }
835
+
836
+ for (FlowEdge <BasicBlock > edge : builder .graph .getEdges (current )) {
837
+ BasicBlock succ = edge .dst ();
838
+ if (succ == block ) {
839
+ return true ;
840
+ }
841
+ queue .add (succ );
842
+ }
843
+ }
844
+
845
+ return false ;
846
+ }
789
847
790
848
private void translateStmt (VarExpr var , boolean resolve , boolean isPhi ) {
791
849
/* Here we only remap local variable loads
@@ -824,15 +882,10 @@ private void translateStmt(VarExpr var, boolean resolve, boolean isPhi) {
824
882
825
883
if (optimise ) {
826
884
if (latest .containsKey (ssaL )) {
827
- /* Try to propagate a simple copy local
828
- * to its use site. It is possible that
829
- * a non simple copy (including phis)
830
- * will not have a mapping. In this case
831
- * they will not have an updated target.*/
832
885
LatestValue value = latest .get (ssaL );
833
886
boolean unpredictable = value .getType () == LatestValue .PARAM || value .getType () == LatestValue .PHI ;
834
887
835
- if (unpredictable && ssaL != value .getSuggestedValue ()) {
888
+ if (unpredictable && value .getSuggestedValue () instanceof VersionedLocal ) {
836
889
VersionedLocal vl = (VersionedLocal ) value .getSuggestedValue ();
837
890
if (shouldPropagate (ssaL , vl )) {
838
891
newL = vl ;
@@ -841,92 +894,49 @@ private void translateStmt(VarExpr var, boolean resolve, boolean isPhi) {
841
894
Expr e = null ;
842
895
843
896
AbstractCopyStmt def = pool .defs .get (ssaL );
844
- Expr rval = (Expr ) value .getSuggestedValue ();
845
- if (ConstraintUtil .isUncopyable (rval )) {
846
- /* A variable might have a value
847
- * that is uncopyable such as an
848
- * invoke or allocation call.
849
- *
850
- * There are two ways this may happen:
851
- * x = call();
852
- * or
853
- * x = call();
854
- * y = x;
855
- *
856
- * we defer optimising the first
857
- * case till the end.
858
- *
859
- * in the second case, we can
860
- * propagate the source var (x)
861
- * in place of the target (y). */
862
- newL = tryDefer (value , ssaL );
863
- } else {
864
- AbstractCopyStmt from = def ;
865
- if (value .getSource () != null ) {
866
- from = pool .defs .get (value .getSource ());
867
- }
868
-
869
- if (!value .hasConstraints () || (canTransferHandlers (def .getBlock (), var .getBlock ()) && value .canPropagate (from , var .getRootParent (), var , false ))) {
870
- /*System.out.printf("d: %s%n", def);
871
- System.out.printf("f: %s%n", from);
872
- System.out.printf("u: %s%n", var.getRootParent());
873
- System.out.printf("l: %s%n", ssaL);
874
- System.out.printf("v: %s%n", value);
875
- System.out.printf("rv: %s%n", rval);
876
- System.out.printf("c: %b%n", value.hasConstraints());
877
- System.out.println();*/
878
-
879
- if (shouldCopy (rval )) {
880
- e = rval ;
881
- } else {
882
- newL = tryDefer (value , ssaL );
897
+ Object suggestedValue = value .getSuggestedValue ();
898
+
899
+ // Make sure suggestedValue is an Expr before casting
900
+ if (suggestedValue instanceof Expr ) {
901
+ Expr rval = (Expr ) suggestedValue ;
902
+ if (ConstraintUtil .isUncopyable (rval )) {
903
+ newL = tryDefer (value , ssaL );
904
+ } else {
905
+ AbstractCopyStmt from = def ;
906
+ if (value .getSource () != null ) {
907
+ from = pool .defs .get (value .getSource ());
883
908
}
884
- } else if (value .getRealValue () instanceof VersionedLocal ) {
885
- VersionedLocal realVal = (VersionedLocal ) value .getRealValue ();
886
- if (shouldPropagate (ssaL , realVal )) {
887
- newL = realVal ;
888
- } else {
889
- // 1/21/2019: fix for propagation across multiple variables in a congruence class
890
- // (i.e. replacing two variables with one spill later in resolveShadowedLocals)
891
- merge (ssaL , realVal );
892
- // This code was incorrect
893
- // shadowed.getNonNull(ssaL).add(realVal);
894
- // shadowed.getNonNull(realVal).add(ssaL);
909
+
910
+ if (!value .hasConstraints () || (canTransferHandlers (def .getBlock (), var .getBlock ()) && value .canPropagate (from , var .getRootParent (), var , false ))) {
911
+ if (shouldCopy (rval )) {
912
+ e = rval ;
913
+ } else {
914
+ newL = tryDefer (value , ssaL );
915
+ }
916
+ } else if (value .getRealValue () instanceof VersionedLocal ) {
917
+ VersionedLocal realVal = (VersionedLocal ) value .getRealValue ();
918
+ if (shouldPropagate (ssaL , realVal )) {
919
+ newL = realVal ;
920
+ } else {
921
+ merge (ssaL , realVal );
922
+ }
895
923
}
896
924
}
897
925
}
898
-
926
+
899
927
if (e != null ) {
900
- // System.out.println("=====");
901
- // System.out.println(" ssaL: " + ssaL);
902
- // System.out.println(" bpar: " + var.getParent());
903
928
CodeUnit parent = var .getParent ();
904
929
int idx = parent .indexOf (var );
905
930
parent .writeAt (e = e .copy (), idx );
906
931
907
- // System.out.println(" def: " + def);
908
- // System.out.println(" idx: " + idx);
909
- // System.out.println(" val: " + value);
910
- // System.out.println(" apar: " + parent);
911
- // System.out.println(" e: " + e);
912
-
913
- /* Remove the use of the var before
914
- * we translate the children of the
915
- * newly propagated expression.*/
916
932
pool .uses .get (ssaL ).remove (var );
917
- // System.out.println(" uses: " + pool.uses.get(ssaL));
918
933
919
- /* Account for the new pool.uses.*/
920
934
collectUses (e );
921
935
922
- /* Finally see if we can reduce
923
- * this statement further.*/
924
936
translate (e , false , isPhi );
925
937
926
938
exists = false ;
927
939
}
928
- } else {
929
- newL = ssaL ;
930
940
}
931
941
} else {
932
942
throw new IllegalStateException ("No (self) ancestors: " + l + " -> " + ssaL );
@@ -935,19 +945,12 @@ private void translateStmt(VarExpr var, boolean resolve, boolean isPhi) {
935
945
936
946
if (exists ) {
937
947
if (optimise || false ) {
938
- /* If we removed the local load expression,
939
- * check to see if we need to update the
940
- * use-map.*/
941
- // System.out.println("replace: " + ssaL + " with " + newL);
942
948
if (ssaL != newL ) {
943
- // System.out.println(ssaL + " --> " + newL);
944
949
pool .uses .get (ssaL ).remove (var );
945
950
pool .uses .get (newL ).add (var );
946
951
}
947
952
}
948
953
949
- /* If the expression still exists, update
950
- * or set both variable and type information.*/
951
954
var .setLocal (newL );
952
955
Type type = types .get (ssaL );
953
956
if (type == null ) {
0 commit comments