User account creation filtered due to spam.

Bug 71724 - [5/6 Regression] ICE: Segmentation fault, deep recursion between combine_simplify_rtx and subst
Summary: [5/6 Regression] ICE: Segmentation fault, deep recursion between combine_simp...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 5.0
: P2 normal
Target Milestone: 5.5
Assignee: Segher Boessenkool
URL:
Keywords: ice-on-valid-code
: 72746 77345 (view as bug list)
Depends on:
Blocks:
 
Reported: 2016-07-01 04:15 UTC by Arseny Solokha
Modified: 2017-01-23 17:10 UTC (History)
6 users (show)

See Also:
Host:
Target: powerpc-e500v2-linux-gnuspe
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-08-09 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Arseny Solokha 2016-07-01 04:15:32 UTC
gcc 5, 6, 7 for 32-bit target all fail to compile the following testcase w/ -O1:

long long int ro, t9;

void
cg (void)
{
  ro = (t9 != 1);
  ro += (t9 != 0) ? t9 : ro;
}

% powerpc-e500v2-linux-gnuspe-gcc-5.4.0 -c -O1 fxgjkta3.c
powerpc-e500v2-linux-gnuspe-gcc-5.4.0: internal compiler error: Segmentation fault (program cc1)

% powerpc-e500v2-linux-gnuspe-gcc-7.0.0-alpha20160626 -c -O1 fxgjkta3.c
powerpc-e500v2-linux-gnuspe-gcc-7.0.0-alpha20160626: internal compiler error: Segmentation fault (program cc1)

Backtrace for gcc 7:

#0  0x0000000000eb99a6 in simplify_binary_operation_1(rtx_code, machine_mode, rtx_def*, rtx_def*, rtx_def*, rtx_def*) ()
#1  0x0000000000eaf44d in simplify_binary_operation(rtx_code, machine_mode, rtx_def*, rtx_def*) ()
#2  0x0000000001779ba1 in combine_simplify_rtx(rtx_def*, machine_mode, int, int) ()
#3  0x000000000177443c in subst(rtx_def*, rtx_def*, rtx_def*, int, int, int) ()
#4  0x000000000177413d in subst(rtx_def*, rtx_def*, rtx_def*, int, int, int) ()
#5  0x000000000177413d in subst(rtx_def*, rtx_def*, rtx_def*, int, int, int) ()
#6  0x0000000001779eaa in combine_simplify_rtx(rtx_def*, machine_mode, int, int) ()
#7  0x000000000177443c in subst(rtx_def*, rtx_def*, rtx_def*, int, int, int) ()
#8  0x0000000001779ee5 in combine_simplify_rtx(rtx_def*, machine_mode, int, int) ()
<…>
#171156 0x0000000001779ee5 in combine_simplify_rtx(rtx_def*, machine_mode, int, int) ()
#171157 0x000000000177443c in subst(rtx_def*, rtx_def*, rtx_def*, int, int, int) ()
#171158 0x000000000177413d in subst(rtx_def*, rtx_def*, rtx_def*, int, int, int) ()
#171159 0x0000000001772bfb in subst(rtx_def*, rtx_def*, rtx_def*, int, int, int) ()
#171160 0x0000000001767ada in try_combine(rtx_insn*, rtx_insn*, rtx_insn*, rtx_insn*, int*, rtx_insn*) ()
#171161 0x0000000001762fea in combine_instructions(rtx_insn*, unsigned int) ()
#171162 0x00000000017625b9 in rest_of_handle_combine() ()
#171163 0x0000000001762565 in (anonymous namespace)::pass_combine::execute(function*) ()
#171164 0x0000000000dbbbd6 in execute_one_pass(opt_pass*) ()
#171165 0x0000000000dbc74b in execute_pass_list_1(opt_pass*) ()
#171166 0x0000000000dbc774 in execute_pass_list_1(opt_pass*) ()
#171167 0x0000000000dac811 in execute_pass_list(function*, opt_pass*) ()
#171168 0x0000000000904e8f in cgraph_node::expand() ()
#171169 0x0000000000909bf8 in expand_all_functions() ()
#171170 0x0000000000908bff in symbol_table::compile() ()
#171171 0x0000000000909dc2 in symbol_table::finalize_compilation_unit() ()
#171172 0x0000000000ef3262 in compile_file() ()
#171173 0x0000000000ef1c86 in do_compile() ()
#171174 0x0000000000ef169a in toplev::main(int, char**) ()
#171175 0x000000000190c540 in main ()
Comment 1 Alan Modra 2016-08-09 03:36:40 UTC
combine goes into infinite recursion inside this call:
 newpat = subst (newpat, i0dest, i0src, 0, 0, 0);

The args of the failing subst are:
x:
(parallel [
        (set (reg:SI 181)
            (plus:SI (ltu:SI (plus:SI (reg:SI 165)
                        (reg:SI 174 [ t9.0_1+4 ]))
                    (reg:SI 165))
                (reg:SI 173 [ t9.0_1 ])))
        (clobber (reg:SI 76 ca))
    ])
