I'll add more details as they unfold, but wanted to get this posted into bugzilla. The autotester has been pretty flaky lately that I don't have a good idea when this broke, but looks to have broken somewhere between Oct 29 and Nov 4. I don't have data between those dates, but Nov 4. build did not compile mesa. SegFault doesn't happen at -O1. SegFault Building mesa. /opt/gcc-nightly/gcc/libexec/gcc/powerpc64-linux/4.0.0/cc1 -O2 context.c context.c: In function gl_create_visual: context.c:1082: internal compiler error: Segmentation fault Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://gcc.gnu.org/bugs.html> for instructions. Watching in GDB shows. Analyzing compilation unit Performing intraprocedural optimizations Assembling functions: free_shared_state init_material gl_create_visual Program received signal SIGSEGV, Segmentation fault. note_stores (x=0x403d62f0, fun=0x10325090 <forget_old_reloads_1>, data=0x0) at /home/gccbuild/gcc_mline_anoncvs/gcc/gcc/rtlanal.c:1405 1405 /home/gccbuild/gcc_mline_anoncvs/gcc/gcc/rtlanal.c: No such file or directory. in /home/gccbuild/gcc_mline_anoncvs/gcc/gcc/rtlanal.c
Testcase reduced from the mesa context.c file. Compiling this with -O2 segfaults on linux-powerpc64 segfaults. typedef unsigned int size_t; extern void *malloc (size_t __size) __attribute__ ((__malloc__)); extern void abort(void); struct _abc { int ebc; }; void xxx ( float rscale, float gscale, float bscale, float ascale) { struct _abc *vis; if (rscale > 255.0) abort(); if (gscale > 255.0) abort(); if (bscale > 255.0) abort(); if (ascale > 255.0) abort(); vis = (struct _abc *) malloc(sizeof(struct _abc) ); if (rscale==255.0F && gscale==255.0F && bscale==255.0F && ascale==255.0F) { vis->ebc = 1; } }
Confirmed, also happens on powerpc-darwin with -O2 -fPIC.
Hmm, someone did an emit_rtx and did not end_sequence as the insn looks like: (insn 143 0 0 (set (nil) (reg:CC 75 cr7)) -1 (nil) (nil))
I was wrong in the sense that is the right RTL except that nill is wrong and is being overwritten.
in gen_reload, we do: emit_insn (gen_rtx_SET (VOIDmode, out, in)); but somehow the set gets changed for the out to be nil. Note out and in are correct here. After this we don't get the correct insn in the sequence at all.
Never mind my comment about "emit_insn (gen_rtx_SET " because we are not calling that but 7530 emit_insn (gen_move_insn (out, in));
The bug is in emit_move_insn_1, we set the out side to null for some reason.
We used to change the mode to CC from CCFP but now we don't.
This is the rtl we used to produce: (insn 144 69 75 8 (set (reg:CC 75 cr7) (reg:CC 30 r30 [125])) 336 {*movcc_internal1} (nil) (nil)) <-- this the insn which we are messing up now. (jump_insn:HI 75 144 80 8 (set (pc) (if_then_else (ne (reg:CCFP 75 cr7) (const_int 0 [0x0])) (label_ref 115) (pc))) 527 {*rs6000.md:13676} (insn_list:REG_DEP_ANTI 67 (insn_list:REG_DEP_ANTI 69 (insn_list:REG_DEP_ANTI 68 (nil)))) (expr_list:REG_BR_PROB (
Found the patch which caused the problem: * simplify-rtx.c (simplify_gen_subreg): Fail if simplify_subreg has failed when passed a hard register.
This patch fixes it: Index: simplify-rtx.c =============================================================== ==== RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v retrieving revision 1.207 diff -u -p -r1.207 simplify-rtx.c --- simplify-rtx.c 28 Oct 2004 12:47:21 -0000 1.207 +++ simplify-rtx.c 11 Nov 2004 00:47:26 -0000 @@ -3790,7 +3790,8 @@ simplify_gen_subreg (enum machine_mode o return newx; if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode - || (REG_P (op) && REGNO (op) < FIRST_PSEUDO_REGISTER)) + || (REG_P (op) && REGNO (op) < FIRST_PSEUDO_REGISTER + && GET_MODE_SIZE (innermode) != GET_MODE_SIZE (innermode))) return NULL_RTX; return gen_rtx_SUBREG (outermode, op, byte);
Even though this patch fixes it, it is not the right fix as simplify_subreg should just return a change in the mode rather than return null.
The problem is that the register is r30 (which is the FRAME_POINTER_REGNUM) and reload is not complete at this point, maybe this is not the correct check. ((reload_completed && !frame_pointer_needed) || (REGNO (op) != FRAME_POINTER_REGNUM #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM && REGNO (op) != HARD_FRAME_POINTER_REGNUM #endif ))
Jan you added that code to simplify_subreg but I could not figure out why it was really added except that it effected x86_64 (when bootstrapped with -fomit-frame-pointer). Note in this case the mode the modes are the same size which is unlike the case you found. Reference: http://gcc.gnu.org/ml/gcc-patches/2001-05/msg01737.html http://gcc.gnu.org/ml/gcc-patches/2001-05/msg01729.html
The reason why we are not using r31 at least on darwin is because that is the PIC register.
This looks like the same problem as 18294 which is an ia64-hpux bootstrap failure. In that PR, I suggested that simplify_gen_subreg should just create the subreg for a hard register when simplify_subreg does not, but I haven't looked at this very closely. This problem occurs early, during virtual register instantiation. The patch in comment #11 is flawed. It has + && GET_MODE_SIZE (innermode) != GET_MODE_SIZE (innermode))) which will always be false. Probably one of these was meant to be outermode. If we are trying to prevent reload from creating subregs, then maybe the reload_completed check could instead be !reload_in_progress. This is just a random guess though. I haven't tried looking at Ulrich Weigand's patch yet.
Now that RTH's validate_subreg patch is in, I guess the right fix for this problem might be to always return a SUBREG in simplify_gen_subreg unless that SUBREG is actually invalid. What do you think of this patch: Index: simplify-rtx.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v retrieving revision 1.211 diff -c -p -r1.211 simplify-rtx.c *** simplify-rtx.c 24 Nov 2004 00:09:03 -0000 1.211 --- simplify-rtx.c 25 Nov 2004 18:29:38 -0000 *************** simplify_gen_subreg (enum machine_mode o *** 3782,3792 **** if (newx) return newx; ! if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode ! || (REG_P (op) && REGNO (op) < FIRST_PSEUDO_REGISTER)) ! return NULL_RTX; ! ! if (validate_subreg (outermode, innermode, op, byte)) return gen_rtx_SUBREG (outermode, op, byte); return NULL_RTX; --- 3782,3788 ---- if (newx) return newx; ! if (REG_P (op) && validate_subreg (outermode, innermode, op, byte)) return gen_rtx_SUBREG (outermode, op, byte); return NULL_RTX; (B.t.w. shouldn't validate_subreg reject non-REG inputs itself?)
Subject: Bug 18420 CVSROOT: /cvs/gcc Module name: gcc Changes by: uweigand@gcc.gnu.org 2004-11-28 13:02:53 Modified files: gcc : ChangeLog simplify-rtx.c Log message: PR rtl-optimization/18420 * simplify-rtx.c (simplify_gen_subreg): Revert 2004-10-28 change. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.6599&r2=2.6600 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/simplify-rtx.c.diff?cvsroot=gcc&r1=1.211&r2=1.212
Fixed.
Verified this fixed mesa too.
This was fixed long ago. Closing.