diff mbox

[RTL-ifcvt] PR rtl-optimization/67465: Handle pairs of complex+simple blocks and empty blocks more gracefully

Message ID 55F2F575.6080609@arm.com
State New
Headers show

Commit Message

Kyrylo Tkachov Sept. 11, 2015, 3:38 p.m. UTC
On 11/09/15 09:51, Rainer Orth wrote:
> Kyrill Tkachov <kyrylo.tkachov@arm.com> writes:
>
>> On 10/09/15 12:43, Rainer Orth wrote:
>>> Hi Kyrill,
>>>
>>>> Rainer, could you please check that this patch still fixes the SPARC
>>>> regressions?
>>> unfortunately, it breaks sparc-sun-solaris2.10 bootstrap: compiling
>>> stage2 libiberty/regex.c FAILs:
>>>
>>>
>> Thanks for providing the preprocessed file.
>> I've reproduced and fixed the ICE in this version of the patch.
>> The problem was that I was taking the mode of x before the check
>> of whether a and b are MEMs, after which we would change x to an
>> address_mode reg,
>> thus confusing emit_move_insn.
>>
>> The fix is to take the mode of x and perform the can_conditionally_move_p check
>> after that transformation.
>>
>> Bootstrapped and tested on aarch64 and x86_64.
>> The preprocessed regex.i that Rainer provided now compiles successfully for me
>> on a sparc-sun-solaris2.10 stage-1 cross-compiler.
>>
>> Rainer, thanks for your help so far, could you please try out this patch?
> While bootstrap succeeds again, the testsuite regression in
> gcc.c-torture/execute/20071216-1.c reoccured.
Right, so I dug into the RTL dumps and I think this is a separate issue that's being exacerbated by my patch.
The code tries to if-convert a block which contains a compare instruction i.e. sets the CC register.
Now, bb_valid_for_noce_process_p should have caught this, and in particular insn_valid_noce_process_p
which should check that the instruction doesn't set the CC register. However, on SPARC the
cc_in_cond returns NULL! This is due to the canonicalize_comparison implementation that seems to
remove the CC register from the condition expression and returns something like:
(leu (reg/v:SI 109 [ b ])
     (const_int -4096 [0xfffffffffffff000])

Therefore the set_of (cc_in_cond (cond), insn) check doesn't get triggered because cc_in_cond returns NULL.
Regardless of how the branch condition got canonicalized, I think we still want to reject any insn in the block
that sets a condition code register, so this patch checks the destination of every set in the block for a MODE_CC
expression and cancels if-conversion if that's the case.

Oleg pointed me to the older PR 58517 affecting SH which seems similar and I think my previous ifcvt patch would expose
this problem more.

Anyway, with this patch the failing SPARC testcase gcc.c-torture/execute/20071216-1.c generates the same assembly
as before r227368 and bootstrap and test on aarch64 and x86_64 passes ok for me.

Rainer, could you try this patch on top of the previous patch? (https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00689.html)
The two together should fix all of PR 67456, 67464, 67465 and 67481.

Thanks,
Kyrill

2015-09-11  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     PR rtl-optimization/67481
     * ifcvt.c (contains_ccmode_rtx_p): New function.
     (insn_valid_noce_process_p): Use it.

Comments

Rainer Orth Sept. 17, 2015, 11:33 a.m. UTC | #1
Hi Kyrill,

> On 11/09/15 09:51, Rainer Orth wrote:
>> Kyrill Tkachov <kyrylo.tkachov@arm.com> writes:
>>
>>> On 10/09/15 12:43, Rainer Orth wrote:
>>>> Hi Kyrill,
>>>>
>>>>> Rainer, could you please check that this patch still fixes the SPARC
>>>>> regressions?
>>>> unfortunately, it breaks sparc-sun-solaris2.10 bootstrap: compiling
>>>> stage2 libiberty/regex.c FAILs:
>>>>
>>>>
>>> Thanks for providing the preprocessed file.
>>> I've reproduced and fixed the ICE in this version of the patch.
>>> The problem was that I was taking the mode of x before the check
>>> of whether a and b are MEMs, after which we would change x to an
>>> address_mode reg,
>>> thus confusing emit_move_insn.
>>>
>>> The fix is to take the mode of x and perform the
>>> can_conditionally_move_p check
>>> after that transformation.
>>>
>>> Bootstrapped and tested on aarch64 and x86_64.
>>> The preprocessed regex.i that Rainer provided now compiles successfully
>>> for me
>>> on a sparc-sun-solaris2.10 stage-1 cross-compiler.
>>>
>>> Rainer, thanks for your help so far, could you please try out this patch?
>> While bootstrap succeeds again, the testsuite regression in
>> gcc.c-torture/execute/20071216-1.c reoccured.
> Right, so I dug into the RTL dumps and I think this is a separate issue
> that's being exacerbated by my patch.
> The code tries to if-convert a block which contains a compare instruction
> i.e. sets the CC register.
> Now, bb_valid_for_noce_process_p should have caught this, and in particular
> insn_valid_noce_process_p
> which should check that the instruction doesn't set the CC
> register. However, on SPARC the
> cc_in_cond returns NULL! This is due to the canonicalize_comparison
> implementation that seems to
> remove the CC register from the condition expression and returns something like:
> (leu (reg/v:SI 109 [ b ])
>     (const_int -4096 [0xfffffffffffff000])
>
> Therefore the set_of (cc_in_cond (cond), insn) check doesn't get triggered
> because cc_in_cond returns NULL.
> Regardless of how the branch condition got canonicalized, I think we still
> want to reject any insn in the block
> that sets a condition code register, so this patch checks the destination
> of every set in the block for a MODE_CC
> expression and cancels if-conversion if that's the case.
>
> Oleg pointed me to the older PR 58517 affecting SH which seems similar and
> I think my previous ifcvt patch would expose
> this problem more.
>
> Anyway, with this patch the failing SPARC testcase
> gcc.c-torture/execute/20071216-1.c generates the same assembly
> as before r227368 and bootstrap and test on aarch64 and x86_64 passes ok for me.
>
> Rainer, could you try this patch on top of the previous patch?
> (https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00689.html)
> The two together should fix all of PR 67456, 67464, 67465 and 67481.

sorry this took me so long: we've had a major switch failure and my
sparc machines are way slow.

Anyway, here's what I found: the two patches on top of each other do
bootstrap just fine and the gcc.c-torture/execute/20071216-1.c
regressions are gone.  However, it introduces a new one:

FAIL: gcc.dg/torture/stackalign/sibcall-1.c   -O1 -fpic execution test

It fails for both 32 and 64-bit.  The testcase SEGVs:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1 (LWP 1)]
0x00010bb0 in ix86_split_ashr (mode=1)
    at /vol/gcc/src/hg/trunk/local/gcc/testsuite/gcc.dg/torture/stackalign/sibcall-1.c:20
20                            : gen_x86_64_shrd) (0);
(gdb) where
#0  0x00010bb0 in ix86_split_ashr (mode=1)
    at /vol/gcc/src/hg/trunk/local/gcc/testsuite/gcc.dg/torture/stackalign/sibcall-1.c:20
