From 54b695e729623a329250bf68894cbd7ae25020ac Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Fri, 14 Jan 2005 21:22:14 +0000 Subject: [PATCH] rs6000.h (CLASS_MAX_NREGS): DF goes in 1 register on e500v2. * config/rs6000/rs6000.h (CLASS_MAX_NREGS): DF goes in 1 register on e500v2. (CANNOT_CHANGE_MODE_CLASS): Restrict DI mode changes on e500v2. (PREDICATE_CODES): Add rs6k_nonimmediate_operand. * config/rs6000/rs6000.c (invalid_e500_subreg): New. (rs6k_nonimmediate_operand): New. (rs6000_legitimate_offset_address_p): Handle DI modes on e500v2 correctly. (legitimate_lo_sum_address_p): Same. (rs6000_legitimize_address): Same. (rs6000_legitimize_reload_address): Same. (rs6000_legitimate_address): Same. (spe_build_register_parallel): Pass DF and DC modes in a DI register. * config/rs6000/rs6000.md ("*movsi_internal1"): Change predicate to rs6k_nonimmediate_operand. * config/rs6000/spe.md ("*frob_df_di"): New. ("*frob_di_df"): New. ("*frob_di_df_2"): New. ("*mov_sidf_e500_subreg0"): New. ("*mov_sidf_e500_subreg4"): New. ("*movdf_e500_double"): Change predicate to rs6k_nonimmediate_operand. From-SVN: r93665 --- gcc/ChangeLog | 29 +++++++++++++ gcc/config/rs6000/rs6000.c | 87 +++++++++++++++++++++++++++---------- gcc/config/rs6000/rs6000.h | 5 +++ gcc/config/rs6000/rs6000.md | 2 +- gcc/config/rs6000/spe.md | 39 ++++++++++++++++- 5 files changed, 137 insertions(+), 25 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d0d11bbfaa..53e9844f428 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2005-01-14 Aldy Hernandez + + * config/rs6000/rs6000.h (CLASS_MAX_NREGS): DF goes in 1 register + on e500v2. + (CANNOT_CHANGE_MODE_CLASS): Restrict DI mode changes on e500v2. + (PREDICATE_CODES): Add rs6k_nonimmediate_operand. + + * config/rs6000/rs6000.c (invalid_e500_subreg): New. + (rs6k_nonimmediate_operand): New. + (rs6000_legitimate_offset_address_p): Handle DI modes on e500v2 + correctly. + (legitimate_lo_sum_address_p): Same. + (rs6000_legitimize_address): Same. + (rs6000_legitimize_reload_address): Same. + (rs6000_legitimate_address): Same. + (spe_build_register_parallel): Pass DF and DC modes in a DI + register. + + * config/rs6000/rs6000.md ("*movsi_internal1"): Change predicate + to rs6k_nonimmediate_operand. + + * config/rs6000/spe.md ("*frob_df_di"): New. + ("*frob_di_df"): New. + ("*frob_di_df_2"): New. + ("*mov_sidf_e500_subreg0"): New. + ("*mov_sidf_e500_subreg4"): New. + ("*movdf_e500_double"): Change predicate to + rs6k_nonimmediate_operand. + 2005-01-14 Aldy Hernandez * postreload.c (move2add_note_store): Only call diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index a6a8871052c..a8586a63aa3 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -710,6 +710,7 @@ static rtx spe_expand_builtin (tree, rtx, bool *); static rtx spe_expand_stv_builtin (enum insn_code, tree); static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx); static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx); +static bool invalid_e500_subreg (rtx, enum machine_mode); static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx); static rs6000_stack_t *rs6000_stack_info (void); static void debug_stack_info (rs6000_stack_t *); @@ -3035,6 +3036,39 @@ input_operand (rtx op, enum machine_mode mode) return 0; } +/* Return TRUE if OP is an invalid SUBREG operation on the e500. */ +static bool +invalid_e500_subreg (rtx op, enum machine_mode mode) +{ + /* Reject (subreg:SI (reg:DF)). */ + if (GET_CODE (op) == SUBREG + && mode == SImode + && REG_P (SUBREG_REG (op)) + && GET_MODE (SUBREG_REG (op)) == DFmode) + return true; + + /* Reject (subreg:DF (reg:DI)). */ + if (GET_CODE (op) == SUBREG + && mode == DFmode + && REG_P (SUBREG_REG (op)) + && GET_MODE (SUBREG_REG (op)) == DImode) + return true; + + return false; +} + +/* Just like nonimmediate_operand, but return 0 for invalid SUBREG's + on the e500. */ +int +rs6k_nonimmediate_operand (rtx op, enum machine_mode mode) +{ + if (TARGET_E500_DOUBLE + && GET_CODE (op) == SUBREG + && invalid_e500_subreg (op, mode)) + return 0; + + return nonimmediate_operand (op, mode); +} /* Darwin, AIX increases natural record alignment to doubleword if the first field is an FP double while the FP fields remain word aligned. */ @@ -3248,6 +3282,14 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict) return SPE_CONST_OFFSET_OK (offset); case DImode: + /* On e500v2, we may have: + + (subreg:DF (mem:DI (plus (reg) (const_int))) 0). + + Which gets addressed with evldd instructions. */ + if (TARGET_E500_DOUBLE) + return SPE_CONST_OFFSET_OK (offset); + if (mode == DFmode || !TARGET_POWERPC64) extra = 4; else if (offset & 3) @@ -3326,7 +3368,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict) return false; if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict)) return false; - if (TARGET_E500_DOUBLE && mode == DFmode) + /* Restrict addressing for DI because of our SUBREG hackery. */ + if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode)) return false; x = XEXP (x, 1); @@ -3403,7 +3446,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, && GET_MODE_NUNITS (mode) == 1 && ((TARGET_HARD_FLOAT && TARGET_FPRS) || TARGET_POWERPC64 - || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode)) + || (((mode != DImode && mode != DFmode) || TARGET_E500_DOUBLE) + && mode != TFmode)) && (TARGET_POWERPC64 || mode != DImode) && mode != TImode) { @@ -3423,8 +3467,11 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, return reg; } else if (SPE_VECTOR_MODE (mode) - || (TARGET_E500_DOUBLE && mode == DFmode)) + || (TARGET_E500_DOUBLE && (mode == DFmode + || mode == DImode))) { + if (mode == DImode) + return NULL_RTX; /* We accept [reg + reg] and [reg + OFFSET]. */ if (GET_CODE (x) == PLUS) @@ -3834,7 +3881,8 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode) && GET_CODE (XEXP (x, 1)) == CONST_INT && !SPE_VECTOR_MODE (mode) - && !(TARGET_E500_DOUBLE && mode == DFmode) + && !(TARGET_E500_DOUBLE && (mode == DFmode + || mode == DImode)) && !ALTIVEC_VECTOR_MODE (mode)) { HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); @@ -3942,7 +3990,8 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict) if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC) && !ALTIVEC_VECTOR_MODE (mode) && !SPE_VECTOR_MODE (mode) - && !(TARGET_E500_DOUBLE && mode == DFmode) + /* Restrict addressing for DI because of our SUBREG hackery. */ + && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode)) && TARGET_UPDATE && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)) return 1; @@ -5084,31 +5133,23 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, static rtx spe_build_register_parallel (enum machine_mode mode, int gregno) { - rtx r1, r2, r3, r4; - enum machine_mode inner = SImode; + rtx r1, r3; if (mode == DFmode) { - r1 = gen_rtx_REG (inner, gregno); - r1 = gen_rtx_EXPR_LIST (SImode, r1, const0_rtx); - r2 = gen_rtx_REG (inner, gregno + 1); - r2 = gen_rtx_EXPR_LIST (SImode, r2, GEN_INT (4)); - return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2)); + r1 = gen_rtx_REG (DImode, gregno); + r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx); + return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1)); } else if (mode == DCmode) { - r1 = gen_rtx_REG (inner, gregno); - r1 = gen_rtx_EXPR_LIST (SImode, r1, const0_rtx); - r2 = gen_rtx_REG (inner, gregno + 1); - r2 = gen_rtx_EXPR_LIST (SImode, r2, GEN_INT (4)); - r3 = gen_rtx_REG (inner, gregno + 2); - r3 = gen_rtx_EXPR_LIST (SImode, r3, GEN_INT (8)); - r4 = gen_rtx_REG (inner, gregno + 3); - r4 = gen_rtx_EXPR_LIST (SImode, r4, GEN_INT (12)); - return gen_rtx_PARALLEL (mode, gen_rtvec (4, r1, r2, r3, r4)); + r1 = gen_rtx_REG (DImode, gregno); + r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx); + r3 = gen_rtx_REG (DImode, gregno + 2); + r3 = gen_rtx_EXPR_LIST (VOIDmode, r3, GEN_INT (8)); + return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r3)); } - - abort (); + abort(); return NULL_RTX; } diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 63c1b839c2d..215fdcdab20 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1429,6 +1429,8 @@ enum reg_class #define CLASS_MAX_NREGS(CLASS, MODE) \ (((CLASS) == FLOAT_REGS) \ ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \ + : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS && (MODE) == DFmode) \ + ? 1 \ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) @@ -1442,6 +1444,8 @@ enum reg_class ? reg_classes_intersect_p (FLOAT_REGS, CLASS) \ : (TARGET_E500_DOUBLE && (((TO) == DFmode) + ((FROM) == DFmode)) == 1) \ ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \ + : (TARGET_E500_DOUBLE && (((TO) == DImode) + ((FROM) == DImode)) == 1) \ + ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \ : (TARGET_SPE && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1) \ ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \ : 0) @@ -2588,6 +2592,7 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ {"current_file_function_operand", {SYMBOL_REF}}, \ {"input_operand", {SUBREG, MEM, REG, CONST_INT, \ CONST_DOUBLE, SYMBOL_REF}}, \ + {"rs6k_nonimmediate_operand", {SUBREG, MEM, REG}}, \ {"load_multiple_operation", {PARALLEL}}, \ {"store_multiple_operation", {PARALLEL}}, \ {"lmw_operation", {PARALLEL}}, \ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index e3ba0211a78..890088e3385 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -7709,7 +7709,7 @@ (set_attr "length" "4")]) (define_insn "*movsi_internal1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h") + [(set (match_operand:SI 0 "rs6k_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h") (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))] "gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode)" diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md index 6e40371f0ca..c43adcb85f9 100644 --- a/gcc/config/rs6000/spe.md +++ b/gcc/config/rs6000/spe.md @@ -2192,8 +2192,45 @@ (set_attr "length" "4")]) ;; Double-precision floating point instructions. + +;; FIXME: Add o=r option. +(define_insn "*frob_df_di" + [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r") + (subreg:DF (match_operand:DI 1 "input_operand" "r,m") 0))] + "TARGET_E500_DOUBLE" + "@ + evmergelo %0,%H1,%L1 + evldd%X1 %0,%y1") + +(define_insn "*frob_di_df" + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r") + (subreg:DI (match_operand:DF 1 "input_operand" "r") 0))] + "TARGET_E500_DOUBLE" /*one of these can be an mr */ + "evmergehi %H0,%1,%1\;evmergelo %L0,%1,%1" + [(set_attr "length" "8")]) + +(define_insn "*frob_di_df_2" + [(set (subreg:DF (match_operand:DI 0 "register_operand" "=&r") 0) + (match_operand:DF 1 "register_operand" "r"))] + "TARGET_E500_DOUBLE" + "evmergehi %H0,%1,%1\;evmergelo %L0,%1,%1" + [(set_attr "length" "8")]) + +(define_insn "*mov_sidf_e500_subreg0" + [(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 0) + (match_operand:SI 1 "register_operand" "r"))] + "TARGET_E500_DOUBLE" + "evmergelo %0,%1,%0") + +(define_insn "*mov_sidf_e500_subreg4" + [(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 4) + (match_operand:SI 1 "register_operand" "r"))] + "TARGET_E500_DOUBLE" + "mr %0,%1") + +;; FIXME: Allow r=CONST0. (define_insn "*movdf_e500_double" - [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m") + [(set (match_operand:DF 0 "rs6k_nonimmediate_operand" "=r,r,m") (match_operand:DF 1 "input_operand" "r,m,r"))] "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && (gpc_reg_operand (operands[0], DFmode) -- 2.30.2