diff options
author | Jan Beulich <jbeulich@novell.com> | 2005-07-28 06:58:58 +0000 |
---|---|---|
committer | Jan Beulich <jbeulich@gcc.gnu.org> | 2005-07-28 06:58:58 +0000 |
commit | a71aef0bb317dfa73527e3fd7c4895ca52551901 (patch) | |
tree | 838ce6bab9b932926e15434849dd188a4a00c659 /gcc | |
parent | 9e7705cbd19b0fc8e5b3589e2a2c2a36eeb954c5 (diff) | |
download | gcc-a71aef0bb317dfa73527e3fd7c4895ca52551901.zip gcc-a71aef0bb317dfa73527e3fd7c4895ca52551901.tar.gz gcc-a71aef0bb317dfa73527e3fd7c4895ca52551901.tar.bz2 |
ia64.c (ia64_load_pair_ok): New.
gcc/
2005-07-28 Jan Beulich <jbeulich@novell.com>
* config/ia64/ia64.c (ia64_load_pair_ok): New.
(ia64_print_operand): Describe and handle 'X'.
(ia64_register_move_cost): Also handle FP_REGS.
(ia64_preferred_reload_class): Likewise.
(ia64_secondary_reload_class): Likewise.
(ia64_dependencies_evaluation_hook): New local variable c. Initialize
it. Also check for ITANIUM_CLASS_FLDP.
* config/ia64/ia64.h (FP_REGNO_P): New.
(HARD_REGNO_MODE_OK): Remove explusion of TImode.
(reg_class): Add FP_REGS.
(REG_CLASS_NAMES): Adjust for it.
(REG_CLASS_CONTENTS): Likewise.
(REGNO_REG_CLASS): Use FP_REGS where appropriate.
(REG_CLASS_FROM_LETTER): Handle 'x'.
(CLASS_MAX_NREGS): Handle FP_REGS.
(MEMORY_MOVE_COST): Likewise.
* config/ia64/ia64.md (itanium_class): Add fldp.
(type): Handle fldp.
(movti_internal): More allowable operand combinations. Use ldfp8 when
splitting unnecessary. Remove predicable attribute. Adjust
itanium_class attribute.
(smuldi3_highpart): Remove outdated comment.
(mulditi3, umulditi3, rotlti3): New expanders.
(addti3, subti3, mulditi3_internal, umulditi3_internal, negti2, rotlti3_internal): New insns.
(absti2): Disabled new insn for future reference.
Respective new splitters.
* config/ia64/itanium1.md (1_fldp, 1b_fldp): New insn reservations.
* config/ia64/itanium2.md (2_fldp, 2b_fldp): Likewise.
* config/ia64/ia64-protos.h (ia64_load_pair_ok): New.
From-SVN: r102463
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/config/ia64/ia64-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 55 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 19 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.md | 267 | ||||
-rw-r--r-- | gcc/config/ia64/itanium1.md | 8 | ||||
-rw-r--r-- | gcc/config/ia64/itanium2.md | 10 |
7 files changed, 369 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d888c82..264b072 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2005-07-28 Jan Beulich <jbeulich@novell.com> + + * config/ia64/ia64.c (ia64_load_pair_ok): New. + (ia64_print_operand): Describe and handle 'X'. + (ia64_register_move_cost): Also handle FP_REGS. + (ia64_preferred_reload_class): Likewise. + (ia64_secondary_reload_class): Likewise. + (ia64_dependencies_evaluation_hook): New local variable c. Initialize + it. Also check for ITANIUM_CLASS_FLDP. + * config/ia64/ia64.h (FP_REGNO_P): New. + (HARD_REGNO_MODE_OK): Remove explusion of TImode. + (reg_class): Add FP_REGS. + (REG_CLASS_NAMES): Adjust for it. + (REG_CLASS_CONTENTS): Likewise. + (REGNO_REG_CLASS): Use FP_REGS where appropriate. + (REG_CLASS_FROM_LETTER): Handle 'x'. + (CLASS_MAX_NREGS): Handle FP_REGS. + (MEMORY_MOVE_COST): Likewise. + * config/ia64/ia64.md (itanium_class): Add fldp. + (type): Handle fldp. + (movti_internal): More allowable operand combinations. Use ldfp8 when + splitting unnecessary. Remove predicable attribute. Adjust + itanium_class attribute. + (smuldi3_highpart): Remove outdated comment. + (mulditi3, umulditi3, rotlti3): New expanders. + (addti3, subti3, mulditi3_internal, umulditi3_internal, negti2, rotlti3_internal): New insns. + (absti2): Disabled new insn for future reference. + Respective new splitters. + * config/ia64/itanium1.md (1_fldp, 1b_fldp): New insn reservations. + * config/ia64/itanium2.md (2_fldp, 2b_fldp): Likewise. + * config/ia64/ia64-protos.h (ia64_load_pair_ok): New. + 2005-07-25 James A. Morrison <phython@gcc.gnu.org> PR rtl-optimization/23047 diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index 8684649..0c6355a 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -41,6 +41,7 @@ extern bool ia64_legitimate_constant_p (rtx); extern rtx ia64_expand_move (rtx, rtx); extern int ia64_move_ok (rtx, rtx); +extern int ia64_load_pair_ok (rtx, rtx); extern int addp4_optimize_ok (rtx, rtx); extern void ia64_emit_cond_move (rtx, rtx, rtx); extern int ia64_depz_field_mask (rtx, rtx); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index fd97cbe..1873f89 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -690,6 +690,37 @@ ia64_move_ok (rtx dst, rtx src) return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src); } +/* Return 1 if the operands are ok for a floating point load pair. */ + +int +ia64_load_pair_ok (rtx dst, rtx src) +{ + if (GET_CODE (dst) != REG || !FP_REGNO_P (REGNO (dst))) + return 0; + if (GET_CODE (src) != MEM || MEM_VOLATILE_P (src)) + return 0; + switch (GET_CODE (XEXP (src, 0))) + { + case REG: + case POST_INC: + break; + case POST_DEC: + return 0; + case POST_MODIFY: + { + rtx adjust = XEXP (XEXP (XEXP (src, 0), 1), 1); + + if (GET_CODE (adjust) != CONST_INT + || INTVAL (adjust) != GET_MODE_SIZE (GET_MODE (src))) + return 0; + } + break; + default: + abort (); + } + return 1; +} + int addp4_optimize_ok (rtx op1, rtx op2) { @@ -4305,6 +4336,7 @@ ia64_print_operand_address (FILE * stream ATTRIBUTE_UNUSED, for Intel assembler. U Print an 8-bit sign extended number (K) as a 64-bit unsigned number for Intel assembler. + X A pair of floating point registers. r Print register name, or constant 0 as r0. HP compatibility for Linux kernel. v Print vector constant value as an 8-byte integer value. */ @@ -4453,6 +4485,13 @@ ia64_print_operand (FILE * file, rtx x, int code) } break; + case 'X': + { + unsigned int regno = REGNO (x); + fprintf (file, "%s, %s", reg_names [regno], reg_names [regno + 1]); + } + return; + case 'r': /* If this operand is the constant zero, write it as register zero. Any register, zero, or CONST_INT value is OK here. */ @@ -4682,6 +4721,7 @@ ia64_register_move_cost (enum machine_mode mode, enum reg_class from, case GR_REGS: case FR_REGS: + case FP_REGS: case GR_AND_FR_REGS: case GR_AND_BR_REGS: case ALL_REGS: @@ -4703,6 +4743,7 @@ ia64_preferred_reload_class (rtx x, enum reg_class class) switch (class) { case FR_REGS: + case FP_REGS: /* Don't allow volatile mem reloads into floating point registers. This is defined to force reload to choose the r/m case instead of the f/f case when reloading (set (reg fX) (mem/v)). */ @@ -4768,6 +4809,7 @@ ia64_secondary_reload_class (enum reg_class class, break; case FR_REGS: + case FP_REGS: /* Need to go through general registers to get to other class regs. */ if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno))) return GR_REGS; @@ -6113,16 +6155,19 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail) { for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1)) { + enum attr_itanium_class c; + if (REG_NOTE_KIND (link) != REG_DEP_TRUE) continue; next = XEXP (link, 0); - if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_ST - || ia64_safe_itanium_class (next) == ITANIUM_CLASS_STF) + c = ia64_safe_itanium_class (next); + if ((c == ITANIUM_CLASS_ST + || c == ITANIUM_CLASS_STF) && ia64_st_address_bypass_p (insn, next)) break; - else if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_LD - || ia64_safe_itanium_class (next) - == ITANIUM_CLASS_FLD) + else if ((c == ITANIUM_CLASS_LD + || c == ITANIUM_CLASS_FLD + || c == ITANIUM_CLASS_FLDP) && ia64_ld_address_bypass_p (insn, next)) break; } diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 9e52773..8b92ced 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -324,6 +324,7 @@ while (0) #define ADDL_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 3) #define GR_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 127) #define FR_REGNO_P(REGNO) ((REGNO) >= 128 && (REGNO) <= 255) +#define FP_REGNO_P(REGNO) ((REGNO) >= 128 && (REGNO) <= 254 && (REGNO) != 159) #define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319) #define BR_REGNO_P(REGNO) ((REGNO) >= 320 && (REGNO) <= 327) #define GENERAL_REGNO_P(REGNO) \ @@ -651,7 +652,6 @@ while (0) #define HARD_REGNO_MODE_OK(REGNO, MODE) \ (FR_REGNO_P (REGNO) ? \ GET_MODE_CLASS (MODE) != MODE_CC && \ - (MODE) != TImode && \ (MODE) != BImode && \ (MODE) != TFmode \ : PR_REGNO_P (REGNO) ? \ @@ -721,6 +721,7 @@ enum reg_class AR_I_REGS, ADDL_REGS, GR_REGS, + FP_REGS, FR_REGS, GR_AND_BR_REGS, GR_AND_FR_REGS, @@ -737,7 +738,7 @@ enum reg_class constants. These names are used in writing some of the debugging dumps. */ #define REG_CLASS_NAMES \ { "NO_REGS", "PR_REGS", "BR_REGS", "AR_M_REGS", "AR_I_REGS", \ - "ADDL_REGS", "GR_REGS", "FR_REGS", \ + "ADDL_REGS", "GR_REGS", "FP_REGS", "FR_REGS", \ "GR_AND_BR_REGS", "GR_AND_FR_REGS", "ALL_REGS" } /* An initializer containing the contents of the register classes, as integers @@ -774,6 +775,10 @@ enum reg_class { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x0100 }, \ + /* FP_REGS. */ \ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ + 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, \ + 0x00000000, 0x00000000, 0x0000 }, \ /* FR_REGS. */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ @@ -801,7 +806,8 @@ enum reg_class #define REGNO_REG_CLASS(REGNO) \ (ADDL_REGNO_P (REGNO) ? ADDL_REGS \ : GENERAL_REGNO_P (REGNO) ? GR_REGS \ - : FR_REGNO_P (REGNO) ? FR_REGS \ + : FR_REGNO_P (REGNO) ? (REGNO) != R_FR (31) \ + && (REGNO) != R_FR(127) ? FP_REGS : FR_REGS \ : PR_REGNO_P (REGNO) ? PR_REGS \ : BR_REGNO_P (REGNO) ? BR_REGS \ : AR_M_REGNO_P (REGNO) ? AR_M_REGS \ @@ -832,6 +838,7 @@ enum reg_class : (CHAR) == 'c' ? PR_REGS \ : (CHAR) == 'd' ? AR_M_REGS \ : (CHAR) == 'e' ? AR_I_REGS \ + : (CHAR) == 'x' ? FP_REGS \ : NO_REGS) /* A C expression which is nonzero if register number NUM is suitable for use @@ -888,8 +895,8 @@ enum reg_class #define CLASS_MAX_NREGS(CLASS, MODE) \ ((MODE) == BImode && (CLASS) == PR_REGS ? 2 \ - : ((CLASS) == FR_REGS && (MODE) == XFmode) ? 1 \ - : ((CLASS) == FR_REGS && (MODE) == XCmode) ? 2 \ + : (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == XFmode) ? 1 \ + : (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == XCmode) ? 2 \ : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) /* In FP regs, we can't change FP values to integer values and vice versa, @@ -1414,7 +1421,7 @@ do { \ /* A C expression for the cost of moving data of mode M between a register and memory. */ #define MEMORY_MOVE_COST(MODE,CLASS,IN) \ - ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS \ + ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS || (CLASS) == FP_REGS \ || (CLASS) == GR_AND_FR_REGS ? 4 : 10) /* A C expression for the cost of a branch instruction. A value of 1 is the diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index 18e6cb3..3f43e48 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -123,15 +123,15 @@ ;; which emit instruction that can go in any slot (e.g. nop). (define_attr "itanium_class" "unknown,ignore,stop_bit,br,fcmp,fcvtfx,fld, - fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,ld, - chk_s,long_i,mmalua,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf, + fldp,fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf, + ld,chk_s,long_i,mmalua,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf, st,syst_m0, syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop, nop_b,nop_f,nop_i,nop_m,nop_x,lfetch,pre_cycle" (const_string "unknown")) ;; chk_s has an I and an M form; use type A for convenience. (define_attr "type" "unknown,A,I,M,F,B,L,X,S" - (cond [(eq_attr "itanium_class" "ld,st,fld,stf,sem,nop_m") (const_string "M") + (cond [(eq_attr "itanium_class" "ld,st,fld,fldp,stf,sem,nop_m") (const_string "M") (eq_attr "itanium_class" "rse_m,syst_m,syst_m0") (const_string "M") (eq_attr "itanium_class" "frar_m,toar_m,frfr,tofr") (const_string "M") (eq_attr "itanium_class" "lfetch") (const_string "M") @@ -659,18 +659,22 @@ }) (define_insn_and_split "*movti_internal" - [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m") - (match_operand:TI 1 "general_operand" "ri,m,r"))] + [(set (match_operand:TI 0 "nonimmediate_operand" "=r, *fm,*x,*f, Q") + (match_operand:TI 1 "general_operand" "r*fim,r, Q, *fOQ,*f"))] "ia64_move_ok (operands[0], operands[1])" - "#" - "reload_completed" + "@ + # + # + ldfp8 %X0 = %1%P1 + # + #" + "reload_completed && !ia64_load_pair_ok(operands[0], operands[1])" [(const_int 0)] { ia64_split_tmode_move (operands); DONE; } - [(set_attr "itanium_class" "unknown") - (set_attr "predicable" "no")]) + [(set_attr "itanium_class" "unknown,unknown,fldp,unknown,unknown")]) ;; Floating Point Moves ;; @@ -2140,9 +2144,6 @@ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))] "") -;; ??? There are highpart multiply and add instructions, but we have no way -;; to generate them. - (define_insn "smuldi3_highpart" [(set (match_operand:DI 0 "fr_register_operand" "=f") (truncate:DI @@ -2493,6 +2494,200 @@ ;; :::::::::::::::::::: ;; :: +;; :: 128 bit Integer arithmetic +;; :: +;; :::::::::::::::::::: + +(define_insn "addti3" + [(set (match_operand:TI 0 "gr_register_operand" "=&r") + (plus:TI (match_operand:TI 1 "gr_register_operand" "%r") + (match_operand:TI 2 "gr_reg_or_14bit_operand" "rI"))) + (clobber (match_scratch:BI 3 "=&c"))] + "" + "#" + [(set_attr "itanium_class" "unknown")]) + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (plus:TI (match_operand:TI 1 "register_operand" "") + (match_operand:TI 2 "register_operand" ""))) + (clobber (match_scratch:BI 3 ""))] + "reload_completed" + [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) + (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1))) + (cond_exec (eq (match_dup 3) (const_int 0)) + (set (match_dup 4) (plus:DI (match_dup 5) (match_dup 6)))) + (cond_exec (ne (match_dup 3) (const_int 0)) + (set (match_dup 4) + (plus:DI (plus:DI (match_dup 5) (match_dup 6)) + (const_int 1))))] +{ + operands[4] = gen_highpart (DImode, operands[0]); + operands[0] = gen_lowpart (DImode, operands[0]); + operands[5] = gen_highpart (DImode, operands[1]); + operands[1] = gen_lowpart (DImode, operands[1]); + operands[6] = gen_highpart (DImode, operands[2]); + operands[2] = gen_lowpart (DImode, operands[2]); +}) + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (plus:TI (match_operand:TI 1 "register_operand" "") + (match_operand:TI 2 "immediate_operand" ""))) + (clobber (match_scratch:BI 3 ""))] + "reload_completed" + [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) + (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1))) + (cond_exec (eq (match_dup 3) (const_int 0)) + (set (match_dup 4) + (plus:DI (match_dup 5) (match_dup 6)))) + (cond_exec (ne (match_dup 3) (const_int 0)) + (set (match_dup 4) + (plus:DI (match_dup 5) (match_dup 7))))] +{ + operands[4] = gen_highpart (DImode, operands[0]); + operands[0] = gen_lowpart (DImode, operands[0]); + operands[5] = gen_highpart (DImode, operands[1]); + operands[1] = gen_lowpart (DImode, operands[1]); + operands[6] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx; + operands[7] = INTVAL (operands[2]) < 0 ? const0_rtx : const1_rtx; +}) + +(define_insn "subti3" + [(set (match_operand:TI 0 "gr_register_operand" "=&r") + (minus:TI (match_operand:TI 1 "gr_reg_or_8bit_operand" "rK") + (match_operand:TI 2 "gr_register_operand" "r"))) + (clobber (match_scratch:BI 3 "=&c"))] + "" + "#" + [(set_attr "itanium_class" "unknown")]) + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (minus:TI (match_operand:TI 1 "register_operand" "") + (match_operand:TI 2 "register_operand" ""))) + (clobber (match_scratch:BI 3 "=&c"))] + "reload_completed" + [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2))) + (set (match_dup 3) (ltu:BI (match_dup 1) (match_dup 0))) + (cond_exec (eq (match_dup 3) (const_int 0)) + (set (match_dup 4) (minus:DI (match_dup 5) (match_dup 6)))) + (cond_exec (ne (match_dup 3) (const_int 0)) + (set (match_dup 4) + (plus:DI (not:DI (match_dup 6)) (match_dup 5))))] +{ + operands[4] = gen_highpart (DImode, operands[0]); + operands[0] = gen_lowpart (DImode, operands[0]); + operands[5] = gen_highpart (DImode, operands[1]); + operands[1] = gen_lowpart (DImode, operands[1]); + operands[6] = gen_highpart (DImode, operands[2]); + operands[2] = gen_lowpart (DImode, operands[2]); +}) + +(define_split + [(set (match_operand:TI 0 "register_operand" "") + (minus:TI (match_operand:TI 1 "immediate_operand" "") + (match_operand:TI 2 "register_operand" ""))) + (clobber (match_scratch:BI 3 "=&c"))] + "reload_completed && CONST_OK_FOR_K (INTVAL (operands[1]))" + [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2))) + (set (match_dup 3) (gtu:BI (match_dup 0) (match_dup 1))) + (cond_exec (ne (match_dup 3) (const_int 0)) + (set (match_dup 4) (minus:DI (match_dup 6) (match_dup 5)))) + (cond_exec (eq (match_dup 3) (const_int 0)) + (set (match_dup 4) (minus:DI (match_dup 7) (match_dup 5))))] +{ + operands[4] = gen_highpart (DImode, operands[0]); + operands[0] = gen_lowpart (DImode, operands[0]); + operands[5] = gen_highpart (DImode, operands[2]); + operands[2] = gen_lowpart (DImode, operands[2]); + operands[6] = INTVAL (operands[1]) < 0 ? GEN_INT (-2) : constm1_rtx; + operands[7] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx; +}) + +(define_expand "mulditi3" + [(set (match_operand:TI 0 "fr_register_operand" "") + (mult:TI (sign_extend:TI + (match_operand:DI 1 "fr_register_operand" "")) + (sign_extend:TI + (match_operand:DI 2 "fr_register_operand" ""))))] + "" + "") + +(define_insn_and_split "*mulditi3_internal" + [(set (match_operand:TI 0 "fr_register_operand" "=&f") + (mult:TI (sign_extend:TI + (match_operand:DI 1 "fr_register_operand" "%f")) + (sign_extend:TI + (match_operand:DI 2 "fr_register_operand" "f"))))] + "" + "#" + "reload_completed" + [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2))) + (set (match_dup 3) (truncate:DI + (lshiftrt:TI + (mult:TI (sign_extend:TI (match_dup 1)) + (sign_extend:TI (match_dup 2))) + (const_int 64))))] +{ + operands[3] = gen_highpart (DImode, operands[0]); + operands[0] = gen_lowpart (DImode, operands[0]); +} + [(set_attr "itanium_class" "unknown")]) + +(define_expand "umulditi3" + [(set (match_operand:TI 0 "fr_register_operand" "") + (mult:TI (zero_extend:TI + (match_operand:DI 1 "fr_register_operand" "")) + (zero_extend:TI + (match_operand:DI 2 "fr_register_operand" ""))))] + "" + "") + +(define_insn_and_split "*umulditi3_internal" + [(set (match_operand:TI 0 "fr_register_operand" "=&f") + (mult:TI (zero_extend:TI + (match_operand:DI 1 "fr_register_operand" "%f")) + (zero_extend:TI + (match_operand:DI 2 "fr_register_operand" "f"))))] + "" + "#" + "reload_completed" + [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2))) + (set (match_dup 3) (truncate:DI + (lshiftrt:TI + (mult:TI (zero_extend:TI (match_dup 1)) + (zero_extend:TI (match_dup 2))) + (const_int 64))))] +{ + operands[3] = gen_highpart (DImode, operands[0]); + operands[0] = gen_lowpart (DImode, operands[0]); +} + [(set_attr "itanium_class" "unknown")]) + +(define_insn_and_split "negti2" + [(set (match_operand:TI 0 "gr_register_operand" "=&r") + (neg:TI (match_operand:TI 1 "gr_register_operand" "r"))) + (clobber (match_scratch:BI 2 "=&c"))] + "" + "#" + "reload_completed" + [(set (match_dup 2) (eq:BI (match_dup 1) (const_int 0))) + (set (match_dup 0) (minus:DI (const_int 0) (match_dup 1))) + (cond_exec (eq (match_dup 2) (const_int 0)) + (set (match_dup 3) (minus:DI (const_int -1) (match_dup 4)))) + (cond_exec (ne (match_dup 2) (const_int 0)) + (set (match_dup 3) (minus:DI (const_int 0) (match_dup 4))))] +{ + operands[3] = gen_highpart (DImode, operands[0]); + operands[0] = gen_lowpart (DImode, operands[0]); + operands[4] = gen_highpart (DImode, operands[1]); + operands[1] = gen_lowpart (DImode, operands[1]); +} + [(set_attr "itanium_class" "unknown")]) + +;; :::::::::::::::::::: +;; :: ;; :: 32 bit floating point arithmetic ;; :: ;; :::::::::::::::::::: @@ -4505,6 +4700,54 @@ DONE; }) +(define_expand "rotlti3" + [(set (match_operand:TI 0 "gr_register_operand" "") + (rotate:TI (match_operand:TI 1 "gr_register_operand" "") + (match_operand:DI 2 "nonmemory_operand" "")))] + "" +{ + if (! dshift_count_operand (operands[2], DImode)) + FAIL; +}) + +(define_insn_and_split "*rotlti3_internal" + [(set (match_operand:TI 0 "gr_register_operand" "=&r") + (rotate:TI (match_operand:TI 1 "gr_register_operand" "r") + (match_operand:DI 2 "dshift_count_operand" "n")))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + HOST_WIDE_INT count = INTVAL (operands[2]); + rtx rl = gen_lowpart (DImode, operands[0]); + rtx rh = gen_highpart (DImode, operands[0]); + rtx lo = gen_lowpart (DImode, operands[1]); + rtx hi = gen_highpart (DImode, operands[1]); + rtx countlo = GEN_INT (-count & 63); + + if (count & 64) + { + if (count & 63) + { + emit_insn (gen_shrp (rl, hi, lo, countlo)); + emit_insn (gen_shrp (rh, lo, hi, countlo)); + } + else + { + emit_move_insn (rl, hi); + emit_move_insn (rh, lo); + } + } + else + { + emit_insn (gen_shrp (rl, lo, hi, countlo)); + emit_insn (gen_shrp (rh, hi, lo, countlo)); + } + DONE; +} + [(set_attr "itanium_class" "unknown")]) + (define_insn "shrp" [(set (match_operand:DI 0 "gr_register_operand" "=r") (unspec:DI [(match_operand:DI 1 "gr_register_operand" "r") diff --git a/gcc/config/ia64/itanium1.md b/gcc/config/ia64/itanium1.md index 21c8764..e93475a 100644 --- a/gcc/config/ia64/itanium1.md +++ b/gcc/config/ia64/itanium1.md @@ -529,6 +529,10 @@ (and (and (eq_attr "cpu" "itanium") (eq_attr "itanium_class" "fld")) (eq (symbol_ref "bundling_p") (const_int 0))) "1_M") +(define_insn_reservation "1_fldp" 9 + (and (and (eq_attr "cpu" "itanium") + (eq_attr "itanium_class" "fldp")) + (eq (symbol_ref "bundling_p") (const_int 0))) "1_M") (define_insn_reservation "1_fmac" 5 (and (and (eq_attr "cpu" "itanium") (eq_attr "itanium_class" "fmac")) @@ -1407,6 +1411,10 @@ (and (and (eq_attr "cpu" "itanium") (eq_attr "itanium_class" "fld")) (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M") +(define_insn_reservation "1b_fldp" 9 + (and (and (eq_attr "cpu" "itanium") + (eq_attr "itanium_class" "fldp")) + (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M") (define_insn_reservation "1b_fmac" 5 (and (and (eq_attr "cpu" "itanium") (eq_attr "itanium_class" "fmac")) diff --git a/gcc/config/ia64/itanium2.md b/gcc/config/ia64/itanium2.md index e00341a..f16d185 100644 --- a/gcc/config/ia64/itanium2.md +++ b/gcc/config/ia64/itanium2.md @@ -734,6 +734,11 @@ (and (and (eq_attr "cpu" "itanium2") (eq_attr "itanium_class" "fld")) (eq (symbol_ref "bundling_p") (const_int 0))) "2_M") +(define_insn_reservation "2_fldp" 6 + (and (and (eq_attr "cpu" "itanium2") + (eq_attr "itanium_class" "fldp")) + (eq (symbol_ref "bundling_p") (const_int 0))) + "2_M_only_um01") (define_insn_reservation "2_fmac" 4 (and (and (eq_attr "cpu" "itanium2") (eq_attr "itanium_class" "fmac")) @@ -1541,6 +1546,11 @@ (and (and (eq_attr "cpu" "itanium2") (eq_attr "itanium_class" "fld")) (ne (symbol_ref "bundling_p") (const_int 0))) "2b_M") +(define_insn_reservation "2b_fldp" 6 + (and (and (eq_attr "cpu" "itanium2") + (eq_attr "itanium_class" "fldp")) + (ne (symbol_ref "bundling_p") (const_int 0))) + "2b_M_only_um01") (define_insn_reservation "2b_fmac" 4 (and (and (eq_attr "cpu" "itanium2") (eq_attr "itanium_class" "fmac")) |