Bug 49721 - convert_memory_address_addr_space may generate invalid new insns
Summary: convert_memory_address_addr_space may generate invalid new insns
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: 5.0
Assignee: Andrew Pinski
URL:
Keywords:
: 55142 (view as bug list)
Depends on:
Blocks: 55142
  Show dependency treegraph
 
Reported: 2011-07-12 19:14 UTC by H.J. Lu
Modified: 2014-11-23 04:13 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-05-30 00:00:00


Attachments
A patch (3.03 KB, patch)
2011-08-02 15:57 UTC, H.J. Lu
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2011-07-12 19:14:03 UTC
When convert_memory_address_addr_space is called by
simplify_unary_operation_1, it may generate new insns
if Pmode != ptr_mode.  But new insns aren't allowed
from simplify_unary_operation_1.
Comment 1 H.J. Lu 2011-07-28 21:11:12 UTC
A testcase:

---
struct
{
  int i;
  double e;
  int j;
} x;

void
f2 (void)
{
#pragma omp atomic
    x.e /= 0.25;
}
---

compiled with -mx32 -O2 -fopenmp, I got

Breakpoint 1, convert_memory_address_addr_space (to_mode=SImode, 
    x=0x7ffff07ad720, as=0 '\000')
    at /export/gnu/import/git/gcc/gcc/explow.c:399
399		return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
(gdb) call debug_rtx (x)
(plus:DI (symbol_ref:DI ("x") <var_decl 0x7ffff0859140 x>)
    (const_int 8 [0x8]))
(gdb) bt
#0  convert_memory_address_addr_space (to_mode=SImode, x=0x7ffff07ad720, 
    as=0 '\000') at /export/gnu/import/git/gcc/gcc/explow.c:399
#1  0x0000000000730a65 in convert_memory_address_addr_space (to_mode=SImode, 
    x=0x7ffff0931cc0, as=0 '\000')
    at /export/gnu/import/git/gcc/gcc/explow.c:380
#2  0x0000000000763d4c in expand_expr_addr_expr (exp=0x7ffff0750b68, 
    target=0x0, tmode=SImode, modifier=EXPAND_SUM)
    at /export/gnu/import/git/gcc/gcc/expr.c:7207
#3  0x0000000000773e81 in expand_expr_real_1 (exp=0x7ffff0750b68, target=0x0, 
    tmode=SImode, modifier=EXPAND_SUM, alt_rtl=0x0)
    at /export/gnu/import/git/gcc/gcc/expr.c:9757
#4  0x0000000000764594 in expand_expr_real (exp=0x7ffff0750b68, target=0x0, 
    tmode=SImode, modifier=EXPAND_SUM, alt_rtl=0x0)
    at /export/gnu/import/git/gcc/gcc/expr.c:7377
#5  0x00000000005c3c9e in expand_expr (exp=0x7ffff0750b68, target=0x0, 
    mode=SImode, modifier=EXPAND_SUM)
    at /export/gnu/import/git/gcc/gcc/expr.h:419
#6  0x00000000005dd4a4 in get_builtin_sync_mem (loc=0x7ffff0750b68, 
    mode=DImode) at /export/gnu/import/git/gcc/gcc/builtins.c:5080
#7  0x00000000005de057 in expand_builtin_compare_and_swap (mode=DImode, 
    exp=0x7ffff07abbe0, is_bool=0 '\000', target=0x7ffff074ede0)
    at /export/gnu/import/git/gcc/gcc/builtins.c:5186
#8  0x00000000005e3018 in expand_builtin (exp=0x7ffff07abbe0, 
---Type <return> to continue, or q <return> to quit---q
target=0x7ffff074eQuit
(gdb) 

This transformation is unsafe.
Comment 2 H.J. Lu 2011-07-28 21:27:33 UTC
The question is we have

(zero_extend:DI (plus:SI (FOO:SI) (const_int Y)))

Is is OK to transform it to

(plus:DI (zero_extend:DI (FOO:SI)) (const_int Y))

