From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id 6D4D3386F430; Sun, 27 Sep 2020 21:26:15 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6D4D3386F430 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r9-8943] optabs: Don't reuse target for multi-word expansions if it overlaps operand(s) [PR97073] X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/releases/gcc-9 X-Git-Oldrev: 7a8c40bca889785fc4664e5e11c430e31d297696 X-Git-Newrev: aa42c1ac24a0427a27aec19c483780662cd150b8 Message-Id: <20200927212615.6D4D3386F430@sourceware.org> Date: Sun, 27 Sep 2020 21:26:15 +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: Sun, 27 Sep 2020 21:26:15 -0000 https://gcc.gnu.org/g:aa42c1ac24a0427a27aec19c483780662cd150b8 commit r9-8943-gaa42c1ac24a0427a27aec19c483780662cd150b8 Author: Jakub Jelinek Date: Sun Sep 27 23:18:26 2020 +0200 optabs: Don't reuse target for multi-word expansions if it overlaps operand(s) [PR97073] The following testcase is miscompiled on i686-linux, because we try to expand a double-word bitwise logic operation with op0 being a (mem:DI u) and target (mem:DI u+4), i.e. partial overlap, and thus end up with: movl 4(%esp), %eax andl u, %eax movl %eax, u+4 ! movl u+4, %eax optimized out andl 8(%esp), %eax movl %eax, u+8 rather than with the desired: movl 4(%esp), %edx movl 8(%esp), %eax andl u, %edx andl u+4, %eax movl %eax, u+8 movl %edx, u+4 because the store of the first word to target overwrites the second word of the operand. expand_binop for this (and several similar places) already check for target == op0 or target == op1, this patch just adds reg_overlap_mentioned_p calls next to it. Pedantically, at least for some of these it might be sufficient to force a different target if there is overlap but target is not rtx_equal_p to the operand (e.g. in this bitwise logical case, but e.g. not in the shift cases where there is reordering), though that would go against the preexisting target == op? checks and the rationale that REG_EQUAL notes in that case isn't correct. 2020-09-27 Jakub Jelinek PR middle-end/97073 * optabs.c (expand_binop, expand_absneg_bit, expand_unop, expand_copysign_bit): Check reg_overlap_mentioned_p between target and operand(s) and if it returns true, force a pseudo as target. * gcc.c-torture/execute/pr97073.c: New test. (cherry picked from commit a4b31d5807f2bc67c8999b3d53369cf2a5c6e1ec) Diff: --- gcc/optabs.c | 14 +++++++++++++- gcc/testsuite/gcc.c-torture/execute/pr97073.c | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/gcc/optabs.c b/gcc/optabs.c index f469e809939..0ae429cad8e 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -1395,6 +1395,8 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, if (target == 0 || target == op0 || target == op1 + || reg_overlap_mentioned_p (target, op0) + || reg_overlap_mentioned_p (target, op1) || !valid_multiword_target_p (target)) target = gen_reg_rtx (int_mode); @@ -1475,6 +1477,8 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, if (target == 0 || target == op0 || target == op1 + || reg_overlap_mentioned_p (target, op0) + || reg_overlap_mentioned_p (target, op1) || !valid_multiword_target_p (target)) target = gen_reg_rtx (int_mode); @@ -1533,6 +1537,8 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, || target == op0 || target == op1 || !REG_P (target) + || reg_overlap_mentioned_p (target, op0) + || reg_overlap_mentioned_p (target, op1) || !valid_multiword_target_p (target)) target = gen_reg_rtx (int_mode); @@ -2670,6 +2676,7 @@ expand_absneg_bit (enum rtx_code code, scalar_float_mode mode, if (target == 0 || target == op0 + || reg_overlap_mentioned_p (target, op0) || (nwords > 1 && !valid_multiword_target_p (target))) target = gen_reg_rtx (mode); @@ -2948,7 +2955,10 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, int i; rtx_insn *insns; - if (target == 0 || target == op0 || !valid_multiword_target_p (target)) + if (target == 0 + || target == op0 + || reg_overlap_mentioned_p (target, op0) + || !valid_multiword_target_p (target)) target = gen_reg_rtx (int_mode); start_sequence (); @@ -3458,6 +3468,8 @@ expand_copysign_bit (scalar_float_mode mode, rtx op0, rtx op1, rtx target, if (target == 0 || target == op0 || target == op1 + || reg_overlap_mentioned_p (target, op0) + || reg_overlap_mentioned_p (target, op1) || (nwords > 1 && !valid_multiword_target_p (target))) target = gen_reg_rtx (mode); diff --git a/gcc/testsuite/gcc.c-torture/execute/pr97073.c b/gcc/testsuite/gcc.c-torture/execute/pr97073.c new file mode 100644 index 00000000000..1955e6b8bd2 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr97073.c @@ -0,0 +1,21 @@ +/* PR middle-end/97073 */ +/* { dg-additional-options "-mno-stv" { target i?86-*-* x86_64-*-* } } */ + +typedef unsigned long long L; +union U { L i; struct T { unsigned k; L l; } j; } u; + +__attribute__((noinline,noclone)) void +foo (L x) +{ + u.j.l = u.i & x; +} + +int +main () +{ + u.i = 5; + foo (-1ULL); + if (u.j.l != 5) + __builtin_abort (); + return 0; +}