*** /home/mnt/rakeshku/try_split/sh.md.backup 2004-01-02 12:55:24.000000000 +0530 --- /home/mnt/rakeshku/gcc_3_4/gcc/config/sh/sh.md 2004-01-02 12:50:49.000000000 +0530 *************** *** 152,157 **** --- 152,158 ---- (UNSPECV_CONST8 6) (UNSPECV_WINDOW_END 10) (UNSPECV_CONST_END 11) + (UNSPECV_DF_SPLIT 27) ]) ;; ------------------------------------------------------------------------- *************** *** 4462,4467 **** --- 4463,4469 ---- rtx mem2 = copy_rtx (operands[1]); rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN); rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN); + bool record_insn = true; PUT_MODE (mem2, SFmode); operands[1] = copy_rtx (mem2); *************** *** 4472,4478 **** read with post-increment might be modified by an interrupt, so write it back. */ if (REGNO (addr) == STACK_POINTER_REGNUM) ! adjust = gen_push_e (reg0); else adjust = gen_addsi3 (addr, addr, GEN_INT (-4)); XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr); --- 4474,4483 ---- read with post-increment might be modified by an interrupt, so write it back. */ if (REGNO (addr) == STACK_POINTER_REGNUM) ! { ! adjust = gen_push_e (reg0); ! record_insn = false; ! } else adjust = gen_addsi3 (addr, addr, GEN_INT (-4)); XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr); *************** *** 4482,4488 **** REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX); insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2])); if (adjust) ! emit_insn (adjust); else REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX); DONE; --- 4487,4505 ---- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX); insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2])); if (adjust) ! { ! rtx add_insn = emit_insn (adjust); ! ! /* Record the address arithmetic insn generated. */ ! if (split_index == 0 && record_insn) ! { ! split_array = (rtx *) xmalloc (sizeof (rtx) * 512); ! emit_insn (gen_df_split ()); ! } ! ! if (record_insn && split_index < 512) ! split_array[split_index++] = add_insn; ! } else REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, addr, NULL_RTX); DONE; *************** *** 4511,4518 **** addr = XEXP (operands[0], 0); if (GET_CODE (addr) != PRE_DEC) { adjust = gen_addsi3 (addr, addr, GEN_INT (4)); ! emit_insn_before (adjust, insn); XEXP (operands[0], 0) = addr = gen_rtx (PRE_DEC, SImode, addr); } --- 4528,4546 ---- addr = XEXP (operands[0], 0); if (GET_CODE (addr) != PRE_DEC) { + rtx add_insn; adjust = gen_addsi3 (addr, addr, GEN_INT (4)); ! add_insn = emit_insn_before (adjust, insn); ! ! /* Record the address arithmetic insn generated. */ ! if (split_index == 0) ! { ! split_array = (rtx *) xmalloc (sizeof (rtx) * 1024); ! emit_insn (gen_df_split ()); ! } ! ! if (split_index < 512) ! split_array[split_index++] = add_insn; XEXP (operands[0], 0) = addr = gen_rtx (PRE_DEC, SImode, addr); } *************** *** 4527,4532 **** --- 4555,4572 ---- DONE; }") + ;; Recombine the address arithmetic insns generated by + ;; DFmode splits + (define_peephole2 + [(unspec_volatile + [(const_int 0)] UNSPECV_DF_SPLIT)] + "TARGET_SH4" + [(const_int 0)] + " + { + fix_df_splits (); + }") + ;; If the output is a register and the input is memory or a register, we have ;; to be careful and see which word needs to be loaded first. *** /home/mnt/rakeshku/try_split/sh.h.backup 2003-12-30 11:23:16.000000000 +0530 --- /home/mnt/rakeshku/gcc_3_4/gcc/config/sh/sh.h 2004-01-02 12:59:41.000000000 +0530 *************** extern int rtx_equal_function_value_matt *** 3322,3325 **** --- 3322,3333 ---- TARGET_SHMEDIA64 ? -8 : -4)) \ : frame_pointer_rtx)) \ : NULL_RTX) + + /* Data structures for recording the address arithmetic insns + generated during DFmode splits. */ + extern rtx *split_array; + extern short split_index; + + /* Function for recombining address arithmetic insns. */ + extern void fix_df_splits (); #endif /* ! GCC_SH_H */ *** /home/mnt/rakeshku/try_split/sh.c.backup 2003-12-30 11:22:40.000000000 +0530 --- /home/mnt/rakeshku/gcc_3_4/gcc/config/sh/sh.c 2004-01-02 12:47:21.000000000 +0530 *************** static void copy_constant PARAMS ((struc *** 301,306 **** --- 301,308 ---- static void fix_deferred_broken_moves PARAMS ((void)); static void add_constants_to_curr_table PARAMS ((rtx)); static rtx create_barrier PARAMS ((rtx)); + + static void try_recombine PARAMS ((rtx, rtx, basic_block)); /* Initialize the GCC target structure. */ #undef TARGET_ATTRIBUTE_TABLE *************** dump_literal_pools () *** 11055,11058 **** --- 11057,11223 ---- curr_table = 0; fpool_listp = 0; } + + /* Data structures for fixing address arithmetic insns generated during + DFmode splits. */ + rtx *split_array = NULL; + short int split_index = 0; + + /* Entry function for recombining address arithmetic insns. */ + void + fix_df_splits () + { + short int i = -1; + bool del; + rtx insn, pat, reg_rtx, scan; + basic_block bb; + + /* Should not be called if df_splits are already fixed. */ + if (!split_array) + abort (); + + /* During life_analysis, the unreachable blocks are deleted. + Do not try to fix insns in such basic blocks. */ + while (++i < split_index) + { + insn = split_array[i]; + + /* Get the block for insn. */ + bb = BLOCK_FOR_INSN (insn); + if (BASIC_BLOCK (bb->index) == NULL) + { + /* The block is deleted in life analysis. */ + split_array[i] = NULL; + continue; + } + } + + i = -1; + + while (++i < split_index) + { + insn = split_array[i]; + del = true; + + if (!insn) + continue; + + bb = BLOCK_FOR_INSN (insn); + pat = single_set (insn); + reg_rtx = SET_DEST (pat); + + /* Check that the insn is present in basic block. */ + for (scan = bb->head; scan != bb->end; scan = NEXT_INSN (scan)) + { + if (insn == scan && !INSN_DELETED_P (scan)) + del = false; + } + + if (del && !(insn == scan && !INSN_DELETED_P (scan))) + { + /* INSN not found. */ + split_array[i] = NULL; + continue; + } + + /* Try to recombine the address arithmetic insn. */ + if (REGNO (reg_rtx) != STACK_POINTER_REGNUM) + try_recombine (reg_rtx, insn, bb); + + /* After recombination, see that if insn can be deleted. + Change it to note. */ + if (INTVAL (XEXP (SET_SRC (pat), 1)) == 0) + { + PUT_CODE (insn, NOTE); + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; + NOTE_SOURCE_FILE (insn) = 0; + } + } + + free (split_array); + split_array = NULL; + split_index = 0; + } + + /* Try recombining the address arithmetic insns. + REG_RTX is the register used for address arithmetic + INSN is the insn for address arithmetic + BB is the basic block containing INSN. */ + static void + try_recombine (reg_rtx, insn, bb) + rtx reg_rtx; + rtx insn; + basic_block bb; + { + rtx scan, end_insn; + int move; + int inc = INTVAL (XEXP (SET_SRC (PATTERN (insn)), 1)); + + /* The addition of negative values is recombined with the + insns ahead in the instruction stream, and those of + positive values is recombined with prior insns. We are + not crossing the basic blocks in any case. */ + if (inc == -4) + { + move = 1; + end_insn = bb->end; + } + else if (inc == 4) + { + move = -1; + end_insn = bb->head; + } + else + abort (); + + scan = (move == -1 ? PREV_INSN (insn) : NEXT_INSN (insn)); + + /* If insn is last insn in the function. */ + if (!scan) + return; + + do + { + if (GET_CODE (scan) == CODE_LABEL || GET_CODE (scan) == BARRIER) + break; + + if (NOTE_INSN_BASIC_BLOCK_P (scan)) + break; + + if (reg_mentioned_p (reg_rtx, scan)) + { + if (GET_CODE (PATTERN (scan)) != PARALLEL && single_set (scan)) + { + rtx set = single_set (scan); + rtx set_src = SET_SRC (set); + rtx set_dest = SET_DEST (set); + + /* scan should be of form ADD #x, REG. */ + if (GET_CODE (set_dest) == REG && GET_CODE (set_src) == PLUS + && GET_CODE (XEXP (set_src, 0)) == REG + && REGNO (set_dest) == REGNO (XEXP (set_src, 0)) + && GET_CODE (XEXP (set_src, 1)) == CONST_INT) + { + rtx prev_scan = scan; + int new_inc = INTVAL (XEXP (set_src, 1)) + inc; + + /* Recombination should not be costly. */ + if (CONST_OK_FOR_I08 (new_inc)) + { + XEXP (SET_SRC (PATTERN (insn)), 1) = GEN_INT (new_inc); + inc = new_inc; + + scan = (move == -1 ? PREV_INSN (scan) : NEXT_INSN (scan)); + delete_insn (prev_scan); + continue; + } + } + } + break; + } + + scan = (move == -1 ? PREV_INSN (scan) : NEXT_INSN (scan)); + + } while (scan && scan != end_insn); + } #include "gt-sh.h"