The current convert_memory_address_addr_space does
transformation if Y > 0. It makes no sense not to
transform it if Y < 0.
Comment 3 Andrew Pinski 2011-07-28 21:31:20 UTC
(In reply to comment #2)
> The question is we have
> 
> (zero_extend:DI (plus:SI (FOO:SI) (const_int Y)))
> 
> Is is OK to transform it to
> 
> (plus:DI (zero_extend:DI (FOO:SI)) (const_int Y))

It is valid if addresses can never extend across singed SI_MAX and SI_MIN.
Comment 4 H.J. Lu 2011-07-28 21:39:47 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > The question is we have
> > 
> > (zero_extend:DI (plus:SI (FOO:SI) (const_int Y)))
> > 
> > Is is OK to transform it to
> > 
> > (plus:DI (zero_extend:DI (FOO:SI)) (const_int Y))
> 
> It is valid if addresses can never extend across singed SI_MAX and SI_MIN.

For POINTERS_EXTEND_UNSIGNED > 0, the valid address arrange is
0 to UINT_MAX.
Comment 5 H.J. Lu 2011-08-02 14:08:31 UTC
Another testcase:

[hjl@gnu-33 gcc]$ cat /export/gnu/import/delta-fortran/testcase-min.f
      subroutine midbloc6(c,a2,a2i,q)
      parameter (ndim2=6)
      parameter (ndim=3)
      dimension cr(ndim2,ndim2),xj(ndim2,ndim2),q(*)
     @,sai(ndim2,ndim2),cm(ndim2,ndim2),w(ndim2,ndim2)
      dimension vr(ndim2,ndim2),vi(ndim2,ndim2),s1(ndim2,ndim2),p(ndim)
      dimension xq(6),qb(2),qc(2),ifl(6),iplane(3)
      save
      call eig66(cr,rr,ri,vr,vi)
      xq(i)=asin(ri(i))/x2pi
      i9=6
      qb(1)=q(1)/x2pi
        do 180 i=1,2
          do 170 j=1,6
  120       if(xq(j)) 130,190,140
  130       if(qb(i)-0.5d0) 160,150,150
  140       if(qb(i)-0.5d0) 150,150,160
  150       continue
            tst=abs(abs(qb(i))-abs(xq(j)))
  160       continue
  170     continue
          iplane(i)=k
  180   continue
  190   continue
      n1=iplane(3)
      if(i9.eq.6) then
        z=vr(1,n1)*vi(2,n1)-vr(2,n1)*vi(1,n1)+vr(3,n1)*vi(4,n1)-vr(4,n1)
      endif
      sai(6,i)=vi(i,n1)/z
      call dacond6(a2,zero)
      end
[hjl@gnu-33 gcc]$ ./xgcc -B./ -O3 -mx32 -O3 -funroll-loops -ffast-math -S /export/gnu/import/delta-fortran/testcase-min.f
/export/gnu/import/delta-fortran/testcase-min.f: In function \u2018midbloc6\u2019:
/export/gnu/import/delta-fortran/testcase-min.f:31:0: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
[hjl@gnu-33 gcc]$
Comment 6 Uroš Bizjak 2011-08-02 15:39:55 UTC
(In reply to comment #5)
> Another testcase:

Program received signal SIGSEGV, Segmentation fault.
try_combine (i3=<optimized out>, i2=<optimized out>, i1=0x0, i0=<optimized out>, new_direct_jump_p=0x7fffffffdf54, 
    last_combined_insn=0x7ffff1a12c60) at ../../gcc-svn/trunk/gcc/combine.c:4154
4154			  if (link->insn == i2)

#0  try_combine (i3=<optimized out>, i2=<optimized out>, i1=0x0, i0=<optimized out>, new_direct_jump_p=0x7fffffffdf54, 
    last_combined_insn=0x7ffff1a12c60) at ../../gcc-svn/trunk/gcc/combine.c:4154
#1  0x0000000000d3192d in combine_instructions (nregs=<optimized out>, f=0x7ffff1a01048) at ../../gcc-svn/trunk/gcc/combine.c:1223
#2  rest_of_handle_combine () at ../../gcc-svn/trunk/gcc/combine.c:13880
#3  0x0000000000871d88 in execute_one_pass (pass=0x13d2620) at ../../gcc-svn/trunk/gcc/passes.c:2063
#4  0x00000000008720f5 in execute_pass_list (pass=0x13d2620) at ../../gcc-svn/trunk/gcc/passes.c:2118
#5  0x0000000000872107 in execute_pass_list (pass=0x13cdc80) at ../../gcc-svn/trunk/gcc/passes.c:2119
#6  0x00000000009752ce in tree_rest_of_compilation (fndecl=0x7ffff1b8cb00) at ../../gcc-svn/trunk/gcc/tree-optimize.c:416
#7  0x000000000065c8c6 in cgraph_expand_function (node=0x7ffff1991900) at ../../gcc-svn/trunk/gcc/cgraphunit.c:1803
#8  0x000000000065e64c in cgraph_expand_all_functions () at ../../gcc-svn/trunk/gcc/cgraphunit.c:1862
Comment 7 H.J. Lu 2011-08-02 15:57:35 UTC
Created attachment 24893 [details]
A patch

With this patch, I got many ICEs in gcc testsuite. One of
them is

[hjl@gnu-6 pr49721]$ cat x.i
struct
{
  int i;
  double e;
  int j;
} x;

void
f2 (void)
{
#pragma omp atomic
    x.e /= 0.25;
}
[hjl@gnu-6 pr49721]$ make x.s
/export/build/gnu/gcc-x32/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/gcc-x32/build-x86_64-linux/gcc/ -S -o x.s -mx32 -O2 -fopenmp  x.i
x.i: In function ‘f2’:
x.i:13:1: error: unrecognizable insn:
(insn 15 14 16 5 (set (reg/f:DI 70)
        (const:DI (reg:DI 67))) x.i:12 -1
     (nil))
x.i:13:1: internal compiler error: in extract_insn, at recog.c:2115
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
make: *** [x.s] Error 1
[hjl@gnu-6 pr49721]$
Comment 8 H.J. Lu 2011-08-02 15:58:56 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > Another testcase:
> 
> Program received signal SIGSEGV, Segmentation fault.
> try_combine (i3=<optimized out>, i2=<optimized out>, i1=0x0, i0=<optimized
> out>, new_direct_jump_p=0x7fffffffdf54, 
>     last_combined_insn=0x7ffff1a12c60) at
> ../../gcc-svn/trunk/gcc/combine.c:4154
> 4154              if (link->insn == i2)
> 
> #0  try_combine (i3=<optimized out>, i2=<optimized out>, i1=0x0, i0=<optimized
> out>, new_direct_jump_p=0x7fffffffdf54, 
>     last_combined_insn=0x7ffff1a12c60) at
> ../../gcc-svn/trunk/gcc/combine.c:4154

