Bug 58067 - ICE in GFortran recog.c:2158
Summary: ICE in GFortran recog.c:2158
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: 4.9.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 46250 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-08-02 23:58 UTC by Ben Woodard
Modified: 2021-08-02 23:00 UTC (History)
4 users (show)

See Also:
Host:
Target: x86_64-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
a flattened self contained version of the NAS benchmark. (4.23 KB, text/x-fortran)
2013-08-02 23:58 UTC, Ben Woodard
Details
Alexandre's patch as a file rather than as text. (446 bytes, patch)
2013-08-06 23:47 UTC, Ben Woodard
Details | Diff
gnu largepic TLS (1.24 KB, patch)
2013-08-13 11:29 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ben Woodard 2013-08-02 23:58:45 UTC
Created attachment 30602 [details]
a flattened self contained version of the NAS benchmark.

When I try to compile one of the NAS benchmark's with -fpic and -mcmodel=large with GCC 4.8.0 up through the current trunk (20130802) I get an internal compiler error. This looks rather similar to PR56797 but that particular bug seems to have been only on ARM and this occurs on x86_64. So it may be that PR56797 is more expansive than initially thought or this might be a different bug. I can't tell.

[ben@snog BT-MZ]$ PATH=/home/ben/Work/gcc-test/bin/:$PATH gfortran -c -save-temps -O2 -g -fopenmp -fpic -mcmodel=large bt-all.f
bt-all.f: In function ‘MAIN__._omp_fn.1’:
bt-all.f:305:0: note: non-delegitimized UNSPEC UNSPEC_PLTOFF (9) found in variable location
        do iz = 1, proc_num_zones
 ^
bt-all.f:305:0: note: non-delegitimized UNSPEC UNSPEC_PLTOFF (9) found in variable location
bt-all.f: In function ‘MAIN__._omp_fn.0’:
bt-all.f:449:0: error: unrecognizable insn:
  999   continue
 ^
(call_insn/u 52 51 53 2 (parallel [
            (set (reg:DI 0 ax)
                (call:DI (mem:QI (symbol_ref:DI ("__tls_get_addr")) [0 S1 A8])
                    (const_int 0 [0])))
            (unspec:DI [
                    (symbol_ref:DI ("omp_cmn2a_") [flags 0x10] <var_decl 0x7f57f37f9390 omp_cmn2a>)
                ] UNSPEC_TLS_GD)
        ]) bt-all.f:48 -1
     (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
        (nil))
    (nil))
bt-all.f:449:0: internal compiler error: in extract_insn, at recog.c:2158
0x922c1a _fatal_insn(char const*, rtx_def const*, char const*, int, char const*)
	../.././gcc/rtl-error.c:109
0x922c49 _fatal_insn_not_found(rtx_def const*, char const*, int, char const*)
	../.././gcc/rtl-error.c:117
0x8f966a extract_insn(rtx_def*)
	../.././gcc/recog.c:2158
0x7bdbee instantiate_virtual_regs_in_insn
	../.././gcc/function.c:1609
0x7bdbee instantiate_virtual_regs
	../.././gcc/function.c:1926
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.

This problem doesn't seem to occur except when you have -fpic and -mcmodel=large. Changing the memory model to medium or small or removing the -fpic allows the code to compile.

Attached is a flattened self contained version of the NAS benchmark my fortran is not good enough to boil it down into a more parsimonious reproducer.
Comment 1 Andrew Pinski 2013-08-03 02:16:44 UTC
I don't think -mcmodel=large support has been added for TLS yet.
Comment 2 Uroš Bizjak 2013-08-03 07:16:12 UTC
You can add -mtls-dialect=gnu2 to -fpic and -mcmodel=large.
Comment 3 Ben Woodard 2013-08-05 23:08:52 UTC
(In reply to Uroš Bizjak from comment #2)
> You can add -mtls-dialect=gnu2 to -fpic and -mcmodel=large.

Though doing that prevents the ICE, the compilation spits out about 78 lines like:

bt-all.f:453:0: note: non-delegitimized UNSPEC UNSPEC_GOTOFF (1) found in variable location

Google doesn't seem to give me any idea as to if I need be concerned about that note.
Comment 4 Alexandre Oliva 2013-08-06 20:08:15 UTC
The note just means the debug info location expression containing this unexpected piece of RTL can't be expressed in dwarf and will thus be dropped on the floor, so you lose a bit of debug info, but that's all.
Comment 5 Alexandre Oliva 2013-08-06 22:03:40 UTC
As Andrew says, the problem with -mtls-dialect=gnu (the default) is lack of TLS support.  The tls_get_addr calls expanded by tls_global_dynamic_64_<mode> are not recognized by the corresponding insns because the call address operand (the __tls_get_addr symbol_ref) doesn't pass the constant_call_address_operand predicate, configured to always fail in the LARGE code models.  I suppose it's not appropriate to make an exception for __tls_get_addr, and we'd instead have to make it an indirect call after loading the address from the GOT.  We'd need new relocations and relaxation smarts in binutils for this to work.  I guess it makes more sense to force the GNU2 tls-dialect for LARGE code models, since that one works, and maybe switch to it by default in other models; we've had it for long enough already.

As for the non-delegitimized notes we get in both modes, that's fixed with something along the lines of the following patch:

--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -13827,6 +13827,21 @@ ix86_delegitimize_address (rtx x)
 	    x = replace_equiv_address_nv (orig_x, x);
 	  return x;
 	}
