On Mon, Jan 19, 2026 at 05:33:38PM +0100, Georg-Johann Lay wrote: > Am 19.01.26 um 15:06 schrieb Stefan Schulze Frielinghaus: > > On Mon, Jan 19, 2026 at 02:26:41PM +0100, Georg-Johann Lay wrote: > > > Am 14.01.26 um 14:55 schrieb Stefan Schulze Frielinghaus: > > > > From: Stefan Schulze Frielinghaus <[email protected]> > > > > > > > > I have put the check into cant_combine_insn_p(). However, I still > > > > haven't convinced myself that this is a full fledged solution. Even the > > > > current behaviour for constraints associated a single register class > > > > seems like only partially solved to me. For the current case it would > > > > solve the problem because we are substituting into a reg-reg move. > > > > However, my current understanding is that I could actually make use of > > > > hard registers in arbitrary patterns which wouldn't be dealt with. > > > > > > > > With this patch I'm conservative when hard register constraints are > > > > involved and skip any combination. > > > > > > > > In light of not having real world examples were it breaks also for > > > > constraints associated a single register class and being in stage 4, I'm > > > > limiting this to hard register constraints for now. > > > > > > > > @Jeff ok for mainline assuming that bootstrap and regtest are successful > > > > for x86_64 and s390? > > > > > > > > @Johann if you have a larger test than what you provided in the PR, > > > > could you give this patch a try? I can confirm that with the machine > > > > description patch provided in the PR, the example from the PR compiles > > > > fine if this patch is applied. If you still see failures in more > > > > complex examples you might also want to apply > > > > https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705494.html > > > > https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705495.html > > > > Note, I haven't tested hard register constraints in clobbers so far, and > > > > would rather assume that they do not work as expected. Once I find some > > > > time, I will look into this. > > > > > > Hi Stefan, > > > > > > I reran the tests, and there are still some ICEs. > > > > > > GCC is: > > > > > > commit 1367db23a5626499468d79b3c12a9b1859e7b819 (HEAD -> master, > > > origin/master, origin/HEAD) > > > Author: Tobias Burnus <[email protected]> > > > Date: Mon Jan 19 12:17:59 2026 +0100 > > > > > > Tests ran with x.diff. z.diff doesn't have an effect on the outcome. > > > > Hmm neither x.diff nor z.diff contain the patch you are currently > > replying to, i.e., the combine patch is missing. Did you still apply > > the combine patch? > > You mean this one? > > https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705494.html
No, that one is about ira. I mean the one you are replying to, i.e. the one about combine: https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705804.html > > I assumed it is upstream since it has been approved by Jeff. > I tried to apply it but patch complains. Because I pushed it last week as r16-6806-g6393102322a. > > Loosing track of what patches I need in what order and which are > outdated... No worries, don't feel obligated to test it. It was just a spontaneous idea I had. Cheers, Stefan > > I also tried the patch below (as y.diff like attached), but it gives > me ICE for unrecognizable insn, called from y.diff's > > extract_insn (insn); // around combine.cc::2246 > > AFAIK insn should be recognizable at this point, but may not be => ICE. > > In file included from > /home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.target/avr/torture/addr-space-1-fx.c:6: > /home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.target/avr/torture/addr-space-1.h: > In function 'main': > /home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.target/avr/torture/addr-space-1.h:96:1: > error: unrecognizable insn: > (insn 77 76 78 10 (set (reg:HI 30 r30) > (subreg:HI (symbol_ref:PSI ("A") [flags 0xe02] <var_decl > 0x7fda2559e000 A>) 0)) > "/home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.target/avr/torture/add\ > r-space-1.h":65:6 -1 > (expr_list:REG_EQUAL (subreg:HI (symbol_ref:PSI ("A") [flags 0xe02] > <var_decl 0x7fda2559e000 A>) 0) > (nil))) > during RTL pass: combine > /home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.target/avr/torture/addr-space-1.h:96:1: > internal compiler error: in extract_insn, at recog.cc:2888 > 0x1e482fc internal_error(char const*, ...) > ../../../source/gcc-x/gcc/diagnostic-global-context.cc:787 > 0x8bdd15 fancy_abort(char const*, int, char const*) > ../../../source/gcc-x/gcc/diagnostics/context.cc:1805 > 0x7597ff _fatal_insn(char const*, rtx_def const*, char const*, int, char > const*) > ../../../source/gcc-x/gcc/rtl-error.cc:108 > 0x75981b _fatal_insn_not_found(rtx_def const*, char const*, int, char const*) > ../../../source/gcc-x/gcc/rtl-error.cc:116 > 0x75814b extract_insn(rtx_insn*) > ../../../source/gcc-x/gcc/recog.cc:2888 > 0x1b9f635 cant_combine_insn_p > ../../../source/gcc-x/gcc/combine.cc:2246 > 0x1bafe17 try_combine > ../../../source/gcc-x/gcc/combine.cc:2681 > 0x1bb704c combine_instructions > ../../../source/gcc-x/gcc/combine.cc:1416 > 0x1bb704c rest_of_handle_combine > ../../../source/gcc-x/gcc/combine.cc:15253 > 0x1bb704c execute > ../../../source/gcc-x/gcc/combine.cc:15297 > > There is no such insn. Presumably there are 2 insns, > pseudo:PSI = symbol_ref:PSI ("A") > reg:HI = subreg:HI (pseudo:PSI 0). > Dunno why it slipped through, but checking that > the insn is recognizable at that point should be doable. > > > > Notice that x.diff is only a very small fraction of avr insns that > > > would use HRCs. > > > > > > Tests that now fail, but worked before (7 tests): > > > > > > atmega128-sim: gcc: gcc.c-torture/execute/pr94412.c -O1 (test for > > > excess errors) > > > atmega128-sim: gcc: gcc.c-torture/execute/pr94412.c -O2 (test for > > > excess errors) > > > atmega128-sim: gcc: gcc.c-torture/execute/pr94412.c -O2 -flto > > > -fno-use-linker-plugin -flto-partition=none (test for excess errors) > > > atmega128-sim: gcc: gcc.c-torture/execute/pr94412.c -O3 -g (test for > > > excess errors) > > > atmega128-sim: gcc: gcc.c-torture/execute/pr94412.c -Os (test for > > > excess errors) > > > atmega128-sim: gcc: gcc.dg/loop-invariant-2.c (test for excess errors) > > > atmega128-sim: gcc: gcc.dg/tree-ssa/ssa-lim-23.c (test for excess errors) > > > > > > The ICEs are like > > > > > > > > > /home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.c-torture/execute/pr94412.c: > > > In function 'bar': > > > /home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.c-torture/execute/pr94412.c:15:1: > > > error: unable to find a register to spill > > > /home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.c-torture/execute/pr94412.c:15:1: > > > error: this is the insn: > > > (insn 12 28 26 2 (parallel [ > > > (set (subreg:HI (reg:SI 73 [orig:52 _3 ] [52]) 0) > > > (udiv:HI (reg:HI 74 [58]) > > > (reg:HI 75 [orig:53 _9 ] [53]))) > > > (set (reg:HI 76 [57]) > > > (umod:HI (reg:HI 74 [58]) > > > (reg:HI 75 [orig:53 _9 ] [53]))) > > > (clobber (reg:HI 77 [67])) > > > (clobber (reg:QI 78 [68])) > > > ]) > > > "/home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.c-torture/execute/pr94412.c":14:12 > > > 604 {udivmodhi4} > > > (expr_list:REG_UNUSED (reg:QI 78 [68]) > > > (expr_list:REG_UNUSED (reg:HI 77 [67]) > > > (expr_list:REG_UNUSED (reg:HI 76 [57]) > > > (expr_list:REG_DEAD (reg:HI 75 [orig:53 _9 ] [53]) > > > (expr_list:REG_DEAD (reg:HI 74 [58]) > > > (nil))))))) > > > during RTL pass: reload > > > /home/gjl/gnu/source/gcc-x/gcc/testsuite/gcc.c-torture/execute/pr94412.c:15:1: > > > internal compiler error: in lra_split_hard_reg_for, at > > > lra-assigns.cc:1882 > > > 0x1e4823c internal_error(char const*, ...) > > > ../../../source/gcc-x/gcc/diagnostic-global-context.cc:787 > > > 0x8bdd15 fancy_abort(char const*, int, char const*) > > > ../../../source/gcc-x/gcc/diagnostics/context.cc:1805 > > > 0x7597ff _fatal_insn(char const*, rtx_def const*, char const*, int, char > > > const*) > > > ../../../source/gcc-x/gcc/rtl-error.cc:108 > > > 0xe39dc6 lra_split_hard_reg_for(bool) > > > ../../../source/gcc-x/gcc/lra-assigns.cc:1882 > > > 0xe338b6 lra(_IO_FILE*, int) > > > ../../../source/gcc-x/gcc/lra.cc:2535 > > > 0xde954f do_reload > > > ../../../source/gcc-x/gcc/ira.cc:6076 > > > 0xde954f execute > > > ../../../source/gcc-x/gcc/ira.cc:6264 > > > > > > As far as I understand, HRC won't work with scratches, > > > but almost all avr insns that would want to use HRCs have > > > hard reg clobbers. Such insns represent libgcc calls with > > > a reg footprint smaller than the ABI, and such functions > > > usually clobber at least some regs. > > > > > > What would happen to hard-reg clobbers under HRC? Wrong code? > > > > I haven't looked into this and cannot tell right away. > > > > > > > > Moreover, quite some insns rely on insn combine, e.g. the > > > ones for mul with sign-, zero- or one-extended operands. > > > AFAIU, HRCs are incompatible with insn combine, so that HRCs > > > are no alternative to the current hard-reg operands? > > > > > > There are almost no insns that don't need insn combine *and* > > > don't have hard-reg clobbers, so that almost nothing of HRC > > > is left to be usable in the avr backend :-( > > > > > > It seems a bit strange that insn combine would interfere with > > > RA. Some problems are when insn combine (or other passes) are > > > propagating hard regs into operands, but they don't match constraints > > > and RA has to kick them out again, perhaps resulting in sub-optimal code. > > > But in no case I saw RA ICEing. > > > > That is because so far RA had a choice here when regular register > > constraints were used with a register class with multiple registers. > > With hard register constraints, however, you really pin a pseudo to a > > particular hard register and if that is already live due to an > > assignment to that hard register you error out because it cannot be > > reloaded. > > Huh, I thought RA would try to spill the non-fitting reg? > I don't know anything about RA though... > > Cheers, > Johann > > > You run into the very same problem when you create single> register classes > > and assign them to new constraints and use those > > instead of hard register constraints. > > > > Cheers, > > Stefan > > > > > > > > > > > Johann > > > > > > > > > > -- 8< -- > > > > > > > > This fixes > > > > > > > > t.c:6:1: error: unable to find a register to spill > > > > 6 | } > > > > | ^ > > > > > > > > for target avr. In the PR we are given a patch which makes use of hard > > > > register constraints in the machine description for divmodhi4. Prior > > > > combine we have for the test from the PR > > > > > > > > (insn 7 6 8 2 (parallel [ > > > > (set (reg:HI 46 [ _1 ]) > > > > (div:HI (reg/v:HI 44 [ k ]) > > > > (reg:HI 48))) > > > > (set (reg:HI 47) > > > > (mod:HI (reg/v:HI 44 [ k ]) > > > > (reg:HI 48))) > > > > (clobber (scratch:HI)) > > > > (clobber (scratch:QI)) > > > > ]) "t.c":5:5 602 {divmodhi4} > > > > (expr_list:REG_DEAD (reg:HI 48) > > > > (expr_list:REG_DEAD (reg/v:HI 44 [ k ]) > > > > (expr_list:REG_UNUSED (reg:HI 47) > > > > (nil))))) > > > > (insn 8 7 9 2 (set (reg:HI 22 r22) > > > > (symbol_ref/f:HI ("*.LC0") [flags 0x2] <var_decl > > > > 0x3fff7950d10 *.LC0>)) "t.c":5:5 128 {*movhi_split} > > > > (nil)) > > > > (insn 9 8 10 2 (set (reg:HI 24 r24) > > > > (reg:HI 46 [ _1 ])) "t.c":5:5 128 {*movhi_split} > > > > (expr_list:REG_DEAD (reg:HI 46 [ _1 ]) > > > > (nil))) > > > > > > > > The patched instruction divmodhi4 constraints operand 2 (here pseudo > > > > 48) to hard register 22. Combine merges insn 7 into 9 by crossing a > > > > hard register assignment of register 22. > > > > > > > > (note 7 6 8 2 NOTE_INSN_DELETED) > > > > (insn 8 7 9 2 (set (reg:HI 22 r22) > > > > (symbol_ref/f:HI ("*.LC0") [flags 0x2] <var_decl > > > > 0x3fff7950d10 *.LC0>)) "t.c":5:5 128 {*movhi_split} > > > > (nil)) > > > > (insn 9 8 10 2 (parallel [ > > > > (set (reg:HI 24 r24) > > > > (div:HI (reg:HI 49 [ k ]) > > > > (reg:HI 48))) > > > > (set (reg:HI 47) > > > > (mod:HI (reg:HI 49 [ k ]) > > > > (reg:HI 48))) > > > > (clobber (scratch:HI)) > > > > (clobber (scratch:QI)) > > > > ]) "t.c":5:5 602 {divmodhi4} > > > > (expr_list:REG_DEAD (reg:HI 48) > > > > (expr_list:REG_DEAD (reg:HI 49 [ k ]) > > > > (nil)))) > > > > > > > > This leaves us with a conflict for pseudo 48 in the updated insn 9 since > > > > register 22 is live here. > > > > > > > > Fixed by pulling the sledge hammer and skipping any potential > > > > combination if a hard register constraint is involved. Ideally we would > > > > skip based on the fact whether there is any usage of a hard register > > > > referred by any hard register constraint between potentially combined > > > > insns. > > > > > > > > gcc/ChangeLog: > > > > > > > > * combine.cc (cant_combine_insn_p): Do not try to combine insns > > > > if hard register constraints are involved. > > > > --- > > > > gcc/combine.cc | 21 +++++++++++++++++++++ > > > > 1 file changed, 21 insertions(+) > > > > > > > > diff --git a/gcc/combine.cc b/gcc/combine.cc > > > > index 816324f4735..a4e7aff971d 100644 > > > > --- a/gcc/combine.cc > > > > +++ b/gcc/combine.cc > > > > @@ -2229,6 +2229,27 @@ cant_combine_insn_p (rtx_insn *insn) > > > > if (!NONDEBUG_INSN_P (insn)) > > > > return true; > > > > + /* Do not try to combine insns which make use of hard register > > > > constraints. > > > > + For example, assume that in the first insn operand r100 of exp_a > > > > is > > > > + constrained to hard register %5. > > > > + > > > > + r101=exp_a(r100) > > > > + %5=... > > > > + r102=exp_b(r101) > > > > + > > > > + Then combining the first insn into the last one creates a > > > > conflict for > > > > + pseudo r100 since hard register %5 is live for the last insn. > > > > Therefore, > > > > + skip for now. This is a sledge hammer approach. Ideally we > > > > would skip > > > > + based on the fact whether there is any definition of a hard > > > > register used > > > > + in a single register constraint between potentially combined > > > > insns. */ > > > > + > > > > + extract_insn (insn); > > > > + for (int nop = recog_data.n_operands - 1; nop >= 0; --nop) > > > > + { > > > > + if (strchr (recog_data.constraints[nop], '{')) > > > > + return true; > > > > + } > > > > + > > > > /* Never combine loads and stores involving hard regs that are > > > > likely > > > > to be spilled. The register allocator can usually handle such > > > > reg-reg moves by tying. If we allow the combiner to make > > > > > commit 4725614255a2a5a428048db76ab931434c829758 > > > Author: Georg-Johann Lay <[email protected]> > > > Date: Tue Aug 5 14:54:35 2025 +0200 > > > > > > htc: [u]divmod hi > > > > > > diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md > > > index 30a02a4b6c9..ebfc16104c3 100644 > > > --- a/gcc/config/avr/avr.md > > > +++ b/gcc/config/avr/avr.md > > > @@ -3846,32 +3846,14 @@ (define_insn "*udivmodqi4_call" > > > [(set_attr "type" "xcall")]) > > > (define_insn_and_split "divmodhi4" > > > - [(set (match_operand:HI 0 "pseudo_register_operand") > > > - (div:HI (match_operand:HI 1 "pseudo_register_operand") > > > - (match_operand:HI 2 "pseudo_register_operand"))) > > > - (set (match_operand:HI 3 "pseudo_register_operand") > > > - (mod:HI (match_dup 1) (match_dup 2))) > > > - (clobber (reg:QI 21)) > > > - (clobber (reg:HI 22)) > > > - (clobber (reg:HI 24)) > > > - (clobber (reg:HI 26))] > > > - "" > > > - { gcc_unreachable(); } > > > - "" > > > - [(set (reg:HI 24) (match_dup 1)) > > > - (set (reg:HI 22) (match_dup 2)) > > > - (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22))) > > > - (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22))) > > > - (clobber (reg:HI 26)) > > > - (clobber (reg:QI 21))]) > > > - (set (match_dup 0) (reg:HI 22)) > > > - (set (match_dup 3) (reg:HI 24))]) > > > - > > > -(define_insn_and_split "*divmodhi4_call_split" > > > - [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22))) > > > - (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22))) > > > - (clobber (reg:HI 26)) > > > - (clobber (reg:QI 21))] > > > + [(set (match_operand:HI 0 "register_operand" "={r22}") > > > + (div:HI (match_operand:HI 1 "register_operand" "{r24}") > > > + (match_operand:HI 2 "register_operand" "{r22}"))) > > > + (set (match_operand:HI 3 "register_operand" "={r24}") > > > + (mod:HI (match_dup 1) > > > + (match_dup 2))) > > > + (clobber (match_scratch:HI 4 "={r26}")) > > > + (clobber (match_scratch:QI 5 "={r21}"))] > > > "" > > > "#" > > > "&& reload_completed" > > > @@ -3889,32 +3871,14 @@ (define_insn "*divmodhi4_call" > > > [(set_attr "type" "xcall")]) > > > (define_insn_and_split "udivmodhi4" > > > - [(set (match_operand:HI 0 "pseudo_register_operand") > > > - (udiv:HI (match_operand:HI 1 "pseudo_register_operand") > > > - (match_operand:HI 2 "pseudo_register_operand"))) > > > - (set (match_operand:HI 3 "pseudo_register_operand") > > > - (umod:HI (match_dup 1) (match_dup 2))) > > > - (clobber (reg:QI 21)) > > > - (clobber (reg:HI 22)) > > > - (clobber (reg:HI 24)) > > > - (clobber (reg:HI 26))] > > > - "" > > > - { gcc_unreachable(); } > > > - "" > > > - [(set (reg:HI 24) (match_dup 1)) > > > - (set (reg:HI 22) (match_dup 2)) > > > - (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22))) > > > - (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22))) > > > - (clobber (reg:HI 26)) > > > - (clobber (reg:QI 21))]) > > > - (set (match_dup 0) (reg:HI 22)) > > > - (set (match_dup 3) (reg:HI 24))]) > > > - > > > -(define_insn_and_split "*udivmodhi4_call_split" > > > - [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22))) > > > - (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22))) > > > - (clobber (reg:HI 26)) > > > - (clobber (reg:QI 21))] > > > + [(set (match_operand:HI 0 "register_operand" "={r22}") > > > + (udiv:HI (match_operand:HI 1 "register_operand" "{r24}") > > > + (match_operand:HI 2 "register_operand" "{r22}"))) > > > + (set (match_operand:HI 3 "register_operand" "={r24}") > > > + (umod:HI (match_dup 1) > > > + (match_dup 2))) > > > + (clobber (match_scratch:HI 4 "={r26}")) > > > + (clobber (match_scratch:QI 5 "={r21}"))] > > > "" > > > "#" > > > "&& reload_completed" > > > @@ -3926,8 +3890,7 @@ (define_insn "*udivmodhi4_call" > > > (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22))) > > > (clobber (reg:HI 26)) > > > (clobber (reg:QI 21)) > > > - (clobber (reg:CC REG_CC)) > > > - ] > > > + (clobber (reg:CC REG_CC))] > > > "reload_completed" > > > "%~call __udivmodhi4" > > > [(set_attr "type" "xcall")]) > > > > > diff --git a/gcc/cse.cc b/gcc/cse.cc > > > index a86fe307819..28175e2732b 100644 > > > --- a/gcc/cse.cc > > > +++ b/gcc/cse.cc > > > @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see > > > #include "backend.h" > > > #include "target.h" > > > #include "rtl.h" > > > +#include "stmt.h" > > > #include "tree.h" > > > #include "cfghooks.h" > > > #include "df.h" > > > @@ -31,6 +32,7 @@ along with GCC; see the file COPYING3. If not see > > > #include "insn-config.h" > > > #include "regs.h" > > > #include "emit-rtl.h" > > > +#include "ira.h" > > > #include "recog.h" > > > #include "cfgrtl.h" > > > #include "cfganal.h" > > > @@ -6217,6 +6219,46 @@ invalidate_from_sets_and_clobbers (rtx_insn *insn) > > > invalidate (SET_DEST (y), VOIDmode); > > > } > > > } > > > + > > > + /* Any single register constraint may introduce a conflict, if the > > > associated > > > + hard register is live. For example: > > > + > > > + r100=%1 > > > + r101=42 > > > + r102=exp(r101) > > > + > > > + If the first operand r101 of exp is constrained to hard register > > > %1, then > > > + r100 cannot be trivially substituted by %1 in the following since > > > %1 got > > > + clobbered. Such conflicts may stem from single register classes as > > > well > > > + as hard register constraints. Since prior RA we do not know which > > > + alternative will be chosen, be conservative and consider any such > > > hard > > > + register from any alternative as a potential clobber. */ > > > + extract_insn (insn); > > > + for (int nop = recog_data.n_operands - 1; nop >= 0; --nop) > > > + { > > > + int c; > > > + const char *p = recog_data.constraints[nop]; > > > + for (; (c = *p); p += CONSTRAINT_LEN (c, p)) > > > + if (c == ',') > > > + ; > > > + else if (c == '{') > > > + { > > > + int regno = decode_hard_reg_constraint (p); > > > + machine_mode mode = recog_data.operand_mode[nop]; > > > + invalidate_reg (gen_rtx_REG (mode, regno)); > > > + } > > > + else > > > + { > > > + enum reg_class cl > > > + = reg_class_for_constraint (lookup_constraint (p)); > > > + if (cl == NO_REGS) > > > + continue; > > > + machine_mode mode = recog_data.operand_mode[nop]; > > > + int regno = ira_class_singleton[cl][mode]; > > > + if (regno >= 0) > > > + invalidate_reg (gen_rtx_REG (mode, regno)); > > > + } > > > + } > > > } > > > > > > static rtx cse_process_note (rtx); > > > diff --git a/gcc/testsuite/gcc.target/powerpc/asm-hard-reg-2.c > > > b/gcc/testsuite/gcc.target/powerpc/asm-hard-reg-2.c > > > new file mode 100644 > > > index 00000000000..c0aad292acb > > > --- /dev/null > > > +++ b/gcc/testsuite/gcc.target/powerpc/asm-hard-reg-2.c > > > @@ -0,0 +1,9 @@ > > > +/* { dg-do compile } */ > > > + > > > +double a; > > > +double b (long double c) { > > > + long double d = 0; > > > + double e; > > > + __asm__ ("" : "=f" (a), "={fr2}" (e) : "{fr1}" (d)); > > > + return c + c; > > > +} > > > diff --git a/gcc/combine.cc b/gcc/combine.cc > index 816324f4735..a4e7aff971d 100644 > --- a/gcc/combine.cc > +++ b/gcc/combine.cc > @@ -2229,6 +2229,27 @@ cant_combine_insn_p (rtx_insn *insn) > if (!NONDEBUG_INSN_P (insn)) > return true; > > + /* Do not try to combine insns which make use of hard register constraints. > + For example, assume that in the first insn operand r100 of exp_a is > + constrained to hard register %5. > + > + r101=exp_a(r100) > + %5=... > + r102=exp_b(r101) > + > + Then combining the first insn into the last one creates a conflict for > + pseudo r100 since hard register %5 is live for the last insn. > Therefore, > + skip for now. This is a sledge hammer approach. Ideally we would skip > + based on the fact whether there is any definition of a hard register > used > + in a single register constraint between potentially combined insns. */ > + > + extract_insn (insn); > + for (int nop = recog_data.n_operands - 1; nop >= 0; --nop) > + { > + if (strchr (recog_data.constraints[nop], '{')) > + return true; > + } > + > /* Never combine loads and stores involving hard regs that are likely > to be spilled. The register allocator can usually handle such > reg-reg moves by tying. If we allow the combiner to make