That is because simplify-rtx.c generates new insns via
convert_memory_address_addr_space.
Comment 9 Uroš Bizjak 2011-08-02 18:36:33 UTC
(In reply to comment #8)

> > #0  try_combine (i3=<optimized out>, i2=<optimized out>, i1=0x0, i0=<optimized
> > out>, new_direct_jump_p=0x7fffffffdf54, 
> >     last_combined_insn=0x7ffff1a12c60) at
> > ../../gcc-svn/trunk/gcc/combine.c:4154
> 
> That is because simplify-rtx.c generates new insns via
> convert_memory_address_addr_space.

Yeah, but during the combine pass?!

Every memory access before the combine is referred via DImode symbol and/or DImode reg combination, which is perfectly OK.

It looks to me that combine pass needs some additional conditions to not do stupid things. To confirm this, try disabling combine pass with:

Index: combine.c
===================================================================
--- combine.c	(revision 177171)
+++ combine.c	(working copy)
@@ -13861,7 +13861,7 @@
 static bool
 gate_handle_combine (void)
 {
-  return (optimize > 0);
+  return (0 && optimize > 0);
 }
 
 /* Try combining insns through substitution.  */

This ""patch"" fixes the segfault.
Comment 10 H.J. Lu 2011-08-02 19:17:43 UTC
Here is the problem:

(gdb) 
Continuing.

Breakpoint 1, convert_memory_address_addr_space (to_mode=DImode, 
    x=0x7ffff07f73c0, as=0 '\000')
    at /export/gnu/import/git/gcc/gcc/explow.c:409
409	  return convert_modes (to_mode, from_mode,
(plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] <var_decl 0x7ffff08593c0 iplane>)
    (const_int -4 [0xfffffffffffffffc]))
(gdb) bt
#0  convert_memory_address_addr_space (to_mode=DImode, x=0x7ffff07f73c0, 
    as=0 '\000') at /export/gnu/import/git/gcc/gcc/explow.c:409
#1  0x0000000000789f95 in convert_memory_address_addr_space (to_mode=DImode, 
    x=0x7ffff07f1c70, as=0 '\000')
    at /export/gnu/import/git/gcc/gcc/explow.c:380
#2  0x0000000000b12b4f in simplify_unary_operation_1 (code=ZERO_EXTEND, 
    mode=DImode, op=0x7ffff07f1c70)
    at /export/gnu/import/git/gcc/gcc/simplify-rtx.c:1246
#3  0x0000000000b108ae in simplify_unary_operation (code=ZERO_EXTEND, 
    mode=DImode, op=0x7ffff07f1c70, op_mode=SImode)
    at /export/gnu/import/git/gcc/gcc/simplify-rtx.c:582
#4  0x0000000000b10092 in simplify_gen_unary (code=ZERO_EXTEND, mode=DImode, 
    op=0x7ffff07f1c70, op_mode=SImode)
    at /export/gnu/import/git/gcc/gcc/simplify-rtx.c:370
#5  0x000000000116cb9a in if_then_else_cond (x=0x7ffff07beb40, 
    ptrue=0x7fffffffd370, pfalse=0x7fffffffd368)
    at /export/gnu/import/git/gcc/gcc/combine.c:8650
#6  0x00000000011639b0 in combine_simplify_rtx (x=0x7ffff07beb40, 
    op0_mode=SImode, in_dest=0, in_cond=0)
    at /export/gnu/import/git/gcc/gcc/combine.c:5316
#7  0x0000000001163710 in subst (x=0x7ffff07beb40, from=0x7ffff07c5ac0, 
    to=0x7ffff07f73d8, in_dest=0, in_cond=0, unique_copy=0)
    at /export/gnu/import/git/gcc/gcc/combine.c:5253
---Type <return> to continue, or q <return> to quit---
#8  0x00000000011634ff in subst (x=0x7ffff07ca990, from=0x7ffff07c5ac0, 
    to=0x7ffff07f73d8, in_dest=0, in_cond=0, unique_copy=0)
    at /export/gnu/import/git/gcc/gcc/combine.c:5189
#9  0x000000000115d5d6 in try_combine (i3=0x7ffff07cb708, i2=0x7ffff07cb6c0, 
    i1=0x0, i0=0x0, new_direct_jump_p=0x7fffffffda64, 
    last_combined_insn=0x7ffff07cb708)
    at /export/gnu/import/git/gcc/gcc/combine.c:3178
#10 0x00000000011588af in combine_instructions (f=0x7ffff07ab880, nregs=487)
    at /export/gnu/import/git/gcc/gcc/combine.c:1223
#11 0x0000000001178a5e in rest_of_handle_combine ()
    at /export/gnu/import/git/gcc/gcc/combine.c:13880
#12 0x0000000000a5384c in execute_one_pass (pass=0x190e600)
    at /export/gnu/import/git/gcc/gcc/passes.c:2063
#13 0x0000000000a53a32 in execute_pass_list (pass=0x190e600)
    at /export/gnu/import/git/gcc/gcc/passes.c:2118
#14 0x0000000000a53a53 in execute_pass_list (pass=0x1909260)
    at /export/gnu/import/git/gcc/gcc/passes.c:2119
