------- Comment #2 from ebotcazou at gcc dot gnu dot org 2008-09-09 19:17 ------- Several files are miscompiled by the stage1 compiler, starting with c-decl.c. Now if you take the preprocessed file c-decl.i and compile it with a cross on Linux, the resulting code is OK (the differences are in offsets against FP).
The discrepancy comes from the second qsort in ira_sort_regnos_for_alter_reg: /* Sort regnos according the slot numbers. */ regno_max_ref_width = reg_max_ref_width; qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_slot_compare); It is not stable and this is quite obvious by looking at the compare function: /* Sort pseudos according their slot numbers (putting ones with smaller numbers first, or last when the frame pointer is not needed). */ static int coalesced_pseudo_reg_slot_compare (const void *v1p, const void *v2p) { const int regno1 = *(const int *) v1p; const int regno2 = *(const int *) v2p; ira_allocno_t a1 = ira_regno_allocno_map[regno1]; ira_allocno_t a2 = ira_regno_allocno_map[regno2]; int diff, slot_num1, slot_num2; int total_size1, total_size2; if (a1 == NULL || ALLOCNO_HARD_REGNO (a1) >= 0) { if (a2 == NULL || ALLOCNO_HARD_REGNO (a2) >= 0) return (const int *) v1p - (const int *) v2p; /* Save the order. */ return 1; } else if (a2 == NULL || ALLOCNO_HARD_REGNO (a2) >= 0) return -1; slot_num1 = -ALLOCNO_HARD_REGNO (a1); slot_num2 = -ALLOCNO_HARD_REGNO (a2); if ((diff = slot_num1 - slot_num2) != 0) return (frame_pointer_needed || !FRAME_GROWS_DOWNWARD == STACK_GROWS_DOWNWARD ? diff : -diff); total_size1 = MAX (PSEUDO_REGNO_BYTES (regno1), regno_max_ref_width[regno1]); total_size2 = MAX (PSEUDO_REGNO_BYTES (regno2), regno_max_ref_width[regno2]); if ((diff = total_size2 - total_size1) != 0) return diff; return (const int *) v1p - (const int *) v2p; /* Save the order. */ } The following patchlet stabilizes the sort: Index: ira-color.c =================================================================== --- ira-color.c (revision 140145) +++ ira-color.c (working copy) @@ -2169,7 +2169,7 @@ coalesced_pseudo_reg_slot_compare (const if (a1 == NULL || ALLOCNO_HARD_REGNO (a1) >= 0) { if (a2 == NULL || ALLOCNO_HARD_REGNO (a2) >= 0) - return (const int *) v1p - (const int *) v2p; /* Save the order. */ + return regno1 - regno2; return 1; } else if (a2 == NULL || ALLOCNO_HARD_REGNO (a2) >= 0) @@ -2183,7 +2183,7 @@ coalesced_pseudo_reg_slot_compare (const total_size2 = MAX (PSEUDO_REGNO_BYTES (regno2), regno_max_ref_width[regno2]); if ((diff = total_size2 - total_size1) != 0) return diff; - return (const int *) v1p - (const int *) v2p; /* Save the order. */ + return regno1 - regno2; } /* Setup REGNO_COALESCED_ALLOCNO_COST and REGNO_COALESCED_ALLOCNO_NUM and the resulting code is the same (and correct) on both Linux and Solaris. Bootstrap is still running, we'll see how far it goes after that. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37424