From 041f25e6ffe48671895d036ceacc7c0ceb787d87 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 19 Aug 2000 00:15:08 -0700 Subject: [PATCH] ia64.c (reg_or_5bit_operand): New. * config/ia64/ia64.c (reg_or_5bit_operand): New. (ia64_depz_field_mask): New. * config/ia64/ia64.h (CONSTRAINT_OK_FOR_R): New. (PREDICATE_CODES): Update. * config/ia64/ia64.md: Update commentary. (depz_internal): New. (ashlsi3): Implement directly. (ashrsi3, lshrsi3): Simplify; rely on extv and extzv for constants. (ashldi3): Use shladd. * config/ia64/ia64-protos.h: Update. From-SVN: r35802 --- gcc/ChangeLog | 13 ++++ gcc/config/ia64/ia64-protos.h | 15 ++-- gcc/config/ia64/ia64.c | 29 +++++++ gcc/config/ia64/ia64.h | 9 ++- gcc/config/ia64/ia64.md | 143 +++++++++++++++------------------- 5 files changed, 120 insertions(+), 89 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 76a9956e3ae..d7ca945af2d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2000-08-19 Richard Henderson + + * config/ia64/ia64.c (reg_or_5bit_operand): New. + (ia64_depz_field_mask): New. + * config/ia64/ia64.h (CONSTRAINT_OK_FOR_R): New. + (PREDICATE_CODES): Update. + * config/ia64/ia64.md: Update commentary. + (depz_internal): New. + (ashlsi3): Implement directly. + (ashrsi3, lshrsi3): Simplify; rely on extv and extzv for constants. + (ashldi3): Use shladd. + * config/ia64/ia64-protos.h: Update. + 2000-08-18 Zack Weinberg * toplev.c (independent_decode_option): Always process -g. diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index af120609ca8..180418d9435 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -35,6 +35,7 @@ extern int function_operand PARAMS((rtx, enum machine_mode)); extern int setjmp_operand PARAMS((rtx, enum machine_mode)); extern int move_operand PARAMS((rtx, enum machine_mode)); extern int reg_or_0_operand PARAMS((rtx, enum machine_mode)); +extern int reg_or_5bit_operand PARAMS((rtx, enum machine_mode)); extern int reg_or_6bit_operand PARAMS((rtx, enum machine_mode)); extern int reg_or_8bit_operand PARAMS((rtx, enum machine_mode)); extern int reg_or_8bit_adjusted_operand PARAMS((rtx, enum machine_mode)); @@ -50,12 +51,6 @@ extern int normal_comparison_operator PARAMS((rtx, enum machine_mode)); extern int adjusted_comparison_operator PARAMS((rtx, enum machine_mode)); extern int call_multiple_values_operation PARAMS((rtx, enum machine_mode)); extern int destination_operand PARAMS((rtx, enum machine_mode)); -extern HOST_WIDE_INT ia64_initial_elimination_offset PARAMS((int, int)); -extern void ia64_expand_prologue PARAMS((void)); -extern void ia64_expand_epilogue PARAMS((void)); -extern void ia64_function_prologue PARAMS((FILE *, int)); -extern void ia64_function_epilogue PARAMS((FILE *, int)); -extern int ia64_direct_return PARAMS((void)); extern int predicate_operator PARAMS((rtx, enum machine_mode)); extern int ar_lc_reg_operand PARAMS((rtx, enum machine_mode)); extern int ar_ccv_reg_operand PARAMS((rtx, enum machine_mode)); @@ -64,10 +59,18 @@ extern int destination_tfmode_operand PARAMS((rtx, enum machine_mode)); extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode)); extern int ia64_move_ok PARAMS((rtx, rtx)); +extern int ia64_depz_field_mask PARAMS((rtx, rtx)); extern rtx ia64_gp_save_reg PARAMS((int)); extern rtx ia64_split_timode PARAMS((rtx[], rtx, rtx)); extern rtx spill_tfmode_operand PARAMS((rtx, int)); +extern HOST_WIDE_INT ia64_initial_elimination_offset PARAMS((int, int)); +extern void ia64_expand_prologue PARAMS((void)); +extern void ia64_expand_epilogue PARAMS((void)); +extern void ia64_function_prologue PARAMS((FILE *, int)); +extern void ia64_function_epilogue PARAMS((FILE *, int)); + +extern int ia64_direct_return PARAMS((void)); extern void ia64_expand_load_address PARAMS((rtx, rtx)); extern void ia64_expand_fetch_and_op PARAMS ((enum fetchop_code, enum machine_mode, rtx [])); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 0c16cd3a100..3088a82a028 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -316,6 +316,18 @@ reg_or_0_operand (op, mode) return (op == const0_rtx || register_operand (op, mode)); } +/* Return 1 if OP is a register operand, or a 5 bit immediate operand. */ + +int +reg_or_5bit_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32) + || GET_CODE (op) == CONSTANT_P_RTX + || register_operand (op, mode)); +} + /* Return 1 if OP is a register operand, or a 6 bit immediate operand. */ int @@ -635,6 +647,23 @@ ia64_move_ok (dst, src) return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src); } +/* Check if OP is a mask suitible for use with SHIFT in a dep.z instruction. + Return the length of the field, or <= 0 on failure. */ + +int +ia64_depz_field_mask (rop, rshift) + rtx rop, rshift; +{ + unsigned HOST_WIDE_INT op = INTVAL (rop); + unsigned HOST_WIDE_INT shift = INTVAL (rshift); + + /* Get rid of the zero bits we're shifting in. */ + op >>= shift; + + /* We must now have a solid block of 1's at bit 0. */ + return exact_log2 (op + 1); +} + /* Expand a symbolic constant load. */ /* ??? Should generalize this, so that we can also support 32 bit pointers. */ diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 90717b8a14d..c327b6cf4ec 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1108,11 +1108,17 @@ enum reg_class letters (`Q', `R', `S', `T', `U') that can be used to segregate specific types of operands, usually memory references, for the target machine. */ +/* Non-volatile memory for FP_REG loads/stores. */ #define CONSTRAINT_OK_FOR_Q(VALUE) \ (memory_operand((VALUE), VOIDmode) && ! MEM_VOLATILE_P (VALUE)) +/* 1..4 for shladd arguments. */ +#define CONSTRAINT_OK_FOR_R(VALUE) \ + (GET_CODE (VALUE) == CONST_INT && INTVAL (VALUE) >= 1 && INTVAL (VALUE) <= 4) #define EXTRA_CONSTRAINT(VALUE, C) \ - ((C) == 'Q' ? CONSTRAINT_OK_FOR_Q (VALUE) : 0) + ((C) == 'Q' ? CONSTRAINT_OK_FOR_Q (VALUE) \ + : (C) == 'R' ? CONSTRAINT_OK_FOR_R (VALUE) \ + : 0) /* Basic Stack Layout */ @@ -2639,6 +2645,7 @@ do { \ { "move_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ CONSTANT_P_RTX, SYMBOL_REF, CONST, LABEL_REF}}, \ { "reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \ +{ "reg_or_5bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \ { "reg_or_6bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \ { "reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \ { "reg_or_8bit_adjusted_operand", {SUBREG, REG, CONST_INT, \ diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index 0734936d1e9..e0173e6a344 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -1113,9 +1113,6 @@ ;; :: ;; :::::::::::::::::::: -;; ??? It would be useful to have SImode versions of the extract and insert -;; patterns. - (define_insn "extv" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extract:DI (match_operand:DI 1 "register_operand" "r") @@ -1229,6 +1226,21 @@ "dep %0 = %3, %0, %2, %1" [(set_attr "type" "I")]) +;; Combine doesn't like to create bitfield insertions into zero. +(define_insn "*depz_internal" + [(set (match_operand:DI 0 "register_operand" "=r") + (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "const_int_operand" "n")) + (match_operand:DI 3 "const_int_operand" "n")))] + "CONST_OK_FOR_M (INTVAL (operands[2])) + && ia64_depz_field_mask (operands[3], operands[2]) > 0" + "* +{ + operands[3] = GEN_INT (ia64_depz_field_mask (operands[3], operands[2])); + return \"%,dep.z %0 = %1, %2, %3\"; +}" + [(set_attr "type" "I")]) + (define_insn "shift_mix4left" [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") (const_int 32) (const_int 0)) @@ -1238,9 +1250,6 @@ "#" [(set_attr "type" "unknown")]) -;; ??? Need to emit an instruction group barrier here because this gets split -;; after md_reorg. - (define_split [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "") (const_int 32) (const_int 0)) @@ -2003,89 +2012,59 @@ ;; :: ;; :::::::::::::::::::: -;; There is no sign-extend form of dep, so we only get 32 bits of valid result -;; instead of 64 like the patterns below. - -;; Using a predicate that accepts only constants doesn't work, because optabs -;; will load the operand into a register and call the pattern if the predicate -;; did not accept it on the first try. So we use nonmemory_operand and then -;; verify that we have an appropriate constant in the expander. - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashift:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (! shift_32bit_count_operand (operands[2], SImode)) - FAIL; -}") - -(define_insn "*ashlsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "shift_32bit_count_operand" "n")))] +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ashift:SI (match_operand:SI 1 "register_operand" "r,r,r") + (match_operand:SI 2 "reg_or_5bit_operand" "R,n,r")))] "" - "dep.z %0 = %1, %2, %E2" - [(set_attr "type" "I")]) - -;; This is really an extract, but this is how combine canonicalizes the -;; operation. + "@ + shladd %0 = %1, %2, r0 + dep.z %0 = %1, %2, %E2 + shl %0 = %1, %2" + [(set_attr "type" "A,I,I")]) (define_expand "ashrsi3" - [(set (match_dup 3) - (ashiftrt:DI (sign_extend:DI - (match_operand:SI 1 "register_operand" "")) - (match_operand:DI 2 "nonmemory_operand" ""))) - (set (match_operand:SI 0 "register_operand" "") (match_dup 4))] + [(set (match_operand:SI 0 "register_operand" "") + (ashiftrt:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_5bit_operand" "")))] "" " { - if (! shift_32bit_count_operand (operands[2], SImode)) - FAIL; - - operands[3] = gen_reg_rtx (DImode); - operands[4] = gen_lowpart (SImode, operands[3]); + rtx subtarget = gen_reg_rtx (DImode); + if (GET_CODE (operands[2]) == CONST_INT) + emit_insn (gen_extv (subtarget, gen_lowpart (DImode, operands[1]), + GEN_INT (32 - INTVAL (operands[2])), operands[2])); + else + { + emit_insn (gen_extendsidi2 (subtarget, operands[1])); + emit_insn (gen_ashrdi3 (subtarget, subtarget, + gen_lowpart (DImode, operands[2]))); + } + emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget); + DONE; }") -(define_insn "*ashrsi3_internal" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashiftrt:DI (sign_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (match_operand:DI 2 "shift_32bit_count_operand" "n")))] - "" - "extr %0 = %1, %2, %E2" - [(set_attr "type" "I")]) - -;; This is really an extract, but this is how combine canonicalizes the -;; operation. - (define_expand "lshrsi3" - [(set (match_dup 3) - (lshiftrt:DI (zero_extend:DI - (match_operand:SI 1 "register_operand" "")) - (match_operand:DI 2 "nonmemory_operand" ""))) - (set (match_operand:SI 0 "register_operand" "") (match_dup 4))] + [(set (match_operand:SI 0 "register_operand" "") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_5bit_operand" "")))] "" " { - if (! shift_32bit_count_operand (operands[2], SImode)) - FAIL; - - operands[3] = gen_reg_rtx (DImode); - operands[4] = gen_lowpart (SImode, operands[3]); + rtx subtarget = gen_reg_rtx (DImode); + if (GET_CODE (operands[2]) == CONST_INT) + emit_insn (gen_extzv (subtarget, gen_lowpart (DImode, operands[1]), + GEN_INT (32 - INTVAL (operands[2])), operands[2])); + else + { + emit_insn (gen_zero_extendsidi2 (subtarget, operands[1])); + emit_insn (gen_lshrdi3 (subtarget, subtarget, + gen_lowpart (DImode, operands[2]))); + } + emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget); + DONE; }") -(define_insn "*lshrsi3_internal" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (zero_extend:DI - (match_operand:SI 1 "register_operand" "r")) - (match_operand:DI 2 "shift_32bit_count_operand" "n")))] - "" - "extr.u %0 = %1, %2, %E2" - [(set_attr "type" "I")]) - ;; Use mix4.r/shr to implement rotrsi3. We only get 32 bits of valid result ;; here, instead of 64 like the patterns above. @@ -2102,11 +2081,9 @@ { if (! shift_32bit_count_operand (operands[2], SImode)) FAIL; - operands[3] = gen_reg_rtx (DImode); operands[4] = gen_lowpart (SImode, operands[3]); }") - ;; :::::::::::::::::::: ;; :: @@ -2115,12 +2092,14 @@ ;; :::::::::::::::::::: (define_insn "ashldi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "reg_or_6bit_operand" "rM")))] + [(set (match_operand:DI 0 "register_operand" "=r,r") + (ashift:DI (match_operand:DI 1 "register_operand" "r,r") + (match_operand:DI 2 "reg_or_6bit_operand" "R,rM")))] "" - "shl %0 = %1, %2" - [(set_attr "type" "I")]) + "@ + shladd %0 = %1, %2, r0 + shl %0 = %1, %2" + [(set_attr "type" "A,I")]) ;; ??? Maybe combine this with the multiply and add instruction? -- 2.30.2