Hi, we currently miss to do RTX unsharing in some cases when mixing validate_change requests with and without rtx unsharing in the same change group.
Debugging a setjmp testcase on s390 I've seen the following behaviour: In an insn like A = B + C B is replaced with D in fold_rtx. Unsharing is requested for D in this replacement (A = D + C). Later on fold_rtx invokes canonicalize_change_group which decides to swap D and C without requesting unsharing again (A = C + D). Since the unsharing for a change group is delayed until confirm_change_group and is bound to a location rather then the expression C is unshared instead of D then. The attached patch prevents that by doing RTX unsharing for all subsequent changes after finding a single change where unsharing has been explicitly requested. Ok for mainline? Bye, -Andreas- 2011-03-04 Andreas Krebbel <andreas.kreb...@de.ibm.com> * recog.c (confirm_change_group): Unshare all RTXs after finding one in the group where unsharing has been requested. Index: gcc/recog.c =================================================================== *** gcc/recog.c.orig --- gcc/recog.c *************** confirm_change_group (void) *** 454,465 **** { int i; rtx last_object = NULL; for (i = 0; i < num_changes; i++) { rtx object = changes[i].object; ! if (changes[i].unshare) *changes[i].loc = copy_rtx (*changes[i].loc); /* Avoid unnecessary rescanning when multiple changes to same instruction --- 454,471 ---- { int i; rtx last_object = NULL; + bool unshare_p = false; for (i = 0; i < num_changes; i++) { rtx object = changes[i].object; ! /* After doing one change which needs unsharing all subsequent ! changes need unsharing as well. A subsequent change might ! move parts of the object which have been requested to get ! unshared before without requesting unsharing itself. */ ! unshare_p = unshare_p || changes[i].unshare; ! if (unshare_p) *changes[i].loc = copy_rtx (*changes[i].loc); /* Avoid unnecessary rescanning when multiple changes to same instruction