+      if (GET_CODE (x) == PLUS
+	  && ix86_pic_register_p (XEXP (x, 0))
+	  && GET_CODE (XEXP (x, 1)) == CONST
+	  && GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
+	  /* These are used in 64-bit CM_LARGE mode.  */
+	  && (XINT (XEXP (XEXP (x, 1), 0), 1) == UNSPEC_PLTOFF
+	      || XINT (XEXP (XEXP (x, 1), 0), 1) == UNSPEC_GOTOFF))
+	{
+	  x = simplify_gen_subreg (GET_MODE (orig_x),
+				   XVECEXP (XEXP (XEXP (x, 1), 0), 0, 0),
+				   GET_MODE (x), 0);
+	  if (x == NULL_RTX)
+	    return orig_x;
+	  return x;
+	}
       if (GET_CODE (x) != CONST
 	  || GET_CODE (XEXP (x, 0)) != UNSPEC
 	  || (XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL

Uros (or anyone), please take this as a starting point; it might require support for addends, even though I haven't needed them for this one testcase.  Or maybe we don't need them, after all.  I'm not sure, so I'll leave it for someone else who knows better.
Comment 6 Ben Woodard 2013-08-06 23:44:47 UTC
I just rebuilt the trunk with the patch that Alexandre Oliva provided and I can confirm that it solves the problem with notes about non-delegitimized addresses. 

However, I haven't yet tested the DWARF to make sure that it works as expected. 

If we do make -mtls-dialect=gnu2 the default or even implied when you specify -mcmodel=large,  won't you still need to fix the problem with the unknown instruction just in case someone does -mtls-dialect=gnu or will you just error out saying: "-mcmodel=large is not supported within -mtls-dialect=gnu". Personally, I believe that erroring out that way is perfectly acceptable.
Comment 7 Ben Woodard 2013-08-06 23:47:41 UTC
Created attachment 30622 [details]
Alexandre's patch as a file rather than as text.
Comment 8 Jakub Jelinek 2013-08-13 11:29:30 UTC
Created attachment 30646 [details]
gnu largepic TLS

An attempt to handle -mcmodel=large -fpic TLS GD/LD in the compiler.
Seems to work for me on testcase like:
__thread int a;
static __thread int b;

int
foo ()
{
  return a++ + b++;
}

int
main ()
{
  return foo () + foo () - 2;
}

but unfortunately ld will fail if this code is being attempted to link into an executable or PIE:
/usr/bin/ld: /tmp/ccWao1Is.o: TLS transition from R_X86_64_TLSGD to R_X86_64_GOTTPOFF against `a' at 0x26 in section `.text' failed
/tmp/ccWao1Is.o: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
Comment 9 Jakub Jelinek 2013-08-14 10:59:29 UTC
Author: jakub
Date: Wed Aug 14 09:09:58 2013
New Revision: 201720

URL: http://gcc.gnu.org/viewcvs?rev=201720&root=gcc&view=rev
Log:
	PR target/58067
	* config/i386/i386.c (ix86_delegitimize_address): For CM_MEDIUM_PIC
	and CM_LARGE_PIC ix86_cmodel fall thru into the -m32 code, handle
	there also UNSPEC_PLTOFF.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/i386/i386.c

Author: jakub
Date: Wed Aug 14 09:29:22 2013
New Revision: 201721

URL: http://gcc.gnu.org/viewcvs?rev=201721&root=gcc&view=rev
Log:
	PR target/58067
	* config/i386/i386.c (ix86_delegitimize_address): For CM_MEDIUM_PIC
	and CM_LARGE_PIC ix86_cmodel fall thru into the -m32 code, handle
	there also UNSPEC_PLTOFF.

Modified:
    branches/gcc-4_8-branch/gcc/ChangeLog
    branches/gcc-4_8-branch/gcc/config/i386/i386.c
Comment 10 Jakub Jelinek 2013-08-28 16:31:43 UTC
Author: jakub
Date: Wed Aug 28 16:31:41 2013
New Revision: 202055

URL: http://gcc.gnu.org/viewcvs?rev=202055&root=gcc&view=rev
Log:
	PR target/58067
	* config/i386/i386.md (*tls_global_dynamic_64_largepic): New insn.
	(*tls_local_dynamic_base_64_largepic): Likewise.
	(tls_global_dynamic_64_<mode>, tls_local_dynamic_base_64_<mode>):
	Remove predicate from call operand.
	* config/i386/i386.c (ix86_tls_get_addr): For -mcmodel=large -fpic
	return sum of pic_offset_table_rtx and UNSPEC_PLTOFF of the symbol.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/i386/i386.c
    trunk/gcc/config/i386/i386.md
Comment 11 Teresa Johnson 2014-06-13 15:05:16 UTC
Is this issue fixed on trunk? The bug is still in state UNCONFIRMED.

Just hit this on the google/4_8 branch, since the last fix (r202055) wasn't backported to gcc-4_8. I am going to backport r202055 to google/4_8 as that seems to fix the problem.

Google ref b/15576865.

Thanks,
Teresa
Comment 12 Arseny Solokha 2018-12-09 04:41:17 UTC
At least the C testcase in comment 8 was fixed for 4.9 and subsequent releases.
Comment 13 Zdenek Sojka 2021-04-29 16:42:52 UTC
Even the original fortran testcase does not fail in 8.3.1, 9.3.0, 10.3.0, 11.1.0 for me.
Comment 14 Andrew Pinski 2021-08-02 22:59:41 UTC
*** Bug 46250 has been marked as a duplicate of this bug. ***
Comment 15 Andrew Pinski 2021-08-02 23:00:41 UTC
Fixed.  There is PR 79497 for the non PIC case with global-dynamic TLS.