from:
(reg:SI 174 [ t9.0_1+4 ])
to:
(if_then_else:SI (eq (reg:CC 185)
        (const_int 0 [0]))
    (reg:SI 165)
    (reg:SI 174 [ t9.0_1+4 ]))
Comment 2 Segher Boessenkool 2016-08-09 18:12:14 UTC
*** Bug 72746 has been marked as a duplicate of this bug. ***
Comment 3 Bernd Schmidt 2016-12-20 14:38:35 UTC
Looks like if_then_else_cond manages to return a false_rtx identical to the original one, and we try to simplify it again.
Comment 4 Bernd Schmidt 2016-12-21 21:21:18 UTC
Maybe we just need to test for that condition, even though it's ugly. However, I think there are some other improvements we could make here.

Part of the problem seems to be what if_then_else_cond does on this rtx:

(plus:SI (if_then_else:SI (eq (reg:CC 185)
            (const_int 0 [0]))
        (reg:SI 165)
        (reg:SI 174 [ t9.0_1+4 ]))
    (reg:SI 165))

Reg 165 is known to be zero or one, so it gets turned into a condition, and we have two different conditions on the operands. That causes us to fail to make the fairly obvious transformation to 
 cond = reg:CC 185
 true_rtx = (plus r165 r165)
 false_rtx = (plus r174 r165)

I'm testing the following, which tries to undo such transformation of plain REG if that seems it'll enable other transformations which are more likely to be beneficial. It makes the crash go away.

Index: combine.c
===================================================================
--- combine.c	(revision 242958)
+++ combine.c	(working copy)
@@ -9031,11 +9031,31 @@ if_then_else_cond (rtx x, rtx *ptrue, rt
      the same value, compute the new true and false values.  */
   else if (BINARY_P (x))
     {
-      cond0 = if_then_else_cond (XEXP (x, 0), &true0, &false0);
-      cond1 = if_then_else_cond (XEXP (x, 1), &true1, &false1);
+      rtx op0 = XEXP (x, 0);
+      rtx op1 = XEXP (x, 1);
+      cond0 = if_then_else_cond (op0, &true0, &false0);
+      cond1 = if_then_else_cond (op1, &true1, &false1);
+
+      if ((cond0 != 0 && cond1 != 0 && !rtx_equal_p (cond0, cond1))
+	  && (REG_P (op0) || REG_P (op1)))
+	{
+	  /* Try to enable a simplification by undoing work done by
+	     if_then_else_cond if it converted a REG into something more
+	     complex.  */
+	  if (REG_P (op0))
+	    {
+	      cond0 = 0;
+	      true0 = false0 = op0;
+	    }
+	  else
+	    {
+	      cond1 = 0;
+	      true1 = false1 = op1;
+	    }
+	}
 
       if ((cond0 != 0 || cond1 != 0)
-	  && ! (cond0 != 0 && cond1 != 0 && ! rtx_equal_p (cond0, cond1)))
+	  && ! (cond0 != 0 && cond1 != 0 && !rtx_equal_p (cond0, cond1)))
 	{
 	  /* If if_then_else_cond returned zero, then true/false are the
 	     same rtl.  We must copy one of them to prevent invalid rtl
Comment 5 Segher Boessenkool 2016-12-21 22:25:23 UTC
I am using the following, which also fixes the infinite loop, and seems to
not regress code quality much at all (I found *one* pattern where it made
things one machine insn worse, involving a define_insn_and_split (with
cost 0, so any finite cost is better -- combine did manage to do something
that is better according to its costs!)

But I am worried something similar then needs to be done to true_rtx, and
I don't see what.


===
diff --git a/gcc/combine.c b/gcc/combine.c
index c7255f0..ecdd3fd 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -5658,7 +5658,7 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in
             here since true_rtx or false_rtx might share RTL with x as a
             result of the if_then_else_cond call above.  */
          true_rtx = subst (copy_rtx (true_rtx), pc_rtx, pc_rtx, 0, 0, 0);
-         false_rtx = subst (copy_rtx (false_rtx), pc_rtx, pc_rtx, 0, 0, 0);
+         false_rtx = subst (copy_rtx (false_rtx), cond, const0_rtx, 0, 0, 0);
 
          /* If true_rtx and false_rtx are not general_operands, an if_then_else
             is unlikely to be simpler.  */

===
Comment 6 Segher Boessenkool 2017-01-13 03:32:34 UTC
*** Bug 77345 has been marked as a duplicate of this bug. ***
Comment 7 Bernd Schmidt 2017-01-23 16:31:27 UTC
Author: bernds
Date: Mon Jan 23 16:30:55 2017
New Revision: 244817

URL: https://gcc.gnu.org/viewcvs?rev=244817&root=gcc&view=rev
Log:
	PR rtl-optimization/71724
	* combine.c (if_then_else_cond): Look for situations where it is
	beneficial to undo the work of one of the recursive calls.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/combine.c
Comment 8 Jeffrey A. Law 2017-01-23 17:10:32 UTC
So I believe the consensus was we want both patches, or variants thereof, so I'm leaving this open, but removing the regression marker.