From: Hans-Peter Nilsson Date: Thu, 5 Feb 2026 17:34:24 +0000 (+0100) Subject: CRIS: Make sure movsf doesn't have two memory operands X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bae3e8edcce9d53350c52ba5bcab6b7749fd1f5;p=thirdparty%2Fgcc.git CRIS: Make sure movsf doesn't have two memory operands Experimenting, I noticed movsf could get two memory operands, and when the pass I was hacking, adjusted both operands, the rtl-ssa framework didn't like the situation and signalled failure, for example compiling gcc.c-torture/compile/pr85945.c. While that's arguably a wart in rtl-ssa and may be a problem by itself, this shouldn't happen: one operand should be either a register or constant 0. It usually doesn't matter because RA fixes up operands per the constraints. Still, this is low-handing fruit for improved performance, letting the RTL passes work on more correct information ...and also, a plausible excuse for not also hacking rtl-ssa proper. Either way, the port is responsible for guarding operand validity, so tweak it. Incidental observation: the two-memory-operands case happened already at expand time. This mem-to-mem situation doesn't happen for movsi, because it has special precautions to keep one operand a register or const_int 0, which were added for reasons of condition-code handling. That particular condition, checking for REG_P or the subreg being REG_P looks too restrictive though, not allowing the (subreg mem) case that register_operand deliberately allows. * config/cris/cris.md (SISF): New mode_iterator for SI and SF. ("mov"): Make "movsi" a define_expand to include SFmode by means of the SISF iterator and adjust to also handle SFmode. ("*movsf_internal"): Anonymize "movsf"; make it a match-only pattern. Add conditions to guard from source and destination both being memory operands. --- diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index 6c5945d3ab5..c18813f306a 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -173,6 +173,9 @@ (define_mode_iterator BWD [SI HI QI]) (define_mode_iterator BWDD [DI SI HI QI]) +;; Need to handle SI and SF similarly, at least in the expander. +(define_mode_iterator SISF [SI SF]) + ;; To be able to refer to the same mode_attr for both a multi-mode ;; and a mode-specific pattern, we use some singleton iterators. (define_mode_iterator DI_ [DI]) @@ -560,11 +563,11 @@ ;; Normal move patterns from SI on. -(define_expand "movsi" +(define_expand "mov" [(parallel [(set - (match_operand:SI 0 "nonimmediate_operand") - (match_operand:SI 1 "general_operand")) + (match_operand:SISF 0 "nonimmediate_operand") + (match_operand:SISF 1 "general_operand")) (clobber (reg:CC CRIS_CC0_REGNUM))])] "" { @@ -572,14 +575,16 @@ input. */ if (MEM_P (operands[0]) && ! REG_S_P (operands[1]) - && operands[1] != const0_rtx + && operands[1] != CONST0_RTX (mode) && can_create_pseudo_p ()) - operands[1] = force_reg (SImode, operands[1]); + operands[1] = force_reg (mode, operands[1]); /* At post-reload time, we'll get here for e.g. split multi-mode insns with a memory destination. Go directly to the clobber-less variant. - FIXME: Also applies to special-register source or destination. */ - if (reload_completed + FIXME: Also applies to special-register source or destination. + Only do this for integer modes. */ + if (SCALAR_INT_MODE_P (mode) + && reload_completed && (MEM_P (operands[0]) || operands[1] == const0_rtx)) { emit_insn (gen_rtx_SET (operands[0], operands[1])); @@ -778,11 +783,13 @@ ;; all ones); the worthwhile one is "0.0". ;; It will use clear, so we know ALL types of immediate 0 never change cc. -(define_insn "movsf" +(define_insn "*movsf_internal" [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,g,g,r,r,x,Q>,m,x, x") (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g,x,r,x, x,Q>,g")) (clobber (reg:CC CRIS_CC0_REGNUM))] - "" + "(register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode) + || operands[1] == CONST0_RTX (SFmode))" "@ move.d %1,%0 move.d %1,%0