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.
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.
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.
(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.
(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.
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]$
(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
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]$
(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.
(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.
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.
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?
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.
(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])))))
(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);
(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?
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.
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?
(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.
Paolo, FYI, problem in comment #11 can be seen on unpatched trunk by compiling the testcase from comment #5.
(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.
(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.
(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).
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
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
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 () ...
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
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.
(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.
This is related to PR 55142.
(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.
I cannot reproduce the original bug with the patch in comment #26 reverted.
(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.
*** Bug 55142 has been marked as a duplicate of this bug. ***
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.
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
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
Fixed for GCC 5.