#15 0x0000000000bec908 in tree_rest_of_compilation (fndecl=0x7ffff0945b00)
    at /export/gnu/import/git/gcc/gcc/tree-optimize.c:416
#16 0x00000000006d4d95 in cgraph_expand_function (node=0x7ffff074a900)
    at /export/gnu/import/git/gcc/gcc/cgraphunit.c:1803
#17 0x00000000006d4f54 in cgraph_expand_all_functions ()
    at /export/gnu/import/git/gcc/gcc/cgraphunit.c:1862
---Type <return> to continue, or q <return> to quit---
#18 0x00000000006d5650 in cgraph_optimize ()
    at /export/gnu/import/git/gcc/gcc/cgraphunit.c:2132
#19 0x00000000006d2acd in cgraph_finalize_compilation_unit ()
    at /export/gnu/import/git/gcc/gcc/cgraphunit.c:1310
#20 0x00000000009cf010 in write_global_declarations ()
    at /export/gnu/import/git/gcc/gcc/langhooks.c:303
#21 0x0000000000559ed0 in gfc_write_global_declarations ()
    at /export/gnu/import/git/gcc/gcc/fortran/f95-lang.c:322
#22 0x0000000000b49830 in compile_file ()
    at /export/gnu/import/git/gcc/gcc/toplev.c:564
#23 0x0000000000b4ba1a in do_compile ()
    at /export/gnu/import/git/gcc/gcc/toplev.c:1886
#24 0x0000000000b4bb8a in toplev_main (argc=19, argv=0x7fffffffdef8)
    at /export/gnu/import/git/gcc/gcc/toplev.c:1962
#25 0x000000000060d9ac in main (argc=19, argv=0x7fffffffdef8)
    at /export/gnu/import/git/gcc/gcc/main.c:36
(gdb) 

In combine, we can't generate any new insns. But we do generate
new insns in this case.
Comment 11 Uroš Bizjak 2011-08-02 19:19:06 UTC
So, we have:

(insn 129 128 131 2 (set (reg:DI 276)
        (sign_extend:DI (reg:SI 277))) pr49721.f:10 123 {*extendsidi2_rex64}
     (expr_list:REG_DEAD (reg:SI 277)
        (nil)))

...

(insn 132 131 133 2 (set (reg:SF 279)
        (mult:SF (reg:SF 146 [ D.1599 ])
            (reg:SF 280))) pr49721.f:10 732 {*fop_sf_comm_sse}
     (expr_list:REG_DEAD (reg:SF 146 [ D.1599 ])
        (expr_list:REG_EQUAL (mult:SF (reg:SF 146 [ D.1599 ])
                (const_double:SF +Inf [+Inf]))
            (nil))))

(insn 133 132 134 2 (set (mem/s:SF (plus:DI (reg:DI 276)
                (symbol_ref:DI ("xq.1569") [flags 0x2]  <var_decl 0x7ffdb8bcaaa0 xq>)) [3 xq S4 A32])
        (reg:SF 279)) pr49721.f:10 107 {*movsf_internal}
     (expr_list:REG_DEAD (reg:SF 279)
        (expr_list:REG_DEAD (reg:DI 276)
            (nil))))

And combine creates:

Trying 132, 129 -> 133:

...

Successfully matched this instruction:
(set (reg:DI 279)
    (sign_extend:DI (reg:SI 277)))
Failed to match this instruction:
(set (mem/s:SF (plus:DI (reg:DI 279)
            (symbol_ref:DI ("xq.1569") [flags 0x2]  <var_decl 0x7f9a07ef3aa0 xq>)) [3 xq S4 A32])
    (mult:SF (reg:SF 146 [ D.1599 ])
        (reg:SF 280)))

A ... WHAT?
Comment 12 H.J. Lu 2011-08-02 19:29:12 UTC
combine.c has

 /* Allocate array for insn info.  */
  max_uid_known = get_max_uid ();
  uid_log_links = XCNEWVEC (struct insn_link *, max_uid_known + 1); 
  uid_insn_cost = XCNEWVEC (int, max_uid_known + 1); 
  gcc_obstack_init (&insn_link_obstack);

combine isn't prepared to deal with new insns generated by convert_memory_address_addr_space and it accesses invalid
memory in

                FOR_EACH_LOG_LINK (link, temp)
                  if (link->insn == i2)
                    link->insn = i3;

on those newly generated insns.
Comment 13 Uroš Bizjak 2011-08-02 19:32:46 UTC
(In reply to comment #10)
> Here is the problem:

No, in your case new insn is rejected (twice):

Trying 434 -> 435:
Failed to match this instruction:
(parallel [
        (set (reg/f:SI 364)
            (if_then_else:SI (eq:SI (reg:SI 442)
                    (const_int 0 [0]))
                (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2]  <var_decl 0x7f9a07ef33c0 iplane>)
                        (const_int -4 [0xfffffffffffffffc])))
                (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2]  <var_decl 0x7f9a07ef33c0 iplane>)
                        (const_int 4 [0x4])))))
        (clobber (reg:CC 17 flags))
    ])
Failed to match this instruction:
(set (reg/f:SI 364)
    (if_then_else:SI (eq:SI (reg:SI 442)
            (const_int 0 [0]))
        (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2]  <var_decl 0x7f9a07ef33c0 iplane>)
                (const_int -4 [0xfffffffffffffffc])))
        (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2]  <var_decl 0x7f9a07ef33c0 iplane>)
                (const_int 4 [0x4])))))
