diff options
author | Michael Meissner <meissner@linux.vnet.ibm.com> | 2010-04-29 23:18:16 +0000 |
---|---|---|
committer | Michael Meissner <meissner@linux.vnet.ibm.com> | 2010-04-29 23:18:16 +0000 |
commit | 044cb8b175ffc2a686ac27fb2eb7ce9677d3bb9e (patch) | |
tree | 3a16e7f3b8afcdb3a7cf850a91439db9133fed72 | |
parent | 659b2fbc3d4a236b0714adc5695ee391d5de5390 (diff) |
Merge in vectorizer stuff from AT 2.1 and cleanups from GCC 4.5
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/ibm/gcc-4_4-branch@158913 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog.ibm | 197 | ||||
-rw-r--r-- | gcc/config/rs6000/constraints.md | 16 | ||||
-rw-r--r-- | gcc/config/rs6000/dfp.md | 235 | ||||
-rw-r--r-- | gcc/config/rs6000/power4.md | 154 | ||||
-rw-r--r-- | gcc/config/rs6000/power5.md | 83 | ||||
-rw-r--r-- | gcc/config/rs6000/ppc-asm.h | 28 | ||||
-rw-r--r-- | gcc/config/rs6000/ppu_intrinsics.h | 42 | ||||
-rw-r--r-- | gcc/config/rs6000/predicates.md | 9 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 220 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 38 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 580 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.opt | 12 | ||||
-rw-r--r-- | gcc/config/rs6000/t-rs6000 | 20 | ||||
-rw-r--r-- | gcc/config/rs6000/vector.md | 2 | ||||
-rw-r--r-- | gcc/doc/md.texi | 35 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 8 | ||||
-rw-r--r-- | gcc/genautomata.c | 531 | ||||
-rw-r--r-- | gcc/gensupport.c | 26 | ||||
-rw-r--r-- | gcc/recog.c | 30 | ||||
-rw-r--r-- | gcc/target-def.h | 7 | ||||
-rw-r--r-- | gcc/target.h | 8 | ||||
-rw-r--r-- | gcc/targhooks.c | 17 | ||||
-rw-r--r-- | gcc/targhooks.h | 3 | ||||
-rw-r--r-- | gcc/tree-vectorizer.c | 17 |
24 files changed, 1434 insertions, 884 deletions
diff --git a/gcc/ChangeLog.ibm b/gcc/ChangeLog.ibm index b38bf11bb0b..87e6fcfe890 100644 --- a/gcc/ChangeLog.ibm +++ b/gcc/ChangeLog.ibm @@ -1,3 +1,200 @@ +2010-04-29 Michael Meissner <meissner@linux.vnet.ibm.com> + + Backport from Advanced Toolchain 2.1: + 2009-09-17 Revital Eres <eres@il.ibm.com> + + * doc/tm.texi (TARGET_SUPPORT_VECTOR_MISALIGNMENT): Document. + * targhooks.c (default_builtin_support_vector_misalignment): + New builtin function. + * targhooks.h (default_builtin_support_vector_misalignment): + Declare. + * target.h (builtin_support_vector_misalignment): + New field in struct gcc_target. + * tree-vectorizer.c (vect_supportable_dr_alignment): Call + new builtin function. + * target-def.h (TARGET_SUPPORT_VECTOR_MISALIGNMENT): + Define. + * config/rs6000/rs6000.c + (rs6000_builtin_support_vector_misalignment): New function. + (TARGET_SUPPORT_VECTOR_MISALIGNMENT): Define. + +2010-04-29 Michael Meissner <meissner@linux.vnet.ibm.com> + + Backport from mainline and/or GCC 4.5.0 + + 2010-03-24 Michael Meissner <meissner@linux.vnet.ibm.com> + * config/rs6000/constraints.md: Update copyright year for my changes. + + PR target/43484 + * config/rs6000/rs6000.c (rs6000_split_multireg_move): If r0 is + used in reg+reg addressing, swap registers. + + 2010-03-22 Mike Stump <mikestump@comcast.net> + PR target/23071 + * config/rs6000/rs6000.c (darwin_rs6000_special_round_type_align): + Don't overly align based upon packed packed fields. + + 2010-03-17 Peter Bergner <bergner@vnet.ibm.com> + PR target/42427 + * config/rs6000/rs6000.c (rs6000_split_multireg_move): Add support for + non-offsettable and pre_modify update addressing. + * config/rs6000/dfp.md (*movdd_hardfloat32): Make the "0", "1" + and "2" alternatives "#". + (*movdd_softfloat32): Make all alternatives "#"; + * config/rs6000/rs6000.md (DIFD): New define_mode_iterator. + (*movdf_hardfloat32): Make the "0", "1" and "2" alternatives "#". + (*movdf_softfloat32): Make all alternatives "#"; + (movdi): Use the new DIFD mode iterator to create a common splitter + for movdi, movdf and movdd patterns. + + 2010-01-11 Janis Johnson <janis187@us.ibm.com> + PR target/42416 + * config/rs6000/rs6000.c (rs6000_override_options): On targets + that support VSX, warn for -mno-altivec if vsx is not disabled, + and disable vsx. + + 2009-07-18 Richard Sandiford <r.sandiford@uk.ibm.com> + * doc/md.texi: Document the new PowerPC "es" constraint. + Document that "m" can include automodified addresses on this target, + and explain how %U must be used. Extend the "Q" and "Z" documentation + to suggest "es" as well as "m". + * config/rs6000/constraints.md (es): New memory constraint. + (Q, Z): Update strings to match new documentation. + + * config/rs6000/rs6000.c (rs6000_mode_dependent_address): Allow any + offset from virtual_stack_vars_rtx and arg_pointer_rtx. + * config/rs6000/predicates.md (volatile_mem_operand): Use + offsettable_nonstrict_memref_p. + * config/rs6000/rs6000.md (*floatsidf2_internal): Remove split check. + (*floatunssidf2_internal): Likewise. + (*fix_truncdfsi2_internal): Likewise. + (*fix_trunctfsi2_internal): Likewise. + + 2009-06-17 Michael Eager <eager@eagercon.com> + * config/rs6000/constraints.md (register_constraint "d"): New. + * config/rs6000/dfp.md (movsd_store, extendsddd2, extendsdtd2, + truncddsd2, *negdd2_fpr, *absdd2_fpr, *nabsdd2_fpr, + *movdd_hardfloat32, *movdd_hardfloat64_mfpgpr, *movdd_hardfloat64, + *negtd2_fp, *abstd2_fpr, *nabstd2_fpr, *movtd_internal, extendddtd2, + trunctddd2, adddd3, addtd3, subdd3, subtd3, muldd3, multd3, divdd3, + divtd3, *cmpdd_internal1, *cmptd_internal1, floatditd2, ftruncdd2, + fixdddi2, ftrunctd2, fixtddi2): replace 'f' constraint with 'd' + * config/rs6000/ppu_intrinsics.h (__mffs, __mtfsf, __mtfsfi, __fabs, + __fnabs, __fmadd, __fmsub, __fnmadd, __fnmsub, __fsel, __frsqrte, + __fsqrt, __fmul, __fmuls, __frsp, __fcfid, __fctid, __fctidz, __fctiw, + __fctiwz): Same. + * config/rs6000/rs6000.md (*extendsfdf2_fpr, *truncdfsf2_fpr, + *fseldfsf4, *negdf2_fpr, *absdf2_fpr, *nabsdf2_fpr, *adddf3_fpr, + *subdf3_fpr, *muldf3_fpr, *divdf3_fpr, recipdf3, fred, sqrtdf2, + *fseldfdf4, *fselsfdf4, *floatsidf2_internal, *floatunssidf2_internal, + *fix_truncdfsi2_internal, fix_truncdfsi2_internal_gfxopt, + fix_truncdfsi2_mfpgpr, fctiwz, btruncdf2, ceildf2, floordf2, rounddf2, + stfiwx, floatdidf2, fix_truncdfdi2, floatdisf2_internal1, + *movdf_hardfloat32, *movdf_hardfloat64_mfpgpr, *movdf_hardfloat64, + *movtf_internal, *extenddftf2_internal, trunctfdf2_internal1, + trunctfdf2_internal2, trunctfsf2_fprs, fix_trunc_helper, + *fix_trunctfsi2_internal, negtf2_internal, *movdi_internal32, + *movdi_mfpgpr, *movdi_internal64, *movdf_update1, *movdf_update2, + *cmpdf_internal1, *cmptf_internal1, *cmptf_internal2): Same. + * doc/md.texi: Describe PowerPC 'd' constraint, update 'f' constraint. + + 2010-02-17 Steven Bosscher <steven@gcc.gnu.org> + * gensupport.c (process_one_cond_exec): Derive name for COND_EXEC + patterns from predicated pattern. + + 2009-10-15 Michael Meissner <meissner@linux.vnet.ibm.com> + * config/rs6000/t-rs6000 (MD_INCLUDES): Add a2.md. + + 2009-09-10 Nathan Froyd <froydnj@codesourcery.com> + * config/rs6000/rs6000.h (DATA_ALIGNMENT): Check that we are dealing + with actual SPE/paired vector modes before using 64-bit alignment. + Check that TYPE is a REAL_TYPE for TARGET_E500_DOUBLE. + + 2009-06-25 Andrew Pinski <andrew_pinski@playstation.sony.com> + PR target/38731 + * config/rs6000/rs6000.c (LOCAL_ALIGNMENT): Redefine to just use + DATA_ALIGNMENT instead. + + 2009-06-16 J"orn Rennecke <joern.rennecke@arc.com> + Janis Johnson <janis187@us.ibm.com> + PR target/39254 + * config/rs6000/rs6000.c (rs6000_emit_move): Don't emit a USE + for the symbol ref of a constant that is the source of a move + - nor for any other not-obvious-label-ref constants. + + 2009-04-30 Michael Matz <matz@suse.de> + PR tree-optimization/39955 + * config/rs6000/rs6000.c (rs6000_check_sdmode): Also check SSA_NAMEs. + + 2009-04-27 Ian Lance Taylor <iant@google.com> + * gensupport.c (std_preds): Use UNKNOWN instead of 0. + + 2009-04-24 Ian Lance Taylor <iant@google.com> + * config/rs6000/rs6000.c (rs6000_override_options): Add casts to + enum type. + + 2009-04-21 Joseph Myers <joseph@codesourcery.com> + * config/rs6000/ppc-asm.h: Add copyright and license notices. + + 2009-04-20 Ian Lance Taylor <iant@google.com> + * gensupport.c (init_predicate_table): Add cast to enum type. + + * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok): Add + cast to enum type. + (altivec_expand_vec_set_builtin): Change 0 to EXPAND_NORMAL in + function call. + (emit_unlikely_jump): Use add_reg_note. + (rs6000_emit_allocate_stack): Likewise. + (rs6000_frame_related, rs6000_emit_prologue): Likewise. + (output_toc): Change 1 to INSERT in function call. + (output_profile_hook): Change 0 to LCT_NORMAL in function call. + (rs6000_initialize_trampoline): Likewise. + (rs6000_init_dwarf_reg_sizes_extra): Change 0 to EXPAND_NORMAL in + function call. + + 2009-04-13 Vladimir Makarov <vmakarov@redhat.com> + * genautomata.c: Put blank after comma. + (automaton_decls): New. + (struct unit_usage): Add comments to member next. + (store_alt_unit_usage): Keep the list ordered. + (unit_present_on_list_p, equal_alternatives_p): New. + (check_regexp_units_distribution): Check units distribution + correctness correctly. + (main): Don't write automata if error is found. Return correct + exit code. + + * config/rs6000/power4.md (lsuq_power4, iq_power4, fpq_power4, + power4-load-ext, power4-store, power4-store-update, + power4-fpstore, power4-fpstore-update, power4-two, power4-three, + power4-insert, power4-compare, power4-lmul-cmp, power4-imul-cmp, + power4-lmul, , power4-imul, power4-imul3, power4-sdiv, + power4-sqrt, power4-isync): Modify reservation to make correct + unit distribution to automata. + + * config/rs6000/power5.md (iq_power5, fpq_power5, power5-store, + power5-store-update, power5-two, power5-three, power5-lmul, + power5-imul, power5-imul3, power5-sdiv, power5-sqrt): Ditto. + + 2009-04-08 Paolo Bonzini <bonzini@gnu.org> + * recog.c (ordered_comparison_operator): New. + * gensupport.c (std_preds): Add it. + * doc/md.texi (Machine-Independent Predicates): Document it. + + 2009-03-31 Alan Modra <amodra@bigpond.net.au> + (doc/invoke.texi, configure.ac, configure, config.in changes not + yet merged in) + * config/rs6000/rs6000.opt (mtls-markers): Add. + * config/rs6000/rs6000.h (TARGET_TLS_MARKERS): Define. + * config/rs6000/rs6000.md (tls_gd_aix, tls_gd_sysv): Add splitter. + (tls_ld_aix, tls_ld_sysv): Likewise. + (tls_gd, tls_gd_call_aix, tls_gd_call_sysv): New insns. + (tls_ld, tls_ld_call_aix, tls_ld_call_sysv): Likewise. + + 2009-03-31 Ben Elliston <bje@au.ibm.com> + PR target/31635 + * config/rs6000/rs6000.c (rs6000_handle_option): Handle + OPT_mvrsave. + 2010-04-29 Peter Bergner <bergner@vnet.ibm.com> Backport from mainline. diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md index 17c2350cfba..7b99094d738 100644 --- a/gcc/config/rs6000/constraints.md +++ b/gcc/config/rs6000/constraints.md @@ -1,5 +1,5 @@ ;; Constraint definitions for RS6000 -;; Copyright (C) 2006, 2007 Free Software Foundation, Inc. +;; Copyright (C) 2006, 2007, 2009, 2010 Free Software Foundation, Inc. ;; ;; This file is part of GCC. ;; @@ -135,8 +135,17 @@ ;; Memory constraints +(define_memory_constraint "es" + "A ``stable'' memory operand; that is, one which does not include any +automodification of the base register. Unlike @samp{m}, this constraint +can be used in @code{asm} statements that might access the operand +several times, or that might not access it at all." + (and (match_code "mem") + (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC"))) + (define_memory_constraint "Q" - "Memory operand that is just an offset from a reg" + "Memory operand that is an offset from a register (it is usually better +to use @samp{m} or @samp{es} in @code{asm} statements)" (and (match_code "mem") (match_test "GET_CODE (XEXP (op, 0)) == REG"))) @@ -145,7 +154,8 @@ (match_operand 0 "word_offset_memref_operand")) (define_memory_constraint "Z" - "Indexed or indirect memory operand" + "Memory operand that is an indexed or indirect from a register (it is +usually better to use @samp{m} or @samp{es} in @code{asm} statements)" (match_operand 0 "indexed_or_indirect_operand")) ;; Address constraints diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md index 377023b0491..5ffe7fcffc7 100644 --- a/gcc/config/rs6000/dfp.md +++ b/gcc/config/rs6000/dfp.md @@ -1,5 +1,5 @@ ;; Decimal Floating Point (DFP) patterns. -;; Copyright (C) 2007, 2008 +;; Copyright (C) 2007, 2008, 2010 ;; Free Software Foundation, Inc. ;; Contributed by Ben Elliston (bje@au.ibm.com) and Peter Bergner ;; (bergner@vnet.ibm.com). @@ -105,7 +105,7 @@ (define_insn "movsd_store" [(set (match_operand:DD 0 "nonimmediate_operand" "=m") - (unspec:DD [(match_operand:SD 1 "input_operand" "f")] + (unspec:DD [(match_operand:SD 1 "input_operand" "d")] UNSPEC_MOVSD_STORE))] "(gpc_reg_operand (operands[0], DDmode) || gpc_reg_operand (operands[1], SDmode)) @@ -128,15 +128,15 @@ ;; Hardware support for decimal floating point operations. (define_insn "extendsddd2" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") (float_extend:DD (match_operand:SD 1 "gpc_reg_operand" "f")))] "TARGET_DFP" "dctdp %0,%1" [(set_attr "type" "fp")]) (define_expand "extendsdtd2" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (float_extend:TD (match_operand:SD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" { rtx tmp = gen_reg_rtx (DDmode); @@ -147,7 +147,7 @@ (define_insn "truncddsd2" [(set (match_operand:SD 0 "gpc_reg_operand" "=f") - (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "f")))] + (float_truncate:SD (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "drsp %0,%1" [(set_attr "type" "fp")]) @@ -159,8 +159,8 @@ "") (define_insn "*negdd2_fpr" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (neg:DD (match_operand:DD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (neg:DD (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS" "fneg %0,%1" [(set_attr "type" "fp")]) @@ -172,15 +172,15 @@ "") (define_insn "*absdd2_fpr" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (abs:DD (match_operand:DD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS" "fabs %0,%1" [(set_attr "type" "fp")]) (define_insn "*nabsdd2_fpr" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (neg:DD (abs:DD (match_operand:DF 1 "gpc_reg_operand" "f"))))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (neg:DD (abs:DD (match_operand:DD 1 "gpc_reg_operand" "d"))))] "TARGET_HARD_FLOAT && TARGET_FPRS" "fnabs %0,%1" [(set_attr "type" "fp")]) @@ -281,8 +281,8 @@ ;; The "??" is a kludge until we can figure out a more reasonable way ;; of handling these non-offsettable values. (define_insn "*movdd_hardfloat32" - [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,f,f,m,!r,!r,!r") - (match_operand:DD 1 "input_operand" "r,m,r,f,m,f,G,H,F"))] + [(set (match_operand:DD 0 "nonimmediate_operand" "=!r,??r,m,d,d,m,!r,!r,!r") + (match_operand:DD 1 "input_operand" "r,m,r,d,m,d,G,H,F"))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && (gpc_reg_operand (operands[0], DDmode) || gpc_reg_operand (operands[1], DDmode))" @@ -293,71 +293,9 @@ default: gcc_unreachable (); case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register - of operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; case 1: - if (rs6000_offsettable_memref_p (operands[1]) - || (GET_CODE (operands[1]) == MEM - && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM - || GET_CODE (XEXP (operands[1], 0)) == PRE_INC - || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC))) - { - /* If the low-address word is used in the address, we must load - it last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is - known to be dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\"; - } - else - { - rtx addreg; - - addreg = find_addr_reg (XEXP (operands[1], 0)); - if (refers_to_regno_p (REGNO (operands[0]), - REGNO (operands[0]) + 1, - operands[1], 0)) - { - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{lx|lwzx} %L0,%1\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"{lx|lwzx} %0,%1\"; - } - else - { - output_asm_insn (\"{lx|lwzx} %0,%1\", operands); - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{lx|lwzx} %L0,%1\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"\"; - } - } case 2: - if (rs6000_offsettable_memref_p (operands[0]) - || (GET_CODE (operands[0]) == MEM - && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM - || GET_CODE (XEXP (operands[0], 0)) == PRE_INC - || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))) - return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; - else - { - rtx addreg; - - addreg = find_addr_reg (XEXP (operands[0], 0)); - output_asm_insn (\"{stx|stwx} %1,%0\", operands); - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{stx|stwx} %L1,%0\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"\"; - } + return \"#\"; case 3: return \"fmr %0,%1\"; case 4: @@ -379,46 +317,15 @@ "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && (gpc_reg_operand (operands[0], DDmode) || gpc_reg_operand (operands[1], DDmode))" - "* -{ - switch (which_alternative) - { - default: - gcc_unreachable (); - case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; - case 1: - /* If the low-address word is used in the address, we must load - it last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is - known to be dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\"; - case 2: - return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; - case 3: - case 4: - case 5: - return \"#\"; - } -}" + "#" [(set_attr "type" "two,load,store,*,*,*") (set_attr "length" "8,8,8,8,12,16")]) ; ld/std require word-aligned displacements -> 'Y' constraint. ; List Y->r and r->Y before r->r for reload. (define_insn "*movdd_hardfloat64_mfpgpr" - [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r,r,f") - (match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F,f,r"))] + [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r,r,d") + (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F,d,r"))] "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS && (gpc_reg_operand (operands[0], DDmode) || gpc_reg_operand (operands[1], DDmode))" @@ -443,8 +350,8 @@ ; ld/std require word-aligned displacements -> 'Y' constraint. ; List Y->r and r->Y before r->r for reload. (define_insn "*movdd_hardfloat64" - [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r") - (match_operand:DD 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))] + [(set (match_operand:DD 0 "nonimmediate_operand" "=Y,r,!r,d,d,m,*c*l,!r,*h,!r,!r,!r") + (match_operand:DD 1 "input_operand" "r,Y,r,d,m,d,r,h,0,G,H,F"))] "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS && (gpc_reg_operand (operands[0], DDmode) || gpc_reg_operand (operands[1], DDmode))" @@ -490,8 +397,8 @@ "") (define_insn "*negtd2_fpr" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (neg:TD (match_operand:TD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (neg:TD (match_operand:TD 1 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS" "fneg %0,%1" [(set_attr "type" "fp")]) @@ -503,15 +410,15 @@ "") (define_insn "*abstd2_fpr" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (abs:TD (match_operand:TD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS" "fabs %0,%1" [(set_attr "type" "fp")]) (define_insn "*nabstd2_fpr" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (neg:TD (abs:TD (match_operand:DF 1 "gpc_reg_operand" "f"))))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (neg:TD (abs:TD (match_operand:TD 1 "gpc_reg_operand" "d"))))] "TARGET_HARD_FLOAT && TARGET_FPRS" "fnabs %0,%1" [(set_attr "type" "fp")]) @@ -526,8 +433,8 @@ ; otherwise reload, given m->f, will try to pick f->f and reload it, ; which doesn't make progress. Likewise r->Y must be before r->r. (define_insn_and_split "*movtd_internal" - [(set (match_operand:TD 0 "nonimmediate_operand" "=o,f,f,r,Y,r") - (match_operand:TD 1 "input_operand" "f,o,f,YGHF,r,r"))] + [(set (match_operand:TD 0 "nonimmediate_operand" "=o,d,d,r,Y,r") + (match_operand:TD 1 "input_operand" "d,o,d,YGHF,r,r"))] "TARGET_HARD_FLOAT && TARGET_FPRS && (gpc_reg_operand (operands[0], TDmode) || gpc_reg_operand (operands[1], TDmode))" @@ -540,8 +447,8 @@ ;; Hardware support for decimal floating point operations. (define_insn "extendddtd2" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (float_extend:TD (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "dctqpq %0,%1" [(set_attr "type" "fp")]) @@ -552,96 +459,96 @@ ;; that the result is the first of the pair receiving the result of drdpq. (define_insn "trunctddd2" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "f"))) - (clobber (match_scratch:TD 2 "=f"))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (float_truncate:DD (match_operand:TD 1 "gpc_reg_operand" "d"))) + (clobber (match_scratch:TD 2 "=d"))] "TARGET_DFP" "drdpq %2,%1\;fmr %0,%2" [(set_attr "type" "fp")]) (define_insn "adddd3" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%f") - (match_operand:DD 2 "gpc_reg_operand" "f")))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (plus:DD (match_operand:DD 1 "gpc_reg_operand" "%d") + (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dadd %0,%1,%2" [(set_attr "type" "fp")]) (define_insn "addtd3" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%f") - (match_operand:TD 2 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (plus:TD (match_operand:TD 1 "gpc_reg_operand" "%d") + (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "daddq %0,%1,%2" [(set_attr "type" "fp")]) (define_insn "subdd3" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (minus:DD (match_operand:DD 1 "gpc_reg_operand" "f") - (match_operand:DD 2 "gpc_reg_operand" "f")))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (minus:DD (match_operand:DD 1 "gpc_reg_operand" "d") + (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dsub %0,%1,%2" [(set_attr "type" "fp")]) (define_insn "subtd3" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (minus:TD (match_operand:TD 1 "gpc_reg_operand" "f") - (match_operand:TD 2 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (minus:TD (match_operand:TD 1 "gpc_reg_operand" "d") + (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dsubq %0,%1,%2" [(set_attr "type" "fp")]) (define_insn "muldd3" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%f") - (match_operand:DD 2 "gpc_reg_operand" "f")))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (mult:DD (match_operand:DD 1 "gpc_reg_operand" "%d") + (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dmul %0,%1,%2" [(set_attr "type" "fp")]) (define_insn "multd3" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%f") - (match_operand:TD 2 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (mult:TD (match_operand:TD 1 "gpc_reg_operand" "%d") + (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dmulq %0,%1,%2" [(set_attr "type" "fp")]) (define_insn "divdd3" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (div:DD (match_operand:DD 1 "gpc_reg_operand" "f") - (match_operand:DD 2 "gpc_reg_operand" "f")))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (div:DD (match_operand:DD 1 "gpc_reg_operand" "d") + (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "ddiv %0,%1,%2" [(set_attr "type" "fp")]) (define_insn "divtd3" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (div:TD (match_operand:TD 1 "gpc_reg_operand" "f") - (match_operand:TD 2 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (div:TD (match_operand:TD 1 "gpc_reg_operand" "d") + (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "ddivq %0,%1,%2" [(set_attr "type" "fp")]) (define_insn "*cmpdd_internal1" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "f") - (match_operand:DD 2 "gpc_reg_operand" "f")))] + (compare:CCFP (match_operand:DD 1 "gpc_reg_operand" "d") + (match_operand:DD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dcmpu %0,%1,%2" [(set_attr "type" "fpcompare")]) (define_insn "*cmptd_internal1" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "f") - (match_operand:TD 2 "gpc_reg_operand" "f")))] + (compare:CCFP (match_operand:TD 1 "gpc_reg_operand" "d") + (match_operand:TD 2 "gpc_reg_operand" "d")))] "TARGET_DFP" "dcmpuq %0,%1,%2" [(set_attr "type" "fpcompare")]) (define_insn "floatditd2" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (float:TD (match_operand:DI 1 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (float:TD (match_operand:DI 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "dcffixq %0,%1" [(set_attr "type" "fp")]) @@ -650,8 +557,8 @@ ;; This is the first stage of converting it to an integer type. (define_insn "ftruncdd2" - [(set (match_operand:DD 0 "gpc_reg_operand" "=f") - (fix:DD (match_operand:DD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DD 0 "gpc_reg_operand" "=d") + (fix:DD (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "drintn. 0,%0,%1,1" [(set_attr "type" "fp")]) @@ -660,8 +567,8 @@ ;; This is the second stage of converting decimal float to integer type. (define_insn "fixdddi2" - [(set (match_operand:DI 0 "gpc_reg_operand" "=f") - (fix:DI (match_operand:DD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") + (fix:DI (match_operand:DD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "dctfix %0,%1" [(set_attr "type" "fp")]) @@ -670,8 +577,8 @@ ;; This is the first stage of converting it to an integer type. (define_insn "ftrunctd2" - [(set (match_operand:TD 0 "gpc_reg_operand" "=f") - (fix:TD (match_operand:TD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:TD 0 "gpc_reg_operand" "=d") + (fix:TD (match_operand:TD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "drintnq. 0,%0,%1,1" [(set_attr "type" "fp")]) @@ -680,8 +587,8 @@ ;; This is the second stage of converting decimal float to integer type. (define_insn "fixtddi2" - [(set (match_operand:DI 0 "gpc_reg_operand" "=f") - (fix:DI (match_operand:TD 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") + (fix:DI (match_operand:TD 1 "gpc_reg_operand" "d")))] "TARGET_DFP" "dctfixq %0,%1" [(set_attr "type" "fp")]) diff --git a/gcc/config/rs6000/power4.md b/gcc/config/rs6000/power4.md index 7b5b6ea2dbd..60dbffd58c9 100644 --- a/gcc/config/rs6000/power4.md +++ b/gcc/config/rs6000/power4.md @@ -41,21 +41,18 @@ |(du4_power4,lsu1_power4)") (define_reservation "lsuq_power4" - "(du1_power4+du2_power4,lsu1_power4+iu2_power4)\ - |(du2_power4+du3_power4,lsu2_power4+iu2_power4)\ - |(du3_power4+du4_power4,lsu2_power4+iu1_power4)") + "((du1_power4+du2_power4,lsu1_power4)\ + |(du2_power4+du3_power4,lsu2_power4)\ + |(du3_power4+du4_power4,lsu2_power4))\ + +(nothing,iu2_power4|nothing,iu1_power4)") (define_reservation "iq_power4" - "(du1_power4,iu1_power4)\ - |(du2_power4,iu2_power4)\ - |(du3_power4,iu2_power4)\ - |(du4_power4,iu1_power4)") + "(du1_power4|du2_power4|du3_power4|du4_power4),\ + (iu1_power4|iu2_power4)") (define_reservation "fpq_power4" - "(du1_power4,fpu1_power4)\ - |(du2_power4,fpu2_power4)\ - |(du3_power4,fpu2_power4)\ - |(du4_power4,fpu1_power4)") + "(du1_power4|du2_power4|du3_power4|du4_power4),\ + (fpu1_power4|fpu2_power4)") (define_reservation "vq_power4" "(du1_power4,vec_power4)\ @@ -86,9 +83,11 @@ (define_insn_reservation "power4-load-ext" 5 (and (eq_attr "type" "load_ext") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4,lsu1_power4,nothing,nothing,iu2_power4)\ - |(du2_power4+du3_power4,lsu2_power4,nothing,nothing,iu2_power4)\ - |(du3_power4+du4_power4,lsu2_power4,nothing,nothing,iu1_power4)") + "(du1_power4+du2_power4,lsu1_power4\ + |du2_power4+du3_power4,lsu2_power4\ + |du3_power4+du4_power4,lsu2_power4),\ + nothing,nothing,\ + (iu2_power4|iu1_power4)") (define_insn_reservation "power4-load-ext-update" 5 (and (eq_attr "type" "load_ext_u") @@ -131,18 +130,23 @@ (define_insn_reservation "power4-store" 12 (and (eq_attr "type" "store") (eq_attr "cpu" "power4")) - "(du1_power4,lsu1_power4,iu1_power4)\ - |(du2_power4,lsu2_power4,iu2_power4)\ - |(du3_power4,lsu2_power4,iu2_power4)\ - |(du4_power4,lsu1_power4,iu1_power4)") + "((du1_power4,lsu1_power4)\ + |(du2_power4,lsu2_power4)\ + |(du3_power4,lsu2_power4)\ + |(du4_power4,lsu1_power4)),\ + (iu1_power4|iu2_power4)") (define_insn_reservation "power4-store-update" 12 (and (eq_attr "type" "store_u") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4,lsu1_power4+iu2_power4,iu1_power4)\ - |(du2_power4+du3_power4,lsu2_power4+iu2_power4,iu2_power4)\ - |(du3_power4+du4_power4,lsu2_power4+iu1_power4,iu2_power4)\ - |(du3_power4+du4_power4,lsu2_power4,iu1_power4,iu2_power4)") + "((du1_power4+du2_power4,lsu1_power4)\ + |(du2_power4+du3_power4,lsu2_power4)\ + |(du3_power4+du4_power4,lsu2_power4)\ + |(du3_power4+du4_power4,lsu2_power4))+\ + ((nothing,iu2_power4,iu1_power4)\ + |(nothing,iu2_power4,iu2_power4)\ + |(nothing,iu1_power4,iu2_power4)\ + |(nothing,iu1_power4,iu2_power4))") (define_insn_reservation "power4-store-update-indexed" 12 (and (eq_attr "type" "store_ux") @@ -153,17 +157,19 @@ (define_insn_reservation "power4-fpstore" 12 (and (eq_attr "type" "fpstore") (eq_attr "cpu" "power4")) - "(du1_power4,lsu1_power4,fpu1_power4)\ - |(du2_power4,lsu2_power4,fpu2_power4)\ - |(du3_power4,lsu2_power4,fpu2_power4)\ - |(du4_power4,lsu1_power4,fpu1_power4)") + "((du1_power4,lsu1_power4)\ + |(du2_power4,lsu2_power4)\ + |(du3_power4,lsu2_power4)\ + |(du4_power4,lsu1_power4)),\ + (fpu1_power4|fpu2_power4)") (define_insn_reservation "power4-fpstore-update" 12 (and (eq_attr "type" "fpstore_u,fpstore_ux") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4,lsu1_power4+iu2_power4,fpu1_power4)\ - |(du2_power4+du3_power4,lsu2_power4+iu2_power4,fpu2_power4)\ - |(du3_power4+du4_power4,lsu2_power4+iu1_power4,fpu2_power4)") + "((du1_power4+du2_power4,lsu1_power4)\ + |(du2_power4+du3_power4,lsu2_power4)\ + |(du3_power4+du4_power4,lsu2_power4))\ + +(nothing,(iu1_power4|iu2_power4),(fpu1_power4|fpu2_power4))") (define_insn_reservation "power4-vecstore" 12 (and (eq_attr "type" "vecstore") @@ -176,8 +182,7 @@ (define_insn_reservation "power4-llsc" 11 (and (eq_attr "type" "load_l,store_c,sync") (eq_attr "cpu" "power4")) - "du1_power4+du2_power4+du3_power4+du4_power4,\ - lsu1_power4") + "du1_power4+du2_power4+du3_power4+du4_power4,lsu1_power4") ; Integer latency is 2 cycles @@ -190,29 +195,32 @@ (define_insn_reservation "power4-two" 2 (and (eq_attr "type" "two") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4,iu1_power4,nothing,iu2_power4)\ - |(du2_power4+du3_power4,iu2_power4,nothing,iu2_power4)\ - |(du3_power4+du4_power4,iu2_power4,nothing,iu1_power4)\ - |(du4_power4+du1_power4,iu1_power4,nothing,iu1_power4)") + "((du1_power4+du2_power4)\ + |(du2_power4+du3_power4)\ + |(du3_power4+du4_power4)\ + |(du4_power4+du1_power4)),\ + ((iu1_power4,nothing,iu2_power4)\ + |(iu2_power4,nothing,iu2_power4)\ + |(iu2_power4,nothing,iu1_power4)\ + |(iu1_power4,nothing,iu1_power4))") (define_insn_reservation "power4-three" 2 (and (eq_attr "type" "three") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4+du3_power4,\ - iu1_power4,nothing,iu2_power4,nothing,iu2_power4)\ - |(du2_power4+du3_power4+du4_power4,\ - iu2_power4,nothing,iu2_power4,nothing,iu1_power4)\ - |(du3_power4+du4_power4+du1_power4,\ - iu2_power4,nothing,iu1_power4,nothing,iu1_power4)\ - |(du4_power4+du1_power4+du2_power4,\ - iu1_power4,nothing,iu2_power4,nothing,iu2_power4)") + "(du1_power4+du2_power4+du3_power4|du2_power4+du3_power4+du4_power4\ + |du3_power4+du4_power4+du1_power4|du4_power4+du1_power4+du2_power4),\ + ((iu1_power4,nothing,iu2_power4,nothing,iu2_power4)\ + |(iu2_power4,nothing,iu2_power4,nothing,iu1_power4)\ + |(iu2_power4,nothing,iu1_power4,nothing,iu1_power4)\ + |(iu1_power4,nothing,iu2_power4,nothing,iu2_power4))") (define_insn_reservation "power4-insert" 4 (and (eq_attr "type" "insert_word") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4,iu1_power4,nothing,iu2_power4)\ - |(du2_power4+du3_power4,iu2_power4,nothing,iu2_power4)\ - |(du3_power4+du4_power4,iu2_power4,nothing,iu1_power4)") + "(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\ + ((iu1_power4,nothing,iu2_power4)\ + |(iu2_power4,nothing,iu2_power4)\ + |(iu2_power4,nothing,iu1_power4))") (define_insn_reservation "power4-cmp" 3 (and (eq_attr "type" "cmp,fast_compare") @@ -222,53 +230,50 @@ (define_insn_reservation "power4-compare" 2 (and (eq_attr "type" "compare,delayed_compare,var_delayed_compare") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4,iu1_power4,iu2_power4)\ - |(du2_power4+du3_power4,iu2_power4,iu2_power4)\ - |(du3_power4+du4_power4,iu2_power4,iu1_power4)") + "(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\ + ((iu1_power4,iu2_power4)\ + |(iu2_power4,iu2_power4)\ + |(iu2_power4,iu1_power4))") (define_bypass 4 "power4-compare" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf") (define_insn_reservation "power4-lmul-cmp" 7 (and (eq_attr "type" "lmul_compare") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4,iu1_power4*6,iu2_power4)\ - |(du2_power4+du3_power4,iu2_power4*6,iu2_power4)\ - |(du3_power4+du4_power4,iu2_power4*6,iu1_power4)") + "(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\ + ((iu1_power4*6,iu2_power4)\ + |(iu2_power4*6,iu2_power4)\ + |(iu2_power4*6,iu1_power4))") (define_bypass 10 "power4-lmul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf") (define_insn_reservation "power4-imul-cmp" 5 (and (eq_attr "type" "imul_compare") (eq_attr "cpu" "power4")) - "(du1_power4+du2_power4,iu1_power4*4,iu2_power4)\ - |(du2_power4+du3_power4,iu2_power4*4,iu2_power4)\ - |(du3_power4+du4_power4,iu2_power4*4,iu1_power4)") + "(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\ + ((iu1_power4*4,iu2_power4)\ + |(iu2_power4*4,iu2_power4)\ + |(iu2_power4*4,iu1_power4))") (define_bypass 8 "power4-imul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf") (define_insn_reservation "power4-lmul" 7 (and (eq_attr "type" "lmul") (eq_attr "cpu" "power4")) - "(du1_power4,iu1_power4*6)\ - |(du2_power4,iu2_power4*6)\ - |(du3_power4,iu2_power4*6)\ - |(du4_power4,iu1_power4*6)") + "(du1_power4|du2_power4|du3_power4|du4_power4),\ + (iu1_power4*6|iu2_power4*6)") (define_insn_reservation "power4-imul" 5 (and (eq_attr "type" "imul") (eq_attr "cpu" "power4")) - "(du1_power4,iu1_power4*4)\ - |(du2_power4,iu2_power4*4)\ - |(du3_power4,iu2_power4*4)\ - |(du4_power4,iu1_power4*4)") + "(du1_power4|du2_power4|du3_power4|du4_power4),\ + (iu1_power4*4|iu2_power4*4)") (define_insn_reservation "power4-imul3" 4 (and (eq_attr "type" "imul2,imul3") (eq_attr "cpu" "power4")) - "(du1_power4,iu1_power4*3)\ - |(du2_power4,iu2_power4*3)\ - |(du3_power4,iu2_power4*3)\ - |(du4_power4,iu1_power4*3)") + "(du1_power4|du2_power4|du3_power4|du4_power4),\ + (iu1_power4*3|iu2_power4*3)") ; SPR move only executes in first IU. @@ -347,24 +352,19 @@ (define_insn_reservation "power4-sdiv" 33 (and (eq_attr "type" "sdiv,ddiv") (eq_attr "cpu" "power4")) - "(du1_power4,fpu1_power4*28)\ - |(du2_power4,fpu2_power4*28)\ - |(du3_power4,fpu2_power4*28)\ - |(du4_power4,fpu1_power4*28)") + "(du1_power4|du2_power4|du3_power4|du4_power4),\ + (fpu1_power4*28|fpu2_power4*28)") (define_insn_reservation "power4-sqrt" 40 (and (eq_attr "type" "ssqrt,dsqrt") (eq_attr "cpu" "power4")) - "(du1_power4,fpu1_power4*35)\ - |(du2_power4,fpu2_power4*35)\ - |(du3_power4,fpu2_power4*35)\ - |(du4_power4,fpu2_power4*35)") + "(du1_power4|du2_power4|du3_power4|du4_power4),\ + (fpu1_power4*35|fpu2_power4*35)") (define_insn_reservation "power4-isync" 2 (and (eq_attr "type" "isync") (eq_attr "cpu" "power4")) - "du1_power4+du2_power4+du3_power4+du4_power4,\ - lsu1_power4") + "du1_power4+du2_power4+du3_power4+du4_power4,lsu1_power4") ; VMX diff --git a/gcc/config/rs6000/power5.md b/gcc/config/rs6000/power5.md index cc96b2b036b..b6db0931219 100644 --- a/gcc/config/rs6000/power5.md +++ b/gcc/config/rs6000/power5.md @@ -40,16 +40,12 @@ |(du4_power5,lsu1_power5)") (define_reservation "iq_power5" - "(du1_power5,iu1_power5)\ - |(du2_power5,iu2_power5)\ - |(du3_power5,iu2_power5)\ - |(du4_power5,iu1_power5)") + "(du1_power5|du2_power5|du3_power5|du4_power5),\ + (iu1_power5|iu2_power5)") (define_reservation "fpq_power5" - "(du1_power5,fpu1_power5)\ - |(du2_power5,fpu2_power5)\ - |(du3_power5,fpu2_power5)\ - |(du4_power5,fpu1_power5)") + "(du1_power5|du2_power5|du3_power5|du4_power5),\ + (fpu1_power5|fpu2_power5)") ; Dispatch slots are allocated in order conforming to program order. (absence_set "du1_power5" "du2_power5,du3_power5,du4_power5,du5_power5") @@ -105,10 +101,11 @@ (define_insn_reservation "power5-store" 12 (and (eq_attr "type" "store") (eq_attr "cpu" "power5")) - "(du1_power5,lsu1_power5,iu1_power5)\ - |(du2_power5,lsu2_power5,iu2_power5)\ - |(du3_power5,lsu2_power5,iu2_power5)\ - |(du4_power5,lsu1_power5,iu1_power5)") + "((du1_power5,lsu1_power5)\ + |(du2_power5,lsu2_power5)\ + |(du3_power5,lsu2_power5)\ + |(du4_power5,lsu1_power5)),\ + (iu1_power5|iu2_power5)") (define_insn_reservation "power5-store-update" 12 (and (eq_attr "type" "store_u") @@ -124,10 +121,11 @@ (define_insn_reservation "power5-fpstore" 12 (and (eq_attr "type" "fpstore") (eq_attr "cpu" "power5")) - "(du1_power5,lsu1_power5,fpu1_power5)\ - |(du2_power5,lsu2_power5,fpu2_power5)\ - |(du3_power5,lsu2_power5,fpu2_power5)\ - |(du4_power5,lsu1_power5,fpu1_power5)") + "((du1_power5,lsu1_power5)\ + |(du2_power5,lsu2_power5)\ + |(du3_power5,lsu2_power5)\ + |(du4_power5,lsu1_power5)),\ + (fpu1_power5|fpu2_power5)") (define_insn_reservation "power5-fpstore-update" 12 (and (eq_attr "type" "fpstore_u,fpstore_ux") @@ -151,22 +149,24 @@ (define_insn_reservation "power5-two" 2 (and (eq_attr "type" "two") (eq_attr "cpu" "power5")) - "(du1_power5+du2_power5,iu1_power5,nothing,iu2_power5)\ - |(du2_power5+du3_power5,iu2_power5,nothing,iu2_power5)\ - |(du3_power5+du4_power5,iu2_power5,nothing,iu1_power5)\ - |(du4_power5+du1_power5,iu1_power5,nothing,iu1_power5)") + "((du1_power5+du2_power5)\ + |(du2_power5+du3_power5)\ + |(du3_power5+du4_power5)\ + |(du4_power5+du1_power5)),\ + ((iu1_power5,nothing,iu2_power5)\ + |(iu2_power5,nothing,iu2_power5)\ + |(iu2_power5,nothing,iu1_power5)\ + |(iu1_power5,nothing,iu1_power5))") (define_insn_reservation "power5-three" 2 (and (eq_attr "type" "three") (eq_attr "cpu" "power5")) - "(du1_power5+du2_power5+du3_power5,\ - iu1_power5,nothing,iu2_power5,nothing,iu2_power5)\ - |(du2_power5+du3_power5+du4_power5,\ - iu2_power5,nothing,iu2_power5,nothing,iu1_power5)\ - |(du3_power5+du4_power5+du1_power5,\ - iu2_power5,nothing,iu1_power5,nothing,iu1_power5)\ - |(du4_power5+du1_power5+du2_power5,\ - iu1_power5,nothing,iu2_power5,nothing,iu2_power5)") + "(du1_power5+du2_power5+du3_power5|du2_power5+du3_power5+du4_power5\ + |du3_power5+du4_power5+du1_power5|du4_power5+du1_power5+du2_power5),\ + ((iu1_power5,nothing,iu2_power5,nothing,iu2_power5)\ + |(iu2_power5,nothing,iu2_power5,nothing,iu1_power5)\ + |(iu2_power5,nothing,iu1_power5,nothing,iu1_power5)\ + |(iu1_power5,nothing,iu2_power5,nothing,iu2_power5))") (define_insn_reservation "power5-insert" 4 (and (eq_attr "type" "insert_word") @@ -202,26 +202,17 @@ (define_insn_reservation "power5-lmul" 7 (and (eq_attr "type" "lmul") (eq_attr "cpu" "power5")) - "(du1_power5,iu1_power5*6)\ - |(du2_power5,iu2_power5*6)\ - |(du3_power5,iu2_power5*6)\ - |(du4_power5,iu1_power5*6)") + "(du1_power5|du2_power5|du3_power5|du4_power5),(iu1_power5*6|iu2_power5*6)") (define_insn_reservation "power5-imul" 5 (and (eq_attr "type" "imul") (eq_attr "cpu" "power5")) - "(du1_power5,iu1_power5*4)\ - |(du2_power5,iu2_power5*4)\ - |(du3_power5,iu2_power5*4)\ - |(du4_power5,iu1_power5*4)") + "(du1_power5|du2_power5|du3_power5|du4_power5),(iu1_power5*4|iu2_power5*4)") (define_insn_reservation "power5-imul3" 4 (and (eq_attr "type" "imul2,imul3") (eq_attr "cpu" "power5")) - "(du1_power5,iu1_power5*3)\ - |(du2_power5,iu2_power5*3)\ - |(du3_power5,iu2_power5*3)\ - |(du4_power5,iu1_power5*3)") + "(du1_power5|du2_power5|du3_power5|du4_power5),(iu1_power5*3|iu2_power5*3)") ; SPR move only executes in first IU. @@ -300,18 +291,14 @@ (define_insn_reservation "power5-sdiv" 33 (and (eq_attr "type" "sdiv,ddiv") (eq_attr "cpu" "power5")) - "(du1_power5,fpu1_power5*28)\ - |(du2_power5,fpu2_power5*28)\ - |(du3_power5,fpu2_power5*28)\ - |(du4_power5,fpu1_power5*28)") + "(du1_power5|du2_power5|du3_power5|du4_power5),\ + (fpu1_power5*28|fpu2_power5*28)") (define_insn_reservation "power5-sqrt" 40 (and (eq_attr "type" "ssqrt,dsqrt") (eq_attr "cpu" "power5")) - "(du1_power5,fpu1_power5*35)\ - |(du2_power5,fpu2_power5*35)\ - |(du3_power5,fpu2_power5*35)\ - |(du4_power5,fpu2_power5*35)") + "(du1_power5|du2_power5|du3_power5|du4_power5),\ + (fpu1_power5*35|fpu2_power5*35)") (define_insn_reservation "power5-isync" 2 (and (eq_attr "type" "isync") diff --git a/gcc/config/rs6000/ppc-asm.h b/gcc/config/rs6000/ppc-asm.h index d32d1f127f4..c963eb98abb 100644 --- a/gcc/config/rs6000/ppc-asm.h +++ b/gcc/config/rs6000/ppc-asm.h @@ -1,4 +1,28 @@ -/* PowerPC asm definitions for GNU C. */ +/* PowerPC asm definitions for GNU C. + +Copyright (C) 2002, 2003, 2008, 2009 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + /* Under winnt, 1) gas supports the following as names and 2) in particular defining "toc" breaks the FUNC_START macro as ".toc" becomes ".2" */ @@ -328,7 +352,7 @@ GLUE(.L,name): \ #endif #endif -#if defined __linux__ +#if defined __linux__ && !defined __powerpc64__ .section .note.GNU-stack .previous #endif diff --git a/gcc/config/rs6000/ppu_intrinsics.h b/gcc/config/rs6000/ppu_intrinsics.h index 2acb32db963..0950f33aa55 100644 --- a/gcc/config/rs6000/ppu_intrinsics.h +++ b/gcc/config/rs6000/ppu_intrinsics.h @@ -385,11 +385,11 @@ typedef int __V4SI __attribute__((vector_size(16))); #define __mffs() __extension__ \ ({double result; \ - __asm__ volatile ("mffs %0" : "=f" (result)); \ + __asm__ volatile ("mffs %0" : "=d" (result)); \ result; }) #define __mtfsf(mask,value) \ - __asm__ volatile ("mtfsf %0,%1" : : "n" (mask), "f" ((double) (value))) + __asm__ volatile ("mtfsf %0,%1" : : "n" (mask), "d" ((double) (value))) #define __mtfsfi(bits,field) \ __asm__ volatile ("mtfsfi %0,%1" : : "n" (bits), "n" (field)) @@ -400,8 +400,8 @@ typedef int __V4SI __attribute__((vector_size(16))); #define __setflm(v) __extension__ \ ({double result; \ __asm__ volatile ("mffs %0\n\tmtfsf 255,%1" \ - : "=&f" (result) \ - : "f" ((double) (v))); \ + : "=&d" (result) \ + : "d" ((double) (v))); \ result; }) /* __builtin_fabs may perform unnecessary rounding. */ @@ -416,7 +416,7 @@ static __inline__ double __fabs(double x) { double r; - __asm__("fabs %0,%1" : "=f"(r) : "f"(x)); + __asm__("fabs %0,%1" : "=d"(r) : "d"(x)); return r; } @@ -434,7 +434,7 @@ static __inline__ double __fnabs(double x) { double r; - __asm__("fnabs %0,%1" : "=f"(r) : "f"(x)); + __asm__("fnabs %0,%1" : "=d"(r) : "d"(x)); return r; } @@ -453,7 +453,7 @@ static __inline__ double __fmadd(double x, double y, double z) { double r; - __asm__("fmadd %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z)); + __asm__("fmadd %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z)); return r; } @@ -463,7 +463,7 @@ static __inline__ double __fmsub(double x, double y, double z) { double r; - __asm__("fmsub %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z)); + __asm__("fmsub %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z)); return r; } @@ -473,7 +473,7 @@ static __inline__ double __fnmadd(double x, double y, double z) { double r; - __asm__("fnmadd %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z)); + __asm__("fnmadd %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z)); return r; } @@ -483,7 +483,7 @@ static __inline__ double __fnmsub(double x, double y, double z) { double r; - __asm__("fnmsub %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z)); + __asm__("fnmsub %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z)); return r; } @@ -533,7 +533,7 @@ static __inline__ double __fsel(double x, double y, double z) { double r; - __asm__("fsel %0,%1,%2,%3" : "=f"(r) : "f"(x),"f"(y),"f"(z)); + __asm__("fsel %0,%1,%2,%3" : "=d"(r) : "d"(x),"d"(y),"d"(z)); return r; } @@ -552,7 +552,7 @@ static __inline__ double __frsqrte(double x) { double r; - __asm__("frsqrte %0,%1" : "=f" (r) : "f" (x)); + __asm__("frsqrte %0,%1" : "=d" (r) : "d" (x)); return r; } @@ -570,7 +570,7 @@ static __inline__ double __fsqrt(double x) { double r; - __asm__("fsqrt %0,%1" : "=f"(r) : "f"(x)); + __asm__("fsqrt %0,%1" : "=d"(r) : "d"(x)); return r; } @@ -588,7 +588,7 @@ static __inline__ double __fmul(double a, double b) { double d; - __asm__ ("fmul %0,%1,%2" : "=f" (d) : "f" (a), "f" (b)); + __asm__ ("fmul %0,%1,%2" : "=d" (d) : "d" (a), "d" (b)); return d; } @@ -597,7 +597,7 @@ static __inline__ float __fmuls (float a, float b) { float d; - __asm__ ("fmuls %0,%1,%2" : "=f" (d) : "f" (a), "f" (b)); + __asm__ ("fmuls %0,%1,%2" : "=d" (d) : "f" (a), "f" (b)); return d; } @@ -606,7 +606,7 @@ static __inline__ float __frsp (float a) { float d; - __asm__ ("frsp %0,%1" : "=f" (d) : "f" (a)); + __asm__ ("frsp %0,%1" : "=d" (d) : "f" (a)); return d; } @@ -615,7 +615,7 @@ static __inline__ double __fcfid (long long a) { double d; - __asm__ ("fcfid %0,%1" : "=f" (d) : "f" (a)); + __asm__ ("fcfid %0,%1" : "=d" (d) : "d" (a)); return d; } @@ -624,7 +624,7 @@ static __inline__ long long __fctid (double a) { long long d; - __asm__ ("fctid %0,%1" : "=f" (d) : "f" (a)); + __asm__ ("fctid %0,%1" : "=d" (d) : "d" (a)); return d; } @@ -633,7 +633,7 @@ static __inline__ long long __fctidz (double a) { long long d; - __asm__ ("fctidz %0,%1" : "=f" (d) : "f" (a)); + __asm__ ("fctidz %0,%1" : "=d" (d) : "d" (a)); return d; } @@ -642,7 +642,7 @@ static __inline__ int __fctiw (double a) { unsigned long long d; - __asm__ ("fctiw %0,%1" : "=f" (d) : "f" (a)); + __asm__ ("fctiw %0,%1" : "=d" (d) : "d" (a)); return (int) d; } @@ -651,7 +651,7 @@ static __inline__ int __fctiwz (double a) { long long d; - __asm__ ("fctiwz %0,%1" : "=f" (d) : "f" (a)); + __asm__ ("fctiwz %0,%1" : "=d" (d) : "d" (a)); return (int) d; } diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 7d4254caab2..6110e3544a0 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -415,9 +415,7 @@ ;; Return 1 if the operand is an offsettable memory operand. (define_predicate "offsettable_mem_operand" (and (match_operand 0 "memory_operand") - (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC - && GET_CODE (XEXP (op, 0)) != PRE_DEC - && GET_CODE (XEXP (op, 0)) != PRE_MODIFY"))) + (match_test "offsettable_nonstrict_memref_p (op)"))) ;; Return 1 if the operand is a memory operand with an address divisible by 4 (define_predicate "word_offset_memref_operand" @@ -894,6 +892,11 @@ GET_MODE (XEXP (op, 0))), 1")))) +(define_predicate "rs6000_cbranch_operator" + (if_then_else (match_test "TARGET_HARD_FLOAT && !TARGET_FPRS") + (match_operand 0 "ordered_comparison_operator") + (match_operand 0 "comparison_operator"))) + ;; Return 1 if OP is a comparison operation that is valid for an SCC insn -- ;; it must be a positive comparison. (define_predicate "scc_comparison_operator" diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index dce1aea7f45..3936af9a109 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -920,7 +920,7 @@ static void rs6000_elf_encode_section_info (tree, rtx, int) ATTRIBUTE_UNUSED; #endif static bool rs6000_use_blocks_for_constant_p (enum machine_mode, const_rtx); -static void rs6000_expand_to_rtl_hook (void); +static void rs6000_alloc_sdmode_stack_slot (void); static void rs6000_instantiate_decls (void); #if TARGET_XCOFF static void rs6000_xcoff_asm_output_anchor (rtx); @@ -980,6 +980,10 @@ static tree rs6000_builtin_mul_widen_even (tree); static tree rs6000_builtin_mul_widen_odd (tree); static tree rs6000_builtin_conversion (enum tree_code, tree); static tree rs6000_builtin_vec_perm (tree, tree *); +static bool rs6000_builtin_support_vector_misalignment (enum + machine_mode, + const_tree, + int, bool); static void def_builtin (int, const char *, tree, int); static bool rs6000_vector_alignment_reachable (const_tree, bool); @@ -1237,9 +1241,6 @@ static const char alt_reg_names[][8] = #endif #ifndef TARGET_PROFILE_KERNEL #define TARGET_PROFILE_KERNEL 0 -#define SET_PROFILE_KERNEL(N) -#else -#define SET_PROFILE_KERNEL(N) TARGET_PROFILE_KERNEL = (N) #endif /* The VRSAVE bitmask puts bit %v0 as the most significant bit. */ @@ -1348,7 +1349,9 @@ static const char alt_reg_names[][8] = #define TARGET_VECTORIZE_BUILTIN_CONVERSION rs6000_builtin_conversion #undef TARGET_VECTORIZE_BUILTIN_VEC_PERM #define TARGET_VECTORIZE_BUILTIN_VEC_PERM rs6000_builtin_vec_perm - +#undef TARGET_SUPPORT_VECTOR_MISALIGNMENT +#define TARGET_SUPPORT_VECTOR_MISALIGNMENT \ + rs6000_builtin_support_vector_misalignment #undef TARGET_VECTOR_ALIGNMENT_REACHABLE #define TARGET_VECTOR_ALIGNMENT_REACHABLE rs6000_vector_alignment_reachable @@ -1494,7 +1497,7 @@ static const char alt_reg_names[][8] = #define TARGET_BUILTIN_RECIPROCAL rs6000_builtin_reciprocal #undef TARGET_EXPAND_TO_RTL_HOOK -#define TARGET_EXPAND_TO_RTL_HOOK rs6000_expand_to_rtl_hook +#define TARGET_EXPAND_TO_RTL_HOOK rs6000_alloc_sdmode_stack_slot #undef TARGET_INSTANTIATE_DECLS #define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls @@ -2356,8 +2359,7 @@ rs6000_override_options (const char *default_cpu) } } - /* Add some warnings for VSX. Enable -maltivec unless the user explicitly - used -mno-altivec */ + /* Add some warnings for VSX. */ if (TARGET_VSX) { const char *msg = NULL; @@ -2378,14 +2380,20 @@ rs6000_override_options (const char *default_cpu) msg = N_("-mvsx used with little endian code"); else if (TARGET_AVOID_XFORM > 0) msg = N_("-mvsx needs indexed addressing"); + else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC)) + { + if (target_flags_explicit & MASK_VSX) + msg = N_("-mvsx and -mno-altivec are incompatible"); + else + msg = N_("-mno-altivec disables vsx"); + } if (msg) { warning (0, msg); target_flags &= ~ MASK_VSX; } - else if (TARGET_VSX && !TARGET_ALTIVEC - && (target_flags_explicit & MASK_ALTIVEC) == 0) + else if (TARGET_VSX && !TARGET_ALTIVEC) target_flags |= MASK_ALTIVEC; } @@ -2572,7 +2580,8 @@ rs6000_override_options (const char *default_cpu) else if (! strcmp (rs6000_sched_costly_dep_str, "store_to_load")) rs6000_sched_costly_dep = store_to_load_dep_costly; else - rs6000_sched_costly_dep = atoi (rs6000_sched_costly_dep_str); + rs6000_sched_costly_dep = ((enum rs6000_dependence_cost) + atoi (rs6000_sched_costly_dep_str)); } /* Handle -minsert-sched-nops option. */ @@ -2588,7 +2597,8 @@ rs6000_override_options (const char *default_cpu) else if (! strcmp (rs6000_sched_insert_nops_str, "regroup_exact")) rs6000_sched_insert_nops = sched_finish_regroup_exact; else - rs6000_sched_insert_nops = atoi (rs6000_sched_insert_nops_str); + rs6000_sched_insert_nops = ((enum rs6000_nop_insertion) + atoi (rs6000_sched_insert_nops_str)); } #ifdef TARGET_REGNAMES @@ -2953,6 +2963,36 @@ rs6000_vector_alignment_reachable (const_tree type ATTRIBUTE_UNUSED, bool is_pac } } +/* Return true if the vector misalignment factor is supported by the + target. */ +bool +rs6000_builtin_support_vector_misalignment (enum machine_mode mode, + const_tree type, + int misalignment, + bool is_packed) +{ + if (TARGET_VSX) + { + /* Return if movmisalign pattern is not supported for this mode. */ + if (optab_handler (movmisalign_optab, mode)->insn_code == + CODE_FOR_nothing) + return false; + + if (misalignment == -1) + { + /* misalignment factor is unknown at compile time but we know + it's word aligned. */ + if (rs6000_vector_alignment_reachable (type, is_packed)) + return true; + return false; + } + /* VSX supports word-aligned vector. */ + if (misalignment % 4 == 0) + return true; + } + return false; +} + /* Implement targetm.vectorize.builtin_vec_perm. */ tree rs6000_builtin_vec_perm (tree type, tree *mask_element_type) @@ -3312,6 +3352,11 @@ rs6000_handle_option (size_t code, const char *arg, int value) rs6000_explicit_options.aix_struct_ret = true; break; + case OPT_mvrsave: + rs6000_explicit_options.vrsave = true; + TARGET_ALTIVEC_VRSAVE = value; + break; + case OPT_mvrsave_: rs6000_explicit_options.vrsave = true; rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE)); @@ -4552,6 +4597,9 @@ darwin_rs6000_special_round_type_align (tree type, unsigned int computed, field = TREE_CHAIN (field); if (! field) break; + /* A packed field does not contribute any extra alignment. */ + if (DECL_PACKED (field)) + return align; type = TREE_TYPE (field); while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); @@ -4950,6 +4998,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, if (model != 0) return rs6000_legitimize_tls_address (x, model); } + switch (mode) { case DFmode: @@ -5790,7 +5839,15 @@ rs6000_mode_dependent_address (rtx addr) switch (GET_CODE (addr)) { case PLUS: - if (GET_CODE (XEXP (addr, 1)) == CONST_INT) + /* Any offset from virtual_stack_vars_rtx and arg_pointer_rtx + is considered a legitimate address before reload, so there + are no offset restrictions in that case. Note that this + condition is safe in strict mode because any address involving + virtual_stack_vars_rtx or arg_pointer_rtx would already have + been rejected as illegitimate. */ + if (XEXP (addr, 0) != virtual_stack_vars_rtx + && XEXP (addr, 0) != arg_pointer_rtx + && GET_CODE (XEXP (addr, 1)) == CONST_INT) { unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1)); return val + 12 + 0x8000 >= 0x10000; @@ -6504,14 +6561,6 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) && ! legitimate_constant_pool_address_p (operands[1]) && ! toc_relative_expr_p (operands[1])) { - /* Emit a USE operation so that the constant isn't deleted if - expensive optimizations are turned on because nobody - references it. This should only be done for operands that - contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set. - This should not be done for operands that contain LABEL_REFs. - For now, we just handle the obvious case. */ - if (GET_CODE (operands[1]) != LABEL_REF) - emit_use (operands[1]); #if TARGET_MACHO /* Darwin uses a special PIC legitimizer. */ @@ -10151,8 +10200,8 @@ altivec_expand_vec_set_builtin (tree exp) mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))); gcc_assert (VECTOR_MODE_P (tmode)); - op0 = expand_expr (arg0, NULL_RTX, tmode, 0); - op1 = expand_expr (arg1, NULL_RTX, mode1, 0); + op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL); + op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL); elt = get_element_number (TREE_TYPE (arg0), arg2); if (GET_MODE (op1) != mode1 && GET_MODE (op1) != VOIDmode) @@ -13101,6 +13150,7 @@ rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) case PARM_DECL: case FIELD_DECL: case RESULT_DECL: + case SSA_NAME: case REAL_CST: case INDIRECT_REF: case ALIGN_INDIRECT_REF: @@ -13556,13 +13606,11 @@ rs6000_ira_cover_classes (void) return (TARGET_VSX) ? cover_vsx : cover_pre_vsx; } -/* Scan the trees looking for certain types. - - Allocate a 64-bit stack slot to be used for copying SDmode values through if - this function has any SDmode references. */ +/* Allocate a 64-bit stack slot to be used for copying SDmode + values through if this function has any SDmode references. */ static void -rs6000_expand_to_rtl_hook (void) +rs6000_alloc_sdmode_stack_slot (void) { tree t; basic_block bb; @@ -13570,7 +13618,6 @@ rs6000_expand_to_rtl_hook (void) gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX); - /* Check for SDmode being used. */ FOR_EACH_BB (bb) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { @@ -16553,6 +16600,7 @@ rs6000_split_multireg_move (rtx dst, rtx src) int i; int j = -1; bool used_update = false; + rtx restore_basereg = NULL_RTX; if (MEM_P (src) && INT_REGNO_P (reg)) { @@ -16571,10 +16619,27 @@ rs6000_split_multireg_move (rtx dst, rtx src) } else if (! rs6000_offsettable_memref_p (src)) { - rtx basereg; - basereg = gen_rtx_REG (Pmode, reg); - emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0))); - src = replace_equiv_address (src, basereg); + if (GET_CODE (XEXP (src, 0)) == PRE_MODIFY) + { + rtx basereg = XEXP (XEXP (src, 0), 0); + if (TARGET_UPDATE) + { + rtx ndst = simplify_gen_subreg (reg_mode, dst, mode, 0); + emit_insn (gen_rtx_SET (VOIDmode, ndst, + gen_rtx_MEM (reg_mode, XEXP (src, 0)))); + used_update = true; + } + else + emit_insn (gen_rtx_SET (VOIDmode, basereg, + XEXP (XEXP (src, 0), 1))); + src = replace_equiv_address (src, basereg); + } + else + { + rtx basereg = gen_rtx_REG (Pmode, reg); + emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0))); + src = replace_equiv_address (src, basereg); + } } breg = XEXP (src, 0); @@ -16588,8 +16653,7 @@ rs6000_split_multireg_move (rtx dst, rtx src) && REGNO (breg) < REGNO (dst) + nregs) j = REGNO (breg) - REGNO (dst); } - - if (GET_CODE (dst) == MEM && INT_REGNO_P (reg)) + else if (MEM_P (dst) && INT_REGNO_P (reg)) { rtx breg; @@ -16619,7 +16683,44 @@ rs6000_split_multireg_move (rtx dst, rtx src) emit_insn (gen_add3_insn (breg, breg, delta_rtx)); dst = replace_equiv_address (dst, breg); } - else + else if (!rs6000_offsettable_memref_p (dst) + && GET_CODE (XEXP (dst, 0)) != LO_SUM) + { + if (GET_CODE (XEXP (dst, 0)) == PRE_MODIFY) + { + rtx basereg = XEXP (XEXP (dst, 0), 0); + if (TARGET_UPDATE) + { + rtx nsrc = simplify_gen_subreg (reg_mode, src, mode, 0); + emit_insn (gen_rtx_SET (VOIDmode, + gen_rtx_MEM (reg_mode, XEXP (dst, 0)), nsrc)); + used_update = true; + } + else + emit_insn (gen_rtx_SET (VOIDmode, basereg, + XEXP (XEXP (dst, 0), 1))); + dst = replace_equiv_address (dst, basereg); + } + else + { + rtx basereg = XEXP (XEXP (dst, 0), 0); + rtx offsetreg = XEXP (XEXP (dst, 0), 1); + gcc_assert (GET_CODE (XEXP (dst, 0)) == PLUS + && REG_P (basereg) + && REG_P (offsetreg) + && REGNO (basereg) != REGNO (offsetreg)); + if (REGNO (basereg) == 0) + { + rtx tmp = offsetreg; + offsetreg = basereg; + basereg = tmp; + } + emit_insn (gen_add3_insn (basereg, basereg, offsetreg)); + restore_basereg = gen_sub3_insn (basereg, basereg, offsetreg); + dst = replace_equiv_address (dst, basereg); + } + } + else if (GET_CODE (XEXP (dst, 0)) != LO_SUM) gcc_assert (rs6000_offsettable_memref_p (dst)); } @@ -16641,6 +16742,8 @@ rs6000_split_multireg_move (rtx dst, rtx src) simplify_gen_subreg (reg_mode, src, mode, j * reg_mode_size))); } + if (restore_basereg != NULL_RTX) + emit_insn (restore_basereg); } } @@ -20622,7 +20725,7 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode) h->key_mode = mode; h->labelno = labelno; - found = htab_find_slot (toc_hash_table, h, 1); + found = htab_find_slot (toc_hash_table, h, INSERT); if (*found == NULL) *found = h; else /* This is indeed a duplicate. @@ -21044,7 +21147,8 @@ output_profile_hook (int labelno ATTRIBUTE_UNUSED) # define NO_PROFILE_COUNTERS 0 #endif if (NO_PROFILE_COUNTERS) - emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 0); + emit_library_call (init_one_libfunc (RS6000_MCOUNT), + LCT_NORMAL, VOIDmode, 0); else { char buf[30]; @@ -21055,8 +21159,8 @@ output_profile_hook (int labelno ATTRIBUTE_UNUSED) label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf)); fun = gen_rtx_SYMBOL_REF (Pmode, label_name); - emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 1, - fun, Pmode); + emit_library_call (init_one_libfunc (RS6000_MCOUNT), + LCT_NORMAL, VOIDmode, 1, fun, Pmode); } } else if (DEFAULT_ABI == ABI_DARWIN) @@ -21075,7 +21179,7 @@ output_profile_hook (int labelno ATTRIBUTE_UNUSED) caller_addr_regno = 0; #endif emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mcount_name), - 0, VOIDmode, 1, + LCT_NORMAL, VOIDmode, 1, gen_rtx_REG (Pmode, caller_addr_regno), Pmode); } } @@ -21204,9 +21308,7 @@ static int load_store_pendulum; instructions to issue in this cycle. */ static int -rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED, - int verbose ATTRIBUTE_UNUSED, - rtx insn, int more) +rs6000_variable_issue_1 (rtx insn, int more) { last_scheduled_insn = insn; if (GET_CODE (PATTERN (insn)) == USE @@ -21245,6 +21347,15 @@ rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED, return cached_can_issue_more; } +static int +rs6000_variable_issue (FILE *stream, int verbose, rtx insn, int more) +{ + int r = rs6000_variable_issue_1 (insn, more); + if (verbose) + fprintf (stream, "// rs6000_variable_issue (more = %d) = %d\n", more, r); + return r; +} + /* Adjust the cost of a scheduling dependency. Return the new cost of a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ @@ -23983,15 +24094,6 @@ rs6000_elf_asm_out_destructor (rtx symbol, int priority) assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); } -#ifdef HAVE_LD_OVERLAPPING_OPD -/* If the linker supports overlapping .opd entries and we know this function - doesn't ever use r11 passed to it, we can overlap the fd_aux function - descriptor field with next function descriptor's fd_func field. */ -# define OVERLAPPING_OPD (cfun->static_chain_decl == NULL) -#else -# define OVERLAPPING_OPD 0 -#endif - void rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl) { @@ -24001,8 +24103,7 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl) ASM_OUTPUT_LABEL (file, name); fputs (DOUBLE_INT_ASM_OP, file); rs6000_output_function_entry (file, name); - fprintf (file, ",.TOC.@tocbase%s\n\t.previous\n", - OVERLAPPING_OPD ? "" : ",0"); + fputs (",.TOC.@tocbase,0\n\t.previous\n", file); if (DOT_SYMBOLS) { fputs ("\t.size\t", file); @@ -24074,13 +24175,6 @@ rs6000_elf_end_indicate_exec_stack (void) { if (TARGET_32BIT) file_end_indicate_exec_stack (); - else - { - int saved_trampolines_created = trampolines_created; - trampolines_created = 0; - file_end_indicate_exec_stack (); - trampolines_created = saved_trampolines_created; - } } #endif @@ -25411,7 +25505,7 @@ rs6000_init_dwarf_reg_sizes_extra (tree address) { int i; enum machine_mode mode = TYPE_MODE (char_type_node); - rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0); + rtx addr = expand_expr (address, NULL_RTX, VOIDmode, EXPAND_NORMAL); rtx mem = gen_rtx_MEM (BLKmode, addr); rtx value = gen_int_mode (4, mode); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 035efc03ebf..6a005f68cac 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -279,6 +279,15 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define TARGET_LWSYNC_INSTRUCTION 0 #endif +/* Define TARGET_TLS_MARKERS if the target assembler does not support + arg markers for __tls_get_addr calls. */ +#ifndef HAVE_AS_TLS_MARKERS +#undef TARGET_TLS_MARKERS +#define TARGET_TLS_MARKERS 0 +#else +#define TARGET_TLS_MARKERS tls_markers +#endif + #ifndef TARGET_SECURE_PLT #define TARGET_SECURE_PLT 0 #endif @@ -707,14 +716,7 @@ extern unsigned rs6000_pointer_size; local store. TYPE is the data type, and ALIGN is the alignment that the object would ordinarily have. */ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \ - (((TARGET_ALTIVEC || TARGET_VSX) \ - && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \ - (TARGET_E500_DOUBLE \ - && TYPE_MODE (TYPE) == DFmode) ? 64 : \ - ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \ - && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \ - && TREE_CODE (TYPE) == VECTOR_TYPE \ - && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN) + DATA_ALIGNMENT (TYPE, ALIGN) /* Alignment of field after `int : 0' in a structure. */ #define EMPTY_FIELD_BOUNDARY 32 @@ -753,14 +755,18 @@ extern unsigned rs6000_pointer_size; /* Make arrays of chars word-aligned for the same reasons. Align vectors to 128 bits. Align SPE vectors and E500 v2 doubles to 64 bits. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == VECTOR_TYPE ? ((TARGET_SPE_ABI \ - || TARGET_PAIRED_FLOAT) ? 64 : 128) \ - : (TARGET_E500_DOUBLE \ - && TYPE_MODE (TYPE) == DFmode) ? 64 \ - : TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + (TREE_CODE (TYPE) == VECTOR_TYPE \ + ? (((TARGET_SPE && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) \ + || (TARGET_PAIRED_FLOAT && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) \ + ? 64 : 128) \ + : ((TARGET_E500_DOUBLE \ + && TREE_CODE (TYPE) == REAL_TYPE \ + && TYPE_MODE (TYPE) == DFmode) \ + ? 64 \ + : (TREE_CODE (TYPE) == ARRAY_TYPE \ + && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ + && (ALIGN) < BITS_PER_WORD) ? BITS_PER_WORD : (ALIGN))) /* Nonzero if move instructions will actually fail to work when given unaligned data. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 155ae1742b6..d8bb2ee8974 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -1,6 +1,6 @@ ;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler ;; Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, -;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 ;; Free Software Foundation, Inc. ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) @@ -55,6 +55,7 @@ (define_constants [(UNSPEC_FRSP 0) ; frsp for POWER machines + (UNSPEC_PROBE_STACK 4) ; probe stack memory reference (UNSPEC_TIE 5) ; tie stack contents and stack pointer (UNSPEC_TOCPTR 6) ; address of a word pointing to the TOC (UNSPEC_TOC 7) ; address of the TOC (more-or-less) @@ -215,6 +216,9 @@ (DD "TARGET_DFP") (TD "TARGET_DFP")]) +; These modes do not fit in integer registers in 32-bit mode. +(define_mode_iterator DIFD [DI DF DD]) + ; Various instructions that come in SI and DI forms. ; A generic w/d attribute, for things like cmpw/cmpd. (define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")]) @@ -5577,7 +5581,7 @@ "") (define_insn_and_split "*extendsfdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f,f") + [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d") (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "@ @@ -5600,7 +5604,7 @@ (define_insn "*truncdfsf2_fpr" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "f")))] + (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "frsp %0,%1" [(set_attr "type" "fp")]) @@ -5807,7 +5811,7 @@ (match_operand:SF 2 "gpc_reg_operand" "f")) (match_operand:SF 3 "gpc_reg_operand" "f"))))] "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD - && TARGET_SINGLE_FLOAT && HONOR_SIGNED_ZEROS (SFmode)" + && TARGET_SINGLE_FLOAT" "fnmadds %0,%1,%2,%3" [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) @@ -5848,7 +5852,7 @@ (match_operand:SF 2 "gpc_reg_operand" "f")) (match_operand:SF 3 "gpc_reg_operand" "f"))))] "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD - && TARGET_SINGLE_FLOAT && HONOR_SIGNED_ZEROS (SFmode)" + && TARGET_SINGLE_FLOAT" "fnmsubs %0,%1,%2,%3" [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) @@ -6085,7 +6089,7 @@ (define_insn "*fseldfsf4" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "f") + (if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "d") (match_operand:DF 4 "zero_fp_constant" "F")) (match_operand:SF 2 "gpc_reg_operand" "f") (match_operand:SF 3 "gpc_reg_operand" "f")))] @@ -6100,8 +6104,8 @@ "") (define_insn "*negdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "fneg %0,%1" @@ -6114,16 +6118,16 @@ "") (define_insn "*absdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "fabs %0,%1" [(set_attr "type" "fp")]) (define_insn "*nabsdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f"))))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d"))))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "fnabs %0,%1" @@ -6137,9 +6141,9 @@ "") (define_insn "*adddf3_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f") - (match_operand:DF 2 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%d") + (match_operand:DF 2 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "{fa|fadd} %0,%1,%2" @@ -6154,9 +6158,9 @@ "") (define_insn "*subdf3_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (minus:DF (match_operand:DF 1 "gpc_reg_operand" "f") - (match_operand:DF 2 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (minus:DF (match_operand:DF 1 "gpc_reg_operand" "d") + (match_operand:DF 2 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "{fs|fsub} %0,%1,%2" @@ -6171,9 +6175,9 @@ "") (define_insn "*muldf3_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f") - (match_operand:DF 2 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d") + (match_operand:DF 2 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "{fm|fmul} %0,%1,%2" @@ -6190,18 +6194,18 @@ "") (define_insn "*divdf3_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (div:DF (match_operand:DF 1 "gpc_reg_operand" "f") - (match_operand:DF 2 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (div:DF (match_operand:DF 1 "gpc_reg_operand" "d") + (match_operand:DF 2 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU && !VECTOR_UNIT_VSX_P (DFmode)" "{fd|fdiv} %0,%1,%2" [(set_attr "type" "ddiv")]) (define_expand "recipdf3" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f") - (match_operand:DF 2 "gpc_reg_operand" "f")] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d") + (match_operand:DF 2 "gpc_reg_operand" "d")] UNSPEC_FRES))] "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_POPCNTB && !optimize_size && flag_finite_math_only && !flag_trapping_math" @@ -6211,8 +6215,8 @@ }) (define_expand "fred" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRES))] "(TARGET_POPCNTB || VECTOR_UNIT_VSX_P (DFmode)) && flag_finite_math_only" "") @@ -6224,10 +6228,10 @@ [(set_attr "type" "fp")]) (define_insn "*fmadddf4_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f") - (match_operand:DF 2 "gpc_reg_operand" "f")) - (match_operand:DF 3 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d") + (match_operand:DF 2 "gpc_reg_operand" "d")) + (match_operand:DF 3 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT && VECTOR_UNIT_NONE_P (DFmode)" "{fma|fmadd} %0,%1,%2,%3" @@ -6235,10 +6239,10 @@ (set_attr "fp_type" "fp_maddsub_d")]) (define_insn "*fmsubdf4_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f") - (match_operand:DF 2 "gpc_reg_operand" "f")) - (match_operand:DF 3 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d") + (match_operand:DF 2 "gpc_reg_operand" "d")) + (match_operand:DF 3 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT && VECTOR_UNIT_NONE_P (DFmode)" "{fms|fmsub} %0,%1,%2,%3" @@ -6246,21 +6250,21 @@ (set_attr "fp_type" "fp_maddsub_d")]) (define_insn "*fnmadddf4_fpr_1" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f") - (match_operand:DF 2 "gpc_reg_operand" "f")) - (match_operand:DF 3 "gpc_reg_operand" "f"))))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d") + (match_operand:DF 2 "gpc_reg_operand" "d")) + (match_operand:DF 3 "gpc_reg_operand" "d"))))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT - && HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)" + && VECTOR_UNIT_NONE_P (DFmode)" "{fnma|fnmadd} %0,%1,%2,%3" [(set_attr "type" "dmul") (set_attr "fp_type" "fp_maddsub_d")]) (define_insn "*fnmadddf4_fpr_2" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")) - (match_operand:DF 2 "gpc_reg_operand" "f")) - (match_operand:DF 3 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d")) + (match_operand:DF 2 "gpc_reg_operand" "d")) + (match_operand:DF 3 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT && ! HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)" "{fnma|fnmadd} %0,%1,%2,%3" @@ -6268,21 +6272,21 @@ (set_attr "fp_type" "fp_maddsub_d")]) (define_insn "*fnmsubdf4_fpr_1" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f") - (match_operand:DF 2 "gpc_reg_operand" "f")) - (match_operand:DF 3 "gpc_reg_operand" "f"))))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d") + (match_operand:DF 2 "gpc_reg_operand" "d")) + (match_operand:DF 3 "gpc_reg_operand" "d"))))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT - && HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)" + && VECTOR_UNIT_NONE_P (DFmode)" "{fnms|fnmsub} %0,%1,%2,%3" [(set_attr "type" "dmul") (set_attr "fp_type" "fp_maddsub_d")]) (define_insn "*fnmsubdf4_fpr_2" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (minus:DF (match_operand:DF 3 "gpc_reg_operand" "f") - (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f") - (match_operand:DF 2 "gpc_reg_operand" "f"))))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (minus:DF (match_operand:DF 3 "gpc_reg_operand" "d") + (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d") + (match_operand:DF 2 "gpc_reg_operand" "d"))))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD && TARGET_DOUBLE_FLOAT && ! HONOR_SIGNED_ZEROS (DFmode) && VECTOR_UNIT_NONE_P (DFmode)" "{fnms|fnmsub} %0,%1,%2,%3" @@ -6297,8 +6301,8 @@ "") (define_insn "*sqrtdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "d")))] "(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" @@ -6357,21 +6361,21 @@ }") (define_insn "*fseldfdf4" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "f") + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "d") (match_operand:DF 4 "zero_fp_constant" "F")) - (match_operand:DF 2 "gpc_reg_operand" "f") - (match_operand:DF 3 "gpc_reg_operand" "f")))] + (match_operand:DF 2 "gpc_reg_operand" "d") + (match_operand:DF 3 "gpc_reg_operand" "d")))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "fsel %0,%1,%2,%3" [(set_attr "type" "fp")]) (define_insn "*fselsfdf4" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") (if_then_else:DF (ge (match_operand:SF 1 "gpc_reg_operand" "f") (match_operand:SF 4 "zero_fp_constant" "F")) - (match_operand:DF 2 "gpc_reg_operand" "f") - (match_operand:DF 3 "gpc_reg_operand" "f")))] + (match_operand:DF 2 "gpc_reg_operand" "d") + (match_operand:DF 3 "gpc_reg_operand" "d")))] "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_SINGLE_FLOAT" "fsel %0,%1,%2,%3" [(set_attr "type" "fp")]) @@ -6439,16 +6443,16 @@ }") (define_insn_and_split "*floatsidf2_internal" - [(set (match_operand:DF 0 "gpc_reg_operand" "=&f") + [(set (match_operand:DF 0 "gpc_reg_operand" "=&d") (float:DF (match_operand:SI 1 "gpc_reg_operand" "r"))) (use (match_operand:SI 2 "gpc_reg_operand" "r")) - (use (match_operand:DF 3 "gpc_reg_operand" "f")) + (use (match_operand:DF 3 "gpc_reg_operand" "d")) (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o")) - (clobber (match_operand:DF 5 "gpc_reg_operand" "=&f")) + (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d")) (clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "#" - "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[4]))" + "" [(pc)] " { @@ -6507,15 +6511,15 @@ }") (define_insn_and_split "*floatunssidf2_internal" - [(set (match_operand:DF 0 "gpc_reg_operand" "=&f") + [(set (match_operand:DF 0 "gpc_reg_operand" "=&d") (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r"))) (use (match_operand:SI 2 "gpc_reg_operand" "r")) - (use (match_operand:DF 3 "gpc_reg_operand" "f")) + (use (match_operand:DF 3 "gpc_reg_operand" "d")) (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o")) - (clobber (match_operand:DF 5 "gpc_reg_operand" "=&f"))] + (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d"))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "#" - "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[4]))" + "" [(pc)] " { @@ -6576,13 +6580,13 @@ (define_insn_and_split "*fix_truncdfsi2_internal" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "=f")) + (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))) + (clobber (match_operand:DI 2 "gpc_reg_operand" "=d")) (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o"))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "#" - "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[3]))" + "" [(pc)] " { @@ -6599,8 +6603,8 @@ (define_insn_and_split "fix_truncdfsi2_internal_gfxopt" [(set (match_operand:SI 0 "memory_operand" "=Z") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))] + (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))) + (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_PPC_GFXOPT" @@ -6617,8 +6621,8 @@ (define_insn_and_split "fix_truncdfsi2_mfpgpr" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "=f")) + (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))) + (clobber (match_operand:DI 2 "gpc_reg_operand" "=d")) (clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))] "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" @@ -6635,8 +6639,8 @@ ; because the first makes it clear that operand 0 is not live ; before the instruction. (define_insn "fctiwz" - [(set (match_operand:DI 0 "gpc_reg_operand" "=f") - (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))] + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") + (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))] UNSPEC_FCTIWZ))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" @@ -6644,8 +6648,8 @@ [(set_attr "type" "fp")]) (define_expand "btruncdf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIZ))] "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "") @@ -6671,8 +6675,8 @@ "") (define_insn "*ceildf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIP))] "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "frip %0,%1" @@ -6692,8 +6696,8 @@ "") (define_insn "*floordf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIM))] "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "frim %0,%1" @@ -6708,8 +6712,8 @@ ;; No VSX equivalent to frin (define_insn "rounddf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIN))] "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "frin %0,%1" [(set_attr "type" "fp")]) @@ -6730,7 +6734,7 @@ ; An UNSPEC is used so we don't have to support SImode in FP registers. (define_insn "stfiwx" [(set (match_operand:SI 0 "memory_operand" "=Z") - (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "f")] + (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "d")] UNSPEC_STFIWX))] "TARGET_PPC_GFXOPT" "stfiwx %1,%y0" @@ -6750,8 +6754,8 @@ "") (define_insn "*floatdidf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (float:DF (match_operand:DI 1 "gpc_reg_operand" "!f#r")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (float:DF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))] "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS && !VECTOR_UNIT_VSX_P (DFmode)" @@ -6772,10 +6776,11 @@ "") (define_insn "*fix_truncdfdi2_fpr" - [(set (match_operand:DI 0 "gpc_reg_operand" "=!f#r") - (fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))] - "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT - && TARGET_DOUBLE_FLOAT && TARGET_FPRS && !VECTOR_UNIT_VSX_P (DFmode)" + [(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r") + (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))] + "(TARGET_POWERPC64 || TARGET_XILINX_FPU) + && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS + && !VECTOR_UNIT_VSX_P (DFmode)" "fctidz %0,%1" [(set_attr "type" "fp")]) @@ -6802,8 +6807,8 @@ ;; from double rounding. (define_insn_and_split "floatdisf2_internal1" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (float:SF (match_operand:DI 1 "gpc_reg_operand" "!f#r"))) - (clobber (match_scratch:DF 2 "=f"))] + (float:SF (match_operand:DI 1 "gpc_reg_operand" "!d#r"))) + (clobber (match_scratch:DF 2 "=d"))] "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" "#" "&& reload_completed" @@ -7220,7 +7225,7 @@ [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r") (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))) (clobber (match_scratch:DI 2 "=&r,&r"))] - "TARGET_POWERPC64" + "TARGET_POWERPC64 && !TARGET_ISEL" "#" "&& reload_completed" [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63))) @@ -8747,8 +8752,8 @@ (define_insn "*movsi_internal1" [(set (match_operand:SI 0 "rs6000_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)" + "!TARGET_SINGLE_FPU && + (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))" "@ mr %0,%1 {cal|la} %0,%a1 @@ -8766,6 +8771,30 @@ [(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*") (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")]) +(define_insn "*movsi_internal1_single" + [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h,m,*f") + (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0,f,m"))] + "TARGET_SINGLE_FPU && + (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))" + "@ + mr %0,%1 + {cal|la} %0,%a1 + {l%U1%X1|lwz%U1%X1} %0,%1 + {st%U0%X0|stw%U0%X0} %1,%0 + {lil|li} %0,%1 + {liu|lis} %0,%v1 + # + {cal|la} %0,%a1 + mf%1 %0 + mt%0 %1 + mt%0 %1 + mt%0 %1 + {cror 0,0,0|nop} + stfs%U0%X0 %1, %0 + lfs%U1%X1 %0, %1" + [(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*,*,*") + (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4,4,4")]) + ;; Split a load of a large constant into the appropriate two-insn ;; sequence. @@ -9077,8 +9106,8 @@ ;; The "??" is a kludge until we can figure out a more reasonable way ;; of handling these non-offsettable values. (define_insn "*movdf_hardfloat32" - [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,ws,?wa,ws,?wa,Z,?Z,f,f,m,wa,!r,!r,!r") - (match_operand:DF 1 "input_operand" "r,m,r,ws,wa,Z,Z,ws,wa,f,m,f,j,G,H,F"))] + [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,ws,?wa,ws,?wa,Z,?Z,d,d,m,wa,!r,!r,!r") + (match_operand:DF 1 "input_operand" "r,m,r,ws,wa,Z,Z,ws,wa,d,m,d,j,G,H,F"))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && (gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode))" @@ -9089,73 +9118,9 @@ default: gcc_unreachable (); case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register - of operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; case 1: - if (rs6000_offsettable_memref_p (operands[1]) - || (GET_CODE (operands[1]) == MEM - && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM - || GET_CODE (XEXP (operands[1], 0)) == PRE_INC - || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC - || GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY))) - { - /* If the low-address word is used in the address, we must load - it last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is - known to be dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\"; - } - else - { - rtx addreg; - - addreg = find_addr_reg (XEXP (operands[1], 0)); - if (refers_to_regno_p (REGNO (operands[0]), - REGNO (operands[0]) + 1, - operands[1], 0)) - { - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"{l%X1|lwz%X1} %0,%1\"; - } - else - { - output_asm_insn (\"{l%X1|lwz%X1} %0,%1\", operands); - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"\"; - } - } case 2: - if (rs6000_offsettable_memref_p (operands[0]) - || (GET_CODE (operands[0]) == MEM - && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM - || GET_CODE (XEXP (operands[0], 0)) == PRE_INC - || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC - || GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY))) - return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\"; - else - { - rtx addreg; - - addreg = find_addr_reg (XEXP (operands[0], 0)); - output_asm_insn (\"{st%X0|stw%X0} %1,%0\", operands); - output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); - output_asm_insn (\"{st%X0|stw%X0} %L1,%0\", operands); - output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); - return \"\"; - } + return \"#\"; case 3: case 4: return \"xxlor %x0,%x1,%x1\"; @@ -9186,50 +9151,19 @@ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r") (match_operand:DF 1 "input_operand" "r,m,r,G,H,F"))] "! TARGET_POWERPC64 - && ((TARGET_FPRS && !TARGET_DOUBLE_FLOAT) + && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE) && (gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode))" - "* -{ - switch (which_alternative) - { - default: - gcc_unreachable (); - case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; - case 1: - /* If the low-address word is used in the address, we must load - it last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is - known to be dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\"; - case 2: - return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\"; - case 3: - case 4: - case 5: - return \"#\"; - } -}" + "#" [(set_attr "type" "two,load,store,*,*,*") (set_attr "length" "8,8,8,8,12,16")]) ; ld/std require word-aligned displacements -> 'Y' constraint. ; List Y->r and r->Y before r->r for reload. (define_insn "*movdf_hardfloat64_mfpgpr" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,f,f,m,wa,*c*l,!r,*h,!r,!r,!r,r,f") - (match_operand:DF 1 "input_operand" "r,Y,r,ws,?wa,Z,Z,ws,wa,f,m,f,j,r,h,0,G,H,F,f,r"))] + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,d,d,m,wa,*c*l,!r,*h,!r,!r,!r,r,d") + (match_operand:DF 1 "input_operand" "r,Y,r,ws,?wa,Z,Z,ws,wa,d,m,d,j,r,h,0,G,H,F,d,r"))] "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && (gpc_reg_operand (operands[0], DFmode) @@ -9262,8 +9196,8 @@ ; ld/std require word-aligned displacements -> 'Y' constraint. ; List Y->r and r->Y before r->r for reload. (define_insn "*movdf_hardfloat64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,f,f,m,wa,*c*l,!r,*h,!r,!r,!r") - (match_operand:DF 1 "input_operand" "r,Y,r,ws,wa,Z,Z,ws,wa,f,m,f,j,r,h,0,G,H,F"))] + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,ws,?wa,ws,?wa,Z,?Z,d,d,m,wa,*c*l,!r,*h,!r,!r,!r") + (match_operand:DF 1 "input_operand" "r,Y,r,ws,wa,Z,Z,ws,wa,d,m,d,j,r,h,0,G,H,F"))] "TARGET_POWERPC64 && !TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && (gpc_reg_operand (operands[0], DFmode) @@ -9320,8 +9254,8 @@ ; otherwise reload, given m->f, will try to pick f->f and reload it, ; which doesn't make progress. Likewise r->Y must be before r->r. (define_insn_and_split "*movtf_internal" - [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,f,r,Y,r") - (match_operand:TF 1 "input_operand" "f,o,f,YGHF,r,r"))] + [(set (match_operand:TF 0 "nonimmediate_operand" "=o,d,d,r,Y,r") + (match_operand:TF 1 "input_operand" "d,o,d,YGHF,r,r"))] "!TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128 && (gpc_reg_operand (operands[0], TFmode) @@ -9375,9 +9309,9 @@ }) (define_insn_and_split "*extenddftf2_internal" - [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,&f,r") - (float_extend:TF (match_operand:DF 1 "input_operand" "fr,mf,mf,rmGHF"))) - (use (match_operand:DF 2 "zero_reg_mem_operand" "rf,m,f,n"))] + [(set (match_operand:TF 0 "nonimmediate_operand" "=o,d,&d,r") + (float_extend:TF (match_operand:DF 1 "input_operand" "dr,md,md,rmGHF"))) + (use (match_operand:DF 2 "zero_reg_mem_operand" "rd,m,d,n"))] "!TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" @@ -9418,8 +9352,8 @@ "") (define_insn_and_split "trunctfdf2_internal1" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f") - (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d") + (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,d")))] "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" "@ @@ -9434,8 +9368,8 @@ [(set_attr "type" "fp")]) (define_insn "trunctfdf2_internal2" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "f")))] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "d")))] "!TARGET_IEEEQUAD && TARGET_XL_COMPAT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" @@ -9460,8 +9394,8 @@ (define_insn_and_split "trunctfsf2_fprs" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f"))) - (clobber (match_scratch:DF 2 "=f"))] + (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "d"))) + (clobber (match_scratch:DF 2 "=d"))] "!TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT && TARGET_LONG_DOUBLE_128" @@ -9490,10 +9424,10 @@ ; fadd, but rounding towards zero. ; This is probably not the optimal code sequence. (define_insn "fix_trunc_helper" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:TF 1 "gpc_reg_operand" "f")] + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec:DF [(match_operand:TF 1 "gpc_reg_operand" "d")] UNSPEC_FIX_TRUNC_TF)) - (clobber (match_operand:DF 2 "gpc_reg_operand" "=&f"))] + (clobber (match_operand:DF 2 "gpc_reg_operand" "=&d"))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "mffs %2\n\tmtfsb1 31\n\tmtfsb0 30\n\tfadd %0,%1,%L1\n\tmtfsf 1,%2" [(set_attr "type" "fp") @@ -9534,15 +9468,15 @@ (define_insn_and_split "*fix_trunctfsi2_internal" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (fix:SI (match_operand:TF 1 "gpc_reg_operand" "f"))) - (clobber (match_operand:DF 2 "gpc_reg_operand" "=f")) - (clobber (match_operand:DF 3 "gpc_reg_operand" "=&f")) - (clobber (match_operand:DI 4 "gpc_reg_operand" "=f")) + (fix:SI (match_operand:TF 1 "gpc_reg_operand" "d"))) + (clobber (match_operand:DF 2 "gpc_reg_operand" "=d")) + (clobber (match_operand:DF 3 "gpc_reg_operand" "=&d")) + (clobber (match_operand:DI 4 "gpc_reg_operand" "=d")) (clobber (match_operand:DI 5 "offsettable_mem_operand" "=o"))] "!TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" "#" - "&& (can_create_pseudo_p () || offsettable_nonstrict_memref_p (operands[5]))" + "" [(pc)] { rtx lowword; @@ -9567,8 +9501,8 @@ "") (define_insn "negtf2_internal" - [(set (match_operand:TF 0 "gpc_reg_operand" "=f") - (neg:TF (match_operand:TF 1 "gpc_reg_operand" "f")))] + [(set (match_operand:TF 0 "gpc_reg_operand" "=d") + (neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))] "!TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" "* @@ -9633,8 +9567,8 @@ ; List r->r after r->"o<>", otherwise reload will try to reload a ; non-offsettable address by using r->r which won't make progress. (define_insn "*movdi_internal32" - [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=o<>,r,r,*f,*f,m,r") - (match_operand:DI 1 "input_operand" "r,r,m,f,m,f,IJKnGHF"))] + [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=o<>,r,r,*d,*d,m,r") + (match_operand:DI 1 "input_operand" "r,r,m,d,m,d,IJKnGHF"))] "! TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode))" @@ -9670,16 +9604,16 @@ }") (define_split - [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "") - (match_operand:DI 1 "input_operand" ""))] + [(set (match_operand:DIFD 0 "rs6000_nonimmediate_operand" "") + (match_operand:DIFD 1 "input_operand" ""))] "reload_completed && !TARGET_POWERPC64 && gpr_or_gpr_p (operands[0], operands[1])" [(pc)] { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) (define_insn "*movdi_mfpgpr" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h,r,*f") - (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0,*f,r"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h,r,*d") + (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0,*d,r"))] "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS && (gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode))" @@ -9703,8 +9637,8 @@ (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4")]) (define_insn "*movdi_internal64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h") - (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h") + (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0"))] "TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS) && (gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode))" @@ -9870,7 +9804,7 @@ || gpc_reg_operand (operands[1], TImode))) && VECTOR_MEM_NONE_P (TImode)" "#" - [(set_attr "type" "*,load,store")]) + [(set_attr "type" "*,store,load")]) (define_split [(set (match_operand:TI 0 "gpc_reg_operand" "") @@ -10899,7 +10833,7 @@ [(set_attr "type" "store_ux,store_u")]) (define_insn "*movdf_update1" - [(set (match_operand:DF 3 "gpc_reg_operand" "=f,f") + [(set (match_operand:DF 3 "gpc_reg_operand" "=d,d") (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0") (match_operand:SI 2 "reg_or_short_operand" "r,I")))) (set (match_operand:SI 0 "gpc_reg_operand" "=b,b") @@ -10915,7 +10849,7 @@ (define_insn "*movdf_update2" [(set (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0") (match_operand:SI 2 "reg_or_short_operand" "r,I"))) - (match_operand:DF 3 "gpc_reg_operand" "f,f")) + (match_operand:DF 3 "gpc_reg_operand" "d,d")) (set (match_operand:SI 0 "gpc_reg_operand" "=b,b") (plus:SI (match_dup 1) (match_dup 2)))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_UPDATE @@ -11004,7 +10938,7 @@ (define_mode_attr tls_sysv_suffix [(SI "si") (DI "di")]) (define_mode_attr tls_insn_suffix [(SI "wz") (DI "d")]) -(define_insn "tls_gd_aix<TLSmode:tls_abi_suffix>" +(define_insn_and_split "tls_gd_aix<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") (call (mem:TLSmode (match_operand:TLSmode 3 "symbol_ref_operand" "s")) (match_operand 4 "" "g"))) @@ -11014,10 +10948,21 @@ (clobber (reg:SI LR_REGNO))] "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX" "addi %0,%1,%2@got@tlsgd\;bl %z3\;%." + "&& TARGET_TLS_MARKERS" + [(set (match_dup 0) + (unspec:TLSmode [(match_dup 1) + (match_dup 2)] + UNSPEC_TLSGD)) + (parallel [(set (match_dup 0) + (call (mem:TLSmode (match_dup 3)) + (match_dup 4))) + (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD) + (clobber (reg:SI LR_REGNO))])] + "" [(set_attr "type" "two") (set_attr "length" "12")]) -(define_insn "tls_gd_sysv<TLSmode:tls_sysv_suffix>" +(define_insn_and_split "tls_gd_sysv<TLSmode:tls_sysv_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") (call (mem:TLSmode (match_operand:TLSmode 3 "symbol_ref_operand" "s")) (match_operand 4 "" "g"))) @@ -11037,10 +10982,62 @@ else return "addi %0,%1,%2@got@tlsgd\;bl %z3"; } + "&& TARGET_TLS_MARKERS" + [(set (match_dup 0) + (unspec:TLSmode [(match_dup 1) + (match_dup 2)] + UNSPEC_TLSGD)) + (parallel [(set (match_dup 0) + (call (mem:TLSmode (match_dup 3)) + (match_dup 4))) + (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD) + (clobber (reg:SI LR_REGNO))])] + "" [(set_attr "type" "two") (set_attr "length" "8")]) -(define_insn "tls_ld_aix<TLSmode:tls_abi_suffix>" +(define_insn "*tls_gd<TLSmode:tls_abi_suffix>" + [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") + (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b") + (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSGD))] + "HAVE_AS_TLS && TARGET_TLS_MARKERS" + "addi %0,%1,%2@got@tlsgd" + [(set_attr "length" "4")]) + +(define_insn "*tls_gd_call_aix<TLSmode:tls_abi_suffix>" + [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") + (call (mem:TLSmode (match_operand:TLSmode 1 "symbol_ref_operand" "s")) + (match_operand 2 "" "g"))) + (unspec:TLSmode [(match_operand:TLSmode 3 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSGD) + (clobber (reg:SI LR_REGNO))] + "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX && TARGET_TLS_MARKERS" + "bl %z1(%3@tlsgd)\;%." + [(set_attr "type" "branch") + (set_attr "length" "8")]) + +(define_insn "*tls_gd_call_sysv<TLSmode:tls_abi_suffix>" + [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") + (call (mem:TLSmode (match_operand:TLSmode 1 "symbol_ref_operand" "s")) + (match_operand 2 "" "g"))) + (unspec:TLSmode [(match_operand:TLSmode 3 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSGD) + (clobber (reg:SI LR_REGNO))] + "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS" +{ + if (flag_pic) + { + if (TARGET_SECURE_PLT && flag_pic == 2) + return "bl %z1+32768(%3@tlsgd)@plt"; + return "bl %z1(%3@tlsgd)@plt"; + } + return "bl %z1(%3@tlsgd)"; +} + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +(define_insn_and_split "tls_ld_aix<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") (call (mem:TLSmode (match_operand:TLSmode 2 "symbol_ref_operand" "s")) (match_operand 3 "" "g"))) @@ -11049,9 +11046,19 @@ (clobber (reg:SI LR_REGNO))] "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX" "addi %0,%1,%&@got@tlsld\;bl %z2\;%." + "&& TARGET_TLS_MARKERS" + [(set (match_dup 0) + (unspec:TLSmode [(match_dup 1)] + UNSPEC_TLSLD)) + (parallel [(set (match_dup 0) + (call (mem:TLSmode (match_dup 2)) + (match_dup 3))) + (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD) + (clobber (reg:SI LR_REGNO))])] + "" [(set_attr "length" "12")]) -(define_insn "tls_ld_sysv<TLSmode:tls_sysv_suffix>" +(define_insn_and_split "tls_ld_sysv<TLSmode:tls_sysv_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") (call (mem:TLSmode (match_operand:TLSmode 2 "symbol_ref_operand" "s")) (match_operand 3 "" "g"))) @@ -11070,8 +11077,56 @@ else return "addi %0,%1,%&@got@tlsld\;bl %z2"; } + "&& TARGET_TLS_MARKERS" + [(set (match_dup 0) + (unspec:TLSmode [(match_dup 1)] + UNSPEC_TLSLD)) + (parallel [(set (match_dup 0) + (call (mem:TLSmode (match_dup 2)) + (match_dup 3))) + (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD) + (clobber (reg:SI LR_REGNO))])] + "" [(set_attr "length" "8")]) +(define_insn "*tls_ld<TLSmode:tls_abi_suffix>" + [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") + (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")] + UNSPEC_TLSLD))] + "HAVE_AS_TLS && TARGET_TLS_MARKERS" + "addi %0,%1,%&@got@tlsld" + [(set_attr "length" "4")]) + +(define_insn "*tls_ld_call_aix<TLSmode:tls_abi_suffix>" + [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") + (call (mem:TLSmode (match_operand:TLSmode 1 "symbol_ref_operand" "s")) + (match_operand 2 "" "g"))) + (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD) + (clobber (reg:SI LR_REGNO))] + "HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX && TARGET_TLS_MARKERS" + "bl %z1(%&@tlsld)\;%." + [(set_attr "type" "branch") + (set_attr "length" "8")]) + +(define_insn "*tls_ld_call_sysv<TLSmode:tls_abi_suffix>" + [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") + (call (mem:TLSmode (match_operand:TLSmode 1 "symbol_ref_operand" "s")) + (match_operand 2 "" "g"))) + (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD) + (clobber (reg:SI LR_REGNO))] + "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS" +{ + if (flag_pic) + { + if (TARGET_SECURE_PLT && flag_pic == 2) + return "bl %z1+32768(%&@tlsld)@plt"; + return "bl %z1(%&@tlsld)@plt"; + } + return "bl %z1(%&@tlsld)"; +} + [(set_attr "type" "branch") + (set_attr "length" "4")]) + (define_insn "tls_dtprel_<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r") (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b") @@ -12377,6 +12432,14 @@ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCK)] "" "") + +(define_insn "probe_stack" + [(set (match_operand 0 "memory_operand" "=m") + (unspec [(const_int 0)] UNSPEC_PROBE_STACK))] + "" + "{st%U0%X0|stw%U0%X0} 0,%0" + [(set_attr "type" "store") + (set_attr "length" "4")]) ;; Compare insns are next. Note that the RS/6000 has two types of compares, ;; signed & unsigned, and one type of branch. @@ -12680,6 +12743,7 @@ (match_operand 2 "" "")] "" { + rtx test, op0, op1; #ifdef TARGET_THREAD_SSP_OFFSET rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2); rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET)); @@ -12843,8 +12907,8 @@ (define_insn "*cmpdf_internal1" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "f") - (match_operand:DF 2 "gpc_reg_operand" "f")))] + (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "d") + (match_operand:DF 2 "gpc_reg_operand" "d")))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !VECTOR_UNIT_VSX_P (DFmode)" "fcmpu %0,%1,%2" @@ -12853,8 +12917,8 @@ ;; Only need to compare second words if first words equal (define_insn "*cmptf_internal1" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "f") - (match_operand:TF 2 "gpc_reg_operand" "f")))] + (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "d") + (match_operand:TF 2 "gpc_reg_operand" "d")))] "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" "fcmpu %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2" @@ -12863,16 +12927,16 @@ (define_insn_and_split "*cmptf_internal2" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "f") - (match_operand:TF 2 "gpc_reg_operand" "f"))) - (clobber (match_scratch:DF 3 "=f")) - (clobber (match_scratch:DF 4 "=f")) - (clobber (match_scratch:DF 5 "=f")) - (clobber (match_scratch:DF 6 "=f")) - (clobber (match_scratch:DF 7 "=f")) - (clobber (match_scratch:DF 8 "=f")) - (clobber (match_scratch:DF 9 "=f")) - (clobber (match_scratch:DF 10 "=f"))] + (compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "d") + (match_operand:TF 2 "gpc_reg_operand" "d"))) + (clobber (match_scratch:DF 3 "=d")) + (clobber (match_scratch:DF 4 "=d")) + (clobber (match_scratch:DF 5 "=d")) + (clobber (match_scratch:DF 6 "=d")) + (clobber (match_scratch:DF 7 "=d")) + (clobber (match_scratch:DF 8 "=d")) + (clobber (match_scratch:DF 9 "=d")) + (clobber (match_scratch:DF 10 "=d"))] "!TARGET_IEEEQUAD && TARGET_XL_COMPAT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" "#" @@ -12890,7 +12954,7 @@ (set (match_dup 10) (minus:DF (match_dup 5) (match_dup 7))) (set (match_dup 9) (minus:DF (match_dup 6) (match_dup 8))) (set (match_dup 9) (plus:DF (match_dup 10) (match_dup 9))) - (set (match_dup 0) (compare:CCFP (match_dup 7) (match_dup 4))) + (set (match_dup 0) (compare:CCFP (match_dup 9) (match_dup 4))) (match_dup 12)] { REAL_VALUE_TYPE rv; @@ -15348,7 +15412,7 @@ (use (match_operand:P 1 "symbol_ref_operand" "s")) (use (match_operand:P 2 "gpc_reg_operand" "r")) (set (match_operand:DF 3 "memory_operand" "=m") - (match_operand:DF 4 "gpc_reg_operand" "f"))])] + (match_operand:DF 4 "gpc_reg_operand" "d"))])] "" "bl %1" [(set_attr "type" "branch") @@ -15468,7 +15532,7 @@ (clobber (match_operand:P 1 "register_operand" "=l")) (use (match_operand:P 2 "symbol_ref_operand" "s")) (use (match_operand:P 3 "gpc_reg_operand" "r")) - (set (match_operand:DF 4 "gpc_reg_operand" "=f") + (set (match_operand:DF 4 "gpc_reg_operand" "=d") (match_operand:DF 5 "memory_operand" "m"))])] "" "b %2" diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index ce429e8f92d..63f0f8c1582 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -171,12 +171,16 @@ mfused-madd Target Report Var(TARGET_FUSED_MADD) Init(1) Generate fused multiply/add instructions -msched-prolog -Target Report Var(TARGET_SCHED_PROLOG) Init(1) -Schedule the start and end of the procedure +mtls-markers +Target Report Var(tls_markers) Init(1) +Mark __tls_get_addr calls with argument info msched-epilog -Target Undocumented Var(TARGET_SCHED_PROLOG) VarExists +Target Undocumented Var(TARGET_SCHED_PROLOG) Init(1) + +msched-prolog +Target Report Var(TARGET_SCHED_PROLOG) VarExists +Schedule the start and end of the procedure maix-struct-return Target Report RejectNegative Var(aix_struct_return) diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000 index d60b616e52d..0aac270e8a0 100644 --- a/gcc/config/rs6000/t-rs6000 +++ b/gcc/config/rs6000/t-rs6000 @@ -1,4 +1,23 @@ # General rules that all rs6000/ targets must have. +# +# Copyright (C) 1995, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2008, 2009 +# Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. TM_H += $(srcdir)/config/rs6000/rs6000-builtin.def @@ -38,6 +57,7 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rios1.md \ $(srcdir)/config/rs6000/power7.md \ $(srcdir)/config/rs6000/cell.md \ $(srcdir)/config/rs6000/xfpu.md \ + $(srcdir)/config/rs6000/a2.md \ $(srcdir)/config/rs6000/predicates.md \ $(srcdir)/config/rs6000/constraints.md \ $(srcdir)/config/rs6000/darwin.md \ diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md index bcfb9fb9777..7f927f103d2 100644 --- a/gcc/config/rs6000/vector.md +++ b/gcc/config/rs6000/vector.md @@ -3,7 +3,7 @@ ;; expander, and the actual vector instructions will be in altivec.md and ;; vsx.md -;; Copyright (C) 2009 +;; Copyright (C) 2009, 2010 ;; Free Software Foundation, Inc. ;; Contributed by Michael Meissner <meissner@linux.vnet.ibm.com> diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index dbaef602509..71e5521b642 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -1973,6 +1973,41 @@ instruction per word Integer/Floating point constant that can be loaded into a register using three instructions +@item m +Memory operand. Note that on PowerPC targets, @code{m} can include +addresses that update the base register. It is therefore only safe +to use @samp{m} in an @code{asm} statement if that @code{asm} statement +accesses the operand exactly once. The @code{asm} statement must also +use @samp{%U@var{<opno>}} as a placeholder for the ``update'' flag in the +corresponding load or store instruction. For example: + +@smallexample +asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val)); +@end smallexample + +is correct but: + +@smallexample +asm ("st %1,%0" : "=m" (mem) : "r" (val)); +@end smallexample + +is not. Use @code{es} rather than @code{m} if you don't want the +base register to be updated. + +@item es +A ``stable'' memory operand; that is, one which does not include any +automodification of the base register. Unlike @samp{m}, this constraint +can be used in @code{asm} statements that might access the operand +several times, or that might not access it at all. + +@item Q +Memory operand that is an offset from a register (it is usually better +to use @samp{m} or @samp{es} in @code{asm} statements) + +@item Z +Memory operand that is an indexed or indirect from a register (it is +usually better to use @samp{m} or @samp{es} in @code{asm} statements) + @item Q Memory operand that is an offset from a register (@samp{m} is preferable for @code{asm} statements) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index d9abcd6ffdd..87e86c722a7 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5609,6 +5609,14 @@ return type of the vectorized function shall be of vector type @var{vec_type_out} and the argument types should be @var{vec_type_in}. @end deftypefn +@deftypefn {Target Hook} bool TARGET_SUPPORT_VECTOR_MISALIGNMENT (enum machine_mode @var{mode}, tree @var{type}, int @var{misalignment}, bool @var{is_packed}) +This hook should return true if the target supports misaligned vector +store/load of a specific factor denoted in the @var{misalignment} +parameter. The vector store/load should be of machine mode @var{mode} and +the elements in the vectors should be of type @var{type}. @var{is_packed} +parameter is true if the memory access is defined in a packed struct. +@end deftypefn + @node Anchored Addresses @section Anchored Addresses @cindex anchored addresses diff --git a/gcc/genautomata.c b/gcc/genautomata.c index ff21512f324..f3321410da5 100644 --- a/gcc/genautomata.c +++ b/gcc/genautomata.c @@ -1,5 +1,5 @@ /* Pipeline hazard description translator. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Written by Vladimir Makarov <vmakarov@redhat.com> @@ -213,19 +213,19 @@ static struct obstack irp; /* Declare vector types for various data structures: */ DEF_VEC_P(alt_state_t); -DEF_VEC_ALLOC_P(alt_state_t,heap); +DEF_VEC_ALLOC_P(alt_state_t, heap); DEF_VEC_P(ainsn_t); -DEF_VEC_ALLOC_P(ainsn_t,heap); +DEF_VEC_ALLOC_P(ainsn_t, heap); DEF_VEC_P(state_t); -DEF_VEC_ALLOC_P(state_t,heap); +DEF_VEC_ALLOC_P(state_t, heap); DEF_VEC_P(decl_t); -DEF_VEC_ALLOC_P(decl_t,heap); +DEF_VEC_ALLOC_P(decl_t, heap); DEF_VEC_P(reserv_sets_t); -DEF_VEC_ALLOC_P(reserv_sets_t,heap); +DEF_VEC_ALLOC_P(reserv_sets_t, heap); DEF_VEC_I(vect_el_t); DEF_VEC_ALLOC_I(vect_el_t, heap); -typedef VEC(vect_el_t,heap) *vla_hwint_t; +typedef VEC(vect_el_t, heap) *vla_hwint_t; /* Forward declarations of functions used before their definitions, only. */ static regexp_t gen_regexp_sequence (const char *); @@ -1137,7 +1137,7 @@ check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED) /* Pointers to all declarations during IR generation are stored in the following. */ -static VEC(decl_t,heap) *decls; +static VEC(decl_t, heap) *decls; /* Given a pointer to a (char *) and a separator, return an alloc'ed string containing the next separated element, taking parentheses @@ -1265,7 +1265,7 @@ gen_cpu_unit (rtx def) DECL_UNIT (decl)->query_p = 0; DECL_UNIT (decl)->min_occ_cycle_num = -1; DECL_UNIT (decl)->in_set_p = 0; - VEC_safe_push (decl_t,heap, decls, decl); + VEC_safe_push (decl_t, heap, decls, decl); } } @@ -1293,7 +1293,7 @@ gen_query_cpu_unit (rtx def) DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos); DECL_UNIT (decl)->automaton_name = XSTR (def, 1); DECL_UNIT (decl)->query_p = 1; - VEC_safe_push (decl_t,heap, decls, decl); + VEC_safe_push (decl_t, heap, decls, decl); } } @@ -1328,7 +1328,7 @@ gen_bypass (rtx def) DECL_BYPASS (decl)->out_insn_name = out_insns [i]; DECL_BYPASS (decl)->in_insn_name = in_insns [j]; DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3); - VEC_safe_push (decl_t,heap, decls, decl); + VEC_safe_push (decl_t, heap, decls, decl); } } @@ -1367,7 +1367,7 @@ gen_excl_set (rtx def) else DECL_EXCL (decl)->names [i] = second_str_cpu_units [i - first_vect_length]; - VEC_safe_push (decl_t,heap, decls, decl); + VEC_safe_push (decl_t, heap, decls, decl); } /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET, @@ -1436,7 +1436,7 @@ gen_presence_absence_set (rtx def, int presence_p, int final_p) DECL_ABSENCE (decl)->patterns_num = patterns_length; DECL_ABSENCE (decl)->final_p = final_p; } - VEC_safe_push (decl_t,heap, decls, decl); + VEC_safe_push (decl_t, heap, decls, decl); } /* Process a PRESENCE_SET. @@ -1505,7 +1505,7 @@ gen_automaton (rtx def) decl->mode = dm_automaton; decl->pos = 0; DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos); - VEC_safe_push (decl_t,heap, decls, decl); + VEC_safe_push (decl_t, heap, decls, decl); } } @@ -1706,7 +1706,7 @@ gen_reserv (rtx def) decl->pos = 0; DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos); DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1)); - VEC_safe_push (decl_t,heap, decls, decl); + VEC_safe_push (decl_t, heap, decls, decl); } /* Process a DEFINE_INSN_RESERVATION. @@ -1727,7 +1727,7 @@ gen_insn_reserv (rtx def) DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1); DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2); DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3)); - VEC_safe_push (decl_t,heap, decls, decl); + VEC_safe_push (decl_t, heap, decls, decl); } @@ -1796,7 +1796,7 @@ insert_automaton_decl (decl_t automaton_decl) { void **entry_ptr; - entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1); + entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT); if (*entry_ptr == NULL) *entry_ptr = (void *) automaton_decl; return (decl_t) *entry_ptr; @@ -1895,7 +1895,7 @@ insert_insn_decl (decl_t insn_decl) { void **entry_ptr; - entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1); + entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT); if (*entry_ptr == NULL) *entry_ptr = (void *) insn_decl; return (decl_t) *entry_ptr; @@ -1996,7 +1996,7 @@ insert_decl (decl_t decl) { void **entry_ptr; - entry_ptr = htab_find_slot (decl_table, decl, 1); + entry_ptr = htab_find_slot (decl_table, decl, INSERT); if (*entry_ptr == NULL) *entry_ptr = (void *) decl; return (decl_t) *entry_ptr; @@ -2314,8 +2314,7 @@ add_presence_absence (unit_set_el_t dest_list, no_error_flag = 0; } else - warning - (0, "unit `%s' excludes and requires presence of `%s'", + warning ("unit `%s' excludes and requires presence of `%s'", dst->unit_decl->name, unit->name); } } @@ -2328,15 +2327,13 @@ add_presence_absence (unit_set_el_t dest_list, { if (!w_flag) { - error - ("unit `%s' requires absence and presence of `%s'", - dst->unit_decl->name, unit->name); + error ("unit `%s' requires absence and presence of `%s'", + dst->unit_decl->name, unit->name); no_error_flag = 0; } else - warning - (0, "unit `%s' requires absence and presence of `%s'", - dst->unit_decl->name, unit->name); + warning ("unit `%s' requires absence and presence of `%s'", + dst->unit_decl->name, unit->name); } if (no_error_flag) { @@ -2385,7 +2382,7 @@ insert_bypass (struct bypass_decl *bypass) struct bypass_decl *curr, *last; struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv; struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv; - + for (curr = out_insn_reserv->bypass_list, last = NULL; curr != NULL; last = curr, curr = curr->next) @@ -2402,7 +2399,7 @@ insert_bypass (struct bypass_decl *bypass) error ("the same bypass `%s - %s' is already defined", bypass->out_insn_name, bypass->in_insn_name); else - warning (0, "the same bypass `%s - %s' is already defined", + warning ("the same bypass `%s - %s' is already defined", bypass->out_insn_name, bypass->in_insn_name); } else if (!w_flag) @@ -2411,7 +2408,7 @@ insert_bypass (struct bypass_decl *bypass) bypass->bypass_guard_name); else warning - (0, "the same bypass `%s - %s' (guard %s) is already defined", + ("the same bypass `%s - %s' (guard %s) is already defined", bypass->out_insn_name, bypass->in_insn_name, bypass->bypass_guard_name); return; @@ -2423,7 +2420,7 @@ insert_bypass (struct bypass_decl *bypass) last = curr; break; } - + } if (last == NULL) { @@ -2465,7 +2462,7 @@ process_decls (void) error ("repeated declaration of automaton `%s'", DECL_AUTOMATON (decl)->name); else - warning (0, "repeated declaration of automaton `%s'", + warning ("repeated declaration of automaton `%s'", DECL_AUTOMATON (decl)->name); } } @@ -2664,7 +2661,7 @@ check_automaton_usage (void) if (!w_flag) error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name); else - warning (0, "automaton `%s' is not used", + warning ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name); } } @@ -2778,14 +2775,14 @@ check_usage (void) if (!w_flag) error ("unit `%s' is not used", DECL_UNIT (decl)->name); else - warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name); + warning ("unit `%s' is not used", DECL_UNIT (decl)->name); } else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used) { if (!w_flag) error ("reservation `%s' is not used", DECL_RESERV (decl)->name); else - warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name); + warning ("reservation `%s' is not used", DECL_RESERV (decl)->name); } } } @@ -2939,7 +2936,7 @@ process_regexp_cycles (regexp_t regexp, int max_start_cycle, { int max_cycle = 0; int min_cycle = 0; - + for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) { process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i], @@ -2959,7 +2956,7 @@ process_regexp_cycles (regexp_t regexp, int max_start_cycle, { int max_cycle = 0; int min_cycle = 0; - + for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) { process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i], @@ -3239,7 +3236,7 @@ static alt_state_t uniq_sort_alt_states (alt_state_t alt_states_list) { alt_state_t curr_alt_state; - VEC(alt_state_t,heap) *alt_states; + VEC(alt_state_t, heap) *alt_states; size_t i; size_t prev_unique_state_ind; alt_state_t result; @@ -3249,11 +3246,11 @@ uniq_sort_alt_states (alt_state_t alt_states_list) if (alt_states_list->next_alt_state == 0) return alt_states_list; - alt_states = VEC_alloc (alt_state_t,heap, 150); + alt_states = VEC_alloc (alt_state_t, heap, 150); for (curr_alt_state = alt_states_list; curr_alt_state != NULL; curr_alt_state = curr_alt_state->next_alt_state) - VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state); + VEC_safe_push (alt_state_t, heap, alt_states, curr_alt_state); qsort (VEC_address (alt_state_t, alt_states), VEC_length (alt_state_t, alt_states), @@ -3277,7 +3274,7 @@ uniq_sort_alt_states (alt_state_t alt_states_list) result = VEC_index (alt_state_t, alt_states, 0); - VEC_free (alt_state_t,heap, alt_states); + VEC_free (alt_state_t, heap, alt_states); return result; } @@ -3748,7 +3745,7 @@ insert_state (state_t state) { void **entry_ptr; - entry_ptr = htab_find_slot (state_table, (void *) state, 1); + entry_ptr = htab_find_slot (state_table, (void *) state, INSERT); if (*entry_ptr == NULL) *entry_ptr = (void *) state; return (state_t) *entry_ptr; @@ -4104,7 +4101,7 @@ automata_list_finish (void) if (current_automata_list == NULL) return NULL; entry_ptr = htab_find_slot (automata_list_table, - (void *) current_automata_list, 1); + (void *) current_automata_list, INSERT); if (*entry_ptr == NULL) *entry_ptr = (void *) current_automata_list; else @@ -4782,7 +4779,7 @@ transform_3 (regexp_t regexp) default: break; } - + if (allof_length == 1) REGEXP_SEQUENCE (result)->regexps [i] = allof_op; else @@ -4918,18 +4915,23 @@ transform_insn_regexps (void) about units to automata distribution has been output. */ static int annotation_message_reported_p; +/* The vector contains all decls which are automata. */ +static VEC(decl_t, heap) *automaton_decls; + /* The following structure describes usage of a unit in a reservation. */ struct unit_usage { unit_decl_t unit_decl; /* The following forms a list of units used on the same cycle in the - same alternative. */ + same alternative. The list is ordered by the correspdoning unit + declarations and there is no unit declaration duplication in the + list. */ struct unit_usage *next; }; typedef struct unit_usage *unit_usage_t; DEF_VEC_P(unit_usage_t); -DEF_VEC_ALLOC_P(unit_usage_t,heap); +DEF_VEC_ALLOC_P(unit_usage_t, heap); /* Obstack for unit_usage structures. */ static struct obstack unit_usages; @@ -4938,9 +4940,9 @@ static struct obstack unit_usages; structures. There is an element for each combination of (alternative number, cycle). Unit usages on given cycle in alternative with given number are referred through element with - index equals to the cycle * number of all alternatives in the regexp - + the alternative number. */ -static VEC(unit_usage_t,heap) *cycle_alt_unit_usages; + index equals to the cycle * number of all alternatives in the + regexp + the alternative number. */ +static VEC(unit_usage_t, heap) *cycle_alt_unit_usages; /* The following function creates the structure unit_usage for UNIT on CYCLE in REGEXP alternative with ALT_NUM. The structure is made @@ -4951,7 +4953,7 @@ store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle, { size_t length; unit_decl_t unit_decl; - unit_usage_t unit_usage_ptr; + unit_usage_t unit_usage_ptr, curr, prev; int index; gcc_assert (regexp && regexp->mode == rm_oneof @@ -4960,33 +4962,100 @@ store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle, length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num; while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length) - VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0); - + VEC_safe_push (unit_usage_t, heap, cycle_alt_unit_usages, 0); + + index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num; + prev = NULL; + for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index); + curr != NULL; + prev = curr, curr = curr->next) + if (curr->unit_decl >= unit_decl) + break; + if (curr != NULL && curr->unit_decl == unit_decl) + return; obstack_blank (&unit_usages, sizeof (struct unit_usage)); unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages); obstack_finish (&unit_usages); unit_usage_ptr->unit_decl = unit_decl; - index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num; - unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index); - VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr); unit_decl->last_distribution_check_cycle = -1; /* undefined */ + unit_usage_ptr->next = curr; + if (prev == NULL) + VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr); + else + prev->next = unit_usage_ptr; } +/* Return true if unit UNIT_DECL is present on the LIST. */ +static bool +unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl) +{ + while (list != NULL) + { + if (list->unit_decl == unit_decl) + return true; + list = list->next; + } + return false; +} + +/* The function returns true if reservations of alternatives ALT1 and + ALT2 are equal after excluding reservations of units of + EXCLUDED_AUTOMATON_DECL. */ +static bool +equal_alternatives_p (int alt1, int alt2, int n_alts, + struct automaton_decl *excluded_automaton_decl) +{ + int i; + unit_usage_t list1, list2; + + for (i = 0; + i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); + i += n_alts) + { + for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1), + list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);; + list1 = list1->next, list2 = list2->next) + { + while (list1 != NULL + && list1->unit_decl->automaton_decl == excluded_automaton_decl) + list1 = list1->next; + while (list2 != NULL + && list2->unit_decl->automaton_decl == excluded_automaton_decl) + list2 = list2->next; + if (list1 == NULL || list2 == NULL) + { + if (list1 != list2) + return false; + else + break; + } + if (list1->unit_decl != list2->unit_decl) + return false; + } + } + return true; +} + +DEF_VEC_I(int); +DEF_VEC_ALLOC_I(int, heap); + /* The function processes given REGEXP to find units with the wrong distribution. */ static void check_regexp_units_distribution (const char *insn_reserv_name, regexp_t regexp) { - int i, j, k, cycle; + int i, j, k, cycle, start, n_alts, alt, alt2; + bool annotation_reservation_message_reported_p; regexp_t seq, allof, unit; - struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr; + struct unit_usage *unit_usage_ptr; + VEC(int, heap) *marked; if (regexp == NULL || regexp->mode != rm_oneof) return; /* Store all unit usages in the regexp: */ obstack_init (&unit_usages); - cycle_alt_unit_usages = 0; + cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10); for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--) { @@ -5009,14 +5078,14 @@ check_regexp_units_distribution (const char *insn_reserv_name, gcc_assert (unit->mode == rm_nothing); } break; - + case rm_unit: store_alt_unit_usage (regexp, allof, j, i); break; - + case rm_nothing: break; - + default: gcc_unreachable (); } @@ -5032,10 +5101,10 @@ check_regexp_units_distribution (const char *insn_reserv_name, case rm_unit: store_alt_unit_usage (regexp, unit, 0, i); break; - + case rm_nothing: break; - + default: gcc_unreachable (); } @@ -5055,48 +5124,84 @@ check_regexp_units_distribution (const char *insn_reserv_name, } /* Check distribution: */ for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++) + for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i); + unit_usage_ptr != NULL; + unit_usage_ptr = unit_usage_ptr->next) + unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1; + n_alts = REGEXP_ONEOF (regexp)->regexps_num; + marked = VEC_alloc (int, heap, n_alts); + for (i = 0; i < n_alts; i++) + VEC_safe_push (int, heap, marked, 0); + annotation_reservation_message_reported_p = false; + for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++) { - cycle = i / REGEXP_ONEOF (regexp)->regexps_num; + cycle = i / n_alts; + start = cycle * n_alts; for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i); unit_usage_ptr != NULL; unit_usage_ptr = unit_usage_ptr->next) - if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle) - { - unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle; - for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num; - k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages) - && k == cycle * REGEXP_ONEOF (regexp)->regexps_num; - k++) - { - for (other_unit_usage_ptr - = VEC_index (unit_usage_t, cycle_alt_unit_usages, k); - other_unit_usage_ptr != NULL; - other_unit_usage_ptr = other_unit_usage_ptr->next) - if (unit_usage_ptr->unit_decl->automaton_decl - == other_unit_usage_ptr->unit_decl->automaton_decl) - break; - if (other_unit_usage_ptr == NULL - && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k) - != NULL)) - break; - } - if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages) - && k == cycle * REGEXP_ONEOF (regexp)->regexps_num) - { - if (!annotation_message_reported_p) - { - fprintf (stderr, "\n"); - error ("The following units do not satisfy units-automata distribution rule"); - error (" (A unit of given unit automaton should be on each reserv. altern.)"); - annotation_message_reported_p = TRUE; - } - error ("Unit %s, reserv. %s, cycle %d", - unit_usage_ptr->unit_decl->name, insn_reserv_name, - cycle); - } - } + { + if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle) + continue; + unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle; + for (alt = 0; alt < n_alts; alt++) + if (! unit_present_on_list_p (VEC_index (unit_usage_t, + cycle_alt_unit_usages, + start + alt), + unit_usage_ptr->unit_decl)) + break; + if (alt >= n_alts) + continue; + memset (VEC_address (int, marked), 0, n_alts * sizeof (int)); + for (alt = 0; alt < n_alts; alt++) + { + if (! unit_present_on_list_p (VEC_index (unit_usage_t, + cycle_alt_unit_usages, + start + alt), + unit_usage_ptr->unit_decl)) + continue; + for (j = 0; + j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); + j++) + { + alt2 = j % n_alts; + if (! unit_present_on_list_p + (VEC_index (unit_usage_t, cycle_alt_unit_usages, + start + alt2), + unit_usage_ptr->unit_decl) + && equal_alternatives_p (alt, alt2, n_alts, + unit_usage_ptr + ->unit_decl->automaton_decl)) + { + VEC_replace (int, marked, alt, 1); + VEC_replace (int, marked, alt2, 1); + } + } + } + for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++) + ; + if (alt < n_alts && 0) + { + if (! annotation_message_reported_p) + { + fprintf (stderr, "\n"); + error ("The following units do not satisfy units-automata distribution rule"); + error ("(Unit presence on one alt and its absence on other alt\n"); + error (" result in different other automata reservations)"); + annotation_message_reported_p = TRUE; + } + if (! annotation_reservation_message_reported_p) + { + error ("Reserv %s:", insn_reserv_name); + annotation_reservation_message_reported_p = true; + } + error (" Unit %s, cycle %d, alt %d, another alt %d", + unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt); + } + } } - VEC_free (unit_usage_t,heap, cycle_alt_unit_usages); + VEC_free (int, heap, marked); + VEC_free (unit_usage_t, heap, cycle_alt_unit_usages); obstack_free (&unit_usages, NULL); } @@ -5110,15 +5215,26 @@ check_unit_distributions_to_automata (void) if (progress_flag) fprintf (stderr, "Check unit distributions to automata..."); - annotation_message_reported_p = FALSE; + automaton_decls = NULL; for (i = 0; i < description->decls_num; i++) { decl = description->decls [i]; - if (decl->mode == dm_insn_reserv) - check_regexp_units_distribution - (DECL_INSN_RESERV (decl)->name, - DECL_INSN_RESERV (decl)->transformed_regexp); + if (decl->mode == dm_automaton) + VEC_safe_push (decl_t, heap, automaton_decls, decl); } + if (VEC_length (decl_t, automaton_decls) > 1) + { + annotation_message_reported_p = FALSE; + for (i = 0; i < description->decls_num; i++) + { + decl = description->decls [i]; + if (decl->mode == dm_insn_reserv) + check_regexp_units_distribution + (DECL_INSN_RESERV (decl)->name, + DECL_INSN_RESERV (decl)->transformed_regexp); + } + } + VEC_free (decl_t, heap, automaton_decls); if (progress_flag) fprintf (stderr, "done\n"); } @@ -5155,7 +5271,7 @@ process_seq_for_forming_states (regexp_t regexp, automaton_t automaton, set_state_reserv (state_being_formed, curr_cycle, REGEXP_UNIT (regexp)->unit_decl->unit_num); return curr_cycle; - + case rm_sequence: for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++) curr_cycle @@ -5167,7 +5283,7 @@ process_seq_for_forming_states (regexp_t regexp, automaton_t automaton, { int finish_cycle = 0; int cycle; - + for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++) { cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp) @@ -5278,7 +5394,7 @@ form_ainsn_with_same_reservs (automaton_t automaton) { ainsn_t curr_ainsn; size_t i; - VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150); + VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150); for (curr_ainsn = automaton->ainsn_list; curr_ainsn != NULL; @@ -5310,7 +5426,7 @@ form_ainsn_with_same_reservs (automaton_t automaton) curr_ainsn->first_insn_with_same_reservs = 1; } } - VEC_free (ainsn_t,heap, last_insns); + VEC_free (ainsn_t, heap, last_insns); } /* Forming unit reservations which can affect creating the automaton @@ -5354,7 +5470,7 @@ make_automaton (automaton_t automaton) state_t state2; ainsn_t advance_cycle_ainsn; arc_t added_arc; - VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150); + VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150); int states_n; reserv_sets_t reservs_matter = form_reservs_matter (automaton); @@ -5362,7 +5478,7 @@ make_automaton (automaton_t automaton) start_state = insert_state (get_free_state (1, automaton)); automaton->start_state = start_state; start_state->it_was_placed_in_stack_for_NDFA_forming = 1; - VEC_safe_push (state_t,heap, state_stack, start_state); + VEC_safe_push (state_t, heap, state_stack, start_state); states_n = 1; while (VEC_length (state_t, state_stack) != 0) { @@ -5391,7 +5507,7 @@ make_automaton (automaton_t automaton) { state2->it_was_placed_in_stack_for_NDFA_forming = 1; - VEC_safe_push (state_t,heap, state_stack, state2); + VEC_safe_push (state_t, heap, state_stack, state2); states_n++; if (progress_flag && states_n % 100 == 0) fprintf (stderr, "."); @@ -5417,7 +5533,7 @@ make_automaton (automaton_t automaton) if (!state2->it_was_placed_in_stack_for_NDFA_forming) { state2->it_was_placed_in_stack_for_NDFA_forming = 1; - VEC_safe_push (state_t,heap, state_stack, state2); + VEC_safe_push (state_t, heap, state_stack, state2); states_n++; if (progress_flag && states_n % 100 == 0) fprintf (stderr, "."); @@ -5425,7 +5541,7 @@ make_automaton (automaton_t automaton) gcc_assert (advance_cycle_ainsn); add_arc (state, state2, advance_cycle_ainsn); } - VEC_free (state_t,heap, state_stack); + VEC_free (state_t, heap, state_stack); } /* Form lists of all arcs of STATE marked by the same ainsn. */ @@ -5458,7 +5574,7 @@ form_arcs_marked_by_insn (state_t state) static int create_composed_state (state_t original_state, arc_t arcs_marked_by_insn, - VEC(state_t,heap) **state_stack) + VEC(state_t, heap) **state_stack) { state_t state; alt_state_t alt_state, curr_alt_state; @@ -5548,7 +5664,7 @@ create_composed_state (state_t original_state, arc_t arcs_marked_by_insn, if (!state->it_was_placed_in_stack_for_DFA_forming) { state->it_was_placed_in_stack_for_DFA_forming = 1; - VEC_safe_push (state_t,heap, *state_stack, state); + VEC_safe_push (state_t, heap, *state_stack, state); } return new_state_p; } @@ -5562,16 +5678,16 @@ NDFA_to_DFA (automaton_t automaton) state_t start_state; state_t state; decl_t decl; - VEC(state_t,heap) *state_stack; + VEC(state_t, heap) *state_stack; int i; int states_n; - state_stack = VEC_alloc (state_t,heap, 0); + state_stack = VEC_alloc (state_t, heap, 0); /* Create the start state (empty state). */ start_state = automaton->start_state; start_state->it_was_placed_in_stack_for_DFA_forming = 1; - VEC_safe_push (state_t,heap, state_stack, start_state); + VEC_safe_push (state_t, heap, state_stack, start_state); states_n = 1; while (VEC_length (state_t, state_stack) != 0) { @@ -5591,7 +5707,7 @@ NDFA_to_DFA (automaton_t automaton) } } } - VEC_free (state_t,heap, state_stack); + VEC_free (state_t, heap, state_stack); } /* The following variable value is current number (1, 2, ...) of passing @@ -5633,14 +5749,14 @@ initiate_pass_states (void) /* The following vla is used for storing pointers to all achieved states. */ -static VEC(state_t,heap) *all_achieved_states; +static VEC(state_t, heap) *all_achieved_states; /* This function is called by function pass_states to add an achieved STATE. */ static void add_achieved_state (state_t state) { - VEC_safe_push (state_t,heap, all_achieved_states, state); + VEC_safe_push (state_t, heap, all_achieved_states, state); } /* The function sets up equivalence numbers of insns which mark all @@ -5703,7 +5819,7 @@ cache_presence (state_t state) unsigned int sz; sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1) / (sizeof (int) * CHAR_BIT); - + state->presence_signature = XCREATENODEVEC (unsigned int, sz); for (i = 0; i < description->units_num; i++) if (units_array [i]->query_p) @@ -5779,13 +5895,13 @@ compare_states_for_equiv (const void *state_ptr_1, classes and saves it into *CLASSES. This function requires the input to be sorted via compare_states_for_equiv(). */ static int -init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes) +init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes) { size_t i; state_t prev = 0; int class_num = 1; - *classes = VEC_alloc (state_t,heap, 150); + *classes = VEC_alloc (state_t, heap, 150); for (i = 0; i < VEC_length (state_t, states); i++) { state_t state = VEC_index (state_t, states, i); @@ -5793,7 +5909,7 @@ init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes) { if (compare_states_for_equiv (&prev, &state) != 0) { - VEC_safe_push (state_t,heap, *classes, prev); + VEC_safe_push (state_t, heap, *classes, prev); class_num++; prev = NULL; } @@ -5803,17 +5919,17 @@ init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes) prev = state; } if (prev) - VEC_safe_push (state_t,heap, *classes, prev); + VEC_safe_push (state_t, heap, *classes, prev); return class_num; } /* The function copies pointers to equivalent states from vla FROM into vla TO. */ static void -copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from) +copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from) { - VEC_free (state_t,heap, *to); - *to = VEC_copy (state_t,heap, from); + VEC_free (state_t, heap, *to); + *to = VEC_copy (state_t, heap, from); } /* The function processes equivalence class given by its first state, @@ -5825,7 +5941,7 @@ copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from) partitioned, the function returns nonzero value. */ static int partition_equiv_class (state_t first_state, int odd_iteration_flag, - VEC(state_t,heap) **next_iteration_classes, + VEC(state_t, heap) **next_iteration_classes, int *new_equiv_class_num_ptr) { state_t new_equiv_class; @@ -5849,7 +5965,7 @@ partition_equiv_class (state_t first_state, int odd_iteration_flag, curr_state = next_state) { next_state = curr_state->next_equiv_class_state; - if (state_is_differed (curr_state, first_state, + if (state_is_differed (curr_state, first_state, odd_iteration_flag)) { /* Remove curr state from the class equivalence. */ @@ -5871,7 +5987,7 @@ partition_equiv_class (state_t first_state, int odd_iteration_flag, clear_arc_insns_equiv_num (first_state); } if (new_equiv_class != NULL) - VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class); + VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class); first_state = new_equiv_class; } return partition_p; @@ -5880,15 +5996,15 @@ partition_equiv_class (state_t first_state, int odd_iteration_flag, /* The function finds equivalent states of AUTOMATON. */ static void evaluate_equiv_classes (automaton_t automaton, - VEC(state_t,heap) **equiv_classes) + VEC(state_t, heap) **equiv_classes) { int new_equiv_class_num; int odd_iteration_flag; int finish_flag; - VEC (state_t,heap) *next_iteration_classes; + VEC (state_t, heap) *next_iteration_classes; size_t i; - all_achieved_states = VEC_alloc (state_t,heap, 1500); + all_achieved_states = VEC_alloc (state_t, heap, 1500); pass_states (automaton, add_achieved_state); pass_states (automaton, cache_presence); qsort (VEC_address (state_t, all_achieved_states), @@ -5922,13 +6038,13 @@ evaluate_equiv_classes (automaton_t automaton, finish_flag = 0; } while (!finish_flag); - VEC_free (state_t,heap, next_iteration_classes); - VEC_free (state_t,heap, all_achieved_states); + VEC_free (state_t, heap, next_iteration_classes); + VEC_free (state_t, heap, all_achieved_states); } /* The function merges equivalent states of AUTOMATON. */ static void -merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes) +merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes) { state_t curr_state; state_t new_state; @@ -6043,13 +6159,13 @@ set_new_cycle_flags (state_t state) static void minimize_DFA (automaton_t automaton) { - VEC(state_t,heap) *equiv_classes = 0; + VEC(state_t, heap) *equiv_classes = 0; evaluate_equiv_classes (automaton, &equiv_classes); merge_states (automaton, equiv_classes); pass_states (automaton, set_new_cycle_flags); - VEC_free (state_t,heap, equiv_classes); + VEC_free (state_t, heap, equiv_classes); } /* Values of two variables are counted number of states and arcs in an @@ -6589,11 +6705,11 @@ form_regexp (regexp_t regexp) const char *name = (regexp->mode == rm_unit ? REGEXP_UNIT (regexp)->name : REGEXP_RESERV (regexp)->name); - + obstack_grow (&irp, name, strlen (name)); break; } - + case rm_sequence: for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++) { @@ -6619,7 +6735,7 @@ form_regexp (regexp_t regexp) } obstack_1grow (&irp, ')'); break; - + case rm_oneof: for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++) { @@ -6632,11 +6748,11 @@ form_regexp (regexp_t regexp) obstack_1grow (&irp, ')'); } break; - + case rm_repeat: { char digits [30]; - + if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof) @@ -6984,7 +7100,7 @@ output_translate_vect (automaton_t automaton) int insn_value; vla_hwint_t translate_vect; - translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num); + translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num); for (insn_value = 0; insn_value < description->insns_num; insn_value++) /* Undefined value */ @@ -7005,7 +7121,7 @@ output_translate_vect (automaton_t automaton) fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n"); output_vect (translate_vect); fprintf (output_file, "};\n\n"); - VEC_free (vect_el_t,heap, translate_vect); + VEC_free (vect_el_t, heap, translate_vect); } /* The value in a table state x ainsn -> something which represents @@ -7032,16 +7148,16 @@ create_state_ainsn_table (automaton_t automaton) tab = XCREATENODE (struct state_ainsn_table); tab->automaton = automaton; - tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000); - tab->check_vect = VEC_alloc (vect_el_t,heap, 10000); + tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000); + tab->check_vect = VEC_alloc (vect_el_t, heap, 10000); tab->base_vect = 0; - VEC_safe_grow (vect_el_t,heap, tab->base_vect, + VEC_safe_grow (vect_el_t, heap, tab->base_vect, automaton->achieved_states_num); full_vect_length = (automaton->insn_equiv_classes_num * automaton->achieved_states_num); - tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length); + tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length); for (i = 0; i < full_vect_length; i++) VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value); @@ -7129,7 +7245,7 @@ add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect) { size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num; if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length) - VEC_safe_grow (vect_el_t,heap, tab->full_vect, + VEC_safe_grow (vect_el_t, heap, tab->full_vect, full_base + vect_length); for (i = 0; i < vect_length; i++) VEC_replace (vect_el_t, tab->full_vect, full_base + i, @@ -7229,8 +7345,8 @@ add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect) no_state_value = tab->automaton->achieved_states_num; while (additional_els_num > 0) { - VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el); - VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value); + VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el); + VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value); additional_els_num--; } gcc_assert (VEC_length (vect_el_t, tab->comb_vect) @@ -7313,19 +7429,19 @@ add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value) for (vect_index = VEC_length (vect_el_t, *vect); vect_index <= equiv_class_num; vect_index++) - VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value); + VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value); VEC_replace (vect_el_t, *vect, equiv_class_num, el_value); } /* This is for forming vector of states of an automaton. */ -static VEC(state_t,heap) *output_states_vect; +static VEC(state_t, heap) *output_states_vect; /* The function is called by function pass_states. The function adds STATE to `output_states_vect'. */ static void add_states_vect_el (state_t state) { - VEC_safe_push (state_t,heap, output_states_vect, state); + VEC_safe_push (state_t, heap, output_states_vect, state); } /* Form and output vectors (comb, check, base or full vector) @@ -7368,8 +7484,8 @@ output_trans_table (automaton_t automaton) output_trans_full_vect_name, output_trans_comb_vect_name, output_trans_check_vect_name, output_trans_base_vect_name); - VEC_free (state_t,heap, output_states_vect); - VEC_free (vect_el_t,heap, transition_vect); + VEC_free (state_t, heap, output_states_vect); + VEC_free (vect_el_t, heap, transition_vect); } /* The current number of passing states to find minimal issue delay @@ -7459,7 +7575,7 @@ output_min_issue_delay_table (automaton_t automaton) min_issue_delay_len = (VEC_length (state_t, output_states_vect) * automaton->insn_equiv_classes_num); - min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len); + min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len); for (i = 0; i < min_issue_delay_len; i++) VEC_quick_push (vect_el_t, min_issue_delay_vect, 0); @@ -7501,7 +7617,7 @@ output_min_issue_delay_table (automaton_t automaton) compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor; compressed_min_issue_delay_vect - = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len); + = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len); for (i = 0; i < compressed_min_issue_delay_len; i++) VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0); @@ -7517,9 +7633,9 @@ output_min_issue_delay_table (automaton_t automaton) } output_vect (compressed_min_issue_delay_vect); fprintf (output_file, "};\n\n"); - VEC_free (state_t,heap, output_states_vect); - VEC_free (vect_el_t,heap, min_issue_delay_vect); - VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect); + VEC_free (state_t, heap, output_states_vect); + VEC_free (vect_el_t, heap, min_issue_delay_vect); + VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect); } /* Form and output vector representing the locked states of @@ -7538,7 +7654,7 @@ output_dead_lock_vect (automaton_t automaton) output_states_vect = 0; pass_states (automaton, add_states_vect_el); - VEC_safe_grow (vect_el_t,heap, dead_lock_vect, + VEC_safe_grow (vect_el_t, heap, dead_lock_vect, VEC_length (state_t, output_states_vect)); for (i = 0; i < VEC_length (state_t, output_states_vect); i++) { @@ -7566,8 +7682,8 @@ output_dead_lock_vect (automaton_t automaton) fprintf (output_file, "[] = {\n"); output_vect (dead_lock_vect); fprintf (output_file, "};\n\n"); - VEC_free (state_t,heap, output_states_vect); - VEC_free (vect_el_t,heap, dead_lock_vect); + VEC_free (state_t, heap, output_states_vect); + VEC_free (vect_el_t, heap, dead_lock_vect); } /* Form and output vector representing reserved units of the states of @@ -7592,8 +7708,8 @@ output_reserved_units_table (automaton_t automaton) reserved_units_size = (VEC_length (state_t, output_states_vect) * state_byte_size); - reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size); - + reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size); + for (i = 0; i < reserved_units_size; i++) VEC_quick_push (vect_el_t, reserved_units_table, 0); for (n = 0; n < VEC_length (state_t, output_states_vect); n++) @@ -7622,8 +7738,8 @@ output_reserved_units_table (automaton_t automaton) fprintf (output_file, "};\n#endif /* #if %s */\n\n", CPU_UNITS_QUERY_MACRO_NAME); - VEC_free (state_t,heap, output_states_vect); - VEC_free (vect_el_t,heap, reserved_units_table); + VEC_free (state_t, heap, output_states_vect); + VEC_free (vect_el_t, heap, reserved_units_table); } /* The function outputs all tables representing DFA(s) used for fast @@ -8102,7 +8218,7 @@ output_min_insn_conflict_delay_func (void) fprintf (output_file, "}\n\n"); } -/* Output the array holding default latency values. These are used in +/* Output the array holding default latency values. These are used in insn_latency and maximal_insn_latency function implementations. */ static void output_default_latencies (void) @@ -8326,7 +8442,7 @@ output_print_reservation_func (void) { gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num); j++; - + fprintf (output_file, "\n \"%s\",", regexp_representation (DECL_INSN_RESERV (decl)->regexp)); finish_regexp_representation (); @@ -8728,7 +8844,7 @@ output_automaton_units (automaton_t automaton) /* The following variable is used for forming array of all possible cpu unit reservations described by the current DFA state. */ -static VEC(reserv_sets_t,heap) *state_reservs; +static VEC(reserv_sets_t, heap) *state_reservs; /* The function forms `state_reservs' for STATE. */ static void @@ -8742,7 +8858,7 @@ add_state_reservs (state_t state) curr_alt_state = curr_alt_state->next_sorted_alt_state) add_state_reservs (curr_alt_state->state); else - VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs); + VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs); } /* The function outputs readable representation of all out arcs of @@ -8840,7 +8956,7 @@ output_state (state_t state) VEC_length (reserv_sets_t, state_reservs), sizeof (reserv_sets_t), state_reservs_cmp); remove_state_duplicate_reservs (); - for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++) + for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++) { fprintf (output_description_file, " "); output_reserv_sets (output_description_file, @@ -8849,7 +8965,7 @@ output_state (state_t state) } fprintf (output_description_file, "\n"); output_state_arcs (state); - VEC_free (reserv_sets_t,heap, state_reservs); + VEC_free (reserv_sets_t, heap, state_reservs); } /* The following function output readable representation of @@ -9114,10 +9230,9 @@ check_automata_insn_issues (void) automaton->corresponding_automaton_decl->name, reserv_ainsn->insn_reserv_decl->name); else - warning - (0, "Automaton `%s': Insn `%s' will never be issued", - automaton->corresponding_automaton_decl->name, - reserv_ainsn->insn_reserv_decl->name); + warning ("Automaton `%s': Insn `%s' will never be issued", + automaton->corresponding_automaton_decl->name, + reserv_ainsn->insn_reserv_decl->name); } else { @@ -9125,7 +9240,7 @@ check_automata_insn_issues (void) error ("Insn `%s' will never be issued", reserv_ainsn->insn_reserv_decl->name); else - warning (0, "Insn `%s' will never be issued", + warning ("Insn `%s' will never be issued", reserv_ainsn->insn_reserv_decl->name); } } @@ -9134,14 +9249,14 @@ check_automata_insn_issues (void) /* The following vla is used for storing pointers to all achieved states. */ -static VEC(state_t,heap) *automaton_states; +static VEC(state_t, heap) *automaton_states; /* This function is called by function pass_states to add an achieved STATE. */ static void add_automaton_state (state_t state) { - VEC_safe_push (state_t,heap, automaton_states, state); + VEC_safe_push (state_t, heap, automaton_states, state); } /* The following function forms list of important automata (whose @@ -9180,7 +9295,7 @@ form_important_insn_automata_lists (void) } } } - VEC_free (state_t,heap, automaton_states); + VEC_free (state_t, heap, automaton_states); /* Create automata sets for the insns. */ for (i = 0; i < description->decls_num; i++) @@ -9434,30 +9549,34 @@ main (int argc, char **argv) if (have_error) return FATAL_EXIT_CODE; - puts ("/* Generated automatically by the program `genautomata'\n" - " from the machine description file `md'. */\n\n" - "#include \"config.h\"\n" - "#include \"system.h\"\n" - "#include \"coretypes.h\"\n" - "#include \"tm.h\"\n" - "#include \"rtl.h\"\n" - "#include \"tm_p.h\"\n" - "#include \"insn-config.h\"\n" - "#include \"recog.h\"\n" - "#include \"regs.h\"\n" - "#include \"real.h\"\n" - "#include \"output.h\"\n" - "#include \"insn-attr.h\"\n" - "#include \"toplev.h\"\n" - "#include \"flags.h\"\n" - "#include \"function.h\"\n"); - if (VEC_length (decl_t, decls) > 0) { expand_automata (); - write_automata (); + if (!have_error) + { + puts ("/* Generated automatically by the program `genautomata'\n" + " from the machine description file `md'. */\n\n" + "#include \"config.h\"\n" + "#include \"system.h\"\n" + "#include \"coretypes.h\"\n" + "#include \"tm.h\"\n" + "#include \"rtl.h\"\n" + "#include \"tm_p.h\"\n" + "#include \"insn-config.h\"\n" + "#include \"recog.h\"\n" + "#include \"regs.h\"\n" + "#include \"real.h\"\n" + "#include \"output.h\"\n" + "#include \"insn-attr.h\"\n" + "#include \"toplev.h\"\n" + "#include \"flags.h\"\n" + "#include \"function.h\"\n"); + + write_automata (); + } } fflush (stdout); - return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); + return (ferror (stdout) != 0 || have_error + ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); } diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 0851596585b..74b1d256ba2 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -1,6 +1,6 @@ /* Support routines for the various generation passes. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 - Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010, Free Software Foundation, Inc. This file is part of GCC. @@ -336,7 +336,7 @@ process_rtx (rtx desc, int lineno) /* Queue them. */ insn_elem - = queue_pattern (desc, &define_insn_tail, read_rtx_filename, + = queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno); split_elem = queue_pattern (split, &other_tail, read_rtx_filename, lineno); @@ -780,6 +780,7 @@ process_one_cond_exec (struct queue_elem *ce_elem) { int alternatives, max_operand; rtx pred, insn, pattern, split; + char *new_name; int i; if (! is_predicable (insn_elem)) @@ -806,7 +807,9 @@ process_one_cond_exec (struct queue_elem *ce_elem) /* Construct a new pattern for the new insn. */ insn = copy_rtx (insn_elem->data); - XSTR (insn, 0) = ""; + new_name = XNEWVAR (char, strlen XSTR (insn_elem->data, 0) + 4); + sprintf (new_name, "*p %s", XSTR (insn_elem->data, 0)); + XSTR (insn, 0) = new_name; pattern = rtx_alloc (COND_EXEC); XEXP (pattern, 0) = pred; if (XVECLEN (insn, 1) == 1) @@ -875,7 +878,7 @@ process_one_cond_exec (struct queue_elem *ce_elem) XVECEXP (split, 2, i) = pattern; } /* Add the new split to the queue. */ - queue_pattern (split, &other_tail, read_rtx_filename, + queue_pattern (split, &other_tail, read_rtx_filename, insn_elem->split->lineno); } } @@ -927,7 +930,7 @@ init_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *)) { if (argv[i][0] != '-') continue; - + c = argv[i][1]; switch (c) { @@ -996,7 +999,7 @@ init_md_reader_args_cb (int argc, char **argv, bool (*parse_opt)(const char *)) /* Read stdin. */ if (already_read_stdin) fatal ("cannot read standard input twice"); - + base_dir = NULL; read_rtx_filename = in_fname = "<stdin>"; read_rtx_lineno = 1; @@ -1358,7 +1361,7 @@ static const struct std_pred_table std_preds[] = { {"register_operand", false, false, {SUBREG, REG}}, {"pmode_register_operand", true, false, {SUBREG, REG}}, {"scratch_operand", false, false, {SCRATCH, REG}}, - {"immediate_operand", false, true, {0}}, + {"immediate_operand", false, true, {UNKNOWN}}, {"const_int_operand", false, false, {CONST_INT}}, {"const_double_operand", false, false, {CONST_INT, CONST_DOUBLE}}, {"nonimmediate_operand", false, false, {SUBREG, REG, MEM}}, @@ -1367,6 +1370,9 @@ static const struct std_pred_table std_preds[] = { {"pop_operand", false, false, {MEM}}, {"memory_operand", false, false, {SUBREG, MEM}}, {"indirect_operand", false, false, {SUBREG, MEM}}, + {"ordered_comparison_operator", false, false, {EQ, NE, + LE, LT, GE, GT, + LEU, LTU, GEU, GTU}}, {"comparison_operator", false, false, {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU, @@ -1401,8 +1407,8 @@ init_predicate_table (void) if (std_preds[i].allows_const_p) for (j = 0; j < NUM_RTX_CODE; j++) if (GET_RTX_CLASS (j) == RTX_CONST_OBJ) - add_predicate_code (pred, j); - + add_predicate_code (pred, (enum rtx_code) j); + add_predicate (pred); } } diff --git a/gcc/recog.c b/gcc/recog.c index 50e7b4e497e..666b7422da6 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1,6 +1,6 @@ /* Subroutines used by or related to instruction recognition. Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -286,7 +286,7 @@ canonicalize_change_group (rtx insn, rtx x) else return false; } - + /* This subroutine of apply_change_group verifies whether the changes to INSN were valid; i.e. whether INSN can still be recognized. */ @@ -1322,6 +1322,32 @@ indirect_operand (rtx op, enum machine_mode mode) && general_operand (XEXP (op, 0), Pmode)); } +/* Return 1 if this is an ordered comparison operator (not including + ORDERED and UNORDERED). */ + +int +ordered_comparison_operator (rtx op, enum machine_mode mode) +{ + if (mode != VOIDmode && GET_MODE (op) != mode) + return false; + switch (GET_CODE (op)) + { + case EQ: + case NE: + case LT: + case LTU: + case LE: + case LEU: + case GT: + case GTU: + case GE: + case GEU: + return true; + default: + return false; + } +} + /* Return 1 if this is a comparison operator. This allows the use of MATCH_OPERATOR to recognize all the branch insns. */ diff --git a/gcc/target-def.h b/gcc/target-def.h index 114bc4ccc3e..0e16ad37d32 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -1,5 +1,5 @@ /* Default initializers for a generic GCC target. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it @@ -383,6 +383,8 @@ #define TARGET_VECTOR_ALIGNMENT_REACHABLE \ default_builtin_vector_alignment_reachable #define TARGET_VECTORIZE_BUILTIN_VEC_PERM 0 +#define TARGET_SUPPORT_VECTOR_MISALIGNMENT \ + default_builtin_support_vector_misalignment #define TARGET_VECTORIZE \ { \ @@ -393,7 +395,8 @@ TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD, \ TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST, \ TARGET_VECTOR_ALIGNMENT_REACHABLE, \ - TARGET_VECTORIZE_BUILTIN_VEC_PERM \ + TARGET_VECTORIZE_BUILTIN_VEC_PERM, \ + TARGET_SUPPORT_VECTOR_MISALIGNMENT \ } #define TARGET_DEFAULT_TARGET_FLAGS 0 diff --git a/gcc/target.h b/gcc/target.h index 675e2791e93..43bc58400f4 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -1,5 +1,5 @@ /* Data structure definitions for a generic GCC target. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it @@ -473,6 +473,12 @@ struct gcc_target /* Target builtin that implements vector permute. */ tree (* builtin_vec_perm) (tree, tree*); + + /* Return true if the target supports misaligned store/load of a + specific factor denoted in the third parameter. The last parameter + is true if the access is defined in a packed struct. */ + bool (* builtin_support_vector_misalignment) (enum machine_mode, + const_tree, int, bool); } vectorize; /* The initial value of target_flags. */ diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 545ff66d178..a69a0b9369e 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -697,6 +697,23 @@ tree default_mangle_decl_assembler_name (tree decl ATTRIBUTE_UNUSED, return id; } +/* By default, assume that a target supports any factor of misalignment + memory access if it supports movmisalign patten. + is_packed is true if the memory access is defined in a packed struct. */ +bool +default_builtin_support_vector_misalignment (enum machine_mode mode, + const_tree type + ATTRIBUTE_UNUSED, + int misalignment + ATTRIBUTE_UNUSED, + bool is_packed + ATTRIBUTE_UNUSED) +{ + if (optab_handler (movmisalign_optab, mode)->insn_code != CODE_FOR_nothing) + return true; + return false; +} + bool default_builtin_vector_alignment_reachable (const_tree type, bool is_packed) { diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 464655d8635..f0358a6edad 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -70,6 +70,9 @@ extern tree default_builtin_vectorized_conversion (enum tree_code, tree); extern tree default_builtin_reciprocal (enum built_in_function, bool, bool); extern bool default_builtin_vector_alignment_reachable (const_tree, bool); +extern bool default_builtin_support_vector_misalignment (enum machine_mode mode, + const_tree, + int, bool); /* These are here, and not in hooks.[ch], because not all users of hooks.h include tm.h, and thus we don't have CUMULATIVE_ARGS. */ diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index c1ff943360d..fe168b384cc 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -1,5 +1,5 @@ /* Loop Vectorization - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Dorit Naishlos <dorit@il.ibm.com> @@ -2112,6 +2112,9 @@ vect_supportable_dr_alignment (struct data_reference *dr) if (DR_IS_READ (dr)) { + bool is_packed = false; + tree type = (TREE_TYPE (DR_REF (dr))); + if (optab_handler (vec_realign_load_optab, mode)->insn_code != CODE_FOR_nothing && (!targetm.vectorize.builtin_mask_for_load @@ -2125,9 +2128,17 @@ vect_supportable_dr_alignment (struct data_reference *dr) else return dr_explicit_realign_optimized; } + if (!known_alignment_for_access_p (dr)) + { + tree ba = DR_BASE_OBJECT (dr); + + if (ba) + is_packed = contains_packed_reference (ba); + } - if (optab_handler (movmisalign_optab, mode)->insn_code != - CODE_FOR_nothing) + if (targetm.vectorize. + builtin_support_vector_misalignment (mode, type, + DR_MISALIGNMENT (dr), is_packed)) /* Can't software pipeline the loads, but can at least do them. */ return dr_unaligned_supported; } |