Commit 42e37616 by David S. Miller Committed by David S. Miller

Improve cstore code generation on 64-bit sparc.

One major suboptimal area of the sparc back end is cstore generation
on 64-bit.

Due to the way arguments and return values of functions must be
promoted, the ideal mode for cstore's result would be DImode.

But this hasn't been done because of a fundamental limitation
of the cstore patterns.  They require a fixed mode be used for
the boolean result value.

I've decided to work around this by building a target hook which
specifies the type to use for conditional store results, and then I
use a special predicate for operans 0 in the cstore expanders so
that they still match even when we use DImode.

The default version of the target hook just does what it does now,
so no other target should be impacted by this at all.

Regstrapped on 32-bit sparc-linux-gnu and I've run the testsuite
with "-m64" to validate the 64-bit side.

gcc/

	* target.def (cstore_mode): New hook.
	* target.h: Include insn-codes.h
	* targhooks.c: Likewise.
	(default_cstore_mode): New function.
	* targhooks.h: Declare it.
	* doc/tm.texi.in: New hook slot for TARGET_CSTORE_MODE.
	* doc/tm.texi: Rebuild.
	* expmed.c (emit_cstore): Obtain cstore boolean result mode using
	target hook, rather than inspecting the insn_data.
	* config/sparc/sparc.c (sparc_cstore_mode): New function.
	(TARGET_CSTORE_MODE): Redefine.
	(emit_scc_insn): When TARGET_ARCH64, emit new 64-bit boolean
	result patterns.
	* config/sparc/predicates.md (cstore_result_operand): New special
	predicate.
	* config/sparc/sparc.md (cstoresi4, cstoredi4, cstore<F:mode>4):
	Use it for operand 0.
	(*seqsi_special): Rewrite using 'P' mode iterator on operand 0.
	(*snesi_special): Likewise.
	(*snesi_zero): Likewise.
	(*seqsi_zero): Likewise.
	(*sltu_insn): Likewise.
	(*sgeu_insn): Likewise.
	(*seqdi_special): Make operand 0 and comparison operation be of
	DImode.
	(*snedi_special): Likewise.
	(*snedi_special_vis3): Likewise.
	(*neg_snesi_zero): Rename to *neg_snesisi_zero.
	(*neg_snesi_sign_extend): Rename to *neg_snesidi_zero.
	(*snesi_zero_extend): Delete, covered by 'P' mode iterator.
	(*neg_seqsi_zero): Rename to *neg_seqsisi_zero.
	(*neg_seqsi_sign_extend): Rename to *neg_seqsidi_zero.
	(*seqsi_zero_extend): Delete, covered by 'P' mode iterator.
	(*sltu_extend_sp64): Likewise.
	(*neg_sltu_insn): Rename to *neg_sltusi_insn.
	(*neg_sltu_extend_sp64): Rename to *neg_sltudi_insn.
	(*sgeu_extend_sp64): Delete, covered by 'P' mode iterator.
	(*neg_sgeu_insn): Rename to *neg_sgeusi_insn.
	(*neg_sgeu_extend_sp64): Rename to *neg_sgeudi_insn.

gcc/testsuite/

	* gcc.target/sparc/setcc-4.c: New test.
	* gcc.target/sparc/setcc-5.c: New test.