Comment 14 H.J. Lu 2011-08-02 19:42:30 UTC
(In reply to comment #13)
> (In reply to comment #10)
> > Here is the problem:
> 
> No, in your case new insn is rejected (twice):
> 
> Trying 434 -> 435:
> Failed to match this instruction:
> (parallel [
>         (set (reg/f:SI 364)
>             (if_then_else:SI (eq:SI (reg:SI 442)
>                     (const_int 0 [0]))
>                 (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] 
> <var_decl 0x7f9a07ef33c0 iplane>)
>                         (const_int -4 [0xfffffffffffffffc])))
>                 (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] 
> <var_decl 0x7f9a07ef33c0 iplane>)
>                         (const_int 4 [0x4])))))
>         (clobber (reg:CC 17 flags))
>     ])
> Failed to match this instruction:
> (set (reg/f:SI 364)
>     (if_then_else:SI (eq:SI (reg:SI 442)
>             (const_int 0 [0]))
>         (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] 
> <var_decl 0x7f9a07ef33c0 iplane>)
>                 (const_int -4 [0xfffffffffffffffc])))
>         (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] 
> <var_decl 0x7f9a07ef33c0 iplane>)
>                 (const_int 4 [0x4])))))

When new insns (even if they are rejected) are generated, max_uid_known
is increased, which breaks combine due to the fixed arrays allocated
at the beginning of the combine pass:

 /* Allocate array for insn info.  */
  max_uid_known = get_max_uid ();
  uid_log_links = XCNEWVEC (struct insn_link *, max_uid_known + 1); 
  uid_insn_cost = XCNEWVEC (int, max_uid_known + 1); 
  gcc_obstack_init (&insn_link_obstack);
Comment 15 Uroš Bizjak 2011-08-02 20:22:27 UTC
(In reply to comment #14)
> (In reply to comment #13)
> > (In reply to comment #10)
> > > Here is the problem:
> > 
> > No, in your case new insn is rejected (twice):
> > 
> > Trying 434 -> 435:
> > Failed to match this instruction:
> > (parallel [
> >         (set (reg/f:SI 364)
> >             (if_then_else:SI (eq:SI (reg:SI 442)
> >                     (const_int 0 [0]))
> >                 (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] 
> > <var_decl 0x7f9a07ef33c0 iplane>)
> >                         (const_int -4 [0xfffffffffffffffc])))
> >                 (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] 
> > <var_decl 0x7f9a07ef33c0 iplane>)
> >                         (const_int 4 [0x4])))))
> >         (clobber (reg:CC 17 flags))
> >     ])
> > Failed to match this instruction:
> > (set (reg/f:SI 364)
> >     (if_then_else:SI (eq:SI (reg:SI 442)
> >             (const_int 0 [0]))
> >         (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] 
> > <var_decl 0x7f9a07ef33c0 iplane>)
> >                 (const_int -4 [0xfffffffffffffffc])))
> >         (const:SI (plus:SI (symbol_ref:SI ("iplane.1553") [flags 0x2] 
> > <var_decl 0x7f9a07ef33c0 iplane>)
> >                 (const_int 4 [0x4])))))
> 
> When new insns (even if they are rejected) are generated, max_uid_known
> is increased, which breaks combine due to the fixed arrays allocated
> at the beginning of the combine pass:
> 
>  /* Allocate array for insn info.  */
>   max_uid_known = get_max_uid ();
>   uid_log_links = XCNEWVEC (struct insn_link *, max_uid_known + 1); 
>   uid_insn_cost = XCNEWVEC (int, max_uid_known + 1); 
>   gcc_obstack_init (&insn_link_obstack);

Yeah, following ""patch"" works:

Index: combine.c
===================================================================
--- combine.c	(revision 177171)
+++ combine.c	(working copy)
@@ -1102,8 +1102,8 @@ combine_instructions (rtx f, unsigned in
 
   /* Allocate array for insn info.  */
   max_uid_known = get_max_uid ();
-  uid_log_links = XCNEWVEC (struct insn_link *, max_uid_known + 1);
-  uid_insn_cost = XCNEWVEC (int, max_uid_known + 1);
+  uid_log_links = XCNEWVEC (struct insn_link *, max_uid_known + 100);
+  uid_insn_cost = XCNEWVEC (int, max_uid_known + 100);
   gcc_obstack_init (&insn_link_obstack);
 
   nonzero_bits_mode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);

It produces something that looks like correct assembly...

Paolo?
Comment 16 H.J. Lu 2011-08-03 02:40:05 UTC
The fundamental question is what the actual address for
(symbol FOO + const_int Y), where the numerical value of
(symbol FOO + const_int Y) is outside of [0 - (2 to the power
of hardware address bits) - 1], should be. I believe the
answer should be "implementation defined" and programs which
depend on certain behavior are broken.
Comment 17 Paolo Bonzini 2011-08-03 06:32:42 UTC
H.J., I agree with what you write in comment 16.  But unless we are sure that the problematic composition will never be generated (e.g. by ivopts), we cannot afford that.

