This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Value profile based optimizations, part 1
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sat, 21 Jun 2003 23:18:31 +0200
- Subject: Re: [PATCH] Value profile based optimizations, part 1
- References: <20030619005931.GA5370@atrey.karlin.mff.cuni.cz> <20030619164735.GC7120@redhat.com> <20030619175714.GA10043@atrey.karlin.mff.cuni.cz> <20030619195600.GA17231@redhat.com> <20030619204213.GA28699@atrey.karlin.mff.cuni.cz> <20030619221849.GK17231@redhat.com> <20030619222315.GB4182@atrey.karlin.mff.cuni.cz> <20030619222613.GL17231@redhat.com> <20030619222918.GA4725@atrey.karlin.mff.cuni.cz> <20030619225010.GM17231@redhat.com>
Hello,
> On Fri, Jun 20, 2003 at 12:29:18AM +0200, Zdenek Dvorak wrote:
> > crtstuff.c:287: error: unrecognizable insn:
> > (insn 83 0 54 (set (subreg:SI (reg:CC 68) 0)
> > (subreg:SI (reg:CC 17 flags) 0)) -1 (nil)
> > (nil))
> > crtstuff.c:287: internal compiler error: in extract_insn, at recog.c:2191
>
> Ok, got it.
>
> Problem is
>
> recog.c:
> 1012 /* A register whose class is NO_REGS is not a general operand. */
> 1013 return (REGNO (op) >= FIRST_PSEUDO_REGISTER
> 1014 || REGNO_REG_CLASS (REGNO (op)) != NO_REGS);
>
> I.e. we must provide a movcc pattern on x86.
I currently don't have a time to do it. Would the following solution
be acceptable in the meantime?
Zdenek
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.345
diff -c -3 -p -r1.345 i386.h
*** config/i386/i386.h 19 Jun 2003 21:47:11 -0000 1.345
--- config/i386/i386.h 21 Jun 2003 21:15:08 -0000
*************** do { \
*** 1115,1120 ****
--- 1115,1123 ----
&& (TARGET_64BIT || !TARGET_PARTIAL_REG_STALL)) \
|| ((MODE2) == DImode && TARGET_64BIT))))
+ /* It is possible to write patterns to move flags; but until someone
+ does it, */
+ #define AVOID_CCMODE_COPIES
/* Specify the modes required to caller save a given hard regno.
We do this on i386 to prevent flags from being saved at all.
Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.81
diff -c -3 -p -r1.81 cfgrtl.c
*** cfgrtl.c 13 Jun 2003 22:56:09 -0000 1.81
--- cfgrtl.c 21 Jun 2003 21:15:03 -0000
*************** Software Foundation, 59 Temple Place - S
*** 56,61 ****
--- 56,63 ----
#include "obstack.h"
#include "insn-config.h"
#include "cfglayout.h"
+ #include "recog.h"
+ #include "expr.h"
/* Stubs in case we don't have a return insn. */
#ifndef HAVE_return
*************** static bool rtl_redirect_edge_and_branch
*** 88,93 ****
--- 90,96 ----
static edge rtl_split_block PARAMS ((basic_block, void *));
static void rtl_dump_bb PARAMS ((basic_block, FILE *));
static int rtl_verify_flow_info_1 PARAMS ((void));
+ static void mark_killed_regs (rtx, rtx, void *);
/* Return true if NOTE is not one of the ones that must be kept paired,
so that we may simply delete it. */
*************** insert_insn_on_edge (pattern, e)
*** 1335,1340 ****
--- 1338,1438 ----
e->insns = get_insns ();
end_sequence ();
+ }
+
+ /* Called from safe_insert_insn_on_edge through note_stores, marks live
+ registers that are killed by the store. */
+ static void
+ mark_killed_regs (rtx reg, rtx set ATTRIBUTE_UNUSED, void *data)
+ {
+ regset killed = data;
+ int regno, i;
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+ if (!REG_P (reg))
+ return;
+ regno = REGNO (reg);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ SET_REGNO_REG_SET (killed, regno);
+ else
+ {
+ for (i = 0; i < HARD_REGNO_NREGS (regno, GET_MODE (reg)); i++)
+ SET_REGNO_REG_SET (killed, regno + i);
+ }
+ }
+
+ /* Similar to insert_insn_on_edge, tries to put INSN to edge E. Additionally
+ it checks whether this will not clobber the registers that are live on the
+ edge (i.e. it requieres liveness information to be up-to-date) and if there
+ are some, then it tries to save and restore them. Returns true if
+ succesful. */
+ bool
+ safe_insert_insn_on_edge (rtx insn, edge e)
+ {
+ rtx x;
+ regset_head killed_head;
+ regset killed = INITIALIZE_REG_SET (killed_head);
+ rtx save_regs = NULL_RTX;
+ int regno, noccmode;
+ enum machine_mode mode;
+
+ #ifdef AVOID_CCMODE_COPIES
+ noccmode = true;
+ #else
+ noccmode = false;
+ #endif
+
+ for (x = insn; x; x = NEXT_INSN (x))
+ if (INSN_P (x))
+ note_stores (PATTERN (x), mark_killed_regs, killed);
+ bitmap_operation (killed, killed, e->dest->global_live_at_start,
+ BITMAP_AND);
+
+ EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno,
+ {
+ mode = regno < FIRST_PSEUDO_REGISTER
+ ? reg_raw_mode[regno]
+ : GET_MODE (regno_reg_rtx[regno]);
+ if (mode == VOIDmode)
+ return false;
+
+ if (noccmode && mode == CCmode)
+ return false;
+
+ save_regs = alloc_EXPR_LIST (0,
+ alloc_EXPR_LIST (0,
+ gen_reg_rtx (mode),
+ gen_raw_REG (mode, regno)),
+ save_regs);
+ });
+
+ if (save_regs)
+ {
+ rtx from, to;
+
+ start_sequence ();
+ for (x = save_regs; x; x = XEXP (x, 1))
+ {
+ from = XEXP (XEXP (x, 0), 1);
+ to = XEXP (XEXP (x, 0), 0);
+ emit_move_insn (to, from);
+ }
+ emit_insn (insn);
+ for (x = save_regs; x; x = XEXP (x, 1))
+ {
+ from = XEXP (XEXP (x, 0), 0);
+ to = XEXP (XEXP (x, 0), 1);
+ emit_move_insn (to, from);
+ }
+ insn = get_insns ();
+ end_sequence ();
+ free_EXPR_LIST_list (&save_regs);
+ }
+ insert_insn_on_edge (insn, e);
+
+ FREE_REG_SET (killed);
+ return true;
}
/* Update the CFG for the instructions queued on edge E. */