From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7820) id 3807B3857836; Wed, 2 Jun 2021 22:26:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3807B3857836 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Przemyslaw Wirkus To: gcc-cvs@gcc.gnu.org Subject: [gcc r10-9880] [PR97969] LRA: Transform pattern `plus (plus (hard reg, const), pseudo)` after elimination X-Act-Checkin: gcc X-Git-Author: Vladimir N. Makarov X-Git-Refname: refs/heads/releases/gcc-10 X-Git-Oldrev: 9f610f5cf810ab90814e89b1b7348a17532aad8e X-Git-Newrev: eb13f3f81d56910626529af52e03e74770ffca98 Message-Id: <20210602222642.3807B3857836@sourceware.org> Date: Wed, 2 Jun 2021 22:26:42 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Jun 2021 22:26:42 -0000 https://gcc.gnu.org/g:eb13f3f81d56910626529af52e03e74770ffca98 commit r10-9880-geb13f3f81d56910626529af52e03e74770ffca98 Author: Vladimir N. Makarov Date: Tue Jan 12 11:26:15 2021 -0500 [PR97969] LRA: Transform pattern `plus (plus (hard reg, const), pseudo)` after elimination LRA can loop infinitely on targets without `reg + imm` insns. Register elimination on such targets can increase register pressure resulting in permanent stack size increase and changing elimination offset. To avoid such situation, a simple transformation can be done to avoid register pressure increase after generating reload insns containing eliminated hard regs. gcc/ChangeLog: PR target/97969 * lra-eliminations.c (eliminate_regs_in_insn): Add transformation of pattern 'plus (plus (hard reg, const), pseudo)'. gcc/testsuite/ChangeLog: PR target/97969 * gcc.target/arm/pr97969.c: New. (cherry picked from commit cf2ac1c30af0fa783c8d72e527904dda5d8cc330) Diff: --- gcc/lra-eliminations.c | 28 +++++++++++++++++- gcc/testsuite/gcc.target/arm/pr97969.c | 54 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c index cf745dc6a26..e2d4b24db2a 100644 --- a/gcc/lra-eliminations.c +++ b/gcc/lra-eliminations.c @@ -885,7 +885,7 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, poly_int64 update_sp_offset) { int icode = recog_memoized (insn); - rtx old_set = single_set (insn); + rtx set, old_set = single_set (insn); bool validate_p; int i; rtx substed_operand[MAX_RECOG_OPERANDS]; @@ -1038,6 +1038,32 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, for (i = 0; i < static_id->n_dups; i++) *id->dup_loc[i] = substed_operand[(int) static_id->dup_num[i]]; + /* Transform plus (plus (hard reg, const), pseudo) to plus (plus (pseudo, + const), hard reg) in order to keep insn containing eliminated register + after all reloads calculating its offset. This permits to keep register + pressure under control and helps to avoid LRA cycling in patalogical + cases. */ + if (! replace_p && (set = single_set (insn)) != NULL + && GET_CODE (SET_SRC (set)) == PLUS + && GET_CODE (XEXP (SET_SRC (set), 0)) == PLUS) + { + rtx reg1, reg2, op1, op2; + + reg1 = op1 = XEXP (XEXP (SET_SRC (set), 0), 0); + reg2 = op2 = XEXP (SET_SRC (set), 1); + if (GET_CODE (reg1) == SUBREG) + reg1 = SUBREG_REG (reg1); + if (GET_CODE (reg2) == SUBREG) + reg2 = SUBREG_REG (reg2); + if (REG_P (reg1) && REG_P (reg2) + && REGNO (reg1) < FIRST_PSEUDO_REGISTER + && REGNO (reg2) >= FIRST_PSEUDO_REGISTER) + { + XEXP (XEXP (SET_SRC (set), 0), 0) = op2; + XEXP (SET_SRC (set), 1) = op1; + } + } + /* If we had a move insn but now we don't, re-recognize it. This will cause spurious re-recognition if the old move had a PARALLEL since the new one still will, but we can't call diff --git a/gcc/testsuite/gcc.target/arm/pr97969.c b/gcc/testsuite/gcc.target/arm/pr97969.c new file mode 100644 index 00000000000..714a1d18870 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr97969.c @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -fno-omit-frame-pointer -mthumb -w -Os" } */ + +typedef a[23]; +enum { b }; +typedef struct { + int c; + char *e; + char f +} d; +typedef enum { g = 1 } h; +typedef struct { + h i; + int j +} k; +typedef struct { + a l; + int a; + int m; + int n; + int o; + short p; + int q; + k r; + char e; + char *s; + d t; + d *u; + short v; + int w +} aa; +c(char x, int y, char z, int ab) { + aa ac; + ac.r.i = 0; + d ad; + ac.t = ad; + ac.u = 0; + ae(&ac.v, 0, 0); + ac.w = 0; + af(&ac, x + y, z, z + ab); + if (ag(0)) + return 0; + if (x) + ac.s = z + ab; + else + ac.s = x + y; + ac.o |= g; + if (!setjmp()) { + ah(ac); + ai(b); + ac.e = z + ab; + aj(ac); + } +}