diff options
author | Kelvin Nilsen <kelvin@gcc.gnu.org> | 2018-10-09 21:11:47 +0000 |
---|---|---|
committer | Kelvin Nilsen <kelvin@gcc.gnu.org> | 2018-10-09 21:11:47 +0000 |
commit | 040bfd1e57bcfd21af3fa7f42b63eb2662370363 (patch) | |
tree | faf70c130c52d0d4a57af55d7c81a1c63b0676db | |
parent | 1d23f77bedfb28d460281a4aa073fdb268116cb0 (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.c | 150 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 158 |
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 |