The patch in comment 7 may have some snafu, but overall it looks very sane.  It's just that a const is not being stripped.  Can it be applied on top of the x32 branch?  Or do I first have to revert some earlier revision?
Comment 18 Uroš Bizjak 2011-08-03 06:40:45 UTC
(In reply to comment #17)
> H.J., I agree with what you write in comment 16.  But unless we are sure that
> the problematic composition will never be generated (e.g. by ivopts), we cannot
> afford that.
> 
> The patch in comment 7 may have some snafu, but overall it looks very sane. 
> It's just that a const is not being stripped.  Can it be applied on top of the
> x32 branch?  Or do I first have to revert some earlier revision?

The patch can be applied to current trunk as-is and all the problems discussed here will be shown by simply compiling with -mx32.
Comment 19 Uroš Bizjak 2011-08-03 06:47:30 UTC
Paolo,

FYI, problem in comment #11 can be seen on unpatched trunk by compiling the testcase from comment #5.
Comment 20 H.J. Lu 2011-08-03 13:56:05 UTC
(In reply to comment #17)
> H.J., I agree with what you write in comment 16.  But unless we are sure that
> the problematic composition will never be generated (e.g. by ivopts), we cannot
> afford that.

I come to a conclusion that we must transform

ptr_extend:DI (plus:SI (FOO:SI) (const_int Y)))

to

(plus:DI (ptr_extend:DI (FOO:SI)) (const_int Y))

since this this how GCC supports Pmode != ptr_mode. You can
disable it and watch its fallout on HP-UX.  We never run into
it for zero_extend before since x32 is the first zero_extend
target.  We should extend it to zero_extend.

> The patch in comment 7 may have some snafu, but overall it looks very sane. 
> It's just that a const is not being stripped.  Can it be applied on top of the

I tried to strip const with

diff --git a/gcc/explow.c b/gcc/explow.c
index 069a68a..17afbbc 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -380,7 +380,7 @@ convert_memory_address_addr_space_1 (enum machine_mode to_mode ATTRIBUTE_UNUSED,
     case CONST:
       temp = convert_memory_address_addr_space_1 (to_mode, XEXP (x, 0),
                    as, no_emit);
-      return temp ? gen_rtx_CONST (to_mode, temp) : temp;
+      return temp && !REG_P (temp) ? gen_rtx_CONST (to_mode, temp) : temp;
       break;
 
     case PLUS:

and it still has massive failures:

http://gcc.gnu.org/ml/gcc-testresults/2011-08/msg00264.html

> x32 branch?  Or do I first have to revert some earlier revision?

The patch in comment 7 is for trunk.
Comment 21 Uroš Bizjak 2011-08-03 14:05:06 UTC
(In reply to comment #20)

> and it still has massive failures:
> 
> http://gcc.gnu.org/ml/gcc-testresults/2011-08/msg00264.html

You broke exceptions. Similar problem can be currently seen on alpha, see PR 49688.
Comment 22 H.J. Lu 2011-08-03 14:48:09 UTC
(In reply to comment #17)
> H.J., I agree with what you write in comment 16.  But unless we are sure that
> the problematic composition will never be generated (e.g. by ivopts), we cannot
> afford that.

My understanding is ivopts only works on ptr_mode (see PR 47383).
Comment 23 hjl@gcc.gnu.org 2011-08-09 13:22:10 UTC
Author: hjl
Date: Tue Aug  9 13:22:05 2011
New Revision: 177591

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=177591
Log:
Revert fix for PR middle-end/49721.

2011-08-08  H.J. Lu  <hongjiu.lu@intel.com>

	Revert
	PR middle-end/49721
	* explow.c (convert_memory_address_addr_space_1): New.
	(convert_memory_address_addr_space): Use it.

	* expr.c (convert_modes_1): New.
	(convert_modes): Use it.

	* expr.h (convert_modes_1): New.

	* rtl.h (convert_memory_address_addr_space_1): New.
	(convert_memory_address_1): Likewise.

	* simplify-rtx.c (simplify_unary_operation_1): Call
	convert_memory_address_1 instead of convert_memory_address.

Modified:
    branches/x32/gcc/ChangeLog.x32
    branches/x32/gcc/explow.c
    branches/x32/gcc/expr.c
    branches/x32/gcc/expr.h
    branches/x32/gcc/rtl.h
    branches/x32/gcc/simplify-rtx.c
Comment 24 hjl@gcc.gnu.org 2011-08-09 13:24:07 UTC
Author: hjl
Date: Tue Aug  9 13:24:04 2011
New Revision: 177592

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=177592
Log:
Also permute zero-extend and addition of constant.

gcc/

2011-08-08  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/49721
	* explow.c (convert_memory_address_addr_space): Also permute
	zero-extend and addition of constant.

gcc/testsuite/

2011-08-08  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/49721
	* gfortran.dg/pr49721.f: New.

Added:
    branches/x32/gcc/testsuite/gfortran.dg/pr49721.f
Modified:
    branches/x32/gcc/ChangeLog.x32
    branches/x32/gcc/explow.c
    branches/x32/gcc/testsuite/ChangeLog.x32
Comment 25 H.J. Lu 2011-08-18 21:56:43 UTC
Another testcase:

[hjl@gnu-6 pr49721]$ cat foo.f
      PARAMETER( LM=7 )
     PARAMETER( NM=2+2**LM, NV=NM**3 )
     PARAMETER( NR = (8*(NM**3+NM**2+5*NM-23+7*LM))/7 )
       COMMON /X/ U, V, R, A
     REAL*8 U(NR),V(NV),R(NR),A(0:3)
     DO 20 IT=1,NIT
       CALL RESID(U,V,R,N,A)
 20   CONTINUE
     END
[hjl@gnu-6 pr49721]$

"-mx32 -O2 -ffast-math" may pass:

(plus:SI (symbol_ref:SI ("x_") <var_decl 0x7ffff188b1e0 x>)
   (const_int 58071104 [0x3761840]))

to

convert_memory_address_addr_space 

#2  0x000000000078c0d1 in convert_memory_address_addr_space (to_mode=DImode,
   x=0x7ffff1971a10, as=0 '\000')
   at /export/gnu/import/git/gcc-x32/gcc/explow.c:380
#3  0x0000000000b06f58 in simplify_unary_operation_1 (code=ZERO_EXTEND,
   mode=DImode, op=0x7ffff1971a10)
   at /export/gnu/import/git/gcc-x32/gcc/simplify-rtx.c:1246
#4  0x0000000000b04cb1 in simplify_unary_operation (code=ZERO_EXTEND,
   mode=DImode, op=0x7ffff1971a10, op_mode=SImode)
   at /export/gnu/import/git/gcc-x32/gcc/simplify-rtx.c:582
#5  0x000000000118b977 in fold_rtx (x=0x7ffff1971a20, insn=0x7ffff1886ee8)
   at /export/gnu/import/git/gcc-x32/gcc/cse.c:3353
#6  0x000000000118e51f in cse_insn (insn=0x7ffff1886ee8)
   at /export/gnu/import/git/gcc-x32/gcc/cse.c:4500
#7  0x000000000119387e in cse_extended_basic_block (ebb_data=0x7fffffffdad0)
   at /export/gnu/import/git/gcc-x32/gcc/cse.c:6345
#8  0x0000000001193e5f in cse_main (f=0x7ffff1881b40, nregs=80)
   at /export/gnu/import/git/gcc-x32/gcc/cse.c:6522
#9  0x0000000001195999 in rest_of_handle_cse ()

If we don't permute, we will get

Program received signal SIGSEGV, Segmentation fault.
0x0000000000622263 in init_alias_analysis ()
   at /export/gnu/import/git/gcc-x32/gcc/alias.c:2870
2870                      else if (DF_REG_DEF_COUNT (regno) == 1
(gdb) bt
#0  0x0000000000622263 in init_alias_analysis ()
   at /export/gnu/import/git/gcc-x32/gcc/alias.c:2870
#1  0x00000000008d07bc in one_pre_gcse_pass ()
   at /export/gnu/import/git/gcc-x32/gcc/gcse.c:2650
#2  0x00000000008d2aa5 in execute_rtl_pre ()
   at /export/gnu/import/git/gcc-x32/gcc/gcse.c:3727
#3  0x0000000000a47514 in execute_one_pass (pass=0x191ea60)
   at /export/gnu/import/git/gcc-x32/gcc/passes.c:2063
#4  0x0000000000a476fa in execute_pass_list (pass=0x191ea60)
   at /export/gnu/import/git/gcc-x32/gcc/passes.c:2118
#5  0x0000000000a4771b in execute_pass_list (pass=0x191f4a0)
   at /export/gnu/import/git/gcc-x32/gcc/passes.c:2119
#6  0x0000000000be1331 in tree_rest_of_compilation (fndecl=0x7ffff197b700)
   at /export/gnu/import/git/gcc-x32/gcc/tree-optimize.c:420
#7  0x00000000006d69ce in cgraph_expand_function (node=0x7ffff1888a20)
   at /export/gnu/import/git/gcc-x32/gcc/cgraphunit.c:1797
#8  0x00000000006d6b8d in cgraph_expand_all_functions ()
   at /export/gnu/import/git/gcc-x32/gcc/cgraphunit.c:1856
#9  0x00000000006d7289 in cgraph_optimize ()
   at /export/gnu/import/git/gcc-x32/gcc/cgraphunit.c:2126
#10 0x00000000006d4755 in cgraph_finalize_compilation_unit ()
   at /export/gnu/import/git/gcc-x32/gcc/cgraphunit.c:1310
#11 0x00000000009d2e84 in write_global_declarations ()
...
Comment 26 hjl@gcc.gnu.org 2011-08-19 21:18:06 UTC
Author: hjl
Date: Fri Aug 19 21:18:03 2011
New Revision: 177914

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=177914
Log:
Permute conversion and addition of constant for zero-extend.

gcc/

2011-08-19  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/49721
	* explow.c (convert_memory_address_addr_space): Also permute the
	conversion and addition of constant for zero-extend.

gcc/testsuite/

2011-08-19  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/49721
	* gfortran.dg/pr49721-1.f: New.
	* gfortran.fortran-torture/compile/pr49721-1.f: Likewise.

Added:
    trunk/gcc/testsuite/gfortran.dg/pr49721-1.f
    trunk/gcc/testsuite/gfortran.fortran-torture/compile/pr49721-1.f
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/explow.c
    trunk/gcc/testsuite/ChangeLog
Comment 27 Andrew Pinski 2014-05-29 04:35:22 UTC
This patch breaks ILP32 with stack pointers.
For this function:
void f(int *a, int b, long long d) __attribute__((noinline,noclone));
void f(int *a, int b, long long d)
{
   if((0x6ffffeff - b) < 11)
     a[(0x6ffffeff - b) +34+0+16+3+12] = d;
}

If a is 0xfffefe90 we get an invalid overflow.  We have the following RTL to begin with:
(plus:SI (plus:SI (mult:SI (reg/v:SI 80 [ b ])
            (const_int -4 [0xfffffffffffffffc]))
        (subreg/s/u:SI (reg/v/f:DI 79 [ a ]) 0))
    (const_int -1073742592 [0xffffffffbffffd00]))

And we decide to put the constant in DImode rather than SImode.
Comment 28 H.J. Lu 2014-05-29 16:00:51 UTC
(In reply to Andrew Pinski from comment #27)
> This patch breaks ILP32 with stack pointers.
> For this function:
> void f(int *a, int b, long long d) __attribute__((noinline,noclone));
> void f(int *a, int b, long long d)
> {
>    if((0x6ffffeff - b) < 11)
>      a[(0x6ffffeff - b) +34+0+16+3+12] = d;
> }
> 
> If a is 0xfffefe90 we get an invalid overflow.  We have the following RTL to
> begin with:
> (plus:SI (plus:SI (mult:SI (reg/v:SI 80 [ b ])
>             (const_int -4 [0xfffffffffffffffc]))
>         (subreg/s/u:SI (reg/v/f:DI 79 [ a ]) 0))
>     (const_int -1073742592 [0xffffffffbffffd00]))
> 
> And we decide to put the constant in DImode rather than SImode.

There is an address overflow and you want to truncate it to 32-bit.
I am not sure if it is defined.
Comment 29 H.J. Lu 2014-05-29 21:39:27 UTC
This is related to PR 55142.
Comment 30 Andrew Pinski 2014-05-30 02:17:38 UTC
(In reply to H.J. Lu from comment #29)
> This is related to PR 55142.

The problem I reported is worked around in the i386 backend though:
(insn:TI 19 18 22 3 (set (mem:SI (plus:DI (reg/f:DI 0 ax [94])
                (const_int -1073742592 [0xffffffffbffffd00])) [2 *_9+0 S4 A32])
        (reg:SI 1 dx [orig:91 d ] [91])) t1234.c:5 90 {*movsi_internal}
     (expr_list:REG_DEAD (reg:SI 1 dx [orig:91 d ] [91])
        (expr_list:REG_DEAD (reg/f:DI 0 ax [94])
            (nil))))

Produces:
	movl	%edx, -1073742592(%eax)

We cannot work around this in the AARCH64 back-end since we don't have instruction which does memory addresses in 32bit.
Comment 31 Andrew Pinski 2014-05-30 20:51:05 UTC
I cannot reproduce the original bug with the patch in comment #26 reverted.
Comment 32 H.J. Lu 2014-05-30 21:28:56 UTC
(In reply to Andrew Pinski from comment #31)
> I cannot reproduce the original bug with the patch in comment #26 reverted.

The original bug only happened with -maddress-mode=long and it may
become latent due to other middle-end changes.
Comment 33 Andrew Pinski 2014-05-30 22:47:23 UTC
*** Bug 55142 has been marked as a duplicate of this bug. ***
Comment 34 Andrew Pinski 2014-05-30 22:52:04 UTC
I have a correct fix (tested by backing all the way to the old code and testing there).  The only time this transformation is safe is inside a CONST rtl.  This fixes both this one and does not cause the regression that was bug 55142.  We also produce better code for -maddress-mode=long for x32 too.
Comment 35 Andrew Pinski 2014-10-15 00:38:35 UTC
Author: pinskia
Date: Wed Oct 15 00:38:03 2014
New Revision: 216229

URL: https://gcc.gnu.org/viewcvs?rev=216229&root=gcc&view=rev
Log:
2014-10-14  Andrew Pinski  <apinski@cavium.com>

	Revert:
	2011-08-19  H.J. Lu  <hongjiu.lu@intel.com>

        PR middle-end/49721
        * explow.c (convert_memory_address_addr_space): Also permute the
        conversion and addition of constant for zero-extend.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/explow.c
Comment 36 Yvan Roux 2014-11-13 14:01:20 UTC
Author: yroux
Date: Thu Nov 13 14:00:48 2014
New Revision: 217497

URL: https://gcc.gnu.org/viewcvs?rev=217497&root=gcc&view=rev
Log:
2014-11-13  Yvan Roux  <yvan.roux@linaro.org>

	Backport from trunk r216229, r216230.
	2014-10-14  Andrew Pinski  <apinski@cavium.com>

	* explow.c (convert_memory_address_addr_space): Rename to ...
	(convert_memory_address_addr_space_1): This.  Add in_const argument.
	Inside a CONST RTL, permute the conversion and addition of constant
	for zero and sign extended pointers.
	(convert_memory_address_addr_space): New function.

	2014-10-14  Andrew Pinski  <apinski@cavium.com>

	Revert:
	2011-08-19  H.J. Lu  <hongjiu.lu@intel.com>

        PR middle-end/49721
        * explow.c (convert_memory_address_addr_space): Also permute the
        conversion and addition of constant for zero-extend.


Modified:
    branches/linaro/gcc-4_9-branch/gcc/ChangeLog.linaro
    branches/linaro/gcc-4_9-branch/gcc/explow.c
Comment 37 Andrew Pinski 2014-11-23 04:13:25 UTC
Fixed for GCC 5.