PR rtl-optimization/78911 * lra-assigns.c (must_not_spill_p): New function. (spill_for): Use it. PR rtl-optimization/78911 * gcc.target/i386/pr78911-1.c: New test. * gcc.target/i386/pr78911-2.c: New test. Index: gcc/lra-assigns.c =================================================================== --- gcc/lra-assigns.c (revision 245685) +++ gcc/lra-assigns.c (working copy) @@ -889,6 +889,30 @@ assign_temporarily (int regno, int hard_ live_pseudos_reg_renumber[regno] = hard_regno; } +/* Return true iff there is a reason why pseudo SPILL_REGNO should not + be spilled. */ +static bool +must_not_spill_p (unsigned spill_regno) +{ + if ((pic_offset_table_rtx != NULL + && spill_regno == REGNO (pic_offset_table_rtx)) + || ((int) spill_regno >= lra_constraint_new_regno_start + && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno) + && ! bitmap_bit_p (&lra_split_regs, spill_regno) + && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno) + && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno))) + return true; + /* A reload pseudo that requires a singleton register class should + not be spilled. + FIXME: this mitigates the issue on certain i386 patterns, but + does not solve the general case where existing reloads fully + cover a limited register class. */ + if (!bitmap_bit_p (&non_reload_pseudos, spill_regno) + && reg_class_size [reg_preferred_class (spill_regno)] == 1) + return true; + return false; +} + /* Array used for sorting reload pseudos for subsequent allocation after spilling some pseudo. */ static int *sorted_reload_pseudos; @@ -960,13 +984,7 @@ spill_for (int regno, bitmap spilled_pse /* Spill pseudos. */ static_p = false; EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi) - if ((pic_offset_table_rtx != NULL - && spill_regno == REGNO (pic_offset_table_rtx)) - || ((int) spill_regno >= lra_constraint_new_regno_start - && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno) - && ! bitmap_bit_p (&lra_split_regs, spill_regno) - && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno) - && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno))) + if (must_not_spill_p (spill_regno)) goto fail; else if (non_spilled_static_chain_regno_p (spill_regno)) static_p = true; Index: gcc/testsuite/gcc.target/i386/pr78911-1.c =================================================================== --- gcc/testsuite/gcc.target/i386/pr78911-1.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr78911-1.c (working copy) @@ -0,0 +1,22 @@ +/* PR rtl-optimization/78911 */ +/* { dg-do compile } */ +/* { dg-options "-O3 -fno-strict-aliasing -fno-omit-frame-pointer" } */ +/* { dg-additional-options "-fPIC" { target fpic } } */ +/* { dg-additional-options "-march=pentium-m" { target ia32 } } */ + +int a, b, d, e; +long long *c; + +static int +foo (long long *x) +{ + return __sync_val_compare_and_swap (x, b, a); +} + +void +bar (void) +{ + if (!c) + return; + e = foo (&c[d]); +} Index: gcc/testsuite/gcc.target/i386/pr78911-2.c =================================================================== --- gcc/testsuite/gcc.target/i386/pr78911-2.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr78911-2.c (working copy) @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-omit-frame-pointer" } */ +/* { dg-additional-options "-fPIC" { target fpic } } */ +/* { dg-additional-options "-march=i686" { target ia32 } } */ + +long long *a, *b, c; +int d, e; +int baz (void); + +static inline long long +foo (long long *x) +{ + return __sync_val_compare_and_swap (x, 0, 0); +} + +void +bar () +{ + int f = baz (); + c = foo (&a[f]); + if (c) + e = d; + a = b; +}