#1  0x00010be4 in main ()
    at /vol/gcc/src/hg/trunk/local/gcc/testsuite/gcc.dg/torture/stackalign/sibcall-1.c:27
1: x/i $pc
=> 0x10bb0 <ix86_split_ashr+40>:        ld  [ %g1 ], %g1
(gdb) p/x $g1
$1 = 0x317f8

truss reveals:

    Incurred fault #6, FLTBOUNDS  %pc = 0x00010BB0
      siginfo: SIGSEGV SEGV_MAPERR addr=0x000317F8
    Received signal #11, SIGSEGV [default]
      siginfo: SIGSEGV SEGV_MAPERR addr=0x000317F8

with

#define FLTBOUNDS       6       /* Memory bounds (invalid address) */

and indeed that address isn't mapped according to

ro@apoc 58 > pmap 26536
26536:  /var/gcc/regression/trunk/11-gcc/build/gcc/testsuite/gcc/sibcall-1.exe
00010000       8K r-x--  /var/gcc/regression/trunk/11-gcc/build/gcc/testsuite/gcc/sibcall-1.exe
00020000       8K rwx--  /var/gcc/regression/trunk/11-gcc/build/gcc/testsuite/gcc/sibcall-1.exe
FEE60000     696K r-x--  /lib/libm.so.2
FEF1C000      16K rwx--  /lib/libm.so.2
FF180000    1464K r-x--  /lib/libc.so.1
FF2FE000      48K rwx--  /lib/libc.so.1
FF350000      24K rwx--    [ anon ]
FF360000       8K rw---    [ anon ]
FF370000       8K rw---    [ anon ]
FF380000       8K rw---    [ anon ]
FF390000       8K rw---    [ anon ]
FF3A0000     248K r-x--  /lib/ld.so.1
FF3EE000      16K rwx--  /lib/ld.so.1
FFBFC000      16K rwx--    [ stack ]
 total      2576K

Something is totally amiss here.

	Rainer
diff mbox

Patch

diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 9af3249..090a584 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -1838,6 +1838,19 @@  noce_try_cmove (struct noce_if_info *if_info)
   return FALSE;
 }
 
+/* Return true if X contains a conditional code mode rtx.  */
+
+static bool
+contains_ccmode_rtx_p (rtx x)
+{
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, x, ALL)
+    if (GET_MODE_CLASS (GET_MODE (*iter)) == MODE_CC)
+      return true;
+
+  return false;
+}
+
 /* Helper for bb_valid_for_noce_process_p.  Validate that
    the rtx insn INSN is a single set that does not set
    the conditional register CC and is in general valid for
@@ -1856,6 +1869,7 @@  insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
   /* Currently support only simple single sets in test_bb.  */
   if (!sset
       || !noce_operand_ok (SET_DEST (sset))
+      || contains_ccmode_rtx_p (SET_DEST (sset))
       || !noce_operand_ok (SET_SRC (sset)))
     return false;