summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-26 19:31:15 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-26 19:31:15 +0000
commit554bbdba51777c554e98715d4988352a319db041 (patch)
tree8dc01bb166b7d6fc97b22df20c170f7ac24bde66
parent9eb16f6a6b383db94fc61b1544c2d8e789301902 (diff)
downloadgcc-554bbdba51777c554e98715d4988352a319db041.tar.gz
gcc/
* config/mips/mips.h (AVOID_CCMODE_COPIES): Update rationale for definition. * config/mips/mips.c (machine_function): Add next_fcc. (mips_output_move): Remove handling of fcc moves. (mips_allocate_fcc): New function. (mips_emit_compare, mips_expand_vcondv2sf): Use it. (mips_hard_regno_mode_ok_p): Restrict CCmode to ST registers. Remove special case for CCmode reloads. (mips_expand_builtin_compare_1): Use mips_allocate_fcc and treat the result a fixed operand. * config/mips/mips.md (move_type): Remove lui_movf. (type, length): Remove references to it. (movcc, reload_incc, reload_outcc): Delete. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@190703 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config/mips/mips.c86
-rw-r--r--gcc/config/mips/mips.h8
-rw-r--r--gcc/config/mips/mips.md56
4 files changed, 86 insertions, 80 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f462c9b3f4e..8c1174e33aa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,21 @@
2012-08-26 Richard Sandiford <rdsandiford@googlemail.com>
+ * config/mips/mips.h (AVOID_CCMODE_COPIES): Update rationale for
+ definition.
+ * config/mips/mips.c (machine_function): Add next_fcc.
+ (mips_output_move): Remove handling of fcc moves.
+ (mips_allocate_fcc): New function.
+ (mips_emit_compare, mips_expand_vcondv2sf): Use it.
+ (mips_hard_regno_mode_ok_p): Restrict CCmode to ST registers.
+ Remove special case for CCmode reloads.
+ (mips_expand_builtin_compare_1): Use mips_allocate_fcc and treat
+ the result a fixed operand.
+ * config/mips/mips.md (move_type): Remove lui_movf.
+ (type, length): Remove references to it.
+ (movcc, reload_incc, reload_outcc): Delete.
+
+2012-08-26 Richard Sandiford <rdsandiford@googlemail.com>
+
* config/mips/mips.c (mips_has_long_branch_p): New function,
split out from...
(mips_expand_ghost_gp_insns): ...here. Look inside sequences.
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 0763f228c42..64e98c3fb91 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -321,6 +321,10 @@ struct GTY(()) mips_frame_info {
};
struct GTY(()) machine_function {
+ /* The next floating-point condition-code register to allocate
+ for ISA_HAS_8CC targets, relative to ST_REG_FIRST. */
+ unsigned int next_fcc;
+
/* The register returned by mips16_gp_pseudo_reg; see there for details. */
rtx mips16_gp_pseudo_rtx;
@@ -4284,9 +4288,6 @@ mips_output_move (rtx dest, rtx src)
retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
return dbl_p ? retval : retval + 1;
}
-
- if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC)
- return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1";
}
if (src_code == MEM)
@@ -4527,6 +4528,63 @@ mips_reversed_fp_cond (enum rtx_code *code)
}
}
+/* Allocate a floating-point condition-code register of mode MODE.
+
+ These condition code registers are used for certain kinds
+ of compound operation, such as compare and branches, vconds,
+ and built-in functions. At expand time, their use is entirely
+ controlled by MIPS-specific code and is entirely internal
+ to these compound operations.
+
+ We could (and did in the past) expose condition-code values
+ as pseudo registers and leave the register allocator to pick
+ appropriate registers. The problem is that it is not practically
+ possible for the rtl optimizers to guarantee that no spills will
+ be needed, even when AVOID_CCMODE_COPIES is defined. We would
+ therefore need spill and reload sequences to handle the worst case.
+
+ Although such sequences do exist, they are very expensive and are
+ not something we'd want to use. This is especially true of CCV2 and
+ CCV4, where all the shuffling would greatly outweigh whatever benefit
+ the vectorization itself provides.
+
+ The main benefit of having more than one condition-code register
+ is to allow the pipelining of operations, especially those involving
+ comparisons and conditional moves. We don't really expect the
+ registers to be live for long periods, and certainly never want
+ them to be live across calls.
+
+ Also, there should be no penalty attached to using all the available
+ registers. They are simply bits in the same underlying FPU control
+ register.
+
+ We therefore expose the hardware registers from the outset and use
+ a simple round-robin allocation scheme. */
+
+static rtx
+mips_allocate_fcc (enum machine_mode mode)
+{
+ unsigned int regno, count;
+
+ gcc_assert (TARGET_HARD_FLOAT && ISA_HAS_8CC);
+
+ if (mode == CCmode)
+ count = 1;
+ else if (mode == CCV2mode)
+ count = 2;
+ else if (mode == CCV4mode)
+ count = 4;
+ else
+ gcc_unreachable ();
+
+ cfun->machine->next_fcc += -cfun->machine->next_fcc & (count - 1);
+ if (cfun->machine->next_fcc > ST_REG_LAST - ST_REG_FIRST)
+ cfun->machine->next_fcc = 0;
+ regno = ST_REG_FIRST + cfun->machine->next_fcc;
+ cfun->machine->next_fcc += count;
+ return gen_rtx_REG (mode, regno);
+}
+
/* Convert a comparison into something that can be used in a branch or
conditional move. On entry, *OP0 and *OP1 are the values being
compared and *CODE is the code used to compare them.
@@ -4590,7 +4648,7 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
cmp_code = *code;
*code = mips_reversed_fp_cond (&cmp_code) ? EQ : NE;
*op0 = (ISA_HAS_8CC
- ? gen_reg_rtx (CCmode)
+ ? mips_allocate_fcc (CCmode)
: gen_rtx_REG (CCmode, FPSW_REGNUM));
*op1 = const0_rtx;
mips_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1);
@@ -4657,7 +4715,7 @@ mips_expand_vcondv2sf (rtx dest, rtx true_src, rtx false_src,
bool reversed_p;
reversed_p = mips_reversed_fp_cond (&cond);
- cmp_result = gen_reg_rtx (CCV2mode);
+ cmp_result = mips_allocate_fcc (CCV2mode);
emit_insn (gen_scc_ps (cmp_result,
gen_rtx_fmt_ee (cond, VOIDmode, cmp_op0, cmp_op1)));
if (reversed_p)
@@ -11098,14 +11156,7 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
&& (regno - ST_REG_FIRST) % 4 == 0);
if (mode == CCmode)
- {
- if (!ISA_HAS_8CC)
- return regno == FPSW_REGNUM;
-
- return (ST_REG_P (regno)
- || GP_REG_P (regno)
- || FP_REG_P (regno));
- }
+ return ISA_HAS_8CC ? ST_REG_P (regno) : regno == FPSW_REGNUM;
size = GET_MODE_SIZE (mode);
mclass = GET_MODE_CLASS (mode);
@@ -11117,10 +11168,6 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
&& (((regno - FP_REG_FIRST) % MAX_FPRS_PER_FMT) == 0
|| (MIN_FPRS_PER_FMT == 1 && size <= UNITS_PER_FPREG)))
{
- /* Allow TFmode for CCmode reloads. */
- if (mode == TFmode && ISA_HAS_8CC)
- return true;
-
/* Allow 64-bit vector modes for Loongson-2E/2F. */
if (TARGET_LOONGSON_VECTORS
&& (mode == V2SImode
@@ -13738,15 +13785,16 @@ mips_expand_builtin_compare_1 (enum insn_code icode,
tree exp, int nargs)
{
struct expand_operand ops[MAX_RECOG_OPERANDS];
+ rtx output;
int opno, argno;
/* The instruction should have a target operand, an operand for each
argument, and an operand for COND. */
gcc_assert (nargs + 2 == insn_data[(int) icode].n_generator_args);
+ output = mips_allocate_fcc (insn_data[(int) icode].operand[0].mode);
opno = 0;
- create_output_operand (&ops[opno++], NULL_RTX,
- insn_data[(int) icode].operand[0].mode);
+ create_fixed_operand (&ops[opno++], output);
for (argno = 0; argno < nargs; argno++)
mips_prepare_builtin_arg (&ops[opno++], exp, argno);
create_integer_operand (&ops[opno++], (int) cond);
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 08c9f53c658..caad3c36db8 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2395,12 +2395,8 @@ typedef struct mips_args {
#define FUNCTION_MODE SImode
-
-/* Define if copies to/from condition code registers should be avoided.
-
- This is needed for the MIPS because reload_outcc is not complete;
- it needs to handle cases where the source is a general or another
- condition code register. */
+/* We allocate $fcc registers by hand and can't cope with moves of
+ CCmode registers to and from pseudos (or memory). */
#define AVOID_CCMODE_COPIES
/* A C expression for the cost of a branch instruction. A value of
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 426a97cef53..86d2c55c55d 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -198,7 +198,6 @@
;; loadpool move a constant into a MIPS16 register by loading it
;; from the pool
;; shift_shift a shift left followed by a shift right
-;; lui_movf an LUI followed by a MOVF (for d<-z CC moves)
;;
;; This attribute is used to determine the instruction's length and
;; scheduling type. For doubleword moves, the attribute always describes
@@ -207,7 +206,7 @@
(define_attr "move_type"
"unknown,load,fpload,store,fpstore,mtc,mfc,mtlo,mflo,move,fmove,
const,constN,signext,ext_ins,logical,arith,sll0,andi,loadpool,
- shift_shift,lui_movf"
+ shift_shift"
(const_string "unknown"))
(define_attr "alu_type" "unknown,add,sub,not,nor,and,or,xor"
@@ -390,8 +389,6 @@
(eq_attr "move_type" "move") (const_string "move")
(eq_attr "move_type" "const") (const_string "const")
(eq_attr "sync_mem" "!none") (const_string "syncloop")]
- ;; We classify "lui_movf" as "unknown" rather than "multi"
- ;; because we don't split it. FIXME: we should split instead.
(const_string "unknown")))
;; Mode for conversion types (fcvt)
@@ -578,10 +575,6 @@
(eq_attr "move_type" "loadpool")
(const_int 8)
- ;; LUI_MOVFs are decomposed into two separate instructions.
- (eq_attr "move_type" "lui_movf")
- (const_int 8)
-
;; SHIFT_SHIFTs are decomposed into two separate instructions.
;; They are extended instructions on MIPS16 targets.
(eq_attr "move_type" "shift_shift")
@@ -4436,53 +4429,6 @@
operands[2] = GEN_INT (val - 0xff);
})
-;; This insn handles moving CCmode values. It's really just a
-;; slightly simplified copy of movsi_internal2, with additional cases
-;; to move a condition register to a general register and to move
-;; between the general registers and the floating point registers.
-
-(define_insn "movcc"
- [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*m,*d,*f,*f,*f,*m")
- (match_operand:CC 1 "general_operand" "z,*d,*m,*d,*f,*d,*f,*m,*f"))]
- "ISA_HAS_8CC && TARGET_HARD_FLOAT"
- { return mips_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "lui_movf,move,load,store,mfc,mtc,fmove,fpload,fpstore")
- (set_attr "mode" "SI")])
-
-;; Reload condition code registers. reload_incc and reload_outcc
-;; both handle moves from arbitrary operands into condition code
-;; registers. reload_incc handles the more common case in which
-;; a source operand is constrained to be in a condition-code
-;; register, but has not been allocated to one.
-;;
-;; Sometimes, such as in movcc, we have a CCmode destination whose
-;; constraints do not include 'z'. reload_outcc handles the case
-;; when such an operand is allocated to a condition-code register.
-;;
-;; Note that reloads from a condition code register to some
-;; other location can be done using ordinary moves. Moving
-;; into a GPR takes a single movcc, moving elsewhere takes
-;; two. We can leave these cases to the generic reload code.
-(define_expand "reload_incc"
- [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
- (match_operand:CC 1 "general_operand" ""))
- (clobber (match_operand:TF 2 "register_operand" "=&f"))]
- "ISA_HAS_8CC && TARGET_HARD_FLOAT"
-{
- mips_expand_fcc_reload (operands[0], operands[1], operands[2]);
- DONE;
-})
-
-(define_expand "reload_outcc"
- [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
- (match_operand:CC 1 "register_operand" ""))
- (clobber (match_operand:TF 2 "register_operand" "=&f"))]
- "ISA_HAS_8CC && TARGET_HARD_FLOAT"
-{
- mips_expand_fcc_reload (operands[0], operands[1], operands[2]);
- DONE;
-})
-
;; MIPS4 supports loading and storing a floating point register from
;; the sum of two general registers. We use two versions for each of
;; these four instructions: one where the two general registers are