aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKelvin Nilsen <kelvin@gcc.gnu.org>2018-10-09 21:11:47 +0000
committerKelvin Nilsen <kelvin@gcc.gnu.org>2018-10-09 21:11:47 +0000
commit040bfd1e57bcfd21af3fa7f42b63eb2662370363 (patch)
treefaf70c130c52d0d4a57af55d7c81a1c63b0676db
parent1d23f77bedfb28d460281a4aa073fdb268116cb0 (diff)
checkpoint of work in progress
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/ibm/git280@264995 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/config/rs6000/rs6000-p9indexing.c150
-rw-r--r--gcc/config/rs6000/rs6000-protos.h2
-rw-r--r--gcc/config/rs6000/rs6000.c158
3 files changed, 245 insertions, 65 deletions
diff --git a/gcc/config/rs6000/rs6000-p9indexing.c b/gcc/config/rs6000/rs6000-p9indexing.c
index 31ea2517c35..e64bc523c87 100644
--- a/gcc/config/rs6000/rs6000-p9indexing.c
+++ b/gcc/config/rs6000/rs6000-p9indexing.c
@@ -94,12 +94,6 @@ class indexing_web_entry : public web_entry_base
unsigned int is_originating: 1;
};
-static void fatal (const char *msg)
-{
- fprintf (stderr, "Fatal error: %s\n", msg);
- exit (-1);
-}
-
static int count_links (struct df_link *def_link)
{
if (def_link == NULL) return 0;
@@ -156,9 +150,9 @@ find_defs (indexing_web_entry *insn_entry, rtx_insn *insn,
unsigned int uid = INSN_UID (insn);
rtx body = PATTERN (insn);
rtx mem;
- if ((GET_CODE (body) == SET) && (GET_CODE (SET_SRC (body)) == MEM))
+ if ((GET_CODE (body) == SET) && MEM_P (SET_SRC (body)))
mem = XEXP (SET_SRC (body), 0);
- else if ((GET_CODE (body) == SET) && (GET_CODE (SET_DEST (body)) == MEM))
+ else if ((GET_CODE (body) == SET) && MEM_P (SET_DEST (body)))
mem = XEXP (SET_DEST (body), 0);
else
mem = NULL;
@@ -190,11 +184,6 @@ find_defs (indexing_web_entry *insn_entry, rtx_insn *insn,
*insn_base = def_link;
else
{
- /* long long int delta = 0; */
- /* unsigned int uid2 =
- find_true_originator (def_link, &delta);
- */
- /* kelvin has cached uid2. */
unsigned int uid2 =
insn_entry[uid].original_base_use;
df_ref use2;
@@ -223,11 +212,6 @@ find_defs (indexing_web_entry *insn_entry, rtx_insn *insn,
*insn_index = def_link;
else
{
- /* kelvin has cached uid2. */
- /* long long int delta = 0; */
- /* unsigned int uid2 =
- find_true_originator (def_link, &delta);
- */
unsigned int uid2 =
insn_entry[uid].original_index_use;
df_ref use2;
@@ -553,12 +537,49 @@ build_and_fixup_equivalence_classes (indexing_web_entry *insn_entry)
}
}
- if (size_of_equivalence > 1)
+ int replacement_count = size_of_equivalence;
+ /* Confirm that everything in the equivalence class is
+ eligible for representation as a d-form insn. Otherwise,
+ remove additional entries from the equivalence class. */
+ long long int dominator_delta =
+ (insn_entry [the_dominator].base_delta
+ + insn_entry [the_dominator].index_delta);
+ for (uid = equivalence_hash [i]; uid != UINT_MAX;
+ uid = insn_entry [uid].equivalent_sibling)
+ {
+ if (uid != the_dominator)
+ {
+ long long int dominated_delta =
+ (insn_entry [uid].base_delta
+ + insn_entry [uid].index_delta);
+ dominated_delta -= dominator_delta;
+
+ rtx_insn *insn = insn_entry [uid].insn;
+ rtx body = PATTERN (insn);
+ rtx mem;
+
+ gcc_assert (GET_CODE (body) == SET);
+
+ if (MEM_P (SET_SRC (body))) /* load */
+ {
+ mem = SET_SRC (body);
+ if (!rs6000_target_supports_dform_offset_p
+ (false, GET_MODE (mem), dominated_delta))
+ replacement_count--;
+ }
+ else
+ {
+ mem = SET_DEST (body); /* store */
+ if (!rs6000_target_supports_dform_offset_p
+ (false, GET_MODE (mem), dominated_delta))
+ replacement_count--;
+ }
+ }
+ }
+
+ if (replacement_count > 1)
{
/* First, fix up the_dominator instruction. */
- long long int dominator_delta =
- (insn_entry [the_dominator].base_delta
- + insn_entry [the_dominator].index_delta);
rtx derived_ptr_reg = gen_reg_rtx (Pmode);
rtx_insn *insn = insn_entry [the_dominator].insn;
rtx body = PATTERN (insn);
@@ -576,7 +597,7 @@ build_and_fixup_equivalence_classes (indexing_web_entry *insn_entry)
}
gcc_assert (GET_CODE (body) == SET);
- if (GET_CODE (SET_SRC (body)) == MEM)
+ if (MEM_P (SET_SRC (body)))
{
/* originating instruction is a load */
mem = SET_SRC (body);
@@ -584,7 +605,7 @@ build_and_fixup_equivalence_classes (indexing_web_entry *insn_entry)
}
else
{ /* originating instruction is a store */
- gcc_assert (GET_CODE (SET_DEST (body)) == MEM);
+ gcc_assert (MEM_P (SET_DEST (body)));
mem = SET_DEST (body);
addr = XEXP (SET_DEST (body), 0);
}
@@ -611,29 +632,12 @@ build_and_fixup_equivalence_classes (indexing_web_entry *insn_entry)
fprintf (dump_file, "\n");
}
- if (dominator_delta)
- {
- rtx ci = gen_rtx_raw_CONST_INT (Pmode, dominator_delta);
- new_delta_expr = gen_rtx_PLUS (Pmode, derived_ptr_reg, ci);
- new_delta_expr =
- gen_rtx_SET (derived_ptr_reg, new_delta_expr);
- new_insn = emit_insn_before (new_delta_expr, insn);
- set_block_for_insn (new_insn, BLOCK_FOR_INSN (insn));
- INSN_CODE (new_insn) = -1; /* force re-recognition. */
- df_insn_rescan (new_insn);
-
- if (dump_file)
- {
- fprintf (dump_file, "and with insn %d: ",
- INSN_UID (new_insn));
- print_inline_rtx (dump_file, new_insn, 2);
- fprintf (dump_file, "\n");
- }
- }
+ /* If dominator_delta != 0, we need to make adjustments
+ for dominator_delta in the D-form constant offsets
+ associated with the propagating instructions. */
rtx new_mem = gen_rtx_MEM (GET_MODE (mem), derived_ptr_reg);
MEM_COPY_ATTRIBUTES (new_mem, mem);
-
rtx new_expr;
if (insn_entry [the_dominator].is_load)
new_expr = gen_rtx_SET (SET_DEST (body), new_mem);
@@ -680,7 +684,7 @@ build_and_fixup_equivalence_classes (indexing_web_entry *insn_entry)
gcc_assert (GET_CODE (body) == SET);
- if (GET_CODE (SET_SRC (body)) == MEM) /* load */
+ if (MEM_P (SET_SRC (body))) /* load */
mem = SET_SRC (body);
else
mem = SET_DEST (body); /* store */
@@ -702,12 +706,30 @@ build_and_fixup_equivalence_classes (indexing_web_entry *insn_entry)
INSN_CODE (new_insn) = -1;
df_insn_rescan (new_insn);
- if (dump_file) {
- fprintf (dump_file,
- "with insn %d: ", INSN_UID (new_insn));
- print_inline_rtx (dump_file, new_insn, 2);
- fprintf (dump_file, "\n");
- }
+kelvin deliberate syntax error - put an invocation of validate_change here. confirm consistency with replacement_count... and maybe rs6000_legitimate_address_p too.
+
+
+ if (dump_file)
+ {
+ extern bool
+ rs6000_legitimate_address_p (machine_mode,
+ rtx, bool);
+
+ fprintf (dump_file,
+ "with insn %d: ", INSN_UID (new_insn));
+ print_inline_rtx (dump_file, new_insn, 2);
+ fprintf (dump_file, "\n");
+
+ /* TARGET_LEGITIMATE_ADDRESS_P is defined to
+ be rs6000_legitimate_address_p. */
+
+ /* This pass occurs before reload, so our
+ inquiry uses the non-strict variant. */
+ if (!rs6000_legitimate_address_p (GET_MODE (mem),
+ new_mem, false))
+ fprintf (dump_file,
+ "Oops! Not unstrictly legit address\n");
+ }
df_insn_delete (insn);
remove_insn (insn);
@@ -715,7 +737,11 @@ build_and_fixup_equivalence_classes (indexing_web_entry *insn_entry)
}
}
}
-
+ else if (dump_file)
+ {
+ fprintf (dump_file,
+ "Abandoning dform optimization: too few dform insns\n");
+ }
}
}
}
@@ -883,8 +909,7 @@ rs6000_fix_indexing (function *fun)
{
rtx body = PATTERN (insn);
rtx mem;
- if ((GET_CODE (body) == SET)
- && (GET_CODE (SET_SRC (body)) == MEM))
+ if ((GET_CODE (body) == SET) && MEM_P (SET_SRC (body)))
{
mem = XEXP (SET_SRC (body), 0);
insn_entry[uid].is_load = true;
@@ -897,8 +922,7 @@ rs6000_fix_indexing (function *fun)
fprintf (dump_file, "\n");
}
}
- else if ((GET_CODE (body) == SET)
- && (GET_CODE (SET_DEST (body)) == MEM))
+ else if ((GET_CODE (body) == SET) && MEM_P (SET_DEST (body)))
{
mem = XEXP (SET_DEST (body), 0);
insn_entry[uid].is_load = false;
@@ -1011,10 +1035,9 @@ rs6000_fix_indexing (function *fun)
DF_INSN_INFO_USES (insn_info2);
if (use2)
{
- if (DF_REF_NEXT_LOC (use2))
- fatal ("expect one use "
- "for true originator");
-
+ /* Expect one use for true
+ originator. */
+ gcc_assert (!DF_REF_NEXT_LOC (use2));
struct df_link *def_link =
DF_REF_CHAIN (use2);
insn_entry[uid].
@@ -1095,10 +1118,9 @@ rs6000_fix_indexing (function *fun)
DF_INSN_INFO_USES (insn_info2);
if (use2)
{
- if (DF_REF_NEXT_LOC (use2))
- fatal ("expect one use "
- "for true originator");
-
+ /* Expect one use for true
+ originator. */
+ gcc_assert (!(DF_REF_NEXT_LOC (use2)));
struct df_link *def_link =
DF_REF_CHAIN (use2);
insn_entry[uid].
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 2a738333962..c55db584ef3 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -47,6 +47,8 @@ extern bool legitimate_constant_pool_address_p (const_rtx, machine_mode,
extern bool legitimate_indirect_address_p (rtx, int);
extern bool legitimate_indexed_address_p (rtx, int);
extern bool avoiding_indexed_address_p (machine_mode);
+extern bool rs6000_target_supports_dform_offset_p (boolean, machine_mode,
+ host_wide_int);
extern rtx rs6000_got_register (rtx);
extern rtx find_addr_reg (rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index aa707b2555e..cd13d97cc30 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -9157,7 +9157,7 @@ rs6000_debug_legitimize_reload_address (rtx x, machine_mode mode,
32-bit DImode, TImode, TFmode, TDmode), indexed addressing cannot be used
because adjacent memory cells are accessed by adding word-sized offsets
during assembly output. */
-static bool
+bool
rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
{
bool reg_offset_p = reg_offset_addressing_ok_p (mode);
@@ -9263,6 +9263,162 @@ rs6000_debug_legitimate_address_p (machine_mode mode, rtx x,
return ret;
}
+/* This function provides an approximation of which d-form addressing
+ expressions are valid on any given target configuration. This
+ approximation guides optimization choices. Secondary validation
+ of the addressing mode is performed before code generation.
+
+ Return true iff target has instructions to perform a memory
+ operation at the specified BYTE_OFFSET from an address held
+ in a general purpose register. if IS_STORE is true, test for
+ availability of a store instruction. Otherwise, test for
+ availability of a load instruction. */
+bool
+rs6000_target_supports_dform_offset_p (boolean is_store, machine_mode mode,
+ host_wide_int byte_offset)
+{
+ const int max_16bit_signed = (0x7fffffff);
+ const int min_16bit_signed = -1 - max_16bit_signed;
+
+ /* available d-form instructions with P1 (the original Power architecture):
+
+ lbz RT,D(RA) - load byte and zero d-form
+ lhz RT,D(RA) - load half word and zero d-form
+ lha RT,D(RA) - load half word algebraic d-form
+ lwz RT,D(RA) - load word and zero d-form
+ lfs FRT,D(RA) - load floating-point single d-form
+ lfd FRT,D(RA) - load floating-point double d-form
+
+ stb RS,D(RA) - store byte d-form
+ sth RS,D(RA) - store half word d-form
+ stfs FRS,D(RA) - store floating point single d-form
+ stfd FRS,D(RA) - store floating point double d-form
+ */
+
+ /* available d-form instructions with PPC (prior to v2.00):
+ (option mpowerpc "existed in the past" but is now "always on"
+
+ lwa RT,DS(RA) - load word algebraic ds-form (2 bottom bits zero)
+ ld RT,DS(RA) - load double word ds-form (2 bottom bits zero)
+
+ std RS,DS(RA) - store double word ds-form (2 bottom bits zero)
+
+ Consider lwa redundant with insn available in prior processors.
+ */
+ switch (mode)
+ {
+ case E_QImode:
+ case E_HImode:
+ case E_SImode:
+ if ((byte_offset >= min_16bit_signed)
+ && (byte_offset <= max_16bit_signed))
+ return true;
+
+ case E_DImode:
+ if ((byte_offset >= min_16bit_signed)
+ && (byte_offset <= max_16bit_signed)
+ && ((byte_offset & 0x03) == 0))
+ return true;
+
+ default:
+ /* fall through to see if other instructions will work. */
+ }
+
+ /* available d-form instructionw with v2.03:
+
+ lq RTp,DQ(RA) - load quadword dq-form (4 bottom bits zero)
+
+ stq RSp,DS(RA) - store quadword ds-form (2 bottom bits zero)
+
+ These instructions are not recommended for general use as they
+ are expected to be very inefficient. Their design was apparently
+ motivated by a need to support atomic quad-word access, which is
+ difficult to implement even in hardware on some architectures.
+ Furthermore, the design of these instructions apparently does the
+ "wrong" thing with regards to swapping of double words on load
+ and store for little-endian targets.
+
+ Therefore, this routine assumes v2.03 does NOT support quadword
+ d-form addressing.
+ */
+
+ /* available d-form instructions with v2.05
+
+ (There are some floating-point load and store double-pair
+ instructions. Consider them "not available". There are
+ described as phasing out, which means they are expected
+ to have poor performance.)
+ */
+
+ /* available d-form instructions with 3.0
+
+ lxsd VRT,DS(RA) - Load VSX scalar double word ds-form (2 bottom bits zero)
+ lxssp VRT,DS(RA) - Load VSX scalar single precision ds-form
+ (bottom 2 bits zero)
+ lxv XT,DQ(RA) - Load VSX Vector dq-form (4 bottom bits zero)
+ (Works on little endian for any element type, but
+ does not preserve lanes.)
+
+ stxsd VRS,DS(RA) - Store VSX scalar double-word DS form
+ (bottom 2 bits zero)
+ stxssp VRS,DS(RA) - Store VSX scalar single precision DS-form
+ (bottom 2 bits zero)
+ stxv XS,DQ(RA) - Store VSX vector dq-form (4 bottom bits zero)
+ (Works on little endian for any element type,
+ but doesn not preserve lanes.)
+
+ lxv and stxv load/store to/from any VSX register, including
+ registers that overlay with floating point and altivec register
+ sets.
+
+ */
+ if (rs6000_isa_flags & OPTION_MASK_MODULO)
+ { /* ISA 3.0 */
+ switch (mode) {
+ case E_V16QImode:
+ case E_V8HImode:
+ case E_V4SFmode:
+ case E_V4SImode:
+ case E_V2DFmode:
+ case E_V2DImode:
+ case E_V1TImode:
+ case E_TImode:
+
+ case E_KFmode: /* ieee 754 128-bit floating point */
+ case E_IFmode: /* IBM extended 128-bit double */
+ case E_TFmode: /* 128-bit double (form depends on
+ gcc command line, which may be
+ either -mabi=ieeelongdouble (KF)
+ or -mabi=ibmlongdouble (IF). */
+ /* All 128-bit loads and stores are handled by lxv and stxv. */
+ if ((byte_offset >= min_16bit_signed)
+ && (byte_offset <= max_16bit_signed)
+ && ((byte_offset & 0x0f) == 0))
+ return true;
+ else
+ break;
+
+ case E_DFmode:
+ case E_SFmode:
+ /* E_DFmode handled by lxsd and stxsd insns. E_SFmode handled
+ by lxssp and stxssp insn. */
+ if ((byte_offset >= min_16bit_signed)
+ && (byte_offset <= max_16bit_signed)
+ && ((byte_offset & 0x03) == 0))
+ return true;
+ else
+ break;
+
+ default:
+ /* fall through to see if other instructions will work. */
+ }
+ }
+
+ /* Add modeling support for newly introduced instructions here. */
+
+ return false;
+}
+
/* Implement TARGET_MODE_DEPENDENT_ADDRESS_P. */
static bool