From-SVN: r197679
parent 95ca411e
2013-04-10 David S. Miller <davem@davemloft.net>
* target.def (cstore_mode): New hook.
* target.h: Include insn-codes.h
* targhooks.c: Likewise.
(default_cstore_mode): New function.
* targhooks.h: Declare it.
* doc/tm.texi.in: New hook slot for TARGET_CSTORE_MODE.
* doc/tm.texi: Rebuild.
* expmed.c (emit_cstore): Obtain cstore boolean result mode using
target hook, rather than inspecting the insn_data.
* config/sparc/sparc.c (sparc_cstore_mode): New function.
(TARGET_CSTORE_MODE): Redefine.
(emit_scc_insn): When TARGET_ARCH64, emit new 64-bit boolean
result patterns.
* config/sparc/predicates.md (cstore_result_operand): New special
predicate.
* config/sparc/sparc.md (cstoresi4, cstoredi4, cstore<F:mode>4):
Use it for operand 0.
(*seqsi_special): Rewrite using 'P' mode iterator on operand 0.
(*snesi_special): Likewise.
(*snesi_zero): Likewise.
(*seqsi_zero): Likewise.
(*sltu_insn): Likewise.
(*sgeu_insn): Likewise.
(*seqdi_special): Make operand 0 and comparison operation be of
DImode.
(*snedi_special): Likewise.
(*snedi_special_vis3): Likewise.
(*neg_snesi_zero): Rename to *neg_snesisi_zero.
(*neg_snesi_sign_extend): Rename to *neg_snesidi_zero.
(*snesi_zero_extend): Delete, covered by 'P' mode iterator.
(*neg_seqsi_zero): Rename to *neg_seqsisi_zero.
(*neg_seqsi_sign_extend): Rename to *neg_seqsidi_zero.
(*seqsi_zero_extend): Delete, covered by 'P' mode iterator.
(*sltu_extend_sp64): Likewise.
(*neg_sltu_insn): Rename to *neg_sltusi_insn.
(*neg_sltu_extend_sp64): Rename to *neg_sltudi_insn.
(*sgeu_extend_sp64): Delete, covered by 'P' mode iterator.
(*neg_sgeu_insn): Rename to *neg_sgeusi_insn.
(*neg_sgeu_extend_sp64): Rename to *neg_sgeudi_insn.
2013-04-10 Yufeng Zhang <yufeng.zhang@arm.com> 2013-04-10 Yufeng Zhang <yufeng.zhang@arm.com>
* config/aarch64/aarch64.c (aarch64_print_extension): New function. * config/aarch64/aarch64.c (aarch64_print_extension): New function.
......
...@@ -265,6 +265,11 @@ ...@@ -265,6 +265,11 @@
(ior (match_test "register_operand (op, SImode)") (ior (match_test "register_operand (op, SImode)")
(match_test "TARGET_ARCH64 && register_operand (op, DImode)"))) (match_test "TARGET_ARCH64 && register_operand (op, DImode)")))
;; Return true if OP is an integer register of the appropriate mode
;; for a cstore result.
(define_special_predicate "cstore_result_operand"
(match_test "register_operand (op, TARGET_ARCH64 ? DImode : SImode)"))
;; Return true if OP is a floating point condition code register. ;; Return true if OP is a floating point condition code register.
(define_predicate "fcc_register_operand" (define_predicate "fcc_register_operand"
(match_code "reg") (match_code "reg")
......
...@@ -597,6 +597,7 @@ static void sparc_print_operand_address (FILE *, rtx); ...@@ -597,6 +597,7 @@ static void sparc_print_operand_address (FILE *, rtx);
static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t, static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
enum machine_mode, enum machine_mode,
secondary_reload_info *); secondary_reload_info *);
static enum machine_mode sparc_cstore_mode (enum insn_code icode);
#ifdef SUBTARGET_ATTRIBUTE_TABLE #ifdef SUBTARGET_ATTRIBUTE_TABLE
/* Table of valid machine attributes. */ /* Table of valid machine attributes. */
...@@ -802,6 +803,9 @@ char sparc_hard_reg_printed[8]; ...@@ -802,6 +803,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
#define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 0xff #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 0xff
#undef TARGET_CSTORE_MODE
#define TARGET_CSTORE_MODE sparc_cstore_mode
struct gcc_target targetm = TARGET_INITIALIZER; struct gcc_target targetm = TARGET_INITIALIZER;
static void static void
...@@ -2572,7 +2576,11 @@ emit_scc_insn (rtx operands[]) ...@@ -2572,7 +2576,11 @@ emit_scc_insn (rtx operands[])
{ {
if (GET_MODE (x) == SImode) if (GET_MODE (x) == SImode)
{ {
rtx pat = gen_seqsi_special (operands[0], x, y); rtx pat;
if (TARGET_ARCH64)
pat = gen_seqsidi_special (operands[0], x, y);
else
pat = gen_seqsisi_special (operands[0], x, y);
emit_insn (pat); emit_insn (pat);
return true; return true;
} }
...@@ -2588,7 +2596,11 @@ emit_scc_insn (rtx operands[]) ...@@ -2588,7 +2596,11 @@ emit_scc_insn (rtx operands[])
{ {
if (GET_MODE (x) == SImode) if (GET_MODE (x) == SImode)
{ {
rtx pat = gen_snesi_special (operands[0], x, y); rtx pat;
if (TARGET_ARCH64)
pat = gen_snesidi_special (operands[0], x, y);
else
pat = gen_snesisi_special (operands[0], x, y);
emit_insn (pat); emit_insn (pat);
return true; return true;
} }
...@@ -2631,7 +2643,7 @@ emit_scc_insn (rtx operands[]) ...@@ -2631,7 +2643,7 @@ emit_scc_insn (rtx operands[])
|| (!TARGET_VIS3 && code == GEU)) || (!TARGET_VIS3 && code == GEU))
{ {
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_fmt_ee (code, SImode, gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
gen_compare_reg_1 (code, x, y), gen_compare_reg_1 (code, x, y),
const0_rtx))); const0_rtx)));
return true; return true;
...@@ -12104,4 +12116,9 @@ sparc_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2) ...@@ -12104,4 +12116,9 @@ sparc_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
return true; return true;
} }
static enum machine_mode sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED)
{
return (TARGET_ARCH64 ? DImode : SImode);
}
#include "gt-sparc.h" #include "gt-sparc.h"
...@@ -2905,6 +2905,10 @@ A target hook which returns true if an address with the same structure can have ...@@ -2905,6 +2905,10 @@ A target hook which returns true if an address with the same structure can have
This hook defines a class of registers which could be used for spilling pseudos of the given mode and class, or @code{NO_REGS} if only memory should be used. Not defining this hook is equivalent to returning @code{NO_REGS} for all inputs. This hook defines a class of registers which could be used for spilling pseudos of the given mode and class, or @code{NO_REGS} if only memory should be used. Not defining this hook is equivalent to returning @code{NO_REGS} for all inputs.
@end deftypefn @end deftypefn
@deftypefn {Target Hook} {enum machine_mode} TARGET_CSTORE_MODE (enum insn_code @var{icode})
This hook defines the machine mode to use for the boolean result of conditional store patterns. The ICODE argument is the instruction code for the cstore being performed. Not definiting this hook is the same as accepting the mode encoded into operand 0 of the cstore expander patterns.
@end deftypefn
@node Old Constraints @node Old Constraints
@section Obsolete Macros for Defining Constraints @section Obsolete Macros for Defining Constraints
@cindex defining constraints, obsolete method @cindex defining constraints, obsolete method
......
...@@ -2873,6 +2873,8 @@ as below: ...@@ -2873,6 +2873,8 @@ as below:
@hook TARGET_SPILL_CLASS @hook TARGET_SPILL_CLASS
@hook TARGET_CSTORE_MODE
@node Old Constraints @node Old Constraints
@section Obsolete Macros for Defining Constraints @section Obsolete Macros for Defining Constraints
@cindex defining constraints, obsolete method @cindex defining constraints, obsolete method
......
...@@ -5081,7 +5081,7 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code, ...@@ -5081,7 +5081,7 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
{ {
struct expand_operand ops[4]; struct expand_operand ops[4];
rtx op0, last, comparison, subtarget; rtx op0, last, comparison, subtarget;
enum machine_mode result_mode = insn_data[(int) icode].operand[0].mode; enum machine_mode result_mode = targetm.cstore_mode (icode);
last = get_last_insn (); last = get_last_insn ();
x = prepare_operand (icode, x, 2, mode, compare_mode, unsignedp); x = prepare_operand (icode, x, 2, mode, compare_mode, unsignedp);
......
...@@ -2457,6 +2457,16 @@ DEFHOOK ...@@ -2457,6 +2457,16 @@ DEFHOOK
reg_class_t, (reg_class_t, enum machine_mode), reg_class_t, (reg_class_t, enum machine_mode),
NULL) NULL)
DEFHOOK
(cstore_mode,
"This hook defines the machine mode to use for the boolean result of\
conditional store patterns. The ICODE argument is the instruction code\
for the cstore being performed. Not definiting this hook is the same\
as accepting the mode encoded into operand 0 of the cstore expander\
patterns.",
enum machine_mode, (enum insn_code icode),
default_cstore_mode)
/* True if a structure, union or array with MODE containing FIELD should /* True if a structure, union or array with MODE containing FIELD should
be accessed using BLKmode. */ be accessed using BLKmode. */
DEFHOOK DEFHOOK
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#define GCC_TARGET_H #define GCC_TARGET_H
#include "insn-modes.h" #include "insn-modes.h"
#include "insn-codes.h"
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
......
...@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h" #include "opts.h"
#include "tree-flow.h" #include "tree-flow.h"
#include "tree-ssa-alias.h" #include "tree-ssa-alias.h"
#include "insn-codes.h"
bool bool
...@@ -1537,6 +1538,14 @@ default_pch_valid_p (const void *data_p, size_t len) ...@@ -1537,6 +1538,14 @@ default_pch_valid_p (const void *data_p, size_t len)
return NULL; return NULL;
} }
/* Default version of cstore_mode. */
enum machine_mode
default_cstore_mode (enum insn_code icode)
{
return insn_data[(int) icode].operand[0].mode;
}
/* Default version of member_type_forces_blk. */ /* Default version of member_type_forces_blk. */
bool bool
......
...@@ -195,4 +195,5 @@ extern const char *default_pch_valid_p (const void *, size_t); ...@@ -195,4 +195,5 @@ extern const char *default_pch_valid_p (const void *, size_t);
extern void default_asm_output_ident_directive (const char*); extern void default_asm_output_ident_directive (const char*);
extern enum machine_mode default_cstore_mode (enum insn_code);
extern bool default_member_type_forces_blk (const_tree, enum machine_mode); extern bool default_member_type_forces_blk (const_tree, enum machine_mode);
2013-04-10 David S. Miller <davem@davemloft.net>
* gcc.target/sparc/setcc-4.c: New test.
* gcc.target/sparc/setcc-5.c: New test.
2013-04-10 Richard Biener <rguenther@suse.de> 2013-04-10 Richard Biener <rguenther@suse.de>
* g++.dg/pr55604.C: Use -fdump-rtl-ira. * g++.dg/pr55604.C: Use -fdump-rtl-ira.
......
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-O1 -mno-vis3" } */
long neq (long a, long b)
{
return a != b;
}
long eq (long a, long b)
{
return a == b;
}
long lt (unsigned long a, unsigned long b)
{
return a < b;
}
long leq (unsigned long a, unsigned long b)
{
return a <= b;
}
long geq (unsigned long a, unsigned long b)
{
return a >= b;
}
long gt (unsigned long a, unsigned long b)
{
return a > b;
}
/* { dg-final { scan-assembler-times "xor\t%" 2 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */
/* { dg-final { scan-assembler-times "movrne\t%" 1 } } */
/* { dg-final { scan-assembler-times "movre\t%" 1 } } */
/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movleu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movgu\t%" 1 } } */
/* { dg-final { scan-assembler-not "sra\t%" } } */
/* { dg-final { scan-assembler-not "and\t%" } } */
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-O1 -mvis3" } */
long neq (long a, long b)
{
return a != b;
}
long eq (long a, long b)
{
return a == b;
}
long lt (unsigned long a, unsigned long b)
{
return a < b;
}
long leq (unsigned long a, unsigned long b)
{
return a <= b;
}
long geq (unsigned long a, unsigned long b)
{
return a >= b;
}
long gt (unsigned long a, unsigned long b)
{
return a > b;
}
/* { dg-final { scan-assembler-times "xor\t%" 2 } } */
/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */
/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */
/* { dg-final { scan-assembler-times "movre\t%" 1 } } */
/* { dg-final { scan-assembler-times "movleu\t%" 1 } } */
/* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */
/* { dg-final { scan-assembler-not "sra\t%" } } */
/* { dg-final { scan-assembler-not "and\t%" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment