@@ -664,6 +664,14 @@ private void makeValue(AbstractCopyStmt copy, VersionedLocal ssaL) {
664664 * the value and value type.
665665 * */
666666 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+
667675 int opcode = e .getOpcode ();
668676 if (opcode == Opcode .LOCAL_LOAD ) {
669677 if (copy .isSynthetic ()) {
@@ -715,6 +723,25 @@ private void makeValue(AbstractCopyStmt copy, VersionedLocal ssaL) {
715723
716724// System.out.println("made val " + ssaL + " -> " + latest.get(ssaL));
717725 }
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+ }
718745
719746 private void collectUses (Expr e ) {
720747 for (Expr c : e .enumerateWithSelf ()) {
@@ -757,6 +784,11 @@ private void merge(VersionedLocal vla, VersionedLocal vlb) {
757784 }
758785
759786 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+
760792 List <ExceptionRange <BasicBlock >> dr = db .cfg .getProtectingRanges (db );
761793 List <ExceptionRange <BasicBlock >> ur = ub .cfg .getProtectingRanges (ub );
762794
@@ -786,6 +818,32 @@ private boolean canTransferHandlers(BasicBlock db, BasicBlock ub) {
786818
787819 return transferable ;
788820 }
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+ }
789847
790848 private void translateStmt (VarExpr var , boolean resolve , boolean isPhi ) {
791849 /* Here we only remap local variable loads
@@ -824,15 +882,10 @@ private void translateStmt(VarExpr var, boolean resolve, boolean isPhi) {
824882
825883 if (optimise ) {
826884 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.*/
832885 LatestValue value = latest .get (ssaL );
833886 boolean unpredictable = value .getType () == LatestValue .PARAM || value .getType () == LatestValue .PHI ;
834887
835- if (unpredictable && ssaL != value .getSuggestedValue ()) {
888+ if (unpredictable && value .getSuggestedValue () instanceof VersionedLocal ) {
836889 VersionedLocal vl = (VersionedLocal ) value .getSuggestedValue ();
837890 if (shouldPropagate (ssaL , vl )) {
838891 newL = vl ;
@@ -841,92 +894,49 @@ private void translateStmt(VarExpr var, boolean resolve, boolean isPhi) {
841894 Expr e = null ;
842895
843896 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 ());
883908 }
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+ }
895923 }
896924 }
897925 }
898-
926+
899927 if (e != null ) {
900- // System.out.println("=====");
901- // System.out.println(" ssaL: " + ssaL);
902- // System.out.println(" bpar: " + var.getParent());
903928 CodeUnit parent = var .getParent ();
904929 int idx = parent .indexOf (var );
905930 parent .writeAt (e = e .copy (), idx );
906931
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.*/
916932 pool .uses .get (ssaL ).remove (var );
917- // System.out.println(" uses: " + pool.uses.get(ssaL));
918933
919- /* Account for the new pool.uses.*/
920934 collectUses (e );
921935
922- /* Finally see if we can reduce
923- * this statement further.*/
924936 translate (e , false , isPhi );
925937
926938 exists = false ;
927939 }
928- } else {
929- newL = ssaL ;
930940 }
931941 } else {
932942 throw new IllegalStateException ("No (self) ancestors: " + l + " -> " + ssaL );
@@ -935,19 +945,12 @@ private void translateStmt(VarExpr var, boolean resolve, boolean isPhi) {
935945
936946 if (exists ) {
937947 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);
942948 if (ssaL != newL ) {
943- // System.out.println(ssaL + " --> " + newL);
944949 pool .uses .get (ssaL ).remove (var );
945950 pool .uses .get (newL ).add (var );
946951 }
947952 }
948953
949- /* If the expression still exists, update
950- * or set both variable and type information.*/
951954 var .setLocal (newL );
952955 Type type = types .get (ssaL );
953956 if (type == null ) {
0 commit comments