Mercurial > hg > CbC > CbC_gcc
diff gcc/config/rs6000/rs6000.md @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | ab0bcb71f44d 84e7813d76e9 |
children | 351920fa3827 |
line wrap: on
line diff
--- a/gcc/config/rs6000/rs6000.md Thu Oct 25 08:08:40 2018 +0900 +++ b/gcc/config/rs6000/rs6000.md Thu Oct 25 10:21:07 2018 +0900 @@ -1,5 +1,5 @@ ;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler -;; Copyright (C) 1990-2017 Free Software Foundation, Inc. +;; Copyright (C) 1990-2018 Free Software Foundation, Inc. ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) ;; This file is part of GCC. @@ -130,16 +130,13 @@ UNSPEC_CDTBCD UNSPEC_CBCDTD UNSPEC_DIVE - UNSPEC_DIVEO UNSPEC_DIVEU - UNSPEC_DIVEUO UNSPEC_UNPACK_128BIT UNSPEC_PACK_128BIT UNSPEC_LSQ UNSPEC_FUSION_GPR UNSPEC_STACK_CHECK UNSPEC_FUSION_P9 - UNSPEC_FUSION_ADDIS UNSPEC_ADD_ROUND_TO_ODD UNSPEC_SUB_ROUND_TO_ODD UNSPEC_MUL_ROUND_TO_ODD @@ -166,8 +163,15 @@ UNSPECV_MFTB ; move from time base UNSPECV_NLGR ; non-local goto receiver UNSPECV_MFFS ; Move from FPSCR - UNSPECV_MTFSF ; Move to FPSCR Fields + UNSPECV_MFFSL ; Move from FPSCR light instruction version + UNSPECV_MFFSCRN ; Move from FPSCR float rounding mode + UNSPECV_MFFSCDRN ; Move from FPSCR decimal float rounding mode + UNSPECV_MTFSF ; Move to FPSCR Fields 8 to 15 + UNSPECV_MTFSF_HI ; Move to FPSCR Fields 0 to 7 + UNSPECV_MTFSB0 ; Set FPSCR Field bit to 0 + UNSPECV_MTFSB1 ; Set FPSCR Field bit to 1 UNSPECV_SPLIT_STACK_RETURN ; A camouflaged return + UNSPECV_SPEC_BARRIER ; Speculation barrier ]) @@ -181,8 +185,8 @@ load,store,fpload,fpstore,vecload,vecstore, cmp, branch,jmpreg,mfjmpr,mtjmpr,trap,isync,sync,load_l,store_c, - cr_logical,delayed_cr,mfcr,mfcrf,mtcr, - fpcompare,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt, + cr_logical,mfcr,mfcrf,mtcr, + fpcompare,fp,fpsimple,dmul,qmul,sdiv,ddiv,ssqrt,dsqrt, vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm, vecfloat,vecfdiv,vecdouble,mffgpr,mftgpr,crypto, veclogical,veccmpfx,vecexts,vecmove, @@ -205,6 +209,9 @@ ;; This is used for load insns. (define_attr "sign_extend" "no,yes" (const_string "no")) +;; Does this cr_logical instruction have three operands? That is, BT != BB. +(define_attr "cr_logical_3op" "no,yes" (const_string "no")) + ;; Does this instruction use indexed (that is, reg+reg) addressing? ;; This is used for load and store insns. If operand 0 or 1 is a MEM ;; it is automatically set based on that. If a load or store instruction @@ -242,21 +249,8 @@ ;; Is copying of this instruction disallowed? (define_attr "cannot_copy" "no,yes" (const_string "no")) -;; Define floating point instruction sub-types for use with Xfpu.md -(define_attr "fp_type" "fp_default,fp_addsub_s,fp_addsub_d,fp_mul_s,fp_mul_d,fp_div_s,fp_div_d,fp_maddsub_s,fp_maddsub_d,fp_sqrt_s,fp_sqrt_d" (const_string "fp_default")) - -;; Length (in bytes). -; '(pc)' in the following doesn't include the instruction itself; it is -; calculated as if the instruction had zero size. -(define_attr "length" "" - (if_then_else (eq_attr "type" "branch") - (if_then_else (and (ge (minus (match_dup 0) (pc)) - (const_int -32768)) - (lt (minus (match_dup 0) (pc)) - (const_int 32764))) - (const_int 4) - (const_int 8)) - (const_int 4))) +;; Length of the instruction (in bytes). +(define_attr "length" "" (const_int 4)) ;; Processor type -- this attribute must exactly match the processor_type ;; enumeration in rs6000-opts.h. @@ -267,7 +261,7 @@ ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500, power4,power5,power6,power7,power8,power9, rs64a,mpccore,cell,ppca2,titan" - (const (symbol_ref "rs6000_cpu_attr"))) + (const (symbol_ref "(enum attr_cpu) rs6000_tune"))) ;; If this instruction is microcoded on the CELL processor @@ -307,7 +301,6 @@ (include "power8.md") (include "power9.md") (include "cell.md") -(include "xfpu.md") (include "a2.md") (include "titan.md") @@ -323,6 +316,9 @@ ; of whole values in GPRs. (define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")]) +; And again, for patterns that need two (potentially) different integer modes. +(define_mode_iterator GPR2 [SI (DI "TARGET_POWERPC64")]) + ; Any supported integer mode. (define_mode_iterator INT [QI HI SI DI TI PTI]) @@ -376,8 +372,8 @@ ; Any hardware-supported floating-point mode (define_mode_iterator FP [ - (SF "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT") - (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT") + (SF "TARGET_HARD_FLOAT") + (DF "TARGET_HARD_FLOAT") (TF "TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128") (IF "TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128") (KF "TARGET_FLOAT128_TYPE") @@ -386,10 +382,8 @@ ; Any fma capable floating-point mode. (define_mode_iterator FMA_F [ - (SF "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT") - (DF "(TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) - || VECTOR_UNIT_VSX_P (DFmode)") - (V2SF "TARGET_PAIRED_FLOAT") + (SF "TARGET_HARD_FLOAT") + (DF "TARGET_HARD_FLOAT || VECTOR_UNIT_VSX_P (DFmode)") (V4SF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)") (V2DF "VECTOR_UNIT_ALTIVEC_OR_VSX_P (V2DFmode)") (KF "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (KFmode)") @@ -423,6 +417,12 @@ ; Iterator for 128-bit VSX types for pack/unpack (define_mode_iterator FMOVE128_VSX [V1TI KF]) +; Iterators for converting to/from TFmode +(define_mode_iterator IFKF [IF KF]) + +; Constraints for moving IF/KFmode. +(define_mode_attr IFKF_reg [(IF "d") (KF "wa")]) + ; Whether a floating point move is ok, don't allow SD without hardware FP (define_mode_attr fmove_ok [(SF "") (DF "") @@ -513,7 +513,7 @@ ; SF/DF constraint for arithmetic on altivec registers (define_mode_attr Fa [(SF "wu") (DF "wv")]) -; s/d suffix for things like fp_addsub_s/fp_addsub_d +; s/d suffix for things like sdiv/ddiv (define_mode_attr Fs [(SF "s") (DF "d")]) ; FRE/FRES support @@ -543,7 +543,7 @@ (define_code_attr su [(sign_extend "s") (zero_extend "u") (fix "s") - (unsigned_fix "s") + (unsigned_fix "u") (float "s") (unsigned_float "u")]) @@ -614,9 +614,6 @@ (define_mode_attr SI_CONVERT_FP [(SF "TARGET_FCFIDS") (DF "TARGET_FCFID")]) -(define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT") - (DF "TARGET_DOUBLE_FLOAT")]) - ;; Mode iterator for logical operations on 128-bit types (define_mode_iterator BOOL_128 [TI PTI @@ -997,7 +994,7 @@ "=r, r, wl, wu, wj, wK, wH, wr") (sign_extend:EXTSI (match_operand:SI 1 "lwa_operand" - "Y, r, Z, Z, r, wK, wH, ?wIwH")))] + "YZ, r, Z, Z, r, wK, wH, ?wIwH")))] "" "@ lwa%U1%X1 %0,%1 @@ -1037,7 +1034,7 @@ rtx dest_v2di = gen_rtx_REG (V2DImode, dest_regno); rtx src_v4si = gen_rtx_REG (V4SImode, src_regno); - if (VECTOR_ELT_ORDER_BIG) + if (BYTES_BIG_ENDIAN) { emit_insn (gen_altivec_vupkhsw (dest_v2di, src_v4si)); emit_insn (gen_vsx_xxspltd_v2di (dest_v2di, dest_v2di, const1_rtx)); @@ -1569,12 +1566,12 @@ "dlmzb. %0,%1,%2") (define_expand "strlensi" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (unspec:SI [(match_operand:BLK 1 "general_operand" "") - (match_operand:QI 2 "const_int_operand" "") - (match_operand 3 "const_int_operand" "")] + [(set (match_operand:SI 0 "gpc_reg_operand") + (unspec:SI [(match_operand:BLK 1 "general_operand") + (match_operand:QI 2 "const_int_operand") + (match_operand 3 "const_int_operand")] UNSPEC_DLMZB_STRLEN)) - (clobber (match_scratch:CC 4 "=x"))] + (clobber (match_scratch:CC 4))] "TARGET_DLMZB && WORDS_BIG_ENDIAN && !optimize_size" { rtx result = operands[0]; @@ -1623,9 +1620,9 @@ ;; Fixed-point arithmetic insns. (define_expand "add<mode>3" - [(set (match_operand:SDI 0 "gpc_reg_operand" "") - (plus:SDI (match_operand:SDI 1 "gpc_reg_operand" "") - (match_operand:SDI 2 "reg_or_add_cint_operand" "")))] + [(set (match_operand:SDI 0 "gpc_reg_operand") + (plus:SDI (match_operand:SDI 1 "gpc_reg_operand") + (match_operand:SDI 2 "reg_or_add_cint_operand")))] "" { if (<MODE>mode == DImode && !TARGET_POWERPC64) @@ -1798,9 +1795,9 @@ ;; add should be last in case the result gets used in an address. (define_split - [(set (match_operand:GPR 0 "gpc_reg_operand" "") - (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "") - (match_operand:GPR 2 "non_add_cint_operand" "")))] + [(set (match_operand:GPR 0 "gpc_reg_operand") + (plus:GPR (match_operand:GPR 1 "gpc_reg_operand") + (match_operand:GPR 2 "non_add_cint_operand")))] "" [(set (match_dup 0) (plus:GPR (match_dup 1) (match_dup 3))) (set (match_dup 0) (plus:GPR (match_dup 0) (match_dup 4)))] @@ -1912,6 +1909,16 @@ "adde %0,%1,%2" [(set_attr "type" "add")]) +(define_insn "*add<mode>3_carry_in_internal2" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") + (reg:GPR CA_REGNO)) + (match_operand:GPR 2 "gpc_reg_operand" "r"))) + (clobber (reg:GPR CA_REGNO))] + "" + "adde %0,%1,%2" + [(set_attr "type" "add")]) + (define_insn "add<mode>3_carry_in_0" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") @@ -1933,8 +1940,8 @@ (define_expand "one_cmpl<mode>2" - [(set (match_operand:SDI 0 "gpc_reg_operand" "") - (not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))] + [(set (match_operand:SDI 0 "gpc_reg_operand") + (not:SDI (match_operand:SDI 1 "gpc_reg_operand")))] "" { if (<MODE>mode == DImode && !TARGET_POWERPC64) @@ -1993,9 +2000,9 @@ (define_expand "sub<mode>3" - [(set (match_operand:SDI 0 "gpc_reg_operand" "") - (minus:SDI (match_operand:SDI 1 "reg_or_short_operand" "") - (match_operand:SDI 2 "gpc_reg_operand" "")))] + [(set (match_operand:SDI 0 "gpc_reg_operand") + (minus:SDI (match_operand:SDI 1 "reg_or_short_operand") + (match_operand:SDI 2 "gpc_reg_operand")))] "" { if (<MODE>mode == DImode && !TARGET_POWERPC64) @@ -2321,8 +2328,8 @@ (define_expand "popcount<mode>2" - [(set (match_operand:GPR 0 "gpc_reg_operand" "") - (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))] + [(set (match_operand:GPR 0 "gpc_reg_operand") + (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand")))] "TARGET_POPCNTB || TARGET_POPCNTD" { rs6000_emit_popcount (operands[0], operands[1]); @@ -2346,8 +2353,8 @@ (define_expand "parity<mode>2" - [(set (match_operand:GPR 0 "gpc_reg_operand" "") - (parity:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))] + [(set (match_operand:GPR 0 "gpc_reg_operand") + (parity:GPR (match_operand:GPR 1 "gpc_reg_operand")))] "TARGET_POPCNTB" { rs6000_emit_parity (operands[0], operands[1]); @@ -2377,8 +2384,7 @@ (bswap:HSI (match_operand:HSI 1 "memory_operand" "Z"))))] "TARGET_POWERPC64" "l<wd>brx %0,%y1" - [(set_attr "length" "4") - (set_attr "type" "load")]) + [(set_attr "type" "load")]) (define_insn "*bswaphi2_extendsi" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") @@ -2386,8 +2392,7 @@ (bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))] "" "lhbrx %0,%y1" - [(set_attr "length" "4") - (set_attr "type" "load")]) + [(set_attr "type" "load")]) ;; Separate the bswap patterns into load, store, and gpr<-gpr. This prevents ;; the register allocator from converting a gpr<-gpr swap into a store and then @@ -2429,13 +2434,15 @@ [(set_attr "type" "store")]) (define_insn_and_split "bswaphi2_reg" - [(set (match_operand:HI 0 "gpc_reg_operand" "=&r") + [(set (match_operand:HI 0 "gpc_reg_operand" "=&r,wo") (bswap:HI - (match_operand:HI 1 "gpc_reg_operand" "r"))) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "#" - "reload_completed" + (match_operand:HI 1 "gpc_reg_operand" "r,wo"))) + (clobber (match_scratch:SI 2 "=&r,X"))] + "" + "@ + # + xxbrh %x0,%x1" + "reload_completed && int_reg_operand (operands[0], HImode)" [(set (match_dup 3) (and:SI (lshiftrt:SI (match_dup 4) (const_int 8)) @@ -2451,18 +2458,20 @@ operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0); operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0); } - [(set_attr "length" "12") - (set_attr "type" "*")]) + [(set_attr "length" "12,4") + (set_attr "type" "*,vecperm")]) ;; We are always BITS_BIG_ENDIAN, so the bit positions below in ;; zero_extract insns do not change for -mlittle. (define_insn_and_split "bswapsi2_reg" - [(set (match_operand:SI 0 "gpc_reg_operand" "=&r") + [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,wo") (bswap:SI - (match_operand:SI 1 "gpc_reg_operand" "r")))] - "" - "#" - "reload_completed" + (match_operand:SI 1 "gpc_reg_operand" "r,wo")))] + "" + "@ + # + xxbrw %x0,%x1" + "reload_completed && int_reg_operand (operands[0], SImode)" [(set (match_dup 0) ; DABC (rotate:SI (match_dup 1) (const_int 24))) @@ -2478,18 +2487,20 @@ (const_int 255)) (and:SI (match_dup 0) (const_int -256))))] - "") + "" + [(set_attr "length" "12,4") + (set_attr "type" "*,vecperm")]) ;; On systems with LDBRX/STDBRX generate the loads/stores directly, just like ;; we do for L{H,W}BRX and ST{H,W}BRX above. If not, we have to generate more ;; complex code. (define_expand "bswapdi2" - [(parallel [(set (match_operand:DI 0 "reg_or_mem_operand" "") + [(parallel [(set (match_operand:DI 0 "reg_or_mem_operand") (bswap:DI - (match_operand:DI 1 "reg_or_mem_operand" ""))) - (clobber (match_scratch:DI 2 "")) - (clobber (match_scratch:DI 3 ""))])] + (match_operand:DI 1 "reg_or_mem_operand"))) + (clobber (match_scratch:DI 2)) + (clobber (match_scratch:DI 3))])] "" { rtx dest = operands[0]; @@ -2504,6 +2515,8 @@ emit_insn (gen_bswapdi2_load (dest, src)); else if (MEM_P (dest)) emit_insn (gen_bswapdi2_store (dest, src)); + else if (TARGET_P9_VECTOR) + emit_insn (gen_bswapdi2_xxbrd (dest, src)); else emit_insn (gen_bswapdi2_reg (dest, src)); DONE; @@ -2534,12 +2547,19 @@ "stdbrx %1,%y0" [(set_attr "type" "store")]) +(define_insn "bswapdi2_xxbrd" + [(set (match_operand:DI 0 "gpc_reg_operand" "=wo") + (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "wo")))] + "TARGET_P9_VECTOR" + "xxbrd %x0,%x1" + [(set_attr "type" "vecperm")]) + (define_insn "bswapdi2_reg" [(set (match_operand:DI 0 "gpc_reg_operand" "=&r") (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "r"))) (clobber (match_scratch:DI 2 "=&r")) (clobber (match_scratch:DI 3 "=&r"))] - "TARGET_POWERPC64 && TARGET_LDBRX" + "TARGET_POWERPC64 && TARGET_LDBRX && !TARGET_P9_VECTOR" "#" [(set_attr "length" "36")]) @@ -2557,13 +2577,12 @@ [(set_attr "length" "16,12,36")]) (define_split - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" ""))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "")) - (clobber (match_operand:DI 3 "gpc_reg_operand" ""))] + [(set (match_operand:DI 0 "gpc_reg_operand") + (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand"))) + (clobber (match_operand:DI 2 "gpc_reg_operand")) + (clobber (match_operand:DI 3 "gpc_reg_operand"))] "TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed" [(const_int 0)] - " { rtx dest = operands[0]; rtx src = operands[1]; @@ -2618,16 +2637,15 @@ emit_insn (gen_ashldi3 (op3, op3, GEN_INT (32))); emit_insn (gen_iordi3 (dest, dest, op3)); DONE; -}") +}) (define_split - [(set (match_operand:DI 0 "indexed_or_indirect_operand" "") - (bswap:DI (match_operand:DI 1 "gpc_reg_operand" ""))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "")) - (clobber (match_operand:DI 3 "gpc_reg_operand" ""))] + [(set (match_operand:DI 0 "indexed_or_indirect_operand") + (bswap:DI (match_operand:DI 1 "gpc_reg_operand"))) + (clobber (match_operand:DI 2 "gpc_reg_operand")) + (clobber (match_operand:DI 3 "gpc_reg_operand"))] "TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed" [(const_int 0)] - " { rtx dest = operands[0]; rtx src = operands[1]; @@ -2681,16 +2699,15 @@ emit_insn (gen_bswapsi2 (word1, op3_si)); } DONE; -}") +}) (define_split - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (bswap:DI (match_operand:DI 1 "gpc_reg_operand" ""))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "")) - (clobber (match_operand:DI 3 "gpc_reg_operand" ""))] - "TARGET_POWERPC64 && reload_completed" + [(set (match_operand:DI 0 "gpc_reg_operand") + (bswap:DI (match_operand:DI 1 "gpc_reg_operand"))) + (clobber (match_operand:DI 2 "gpc_reg_operand")) + (clobber (match_operand:DI 3 "gpc_reg_operand"))] + "TARGET_POWERPC64 && !TARGET_P9_VECTOR && reload_completed" [(const_int 0)] - " { rtx dest = operands[0]; rtx src = operands[1]; @@ -2708,7 +2725,7 @@ emit_insn (gen_ashldi3 (dest, dest, GEN_INT (32))); emit_insn (gen_iordi3 (dest, dest, op3)); DONE; -}") +}) (define_insn "bswapdi2_32bit" [(set (match_operand:DI 0 "reg_or_mem_operand" "=r,Z,?&r") @@ -2719,12 +2736,11 @@ [(set_attr "length" "16,12,36")]) (define_split - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" ""))) - (clobber (match_operand:SI 2 "gpc_reg_operand" ""))] + [(set (match_operand:DI 0 "gpc_reg_operand") + (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand"))) + (clobber (match_operand:SI 2 "gpc_reg_operand"))] "!TARGET_POWERPC64 && reload_completed" [(const_int 0)] - " { rtx dest = operands[0]; rtx src = operands[1]; @@ -2769,15 +2785,14 @@ thus allowing us to omit an early clobber on the output. */ emit_insn (gen_bswapsi2 (dest1, word2)); DONE; -}") +}) (define_split - [(set (match_operand:DI 0 "indexed_or_indirect_operand" "") - (bswap:DI (match_operand:DI 1 "gpc_reg_operand" ""))) - (clobber (match_operand:SI 2 "gpc_reg_operand" ""))] + [(set (match_operand:DI 0 "indexed_or_indirect_operand") + (bswap:DI (match_operand:DI 1 "gpc_reg_operand"))) + (clobber (match_operand:SI 2 "gpc_reg_operand"))] "!TARGET_POWERPC64 && reload_completed" [(const_int 0)] - " { rtx dest = operands[0]; rtx src = operands[1]; @@ -2818,15 +2833,14 @@ emit_insn (gen_bswapsi2 (word2, src1)); emit_insn (gen_bswapsi2 (word1, src2)); DONE; -}") +}) (define_split - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (bswap:DI (match_operand:DI 1 "gpc_reg_operand" ""))) - (clobber (match_operand:SI 2 "" ""))] + [(set (match_operand:DI 0 "gpc_reg_operand") + (bswap:DI (match_operand:DI 1 "gpc_reg_operand"))) + (clobber (match_operand:SI 2 ""))] "!TARGET_POWERPC64 && reload_completed" [(const_int 0)] - " { rtx dest = operands[0]; rtx src = operands[1]; @@ -2838,7 +2852,7 @@ emit_insn (gen_bswapsi2 (dest1, src2)); emit_insn (gen_bswapsi2 (dest2, src1)); DONE; -}") +}) (define_insn "mul<mode>3" @@ -2851,9 +2865,9 @@ mulli %0,%1,%2" [(set_attr "type" "mul") (set (attr "size") - (cond [(match_operand:GPR 2 "s8bit_cint_operand" "") + (cond [(match_operand:GPR 2 "s8bit_cint_operand") (const_string "8") - (match_operand:GPR 2 "short_cint_operand" "") + (match_operand:GPR 2 "short_cint_operand") (const_string "16")] (const_string "<bits>")))]) @@ -3022,9 +3036,9 @@ ;; modulus. If it isn't a power of two, force operands into register and do ;; a normal divide. (define_expand "div<mode>3" - [(set (match_operand:GPR 0 "gpc_reg_operand" "") - (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "") - (match_operand:GPR 2 "reg_or_cint_operand" "")))] + [(set (match_operand:GPR 0 "gpc_reg_operand") + (div:GPR (match_operand:GPR 1 "gpc_reg_operand") + (match_operand:GPR 2 "reg_or_cint_operand")))] "" { if (CONST_INT_P (operands[2]) @@ -3164,10 +3178,10 @@ ;; after a divide. (define_peephole2 - [(set (match_operand:GPR 0 "gpc_reg_operand" "") - (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "") - (match_operand:GPR 2 "gpc_reg_operand" ""))) - (set (match_operand:GPR 3 "gpc_reg_operand" "") + [(set (match_operand:GPR 0 "gpc_reg_operand") + (div:GPR (match_operand:GPR 1 "gpc_reg_operand") + (match_operand:GPR 2 "gpc_reg_operand"))) + (set (match_operand:GPR 3 "gpc_reg_operand") (mod:GPR (match_dup 1) (match_dup 2)))] "TARGET_MODULO @@ -3186,10 +3200,10 @@ (match_dup 3)))]) (define_peephole2 - [(set (match_operand:GPR 0 "gpc_reg_operand" "") - (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "") - (match_operand:GPR 2 "gpc_reg_operand" ""))) - (set (match_operand:GPR 3 "gpc_reg_operand" "") + [(set (match_operand:GPR 0 "gpc_reg_operand") + (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand") + (match_operand:GPR 2 "gpc_reg_operand"))) + (set (match_operand:GPR 3 "gpc_reg_operand") (umod:GPR (match_dup 1) (match_dup 2)))] "TARGET_MODULO @@ -3215,9 +3229,9 @@ ;; those rotate-and-mask operations. Thus, the AND insns come first. (define_expand "and<mode>3" - [(set (match_operand:SDI 0 "gpc_reg_operand" "") - (and:SDI (match_operand:SDI 1 "gpc_reg_operand" "") - (match_operand:SDI 2 "reg_or_cint_operand" "")))] + [(set (match_operand:SDI 0 "gpc_reg_operand") + (and:SDI (match_operand:SDI 1 "gpc_reg_operand") + (match_operand:SDI 2 "reg_or_cint_operand")))] "" { if (<MODE>mode == DImode && !TARGET_POWERPC64) @@ -3513,9 +3527,9 @@ (define_expand "<code><mode>3" - [(set (match_operand:SDI 0 "gpc_reg_operand" "") - (iorxor:SDI (match_operand:SDI 1 "gpc_reg_operand" "") - (match_operand:SDI 2 "reg_or_cint_operand" "")))] + [(set (match_operand:SDI 0 "gpc_reg_operand") + (iorxor:SDI (match_operand:SDI 1 "gpc_reg_operand") + (match_operand:SDI 2 "reg_or_cint_operand")))] "" { if (<MODE>mode == DImode && !TARGET_POWERPC64) @@ -3544,9 +3558,9 @@ }) (define_split - [(set (match_operand:GPR 0 "gpc_reg_operand" "") - (iorxor:GPR (match_operand:GPR 1 "gpc_reg_operand" "") - (match_operand:GPR 2 "non_logical_cint_operand" "")))] + [(set (match_operand:GPR 0 "gpc_reg_operand") + (iorxor:GPR (match_operand:GPR 1 "gpc_reg_operand") + (match_operand:GPR 2 "non_logical_cint_operand")))] "" [(set (match_dup 3) (iorxor:GPR (match_dup 1) @@ -3829,11 +3843,19 @@ ; Special case for less-than-0. We can do it with just one machine ; instruction, but the generic optimizers do not realise it is cheap. -(define_insn "*lt0_disi" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (lt:DI (match_operand:SI 1 "gpc_reg_operand" "r") - (const_int 0)))] +(define_insn "*lt0_<mode>di" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (lt:GPR (match_operand:DI 1 "gpc_reg_operand" "r") + (const_int 0)))] "TARGET_POWERPC64" + "srdi %0,%1,63" + [(set_attr "type" "shift")]) + +(define_insn "*lt0_<mode>si" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (lt:GPR (match_operand:SI 1 "gpc_reg_operand" "r") + (const_int 0)))] + "" "rlwinm %0,%1,1,31,31" [(set_attr "type" "shift")]) @@ -4036,6 +4058,47 @@ (set_attr "length" "8")]) +; Yet another case is an rldimi with the second value coming from memory. +; The zero_extend that should become part of the rldimi is merged into the +; load from memory instead. Split things properly again. +(define_split + [(set (match_operand:DI 0 "gpc_reg_operand") + (ior:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand") + (match_operand:SI 2 "const_int_operand")) + (zero_extend:DI (match_operand:QHSI 3 "memory_operand"))))] + "INTVAL (operands[2]) == <bits>" + [(set (match_dup 4) + (zero_extend:DI (match_dup 3))) + (set (match_dup 0) + (ior:DI (and:DI (match_dup 4) + (match_dup 5)) + (ashift:DI (match_dup 1) + (match_dup 2))))] +{ + operands[4] = gen_reg_rtx (DImode); + operands[5] = GEN_INT ((HOST_WIDE_INT_1U << <bits>) - 1); +}) + +; rlwimi, too. +(define_split + [(set (match_operand:SI 0 "gpc_reg_operand") + (ior:SI (ashift:SI (match_operand:SI 1 "gpc_reg_operand") + (match_operand:SI 2 "const_int_operand")) + (zero_extend:SI (match_operand:QHI 3 "memory_operand"))))] + "INTVAL (operands[2]) == <bits>" + [(set (match_dup 4) + (zero_extend:SI (match_dup 3))) + (set (match_dup 0) + (ior:SI (and:SI (match_dup 4) + (match_dup 5)) + (ashift:SI (match_dup 1) + (match_dup 2))))] +{ + operands[4] = gen_reg_rtx (SImode); + operands[5] = GEN_INT ((HOST_WIDE_INT_1U << <bits>) - 1); +}) + + ;; Now the simple shifts. (define_insn "rotl<mode>3" @@ -4439,9 +4502,9 @@ ;; Builtins to replace a division to generate FRE reciprocal estimate ;; instructions and the necessary fixup instructions (define_expand "recip<mode>3" - [(match_operand:RECIPF 0 "gpc_reg_operand" "") - (match_operand:RECIPF 1 "gpc_reg_operand" "") - (match_operand:RECIPF 2 "gpc_reg_operand" "")] + [(match_operand:RECIPF 0 "gpc_reg_operand") + (match_operand:RECIPF 1 "gpc_reg_operand") + (match_operand:RECIPF 2 "gpc_reg_operand")] "RS6000_RECIP_HAVE_RE_P (<MODE>mode)" { rs6000_emit_swdiv (operands[0], operands[1], operands[2], false); @@ -4454,9 +4517,9 @@ ;; We used to also check optimize_insn_for_speed_p () but problems with guessed ;; frequencies (pr68212/pr77536) yields that unreliable so it was removed. (define_split - [(set (match_operand:RECIPF 0 "gpc_reg_operand" "") - (div:RECIPF (match_operand 1 "gpc_reg_operand" "") - (match_operand 2 "gpc_reg_operand" "")))] + [(set (match_operand:RECIPF 0 "gpc_reg_operand") + (div:RECIPF (match_operand 1 "gpc_reg_operand") + (match_operand 2 "gpc_reg_operand")))] "RS6000_RECIP_AUTO_RE_P (<MODE>mode) && can_create_pseudo_p () && flag_finite_math_only && !flag_trapping_math && flag_reciprocal_math" @@ -4469,8 +4532,8 @@ ;; Builtins to replace 1/sqrt(x) with instructions using RSQRTE and the ;; appropriate fixup. (define_expand "rsqrt<mode>2" - [(match_operand:RECIPF 0 "gpc_reg_operand" "") - (match_operand:RECIPF 1 "gpc_reg_operand" "")] + [(match_operand:RECIPF 0 "gpc_reg_operand") + (match_operand:RECIPF 1 "gpc_reg_operand")] "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)" { rs6000_emit_swsqrt (operands[0], operands[1], 1); @@ -4483,108 +4546,102 @@ ;; -mupper-regs-{df,sf} option is enabled. (define_expand "abs<mode>2" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))] - "TARGET_<MODE>_INSN" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT" "") (define_insn "*abs<mode>2_fpr" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fabs %0,%1 xsabsdp %x0,%x1" - [(set_attr "type" "fpsimple") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fpsimple")]) (define_insn "*nabs<mode>2_fpr" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") (neg:SFDF (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fnabs %0,%1 xsnabsdp %x0,%x1" - [(set_attr "type" "fpsimple") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fpsimple")]) (define_expand "neg<mode>2" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))] - "TARGET_<MODE>_INSN" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT" "") (define_insn "*neg<mode>2_fpr" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fneg %0,%1 xsnegdp %x0,%x1" - [(set_attr "type" "fpsimple") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fpsimple")]) (define_expand "add<mode>3" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") - (match_operand:SFDF 2 "gpc_reg_operand" "")))] - "TARGET_<MODE>_INSN" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand") + (match_operand:SFDF 2 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT" "") (define_insn "*add<mode>3_fpr" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>") (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fadd<Ftrad> %0,%1,%2 xsadd<Fvsx> %x0,%x1,%x2" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fp")]) (define_expand "sub<mode>3" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") - (match_operand:SFDF 2 "gpc_reg_operand" "")))] - "TARGET_<MODE>_INSN" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand") + (match_operand:SFDF 2 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT" "") (define_insn "*sub<mode>3_fpr" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>") (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fsub<Ftrad> %0,%1,%2 xssub<Fvsx> %x0,%x1,%x2" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fp")]) (define_expand "mul<mode>3" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") - (match_operand:SFDF 2 "gpc_reg_operand" "")))] - "TARGET_<MODE>_INSN" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand") + (match_operand:SFDF 2 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT" "") (define_insn "*mul<mode>3_fpr" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>") (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fmul<Ftrad> %0,%1,%2 xsmul<Fvsx> %x0,%x1,%x2" - [(set_attr "type" "dmul") - (set_attr "fp_type" "fp_mul_<Fs>")]) + [(set_attr "type" "dmul")]) (define_expand "div<mode>3" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") - (match_operand:SFDF 2 "gpc_reg_operand" "")))] - "TARGET_<MODE>_INSN && !TARGET_SIMPLE_FPU" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand") + (match_operand:SFDF 2 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT" { if (RS6000_RECIP_AUTO_RE_P (<MODE>mode) && can_create_pseudo_p () && flag_finite_math_only @@ -4599,29 +4656,25 @@ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>") (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))] - "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU" + "TARGET_HARD_FLOAT" "@ fdiv<Ftrad> %0,%1,%2 xsdiv<Fvsx> %x0,%x1,%x2" - [(set_attr "type" "<Fs>div") - (set_attr "fp_type" "fp_div_<Fs>")]) + [(set_attr "type" "<Fs>div")]) (define_insn "*sqrt<mode>2_internal" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>") (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")))] - "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU - && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))" + "TARGET_HARD_FLOAT && TARGET_PPC_GPOPT" "@ fsqrt<Ftrad> %0,%1 xssqrt<Fvsx> %x0,%x1" - [(set_attr "type" "<Fs>sqrt") - (set_attr "fp_type" "fp_sqrt_<Fs>")]) + [(set_attr "type" "<Fs>sqrt")]) (define_expand "sqrt<mode>2" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))] - "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU - && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT && TARGET_PPC_GPOPT" { if (<MODE>mode == SFmode && TARGET_RECIP_PRECISION @@ -4661,7 +4714,7 @@ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y") (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fcmpu %0,%1,%2 xscmpudp %0,%x1,%x2" @@ -4671,7 +4724,7 @@ (define_expand "extendsfdf2" [(set (match_operand:DF 0 "gpc_reg_operand") (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "TARGET_HARD_FLOAT" { if (HONOR_SNANS (SFmode)) operands[1] = force_reg (SFmode, operands[1]); @@ -4680,7 +4733,7 @@ (define_insn_and_split "*extendsfdf2_fpr" [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wu,wb") (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z,wY")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !HONOR_SNANS (SFmode)" + "TARGET_HARD_FLOAT && !HONOR_SNANS (SFmode)" "@ # fmr %0,%1 @@ -4700,22 +4753,22 @@ (define_insn "*extendsfdf2_snan" [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws") (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f,wy")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && HONOR_SNANS (SFmode)" + "TARGET_HARD_FLOAT && HONOR_SNANS (SFmode)" "@ frsp %0,%1 xsrsp %x0,%x1" [(set_attr "type" "fp")]) (define_expand "truncdfsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + [(set (match_operand:SF 0 "gpc_reg_operand") + (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT" "") (define_insn "*truncdfsf2_fpr" [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy") (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d,ws")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "TARGET_HARD_FLOAT" "@ frsp %0,%1 xsrsp %x0,%x1" @@ -4726,12 +4779,12 @@ ;; when little-endian. (define_expand "signbit<mode>2" [(set (match_dup 2) - (float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand" ""))) + (float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand"))) (set (match_dup 3) (subreg:DI (match_dup 2) 0)) (set (match_dup 4) (match_dup 5)) - (set (match_operand:SI 0 "gpc_reg_operand" "") + (set (match_operand:SI 0 "gpc_reg_operand") (match_dup 6))] "TARGET_HARD_FLOAT && (!FLOAT128_IEEE_P (<MODE>mode) @@ -4739,12 +4792,19 @@ { if (FLOAT128_IEEE_P (<MODE>mode)) { + rtx dest = operands[0]; + rtx src = operands[1]; + rtx tmp = gen_reg_rtx (DImode); + rtx dest_di = gen_lowpart (DImode, dest); + if (<MODE>mode == KFmode) - emit_insn (gen_signbitkf2_dm (operands[0], operands[1])); + emit_insn (gen_signbitkf2_dm (tmp, src)); else if (<MODE>mode == TFmode) - emit_insn (gen_signbittf2_dm (operands[0], operands[1])); + emit_insn (gen_signbittf2_dm (tmp, src)); else gcc_unreachable (); + + emit_insn (gen_lshrdi3 (dest_di, tmp, GEN_INT (63))); DONE; } operands[2] = gen_reg_rtx (DFmode); @@ -4765,17 +4825,77 @@ } }) +;; Optimize IEEE 128-bit signbit on 64-bit systems with direct move to avoid +;; multiple direct moves. If we used a SUBREG:DI of the Floa128 type, the +;; register allocator would typically move the entire _Float128 item to GPRs (2 +;; instructions on ISA 3.0, 3-4 instructions on ISA 2.07). +;; +;; After register allocation, if the _Float128 had originally been in GPRs, the +;; split allows the post reload phases to eliminate the move, and do the shift +;; directly with the register that contains the signbit. +(define_insn_and_split "signbit<mode>2_dm" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") + (unspec:DI [(match_operand:SIGNBIT 1 "gpc_reg_operand" "wa,r")] + UNSPEC_SIGNBIT))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "@ + mfvsrd %0,%x1 + #" + "&& reload_completed && int_reg_operand (operands[1], <MODE>mode)" + [(set (match_dup 0) + (match_dup 2))] +{ + operands[2] = gen_highpart (DImode, operands[1]); +} + [(set_attr "type" "mftgpr,*")]) + +;; Optimize IEEE 128-bit signbit on to avoid loading the value into a vector +;; register and then doing a direct move if the value comes from memory. On +;; little endian, we have to load the 2nd double-word to get the sign bit. +(define_insn_and_split "*signbit<mode>2_dm_mem" + [(set (match_operand:DI 0 "gpc_reg_operand" "=b") + (unspec:DI [(match_operand:SIGNBIT 1 "memory_operand" "m")] + UNSPEC_SIGNBIT))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "#" + "&& 1" + [(set (match_dup 0) + (match_dup 2))] +{ + rtx dest = operands[0]; + rtx src = operands[1]; + rtx addr = XEXP (src, 0); + + if (WORDS_BIG_ENDIAN) + operands[2] = adjust_address (src, DImode, 0); + + else if (REG_P (addr) || SUBREG_P (addr)) + operands[2] = adjust_address (src, DImode, 8); + + else if (GET_CODE (addr) == PLUS && REG_P (XEXP (addr, 0)) + && CONST_INT_P (XEXP (addr, 1)) && mem_operand_gpr (src, DImode)) + operands[2] = adjust_address (src, DImode, 8); + + else + { + rtx tmp = can_create_pseudo_p () ? gen_reg_rtx (DImode) : dest; + emit_insn (gen_rtx_SET (tmp, addr)); + operands[2] = change_address (src, DImode, + gen_rtx_PLUS (DImode, tmp, GEN_INT (8))); + } +}) + (define_expand "copysign<mode>3" [(set (match_dup 3) - (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" ""))) + (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand"))) (set (match_dup 4) (neg:SFDF (abs:SFDF (match_dup 1)))) - (set (match_operand:SFDF 0 "gpc_reg_operand" "") - (if_then_else:SFDF (ge (match_operand:SFDF 2 "gpc_reg_operand" "") + (set (match_operand:SFDF 0 "gpc_reg_operand") + (if_then_else:SFDF (ge (match_operand:SFDF 2 "gpc_reg_operand") (match_dup 5)) (match_dup 3) (match_dup 4)))] - "TARGET_HARD_FLOAT && <TARGET_FLOAT> + "TARGET_HARD_FLOAT && ((TARGET_PPC_GFXOPT && !HONOR_NANS (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)) @@ -4794,54 +4914,6 @@ operands[5] = CONST0_RTX (<MODE>mode); }) -;; Optimize signbit on 64-bit systems with direct move to avoid doing the store -;; and load. -(define_insn_and_split "signbit<mode>2_dm" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r") - (unspec:SI - [(match_operand:SIGNBIT 1 "input_operand" "wa,m,r")] - UNSPEC_SIGNBIT))] - "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" - "#" - "&& reload_completed" - [(const_int 0)] -{ - rs6000_split_signbit (operands[0], operands[1]); - DONE; -} - [(set_attr "length" "8,8,4") - (set_attr "type" "mftgpr,load,integer")]) - -(define_insn_and_split "*signbit<mode>2_dm_<su>ext" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r") - (any_extend:DI - (unspec:SI - [(match_operand:SIGNBIT 1 "input_operand" "wa,m,r")] - UNSPEC_SIGNBIT)))] - "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" - "#" - "&& reload_completed" - [(const_int 0)] -{ - rs6000_split_signbit (operands[0], operands[1]); - DONE; -} - [(set_attr "length" "8,8,4") - (set_attr "type" "mftgpr,load,integer")]) - -;; TARGET_MODES_TIEABLE_P doesn't allow DImode to be tied with the various -;; floating point types, which makes normal SUBREG's problematical. Instead -;; use a special pattern to avoid using a normal movdi. -(define_insn "signbit<mode>2_dm2" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (unspec:DI [(match_operand:SIGNBIT 1 "gpc_reg_operand" "wa") - (const_int 0)] - UNSPEC_SIGNBIT))] - "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" - "mfvsrd %0,%x1" - [(set_attr "type" "mftgpr")]) - - ;; Use an unspec rather providing an if-then-else in RTL, to prevent the ;; compiler from optimizing -0.0 (define_insn "copysign<mode>3_fcpsgn" @@ -4849,7 +4921,7 @@ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")] UNSPEC_COPYSIGN))] - "TARGET_<MODE>_FPR && (TARGET_CMPB || VECTOR_UNIT_VSX_P (<MODE>mode))" + "TARGET_HARD_FLOAT && (TARGET_CMPB || VECTOR_UNIT_VSX_P (<MODE>mode))" "@ fcpsgn %0,%2,%1 xscpsgndp %x0,%x2,%x1" @@ -4869,10 +4941,10 @@ ;; to allow either DF/SF to use only traditional registers. (define_expand "s<minmax><mode>3" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (fp_minmax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") - (match_operand:SFDF 2 "gpc_reg_operand" "")))] - "TARGET_MINMAX_<MODE>" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (fp_minmax:SFDF (match_operand:SFDF 1 "gpc_reg_operand") + (match_operand:SFDF 2 "gpc_reg_operand")))] + "TARGET_MINMAX" { rs6000_emit_minmax (operands[0], <SMINMAX>, operands[1], operands[2]); DONE; @@ -4882,7 +4954,7 @@ [(set (match_operand:SFDF 0 "vsx_register_operand" "=<Fv>") (fp_minmax:SFDF (match_operand:SFDF 1 "vsx_register_operand" "<Fv>") (match_operand:SFDF 2 "vsx_register_operand" "<Fv>")))] - "TARGET_VSX && TARGET_<MODE>_FPR" + "TARGET_VSX && TARGET_HARD_FLOAT" { return (TARGET_P9_MINMAX ? "xs<minmax>cdp %x0,%x1,%x2" @@ -4895,10 +4967,10 @@ ;; instruction. (define_insn_and_split "*s<minmax><mode>3_fpr" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (fp_minmax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "") - (match_operand:SFDF 2 "gpc_reg_operand" "")))] - "!TARGET_VSX && TARGET_MINMAX_<MODE>" + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (fp_minmax:SFDF (match_operand:SFDF 1 "gpc_reg_operand") + (match_operand:SFDF 2 "gpc_reg_operand")))] + "!TARGET_VSX && TARGET_MINMAX" "#" "&& 1" [(const_int 0)] @@ -4908,18 +4980,17 @@ }) (define_expand "mov<mode>cc" - [(set (match_operand:GPR 0 "gpc_reg_operand" "") - (if_then_else:GPR (match_operand 1 "comparison_operator" "") - (match_operand:GPR 2 "gpc_reg_operand" "") - (match_operand:GPR 3 "gpc_reg_operand" "")))] + [(set (match_operand:GPR 0 "gpc_reg_operand") + (if_then_else:GPR (match_operand 1 "comparison_operator") + (match_operand:GPR 2 "gpc_reg_operand") + (match_operand:GPR 3 "gpc_reg_operand")))] "TARGET_ISEL" - " { if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) DONE; else FAIL; -}") +}) ;; We use the BASE_REGS for the isel input operands because, if rA is ;; 0, the value of 0 is placed in rD upon truth. Similarly for rB @@ -4989,18 +5060,17 @@ ;; Floating point conditional move (define_expand "mov<mode>cc" - [(set (match_operand:SFDF 0 "gpc_reg_operand" "") - (if_then_else:SFDF (match_operand 1 "comparison_operator" "") - (match_operand:SFDF 2 "gpc_reg_operand" "") - (match_operand:SFDF 3 "gpc_reg_operand" "")))] - "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT" - " + [(set (match_operand:SFDF 0 "gpc_reg_operand") + (if_then_else:SFDF (match_operand 1 "comparison_operator") + (match_operand:SFDF 2 "gpc_reg_operand") + (match_operand:SFDF 3 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT" { if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) DONE; else FAIL; -}") +}) (define_insn "*fsel<SFDF:mode><SFDF2:mode>4" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=&<SFDF:rreg2>") @@ -5009,7 +5079,7 @@ (match_operand:SFDF2 4 "zero_fp_constant" "F")) (match_operand:SFDF 2 "gpc_reg_operand" "<SFDF:rreg2>") (match_operand:SFDF 3 "gpc_reg_operand" "<SFDF:rreg2>")))] - "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT" + "TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT" "fsel %0,%1,%2,%3" [(set_attr "type" "fp")]) @@ -5112,7 +5182,7 @@ [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wj,wj,wK") (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,wK")] UNSPEC_LFIWAX))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX" + "TARGET_HARD_FLOAT && TARGET_LFIWAX" "@ lfiwax %0,%y1 lxsiwax %x0,%y1 @@ -5129,12 +5199,11 @@ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>") (float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r"))) (clobber (match_scratch:DI 2 "=wi"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX + "TARGET_HARD_FLOAT && TARGET_LFIWAX && <SI_CONVERT_FP> && can_create_pseudo_p ()" "#" "" [(pc)] - " { rtx dest = operands[0]; rtx src = operands[1]; @@ -5162,7 +5231,7 @@ } emit_insn (gen_floatdi<mode>2 (dest, tmp)); DONE; -}" +} [(set_attr "length" "12") (set_attr "type" "fpload")]) @@ -5172,11 +5241,10 @@ (sign_extend:DI (match_operand:SI 1 "indexed_or_indirect_operand" "Z")))) (clobber (match_scratch:DI 2 "=wi"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LFIWAX && <SI_CONVERT_FP>" + "TARGET_HARD_FLOAT && TARGET_LFIWAX && <SI_CONVERT_FP>" "#" "" [(pc)] - " { operands[1] = rs6000_address_for_fpconvert (operands[1]); if (GET_CODE (operands[2]) == SCRATCH) @@ -5187,7 +5255,7 @@ emit_insn (gen_lfiwax (operands[2], operands[1])); emit_insn (gen_floatdi<mode>2 (operands[0], operands[2])); DONE; -}" +} [(set_attr "length" "8") (set_attr "type" "fpload")]) @@ -5195,7 +5263,7 @@ [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wj,wj,wJwK") (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,wJwK")] UNSPEC_LFIWZX))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX" + "TARGET_HARD_FLOAT && TARGET_LFIWZX" "@ lfiwzx %0,%y1 lxsiwzx %x0,%y1 @@ -5207,11 +5275,10 @@ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>") (unsigned_float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r"))) (clobber (match_scratch:DI 2 "=wi"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX && <SI_CONVERT_FP>" + "TARGET_HARD_FLOAT && TARGET_LFIWZX && <SI_CONVERT_FP>" "#" "" [(pc)] - " { rtx dest = operands[0]; rtx src = operands[1]; @@ -5239,7 +5306,7 @@ } emit_insn (gen_floatdi<mode>2 (dest, tmp)); DONE; -}" +} [(set_attr "length" "12") (set_attr "type" "fpload")]) @@ -5249,11 +5316,10 @@ (zero_extend:DI (match_operand:SI 1 "indexed_or_indirect_operand" "Z")))) (clobber (match_scratch:DI 2 "=wi"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LFIWZX && <SI_CONVERT_FP>" + "TARGET_HARD_FLOAT && TARGET_LFIWZX && <SI_CONVERT_FP>" "#" "" [(pc)] - " { operands[1] = rs6000_address_for_fpconvert (operands[1]); if (GET_CODE (operands[2]) == SCRATCH) @@ -5264,7 +5330,7 @@ emit_insn (gen_lfiwzx (operands[2], operands[1])); emit_insn (gen_floatdi<mode>2 (operands[0], operands[2])); DONE; -}" +} [(set_attr "length" "8") (set_attr "type" "fpload")]) @@ -5274,15 +5340,14 @@ ; then to have the insns split later (between sched1 and final). (define_expand "floatsidf2" - [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "") - (float:DF (match_operand:SI 1 "nonimmediate_operand" ""))) + [(parallel [(set (match_operand:DF 0 "gpc_reg_operand") + (float:DF (match_operand:SI 1 "nonimmediate_operand"))) (use (match_dup 2)) (use (match_dup 3)) (clobber (match_dup 4)) (clobber (match_dup 5)) (clobber (match_dup 6))])] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " + "TARGET_HARD_FLOAT" { if (TARGET_LFIWAX && TARGET_FCFID) { @@ -5306,7 +5371,7 @@ operands[4] = rs6000_allocate_stack_temp (DFmode, true, false); operands[5] = gen_reg_rtx (DFmode); operands[6] = gen_reg_rtx (SImode); -}") +}) (define_insn_and_split "*floatsidf2_internal" [(set (match_operand:DF 0 "gpc_reg_operand" "=&d") @@ -5316,11 +5381,10 @@ (clobber (match_operand:DF 4 "offsettable_mem_operand" "=o")) (clobber (match_operand:DF 5 "gpc_reg_operand" "=&d")) (clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))] - "! TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "!TARGET_FCFID && TARGET_HARD_FLOAT" "#" "" [(pc)] - " { rtx lowword, highword; gcc_assert (MEM_P (operands[4])); @@ -5336,7 +5400,7 @@ emit_move_insn (operands[5], operands[4]); emit_insn (gen_subdf3 (operands[0], operands[5], operands[3])); DONE; -}" +} [(set_attr "length" "24") (set_attr "type" "fp")]) @@ -5344,13 +5408,12 @@ ;; conversion for 32-bit without fast math, because we don't have the insn to ;; generate the fixup swizzle to avoid double rounding problems. (define_expand "floatunssisf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (unsigned_float:SF (match_operand:SI 1 "nonimmediate_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT + [(set (match_operand:SF 0 "gpc_reg_operand") + (unsigned_float:SF (match_operand:SI 1 "nonimmediate_operand")))] + "TARGET_HARD_FLOAT && ((TARGET_FCFIDUS && TARGET_LFIWZX) - || (TARGET_DOUBLE_FLOAT && TARGET_FCFID + || (TARGET_FCFID && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))" - " { if (TARGET_LFIWZX && TARGET_FCFIDUS) { @@ -5366,17 +5429,16 @@ emit_insn (gen_floatdisf2 (operands[0], dreg)); DONE; } -}") +}) (define_expand "floatunssidf2" - [(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "") - (unsigned_float:DF (match_operand:SI 1 "nonimmediate_operand" ""))) + [(parallel [(set (match_operand:DF 0 "gpc_reg_operand") + (unsigned_float:DF (match_operand:SI 1 "nonimmediate_operand"))) (use (match_dup 2)) (use (match_dup 3)) (clobber (match_dup 4)) (clobber (match_dup 5))])] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " + "TARGET_HARD_FLOAT" { if (TARGET_LFIWZX && TARGET_FCFID) { @@ -5399,7 +5461,7 @@ operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503599627370496\", DFmode)); operands[4] = rs6000_allocate_stack_temp (DFmode, true, false); operands[5] = gen_reg_rtx (DFmode); -}") +}) (define_insn_and_split "*floatunssidf2_internal" [(set (match_operand:DF 0 "gpc_reg_operand" "=&d") @@ -5408,12 +5470,11 @@ (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" "=&d"))] - "! TARGET_FCFIDU && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + "!TARGET_FCFIDU && TARGET_HARD_FLOAT && !(TARGET_FCFID && TARGET_POWERPC64)" "#" "" [(pc)] - " { rtx lowword, highword; gcc_assert (MEM_P (operands[4])); @@ -5427,7 +5488,7 @@ emit_move_insn (operands[5], operands[4]); emit_insn (gen_subdf3 (operands[0], operands[5], operands[3])); DONE; -}" +} [(set_attr "length" "20") (set_attr "type" "fp")]) @@ -5492,9 +5553,9 @@ (define_expand "floatuns<QHI:mode><FP_ISA3:mode>2" [(parallel [(set (match_operand:FP_ISA3 0 "vsx_register_operand") (unsigned_float:FP_ISA3 - (match_operand:QHI 1 "input_operand" ""))) - (clobber (match_scratch:DI 2 "")) - (clobber (match_scratch:DI 3 ""))])] + (match_operand:QHI 1 "input_operand"))) + (clobber (match_scratch:DI 2)) + (clobber (match_scratch:DI 3))])] "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64" { if (MEM_P (operands[1])) @@ -5535,12 +5596,11 @@ }) (define_expand "fix_trunc<mode>si2" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && <TARGET_FLOAT>" - " -{ - if (!TARGET_P8_VECTOR) + [(set (match_operand:SI 0 "gpc_reg_operand") + (fix:SI (match_operand:SFDF 1 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT" +{ + if (!(TARGET_P8_VECTOR && TARGET_DIRECT_MOVE)) { rtx src = force_reg (<MODE>mode, operands[1]); @@ -5555,7 +5615,7 @@ } DONE; } -}") +}) ; Like the convert to float patterns, this insn must be split before ; register allocation so that it can allocate the memory slot if it @@ -5564,10 +5624,8 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))) (clobber (match_scratch:DI 2 "=d"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT - && (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT) - && TARGET_STFIWX && can_create_pseudo_p () - && !TARGET_P8_VECTOR" + "TARGET_HARD_FLOAT && TARGET_STFIWX && can_create_pseudo_p () + && !(TARGET_P8_VECTOR && TARGET_DIRECT_MOVE)" "#" "" [(pc)] @@ -5608,11 +5666,11 @@ (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,<rreg>"))) (clobber (match_operand:DI 2 "gpc_reg_operand" "=1,d")) (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o,o"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_P8_VECTOR" + "TARGET_HARD_FLOAT + && !(TARGET_P8_VECTOR && TARGET_DIRECT_MOVE)" "#" "" [(pc)] - " { rtx lowword; gcc_assert (MEM_P (operands[3])); @@ -5622,82 +5680,97 @@ emit_move_insn (operands[3], operands[2]); emit_move_insn (operands[0], lowword); DONE; -}" +} [(set_attr "length" "16") (set_attr "type" "fp")]) (define_expand "fix_trunc<mode>di2" - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FCFID" + [(set (match_operand:DI 0 "gpc_reg_operand") + (fix:DI (match_operand:SFDF 1 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT && TARGET_FCFID" "") (define_insn "*fix_trunc<mode>di2_fctidz" [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi") (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FCFID" + "TARGET_HARD_FLOAT && TARGET_FCFID" "@ fctidz %0,%1 xscvdpsxds %x0,%x1" [(set_attr "type" "fp")]) -(define_expand "fix_trunc<SFDF:mode><QHI:mode>2" - [(parallel [(set (match_operand:<QHI:MODE> 0 "nonimmediate_operand") - (fix:QHI (match_operand:SFDF 1 "gpc_reg_operand"))) - (clobber (match_scratch:DI 2))])] - "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT" -{ - if (MEM_P (operands[0])) - operands[0] = rs6000_address_for_fpconvert (operands[0]); -}) - -(define_insn_and_split "*fix_trunc<SFDF:mode><QHI:mode>2_internal" - [(set (match_operand:<QHI:MODE> 0 "reg_or_indexed_operand" "=wIwJ,rZ") - (fix:QHI - (match_operand:SFDF 1 "gpc_reg_operand" "<SFDF:Fv>,<SFDF:Fv>"))) - (clobber (match_scratch:DI 2 "=X,wi"))] - "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT" +;; If we have ISA 3.0, QI/HImode values can go in both VSX registers and GPR +;; registers. If we have ISA 2.07, we don't allow QI/HImode values in the +;; vector registers, so we need to do direct moves to the GPRs, but SImode +;; values can go in VSX registers. Keeping the direct move part through +;; register allocation prevents the register allocator from doing a direct move +;; of the SImode value to a GPR, and then a store/load. +(define_insn_and_split "fix<uns>_trunc<SFDF:mode><QHI:mode>2" + [(set (match_operand:<QHI:MODE> 0 "gpc_reg_operand" "=wJ,wJwK,r") + (any_fix:QHI (match_operand:SFDF 1 "gpc_reg_operand" "wJ,wJwK,wa"))) + (clobber (match_scratch:SI 2 "=X,X,wi"))] + "TARGET_DIRECT_MOVE" + "@ + fctiw<u>z %0,%1 + xscvdp<su>xws %x0,%x1 + #" + "&& reload_completed && int_reg_operand (operands[0], <QHI:MODE>mode)" + [(set (match_dup 2) + (any_fix:SI (match_dup 1))) + (set (match_dup 3) + (match_dup 2))] +{ + operands[3] = gen_rtx_REG (SImode, REGNO (operands[0])); +} + [(set_attr "length" "4,4,8") + (set_attr "type" "fp")]) + +(define_insn "*fix<uns>_trunc<SFDF:mode>si2_p8" + [(set (match_operand:SI 0 "gpc_reg_operand" "=d,wa") + (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,wa")))] + "TARGET_DIRECT_MOVE" + "@ + fctiw<u>z %0,%1 + xscvdp<su>xws %x0,%x1" + [(set_attr "type" "fp")]) + +;; Keep the convert and store together through register allocation to prevent +;; the register allocator from getting clever and doing a direct move to a GPR +;; and then store for reg+offset stores. +(define_insn_and_split "*fix<uns>_trunc<SFDF:mode><QHSI:mode>2_mem" + [(set (match_operand:QHSI 0 "memory_operand" "=Z") + (any_fix:QHSI (match_operand:SFDF 1 "gpc_reg_operand" "wa"))) + (clobber (match_scratch:SI 2 "=wa"))] + "(<QHSI:MODE>mode == SImode && TARGET_P8_VECTOR) || TARGET_P9_VECTOR" "#" "&& reload_completed" - [(const_int 0)] -{ - rtx dest = operands[0]; - rtx src = operands[1]; - - if (vsx_register_operand (dest, <QHI:MODE>mode)) - { - rtx di_dest = gen_rtx_REG (DImode, REGNO (dest)); - emit_insn (gen_fix_trunc<SFDF:mode>di2 (di_dest, src)); - } - else - { - rtx tmp = operands[2]; - rtx tmp2 = gen_rtx_REG (<QHI:MODE>mode, REGNO (tmp)); - - emit_insn (gen_fix_trunc<SFDF:mode>di2 (tmp, src)); - emit_move_insn (dest, tmp2); - } - DONE; + [(set (match_dup 2) + (any_fix:SI (match_dup 1))) + (set (match_dup 0) + (match_dup 3))] +{ + operands[3] = (<QHSI:MODE>mode == SImode + ? operands[2] + : gen_rtx_REG (<QHSI:MODE>mode, REGNO (operands[2]))); }) (define_expand "fixuns_trunc<mode>si2" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && <TARGET_FLOAT> && TARGET_FCTIWUZ && TARGET_STFIWX" - " + [(set (match_operand:SI 0 "gpc_reg_operand") + (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT && TARGET_FCTIWUZ && TARGET_STFIWX" { if (!TARGET_P8_VECTOR) { emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1])); DONE; } -}") +}) (define_insn_and_split "fixuns_trunc<mode>si2_stfiwx" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))) (clobber (match_scratch:DI 2 "=d"))] - "TARGET_HARD_FLOAT && <TARGET_FLOAT> && TARGET_FCTIWUZ + "TARGET_HARD_FLOAT && TARGET_FCTIWUZ && TARGET_STFIWX && can_create_pseudo_p () && !TARGET_P8_VECTOR" "#" @@ -5738,76 +5811,133 @@ (define_insn "fixuns_trunc<mode>di2" [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi") (unsigned_fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FCTIDUZ" + "TARGET_HARD_FLOAT && TARGET_FCTIDUZ" "@ fctiduz %0,%1 xscvdpuxds %x0,%x1" [(set_attr "type" "fp")]) -(define_expand "fixuns_trunc<SFDF:mode><QHI:mode>2" - [(parallel [(set (match_operand:<QHI:MODE> 0 "nonimmediate_operand") - (unsigned_fix:QHI (match_operand:SFDF 1 "gpc_reg_operand"))) - (clobber (match_scratch:DI 2))])] - "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT" -{ - if (MEM_P (operands[0])) - operands[0] = rs6000_address_for_fpconvert (operands[0]); -}) - -(define_insn_and_split "*fixuns_trunc<SFDF:mode><QHI:mode>2_internal" - [(set (match_operand:<QHI:MODE> 0 "reg_or_indexed_operand" "=wIwJ,rZ") - (unsigned_fix:QHI - (match_operand:SFDF 1 "gpc_reg_operand" "<SFDF:Fv>,<SFDF:Fv>"))) - (clobber (match_scratch:DI 2 "=X,wi"))] - "TARGET_P9_VECTOR && TARGET_DIRECT_MOVE_64BIT" - "#" - "&& reload_completed" - [(const_int 0)] -{ - rtx dest = operands[0]; - rtx src = operands[1]; - - if (vsx_register_operand (dest, <QHI:MODE>mode)) - { - rtx di_dest = gen_rtx_REG (DImode, REGNO (dest)); - emit_insn (gen_fixuns_trunc<SFDF:mode>di2 (di_dest, src)); - } - else - { - rtx tmp = operands[2]; - rtx tmp2 = gen_rtx_REG (<QHI:MODE>mode, REGNO (tmp)); - - emit_insn (gen_fixuns_trunc<SFDF:mode>di2 (tmp, src)); - emit_move_insn (dest, tmp2); - } - DONE; -}) - -;; If -mvsx-small-integer, we can represent the FIX operation directly. On -;; older machines, we have to use an UNSPEC to produce a SImode and move it -;; to another location, since SImode is not allowed in vector registers. -(define_insn "*fctiw<u>z_<mode>_smallint" - [(set (match_operand:SI 0 "vsx_register_operand" "=d,wi") - (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_P8_VECTOR" - "@ - fctiw<u>z %0,%1 - xscvdp<su>xws %x0,%x1" +(define_insn "rs6000_mtfsb0" + [(unspec_volatile [(match_operand:SI 0 "u5bit_cint_operand" "n")] + UNSPECV_MTFSB0)] + "TARGET_HARD_FLOAT" + "mtfsb0 %0" + [(set_attr "type" "fp")]) + +(define_insn "rs6000_mtfsb1" + [(unspec_volatile [(match_operand:SI 0 "u5bit_cint_operand" "n")] + UNSPECV_MTFSB1)] + "TARGET_HARD_FLOAT" + "mtfsb1 %0" + [(set_attr "type" "fp")]) + +(define_insn "rs6000_mffscrn" + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec_volatile:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] + UNSPECV_MFFSCRN))] + "TARGET_P9_MISC" + "mffscrn %0,%1" + [(set_attr "type" "fp")]) + +(define_insn "rs6000_mffscdrn" + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFSCDRN)) + (use (match_operand:DF 1 "gpc_reg_operand" "d"))] + "TARGET_P9_MISC" + "mffscdrn %0,%1" [(set_attr "type" "fp")]) -;; Combiner pattern to prevent moving the result of converting a floating point -;; value to 32-bit integer to GPR in order to save it. -(define_insn_and_split "*fctiw<u>z_<mode>_mem" - [(set (match_operand:SI 0 "memory_operand" "=Z") - (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "wa"))) - (clobber (match_scratch:SI 2 "=wa"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_P8_VECTOR" - "#" - "&& reload_completed" - [(set (match_dup 2) - (any_fix:SI (match_dup 1))) - (set (match_dup 0) - (match_dup 2))]) +(define_expand "rs6000_set_fpscr_rn" + [(match_operand:DI 0 "reg_or_cint_operand")] + "TARGET_HARD_FLOAT" +{ + rtx tmp_df = gen_reg_rtx (DFmode); + + /* The floating point rounding control bits are FPSCR[62:63]. Put the + new rounding mode bits from operands[0][62:63] into FPSCR[62:63]. */ + if (TARGET_P9_MISC) + { + rtx src_df = force_reg (DImode, operands[0]); + src_df = simplify_gen_subreg (DFmode, src_df, DImode, 0); + emit_insn (gen_rs6000_mffscrn (tmp_df, src_df)); + DONE; + } + + if (CONST_INT_P (operands[0])) + { + if ((INTVAL (operands[0]) & 0x1) == 0x1) + emit_insn (gen_rs6000_mtfsb1 (GEN_INT (31))); + else + emit_insn (gen_rs6000_mtfsb0 (GEN_INT (31))); + + if ((INTVAL (operands[0]) & 0x2) == 0x2) + emit_insn (gen_rs6000_mtfsb1 (GEN_INT (30))); + else + emit_insn (gen_rs6000_mtfsb0 (GEN_INT (30))); + } + else + { + rtx tmp_rn = gen_reg_rtx (DImode); + rtx tmp_di = gen_reg_rtx (DImode); + + /* Extract new RN mode from operand. */ + emit_insn (gen_anddi3 (tmp_rn, operands[0], GEN_INT (0x3))); + + /* Insert new RN mode into FSCPR. */ + emit_insn (gen_rs6000_mffs (tmp_df)); + tmp_di = simplify_gen_subreg (DImode, tmp_df, DFmode, 0); + emit_insn (gen_anddi3 (tmp_di, tmp_di, GEN_INT (-4))); + emit_insn (gen_iordi3 (tmp_di, tmp_di, tmp_rn)); + + /* Need to write to field k=15. The fields are [0:15]. Hence with + L=0, W=0, FLM_i must be equal to 8, 16 = i + 8*(1-W). FLM is an + 8-bit field[0:7]. Need to set the bit that corresponds to the + value of i that you want [0:7]. */ + tmp_df = simplify_gen_subreg (DFmode, tmp_di, DImode, 0); + emit_insn (gen_rs6000_mtfsf (GEN_INT (0x01), tmp_df)); + } + DONE; +}) + +(define_expand "rs6000_set_fpscr_drn" + [(match_operand:DI 0 "gpc_reg_operand")] + "TARGET_HARD_FLOAT" +{ + rtx tmp_df = gen_reg_rtx (DFmode); + + /* The decimal floating point rounding control bits are FPSCR[29:31]. Put the + new rounding mode bits from operands[0][61:63] into FPSCR[29:31]. */ + if (TARGET_P9_MISC) + { + rtx src_df = gen_reg_rtx (DFmode); + + emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32))); + src_df = simplify_gen_subreg (DFmode, operands[0], DImode, 0); + emit_insn (gen_rs6000_mffscdrn (tmp_df, src_df)); + } + else + { + rtx tmp_rn = gen_reg_rtx (DImode); + rtx tmp_di = gen_reg_rtx (DImode); + + /* Extract new DRN mode from operand. */ + emit_insn (gen_anddi3 (tmp_rn, operands[0], GEN_INT (0x7))); + emit_insn (gen_ashldi3 (tmp_rn, tmp_rn, GEN_INT (32))); + + /* Insert new RN mode into FSCPR. */ + emit_insn (gen_rs6000_mffs (tmp_df)); + tmp_di = simplify_gen_subreg (DImode, tmp_df, DFmode, 0); + emit_insn (gen_anddi3 (tmp_di, tmp_di, GEN_INT (0xFFFFFFF8FFFFFFFF))); + emit_insn (gen_iordi3 (tmp_di, tmp_di, tmp_rn)); + + /* Need to write to field 7. The fields are [0:15]. The equation to + select the field is i + 8*(1-W). Hence with L=0 and W=1, need to set + i to 0x1 to get field 7 where i selects the field. */ + tmp_df = simplify_gen_subreg (DFmode, tmp_di, DImode, 0); + emit_insn (gen_rs6000_mtfsf_hi (GEN_INT (0x01), tmp_df)); + } + DONE; +}) ;; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ)) ;; rather than (set (subreg:SI (reg)) (fix:SI ...)) @@ -5818,7 +5948,7 @@ (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))] UNSPEC_FCTIWZ))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "TARGET_HARD_FLOAT" "@ fctiwz %0,%1 xscvdpsxws %x0,%x1" @@ -5829,7 +5959,7 @@ (unspec:DI [(unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))] UNSPEC_FCTIWUZ))] - "TARGET_HARD_FLOAT && <TARGET_FLOAT> && TARGET_FCTIWUZ" + "TARGET_HARD_FLOAT && TARGET_FCTIWUZ" "@ fctiwuz %0,%1 xscvdpuxws %x0,%x1" @@ -5841,7 +5971,7 @@ (define_insn "*friz" [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws") (float:DF (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d,ws"))))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRND + "TARGET_HARD_FLOAT && TARGET_FPRND && flag_unsafe_math_optimizations && !flag_trapping_math && TARGET_FRIZ" "@ friz %0,%1 @@ -5860,7 +5990,7 @@ (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))) (clobber (match_scratch:DI 2 "=d")) (clobber (match_scratch:DI 3 "=d"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + "TARGET_HARD_FLOAT && <SI_CONVERT_FP> && TARGET_LFIWAX && TARGET_STFIWX && TARGET_FCFID && !TARGET_DIRECT_MOVE && can_create_pseudo_p ()" "#" @@ -5893,7 +6023,7 @@ (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))) (clobber (match_scratch:DI 2 "=d")) (clobber (match_scratch:DI 3 "=d"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + "TARGET_HARD_FLOAT && TARGET_LFIWZX && TARGET_STFIWX && TARGET_FCFIDU && !TARGET_DIRECT_MOVE && can_create_pseudo_p ()" "#" @@ -5920,20 +6050,12 @@ [(set_attr "type" "fpload") (set_attr "length" "16")]) -(define_insn "lrintsfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=d") - (unspec:SI [(match_operand:DF 1 "gpc_reg_operand" "d")] - UNSPEC_FCTIW))] - "TARGET_SF_FPR && TARGET_FPRND" - "fctiw %0,%1" - [(set_attr "type" "fp")]) - ;; No VSX equivalent to fctid (define_insn "lrint<mode>di2" [(set (match_operand:DI 0 "gpc_reg_operand" "=d") (unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] UNSPEC_FCTID))] - "TARGET_<MODE>_FPR && TARGET_FPRND" + "TARGET_HARD_FLOAT && TARGET_FPRND" "fctid %0,%1" [(set_attr "type" "fp")]) @@ -5941,62 +6063,57 @@ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")] UNSPEC_FRIZ))] - "TARGET_<MODE>_FPR && TARGET_FPRND" + "TARGET_HARD_FLOAT && TARGET_FPRND" "@ friz %0,%1 xsrdpiz %x0,%x1" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fp")]) (define_insn "ceil<mode>2" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")] UNSPEC_FRIP))] - "TARGET_<MODE>_FPR && TARGET_FPRND" + "TARGET_HARD_FLOAT && TARGET_FPRND" "@ frip %0,%1 xsrdpip %x0,%x1" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fp")]) (define_insn "floor<mode>2" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>") (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")] UNSPEC_FRIM))] - "TARGET_<MODE>_FPR && TARGET_FPRND" + "TARGET_HARD_FLOAT && TARGET_FPRND" "@ frim %0,%1 xsrdpim %x0,%x1" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fp")]) ;; No VSX equivalent to frin (define_insn "round<mode>2" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>") (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] UNSPEC_FRIN))] - "TARGET_<MODE>_FPR && TARGET_FPRND" + "TARGET_HARD_FLOAT && TARGET_FPRND" "frin %0,%1" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fp")]) (define_insn "*xsrdpi<mode>2" [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>") (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Fv>")] UNSPEC_XSRDPI))] - "TARGET_<MODE>_FPR && TARGET_VSX" + "TARGET_HARD_FLOAT && TARGET_VSX" "xsrdpi %x0,%x1" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_<Fs>")]) + [(set_attr "type" "fp")]) (define_expand "lround<mode>di2" [(set (match_dup 2) - (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand")] UNSPEC_XSRDPI)) - (set (match_operand:DI 0 "gpc_reg_operand" "") + (set (match_operand:DI 0 "gpc_reg_operand") (unspec:DI [(match_dup 2)] UNSPEC_FCTID))] - "TARGET_<MODE>_FPR && TARGET_VSX" + "TARGET_HARD_FLOAT && TARGET_VSX && TARGET_FPRND" { operands[2] = gen_reg_rtx (<MODE>mode); }) @@ -6018,13 +6135,12 @@ ;; conversion for 32-bit without fast math, because we don't have the insn to ;; generate the fixup swizzle to avoid double rounding problems. (define_expand "floatsisf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT + [(set (match_operand:SF 0 "gpc_reg_operand") + (float:SF (match_operand:SI 1 "nonimmediate_operand")))] + "TARGET_HARD_FLOAT && ((TARGET_FCFIDS && TARGET_LFIWAX) - || (TARGET_DOUBLE_FLOAT && TARGET_FCFID + || (TARGET_FCFID && (TARGET_POWERPC64 || flag_unsafe_math_optimizations)))" - " { if (TARGET_FCFIDS && TARGET_LFIWAX) { @@ -6047,12 +6163,12 @@ emit_insn (gen_floatdisf2 (operands[0], dreg)); DONE; } -}") +}) (define_insn "floatdidf2" [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws") (float:DF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))] - "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "TARGET_FCFID && TARGET_HARD_FLOAT" "@ fcfid %0,%1 xscvsxddp %x0,%x1" @@ -6067,7 +6183,7 @@ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws") (float:DF (match_operand:DI 1 "memory_operand" "m,Z"))) (clobber (match_scratch:DI 2 "=d,wi"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FCFID" + "TARGET_HARD_FLOAT && TARGET_FCFID" "#" "&& reload_completed" [(set (match_dup 2) (match_dup 1)) @@ -6077,9 +6193,9 @@ (set_attr "type" "fpload")]) (define_expand "floatunsdidf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") + [(set (match_operand:DF 0 "gpc_reg_operand") (unsigned_float:DF - (match_operand:DI 1 "gpc_reg_operand" "")))] + (match_operand:DI 1 "gpc_reg_operand")))] "TARGET_HARD_FLOAT && TARGET_FCFIDU" "") @@ -6090,8 +6206,7 @@ "@ fcfidu %0,%1 xscvuxddp %x0,%x1" - [(set_attr "type" "fp") - (set_attr "length" "4")]) + [(set_attr "type" "fp")]) (define_insn_and_split "*floatunsdidf2_mem" [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws") @@ -6107,11 +6222,10 @@ (set_attr "type" "fpload")]) (define_expand "floatdisf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (float:SF (match_operand:DI 1 "gpc_reg_operand" "")))] - "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT + [(set (match_operand:SF 0 "gpc_reg_operand") + (float:SF (match_operand:DI 1 "gpc_reg_operand")))] + "TARGET_FCFID && TARGET_HARD_FLOAT && (TARGET_FCFIDS || TARGET_POWERPC64 || flag_unsafe_math_optimizations)" - " { if (!TARGET_FCFIDS) { @@ -6126,13 +6240,12 @@ emit_insn (gen_floatdisf2_internal1 (operands[0], val)); DONE; } -}") +}) (define_insn "floatdisf2_fcfids" [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy") (float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT - && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS" + "TARGET_HARD_FLOAT && TARGET_FCFIDS" "@ fcfids %0,%1 xscvsxdsp %x0,%x1" @@ -6142,17 +6255,15 @@ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy,wy") (float:SF (match_operand:DI 1 "memory_operand" "m,m,Z"))) (clobber (match_scratch:DI 2 "=d,d,wi"))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT - && TARGET_DOUBLE_FLOAT && TARGET_FCFIDS" + "TARGET_HARD_FLOAT && TARGET_FCFIDS" "#" "&& reload_completed" [(pc)] - " { emit_move_insn (operands[2], operands[1]); emit_insn (gen_floatdisf2_fcfids (operands[0], operands[2])); DONE; -}" +} [(set_attr "length" "8")]) ;; This is not IEEE compliant if rounding mode is "round to nearest". @@ -6163,7 +6274,7 @@ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (float:SF (match_operand:DI 1 "gpc_reg_operand" "d"))) (clobber (match_scratch:DF 2 "=d"))] - "TARGET_FCFID && TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT && !TARGET_FCFIDS" + "TARGET_FCFID && TARGET_HARD_FLOAT && !TARGET_FCFIDS" "#" "&& reload_completed" [(set (match_dup 2) @@ -6179,11 +6290,11 @@ ;; by a bit that won't be lost at that stage, but is below the SFmode ;; rounding position. (define_expand "floatdisf2_internal2" - [(parallel [(set (match_dup 3) (ashiftrt:DI (match_operand:DI 1 "" "") + [(parallel [(set (match_dup 3) (ashiftrt:DI (match_operand:DI 1 "") (const_int 53))) (clobber (reg:DI CA_REGNO))]) - (set (match_operand:DI 0 "" "") (and:DI (match_dup 1) - (const_int 2047))) + (set (match_operand:DI 0 "") (and:DI (match_dup 1) + (const_int 2047))) (set (match_dup 3) (plus:DI (match_dup 3) (const_int 1))) (set (match_dup 0) (plus:DI (match_dup 0) @@ -6195,29 +6306,25 @@ (set (match_dup 0) (and:DI (match_dup 0) (const_int -2048))) (set (pc) (if_then_else (geu (match_dup 4) (const_int 0)) - (label_ref (match_operand:DI 2 "" "")) + (label_ref (match_operand:DI 2 "")) (pc))) (set (match_dup 0) (match_dup 1))] - "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT - && !TARGET_FCFIDS" - " + "TARGET_POWERPC64 && TARGET_HARD_FLOAT && !TARGET_FCFIDS" { operands[3] = gen_reg_rtx (DImode); operands[4] = gen_reg_rtx (CCUNSmode); -}") +}) (define_expand "floatunsdisf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT - && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS" + [(set (match_operand:SF 0 "gpc_reg_operand") + (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand")))] + "TARGET_HARD_FLOAT && TARGET_FCFIDUS" "") (define_insn "floatunsdisf2_fcfidus" [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wu") (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT - && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS" + "TARGET_HARD_FLOAT && TARGET_FCFIDUS" "@ fcfidus %0,%1 xscvuxdsp %x0,%x1" @@ -6227,17 +6334,15 @@ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy,wy") (unsigned_float:SF (match_operand:DI 1 "memory_operand" "m,m,Z"))) (clobber (match_scratch:DI 2 "=d,d,wi"))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT - && TARGET_DOUBLE_FLOAT && TARGET_FCFIDUS" + "TARGET_HARD_FLOAT && TARGET_FCFIDUS" "#" "&& reload_completed" [(pc)] - " { emit_move_insn (operands[2], operands[1]); emit_insn (gen_floatunsdisf2_fcfidus (operands[0], operands[2])); DONE; -}" +} [(set_attr "length" "8") (set_attr "type" "fpload")]) @@ -6248,9 +6353,9 @@ ;; also allow for the output being the same as one of the inputs. (define_expand "addti3" - [(set (match_operand:TI 0 "gpc_reg_operand" "") - (plus:TI (match_operand:TI 1 "gpc_reg_operand" "") - (match_operand:TI 2 "reg_or_short_operand" "")))] + [(set (match_operand:TI 0 "gpc_reg_operand") + (plus:TI (match_operand:TI 1 "gpc_reg_operand") + (match_operand:TI 2 "reg_or_short_operand")))] "TARGET_64BIT" { rtx lo0 = gen_lowpart (DImode, operands[0]); @@ -6271,9 +6376,9 @@ }) (define_expand "subti3" - [(set (match_operand:TI 0 "gpc_reg_operand" "") - (minus:TI (match_operand:TI 1 "reg_or_short_operand" "") - (match_operand:TI 2 "gpc_reg_operand" "")))] + [(set (match_operand:TI 0 "gpc_reg_operand") + (minus:TI (match_operand:TI 1 "reg_or_short_operand") + (match_operand:TI 2 "gpc_reg_operand")))] "TARGET_64BIT" { rtx lo0 = gen_lowpart (DImode, operands[0]); @@ -6296,73 +6401,73 @@ ;; 128-bit logical operations expanders (define_expand "and<mode>3" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") - (and:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "") - (match_operand:BOOL_128 2 "vlogical_operand" "")))] + [(set (match_operand:BOOL_128 0 "vlogical_operand") + (and:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand") + (match_operand:BOOL_128 2 "vlogical_operand")))] "" "") (define_expand "ior<mode>3" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") - (ior:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "") - (match_operand:BOOL_128 2 "vlogical_operand" "")))] + [(set (match_operand:BOOL_128 0 "vlogical_operand") + (ior:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand") + (match_operand:BOOL_128 2 "vlogical_operand")))] "" "") (define_expand "xor<mode>3" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") - (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "") - (match_operand:BOOL_128 2 "vlogical_operand" "")))] + [(set (match_operand:BOOL_128 0 "vlogical_operand") + (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand") + (match_operand:BOOL_128 2 "vlogical_operand")))] "" "") (define_expand "one_cmpl<mode>2" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") - (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")))] + [(set (match_operand:BOOL_128 0 "vlogical_operand") + (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand")))] "" "") (define_expand "nor<mode>3" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + [(set (match_operand:BOOL_128 0 "vlogical_operand") (and:BOOL_128 - (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")) - (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))))] + (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand")) + (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand"))))] "" "") (define_expand "andc<mode>3" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + [(set (match_operand:BOOL_128 0 "vlogical_operand") (and:BOOL_128 - (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" "")) - (match_operand:BOOL_128 1 "vlogical_operand" "")))] + (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand")) + (match_operand:BOOL_128 1 "vlogical_operand")))] "" "") ;; Power8 vector logical instructions. (define_expand "eqv<mode>3" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + [(set (match_operand:BOOL_128 0 "vlogical_operand") (not:BOOL_128 - (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "") - (match_operand:BOOL_128 2 "vlogical_operand" ""))))] + (xor:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand") + (match_operand:BOOL_128 2 "vlogical_operand"))))] "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR" "") ;; Rewrite nand into canonical form (define_expand "nand<mode>3" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + [(set (match_operand:BOOL_128 0 "vlogical_operand") (ior:BOOL_128 - (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")) - (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" ""))))] + (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand")) + (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand"))))] "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR" "") ;; The canonical form is to have the negated element first, so we need to ;; reverse arguments. (define_expand "orc<mode>3" - [(set (match_operand:BOOL_128 0 "vlogical_operand" "") + [(set (match_operand:BOOL_128 0 "vlogical_operand") (ior:BOOL_128 - (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand" "")) - (match_operand:BOOL_128 1 "vlogical_operand" "")))] + (not:BOOL_128 (match_operand:BOOL_128 2 "vlogical_operand")) + (match_operand:BOOL_128 1 "vlogical_operand")))] "<MODE>mode == TImode || <MODE>mode == PTImode || TARGET_P8_VECTOR" "") @@ -6656,11 +6761,10 @@ ;; Set up a register with a value from the GOT table (define_expand "movsi_got" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (unspec:SI [(match_operand:SI 1 "got_operand" "") + [(set (match_operand:SI 0 "gpc_reg_operand") + (unspec:SI [(match_operand:SI 1 "got_operand") (match_dup 2)] UNSPEC_MOVSI_GOT))] "DEFAULT_ABI == ABI_V4 && flag_pic == 1" - " { if (GET_CODE (operands[1]) == CONST) { @@ -6681,7 +6785,7 @@ } operands[2] = rs6000_got_register (operands[1]); -}") +}) (define_insn "*movsi_got_internal" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") @@ -6695,9 +6799,9 @@ ;; Used by sched, shorten_branches and final when the GOT pseudo reg ;; didn't get allocated to a hard register. (define_split - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (unspec:SI [(match_operand:SI 1 "got_no_const_operand" "") - (match_operand:SI 2 "memory_operand" "")] + [(set (match_operand:SI 0 "gpc_reg_operand") + (unspec:SI [(match_operand:SI 1 "got_no_const_operand") + (match_operand:SI 2 "memory_operand")] UNSPEC_MOVSI_GOT))] "DEFAULT_ABI == ABI_V4 && flag_pic == 1 @@ -6717,8 +6821,7 @@ (match_operand 2 "" ""))))] "TARGET_MACHO && ! TARGET_64BIT" "lwz %0,lo16(%2)(%1)" - [(set_attr "type" "load") - (set_attr "length" "4")]) + [(set_attr "type" "load")]) ;; MR LA LWZ LFIWZX LXSIWZX ;; STW STFIWX STXSIWX LI LIS @@ -6740,8 +6843,8 @@ O, wM, wS, r, wIwH, *h, r, r, 0"))] - "!TARGET_SINGLE_FPU && - (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))" + "gpc_reg_operand (operands[0], SImode) + || gpc_reg_operand (operands[1], SImode)" "@ mr %0,%1 la %0,%a1 @@ -6781,28 +6884,6 @@ 4, 4, 8, 4, 4, 4, 4, 4, 4")]) -(define_insn "*movsi_internal1_single" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,*c*l,*h,*h,m,*f") - (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,*h,r,r,0,f,m"))] - "TARGET_SINGLE_FPU && - (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))" - "@ - mr %0,%1 - la %0,%a1 - lwz%U1%X1 %0,%1 - stw%U0%X0 %1,%0 - li %0,%1 - lis %0,%v1 - # - mf%1 %0 - mt%0 %1 - mt%0 %1 - nop - stfs%U0%X0 %1,%0 - lfs%U1%X1 %0,%1" - [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*,fpstore,fpload") - (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")]) - ;; Like movsi, but adjust a SF value to be used in a SI context, i.e. ;; (set (reg:SI ...) (subreg:SI (reg:SF ...) 0)) ;; @@ -6956,8 +7037,8 @@ ;; sequence. (define_split - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (match_operand:SI 1 "const_int_operand" ""))] + [(set (match_operand:SI 0 "gpc_reg_operand") + (match_operand:SI 1 "const_int_operand"))] "(unsigned HOST_WIDE_INT) (INTVAL (operands[1]) + 0x8000) >= 0x10000 && (INTVAL (operands[1]) & 0xffff) != 0" [(set (match_dup 0) @@ -6965,13 +7046,12 @@ (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))] - " { if (rs6000_emit_set_const (operands[0], operands[1])) DONE; else FAIL; -}") +}) ;; Split loading -128..127 to use XXSPLITB and VEXTSW2D (define_split @@ -7017,10 +7097,13 @@ "") (define_expand "mov<mode>" - [(set (match_operand:INT 0 "general_operand" "") - (match_operand:INT 1 "any_operand" ""))] - "" - "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") + [(set (match_operand:INT 0 "general_operand") + (match_operand:INT 1 "any_operand"))] + "" +{ + rs6000_emit_move (operands[0], operands[1], <MODE>mode); + DONE; +}) ;; MR LHZ/LBZ LXSI*ZX STH/STB STXSI*X LI ;; XXLOR load 0 load -1 VSPLTI* # MFVSRWZ @@ -7070,8 +7153,8 @@ ;; an integer register or memory, we store just the high-order 4 bits. ;; This lets us not shift in the most common case of CR0. (define_expand "movcc" - [(set (match_operand:CC 0 "nonimmediate_operand" "") - (match_operand:CC 1 "nonimmediate_operand" ""))] + [(set (match_operand:CC 0 "nonimmediate_operand") + (match_operand:CC 1 "nonimmediate_operand"))] "" "") @@ -7095,25 +7178,21 @@ mt%0 %1 lwz%U1%X1 %0,%1 stw%U0%X0 %1,%0" - [(set (attr "type") - (cond [(eq_attr "alternative" "0,3") - (const_string "cr_logical") - (eq_attr "alternative" "1,2") - (const_string "mtcr") - (eq_attr "alternative" "6,7") - (const_string "integer") - (eq_attr "alternative" "8") - (const_string "mfjmpr") - (eq_attr "alternative" "9") - (const_string "mtjmpr") - (eq_attr "alternative" "10") - (const_string "load") - (eq_attr "alternative" "11") - (const_string "store") - (match_test "TARGET_MFCRF") - (const_string "mfcrf") - ] - (const_string "mfcr"))) + [(set_attr_alternative "type" + [(const_string "cr_logical") + (const_string "mtcr") + (const_string "mtcr") + (const_string "cr_logical") + (if_then_else (match_test "TARGET_MFCRF") + (const_string "mfcrf") (const_string "mfcr")) + (if_then_else (match_test "TARGET_MFCRF") + (const_string "mfcrf") (const_string "mfcr")) + (const_string "integer") + (const_string "integer") + (const_string "mfjmpr") + (const_string "mtjmpr") + (const_string "load") + (const_string "store")]) (set_attr "length" "4,4,12,4,4,8,4,4,4,4,4,4")]) ;; For floating-point, we normally deal with the floating-point registers @@ -7124,21 +7203,23 @@ ;; Move 32-bit binary/decimal floating point (define_expand "mov<mode>" - [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "") - (match_operand:FMOVE32 1 "any_operand" ""))] + [(set (match_operand:FMOVE32 0 "nonimmediate_operand") + (match_operand:FMOVE32 1 "any_operand"))] "<fmove_ok>" - "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") +{ + rs6000_emit_move (operands[0], operands[1], <MODE>mode); + DONE; +}) (define_split - [(set (match_operand:FMOVE32 0 "gpc_reg_operand" "") - (match_operand:FMOVE32 1 "const_double_operand" ""))] + [(set (match_operand:FMOVE32 0 "gpc_reg_operand") + (match_operand:FMOVE32 1 "const_double_operand"))] "reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG && GET_CODE (SUBREG_REG (operands[0])) == REG && REGNO (SUBREG_REG (operands[0])) <= 31))" [(set (match_dup 2) (match_dup 3))] - " { long l; @@ -7150,7 +7231,7 @@ operands[2] = gen_lowpart (SImode, operands[0]); operands[3] = gen_int_mode (l, SImode); -}") +}) ;; Originally, we tried to keep movsf and movsd common, but the differences ;; addressing was making it rather difficult to hide with mode attributes. In @@ -7176,7 +7257,7 @@ r, r, *h, 0"))] "(register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)) - && TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT + && TARGET_HARD_FLOAT && (TARGET_ALLOW_SF_SUBREG || valid_sf_si_move (operands[0], operands[1], SFmode))" "@ @@ -7212,7 +7293,7 @@ f, r, r, *h, 0"))] "(register_operand (operands[0], SDmode) || register_operand (operands[1], SDmode)) - && TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT" + && TARGET_HARD_FLOAT" "@ lwz%U1%X1 %0,%1 lfiwzx %0,%y1 @@ -7229,9 +7310,17 @@ "load, fpload, store, fpstore, mffgpr, mftgpr, fpsimple, *, mtjmpr, mfjmpr, *")]) +;; MR MT%0 MF%0 LWZ STW LI +;; LIS G-const. F/n-const NOP (define_insn "*mov<mode>_softfloat" - [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r,r,*h") - (match_operand:FMOVE32 1 "input_operand" "r,r,h,m,r,I,L,G,Fn,0"))] + [(set (match_operand:FMOVE32 0 "nonimmediate_operand" + "=r, cl, r, r, m, r, + r, r, r, *h") + + (match_operand:FMOVE32 1 "input_operand" + "r, r, h, m, r, I, + L, G, Fn, 0"))] + "(gpc_reg_operand (operands[0], <MODE>mode) || gpc_reg_operand (operands[1], <MODE>mode)) && TARGET_SOFT_FLOAT" @@ -7246,8 +7335,13 @@ # # nop" - [(set_attr "type" "*,mtjmpr,mfjmpr,load,store,*,*,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,8,4")]) + [(set_attr "type" + "*, mtjmpr, mfjmpr, load, store, *, + *, *, *, *") + + (set_attr "length" + "4, 4, 4, 4, 4, 4, + 4, 4, 8, 4")]) ;; Like movsf, but adjust a SI value to be used in a SF context, i.e. ;; (set (reg:SF ...) (subreg:SF (reg:SI ...) 0)) @@ -7321,14 +7415,17 @@ ;; Move 64-bit binary/decimal floating point (define_expand "mov<mode>" - [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "") - (match_operand:FMOVE64 1 "any_operand" ""))] - "" - "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") + [(set (match_operand:FMOVE64 0 "nonimmediate_operand") + (match_operand:FMOVE64 1 "any_operand"))] + "" +{ + rs6000_emit_move (operands[0], operands[1], <MODE>mode); + DONE; +}) (define_split - [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") - (match_operand:FMOVE64 1 "const_int_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand") + (match_operand:FMOVE64 1 "const_int_operand"))] "! TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -7336,7 +7433,6 @@ && REGNO (SUBREG_REG (operands[0])) <= 31))" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 1))] - " { int endian = (WORDS_BIG_ENDIAN == 0); HOST_WIDE_INT value = INTVAL (operands[1]); @@ -7345,11 +7441,11 @@ operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode); operands[4] = GEN_INT (value >> 32); operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000); -}") +}) (define_split - [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") - (match_operand:FMOVE64 1 "const_double_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand") + (match_operand:FMOVE64 1 "const_double_operand"))] "! TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG @@ -7357,7 +7453,6 @@ && REGNO (SUBREG_REG (operands[0])) <= 31))" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] - " { int endian = (WORDS_BIG_ENDIAN == 0); long l[2]; @@ -7368,18 +7463,17 @@ operands[3] = operand_subword (operands[0], 1 - endian, 0, <MODE>mode); operands[4] = gen_int_mode (l[endian], SImode); operands[5] = gen_int_mode (l[1 - endian], SImode); -}") +}) (define_split - [(set (match_operand:FMOVE64 0 "gpc_reg_operand" "") - (match_operand:FMOVE64 1 "const_double_operand" ""))] + [(set (match_operand:FMOVE64 0 "gpc_reg_operand") + (match_operand:FMOVE64 1 "const_double_operand"))] "TARGET_POWERPC64 && reload_completed && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31) || (GET_CODE (operands[0]) == SUBREG && GET_CODE (SUBREG_REG (operands[0])) == REG && REGNO (SUBREG_REG (operands[0])) <= 31))" [(set (match_dup 2) (match_dup 3))] - " { int endian = (WORDS_BIG_ENDIAN == 0); long l[2]; @@ -7393,7 +7487,7 @@ | ((HOST_WIDE_INT)(unsigned long)l[1 - endian])); operands[3] = gen_int_mode (val, DImode); -}") +}) ;; Don't have reload use general registers to load a constant. It is ;; less efficient than loading the constant into an FP register, since @@ -7410,10 +7504,23 @@ ;; If we have FPR registers, rs6000_emit_move has moved all constants to memory, ;; except for 0.0 which can be created on VSX with an xor instruction. +;; STFD LFD FMR LXSD STXSD +;; LXSD STXSD XXLOR XXLXOR GPR<-0 +;; LWZ STW MR + + (define_insn "*mov<mode>_hardfloat32" - [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,<f64_p9>,wY,<f64_av>,Z,<f64_vsx>,<f64_vsx>,!r,Y,r,!r") - (match_operand:FMOVE64 1 "input_operand" "d,m,d,wY,<f64_p9>,Z,<f64_av>,<f64_vsx>,<zero_fp>,<zero_fp>,r,Y,r"))] - "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" + "=m, d, d, <f64_p9>, wY, + <f64_av>, Z, <f64_vsx>, <f64_vsx>, !r, + Y, r, !r") + + (match_operand:FMOVE64 1 "input_operand" + "d, m, d, wY, <f64_p9>, + Z, <f64_av>, <f64_vsx>, <zero_fp>, <zero_fp>, + r, Y, r"))] + + "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && (gpc_reg_operand (operands[0], <MODE>mode) || gpc_reg_operand (operands[1], <MODE>mode))" "@ @@ -7422,35 +7529,66 @@ fmr %0,%1 lxsd %0,%1 stxsd %1,%0 - lxsd%U1x %x0,%y1 - stxsd%U0x %x1,%y0 + lxsdx %x0,%y1 + stxsdx %x1,%y0 xxlor %x0,%x1,%x1 xxlxor %x0,%x0,%x0 # # # #" - [(set_attr "type" "fpstore,fpload,fpsimple,fpload,fpstore,fpload,fpstore,veclogical,veclogical,two,store,load,two") + [(set_attr "type" + "fpstore, fpload, fpsimple, fpload, fpstore, + fpload, fpstore, veclogical, veclogical, two, + store, load, two") + (set_attr "size" "64") - (set_attr "length" "4,4,4,4,4,4,4,4,4,8,8,8,8")]) + (set_attr "length" + "4, 4, 4, 4, 4, + 4, 4, 4, 4, 8, + 8, 8, 8")]) + +;; STW LWZ MR G-const H-const F-const (define_insn "*mov<mode>_softfloat32" - [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r") - (match_operand:FMOVE64 1 "input_operand" "r,Y,r,G,H,F"))] - "! TARGET_POWERPC64 - && (TARGET_SINGLE_FLOAT || TARGET_SOFT_FLOAT) + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" + "=Y, r, r, r, r, r") + + (match_operand:FMOVE64 1 "input_operand" + "r, Y, r, G, H, F"))] + + "!TARGET_POWERPC64 && (gpc_reg_operand (operands[0], <MODE>mode) || gpc_reg_operand (operands[1], <MODE>mode))" "#" - [(set_attr "type" "store,load,two,*,*,*") - (set_attr "length" "8,8,8,8,12,16")]) + [(set_attr "type" + "store, load, two, *, *, *") + + (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. + +;; STFD LFD FMR LXSD STXSD +;; LXSDX STXSDX XXLOR XXLXOR LI 0 +;; STD LD MR MT{CTR,LR} MF{CTR,LR} +;; NOP MFTGPR MFFGPR MFVSRD MTVSRD + (define_insn "*mov<mode>_hardfloat64" - [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,<f64_p9>,wY,<f64_av>,Z,<f64_vsx>,<f64_vsx>,!r,Y,r,!r,*c*l,!r,*h,r,wg,r,<f64_dm>") - (match_operand:FMOVE64 1 "input_operand" "d,m,d,wY,<f64_p9>,Z,<f64_av>,<f64_vsx>,<zero_fp>,<zero_fp>,r,Y,r,r,h,0,wg,r,<f64_dm>,r"))] - "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" + "=m, d, d, <f64_p9>, wY, + <f64_av>, Z, <f64_vsx>, <f64_vsx>, !r, + YZ, r, !r, *c*l, !r, + *h, r, wg, r, <f64_dm>") + + (match_operand:FMOVE64 1 "input_operand" + "d, m, d, wY, <f64_p9>, + Z, <f64_av>, <f64_vsx>, <zero_fp>, <zero_fp>, + r, YZ, r, r, h, + 0, wg, r, <f64_dm>, r"))] + + "TARGET_POWERPC64 && TARGET_HARD_FLOAT && (gpc_reg_operand (operands[0], <MODE>mode) || gpc_reg_operand (operands[1], <MODE>mode))" "@ @@ -7459,8 +7597,8 @@ fmr %0,%1 lxsd %0,%1 stxsd %1,%0 - lxsd%U1x %x0,%y1 - stxsd%U0x %x1,%y0 + lxsdx %x0,%y1 + stxsdx %x1,%y0 xxlor %x0,%x1,%x1 xxlxor %x0,%x0,%x0 li %0,0 @@ -7474,13 +7612,27 @@ mffgpr %0,%1 mfvsrd %0,%x1 mtvsrd %x0,%1" - [(set_attr "type" "fpstore,fpload,fpsimple,fpload,fpstore,fpload,fpstore,veclogical,veclogical,integer,store,load,*,mtjmpr,mfjmpr,*,mftgpr,mffgpr,mftgpr,mffgpr") + [(set_attr "type" + "fpstore, fpload, fpsimple, fpload, fpstore, + fpload, fpstore, veclogical, veclogical, integer, + store, load, *, mtjmpr, mfjmpr, + *, mftgpr, mffgpr, mftgpr, mffgpr") + (set_attr "size" "64") (set_attr "length" "4")]) +;; STD LD MR MT<SPR> MF<SPR> G-const +;; H-const F-const Special + (define_insn "*mov<mode>_softfloat64" - [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h") - (match_operand:FMOVE64 1 "input_operand" "r,Y,r,r,h,G,H,F,0"))] + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" + "=Y, r, r, cl, r, r, + r, r, *h") + + (match_operand:FMOVE64 1 "input_operand" + "r, Y, r, r, h, G, + H, F, 0"))] + "TARGET_POWERPC64 && TARGET_SOFT_FLOAT && (gpc_reg_operand (operands[0], <MODE>mode) || gpc_reg_operand (operands[1], <MODE>mode))" @@ -7494,14 +7646,22 @@ # # nop" - [(set_attr "type" "store,load,*,mtjmpr,mfjmpr,*,*,*,*") - (set_attr "length" "4,4,4,4,4,8,12,16,4")]) + [(set_attr "type" + "store, load, *, mtjmpr, mfjmpr, *, + *, *, *") + + (set_attr "length" + "4, 4, 4, 4, 4, 8, + 12, 16, 4")]) (define_expand "mov<mode>" - [(set (match_operand:FMOVE128 0 "general_operand" "") - (match_operand:FMOVE128 1 "any_operand" ""))] - "" - "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") + [(set (match_operand:FMOVE128 0 "general_operand") + (match_operand:FMOVE128 1 "any_operand"))] + "" +{ + rs6000_emit_move (operands[0], operands[1], <MODE>mode); + DONE; +}) ;; It's important to list Y->r and r->Y before r->r because otherwise ;; reload, given m->r, will try to pick r->r and reload it, which @@ -7564,8 +7724,8 @@ [(set_attr "length" "20,20,16")]) (define_expand "extenddf<mode>2" - [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "") - (float_extend:FLOAT128 (match_operand:DF 1 "gpc_reg_operand" "")))] + [(set (match_operand:FLOAT128 0 "gpc_reg_operand") + (float_extend:FLOAT128 (match_operand:DF 1 "gpc_reg_operand")))] "TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" { if (FLOAT128_IEEE_P (<MODE>mode)) @@ -7600,7 +7760,7 @@ (float_extend:IBM128 (match_operand:DF 1 "nonimmediate_operand" "d,m,d"))) (use (match_operand:DF 2 "nonimmediate_operand" "m,m,d"))] - "!TARGET_VSX && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + "!TARGET_VSX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)" "#" "&& reload_completed" @@ -7633,8 +7793,8 @@ }) (define_expand "extendsf<mode>2" - [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "") - (float_extend:FLOAT128 (match_operand:SF 1 "gpc_reg_operand" "")))] + [(set (match_operand:FLOAT128 0 "gpc_reg_operand") + (float_extend:FLOAT128 (match_operand:SF 1 "gpc_reg_operand")))] "TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" { if (FLOAT128_IEEE_P (<MODE>mode)) @@ -7649,8 +7809,8 @@ }) (define_expand "trunc<mode>df2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))] + [(set (match_operand:DF 0 "gpc_reg_operand") + (float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand")))] "TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" { if (FLOAT128_IEEE_P (<MODE>mode)) @@ -7681,40 +7841,25 @@ [(set (match_operand:DF 0 "gpc_reg_operand" "=d") (float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "d")))] "FLOAT128_IBM_P (<MODE>mode) && TARGET_XL_COMPAT && TARGET_HARD_FLOAT - && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" + && TARGET_LONG_DOUBLE_128" "fadd %0,%1,%L1" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_addsub_d")]) + [(set_attr "type" "fp")]) (define_expand "trunc<mode>sf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (float_truncate:SF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))] + [(set (match_operand:SF 0 "gpc_reg_operand") + (float_truncate:SF (match_operand:FLOAT128 1 "gpc_reg_operand")))] "TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" { if (FLOAT128_IEEE_P (<MODE>mode)) rs6000_expand_float128_convert (operands[0], operands[1], false); - else if (<MODE>mode == TFmode) - emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1])); - else if (<MODE>mode == IFmode) - emit_insn (gen_truncifsf2_fprs (operands[0], operands[1])); - else - gcc_unreachable (); - DONE; -}) - -(define_insn_and_split "trunc<mode>sf2_fprs" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (float_truncate:SF (match_operand:IBM128 1 "gpc_reg_operand" "d"))) - (clobber (match_scratch:DF 2 "=d"))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT - && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)" - "#" - "&& reload_completed" - [(set (match_dup 2) - (float_truncate:DF (match_dup 1))) - (set (match_dup 0) - (float_truncate:SF (match_dup 2)))] - "") + else + { + rtx tmp = gen_reg_rtx (DFmode); + emit_insn (gen_trunc<mode>df2 (tmp, operands[1])); + emit_insn (gen_truncdfsf2 (operands[0], tmp)); + } + DONE; +}) (define_expand "floatsi<mode>2" [(parallel [(set (match_operand:FLOAT128 0 "gpc_reg_operand") @@ -7753,14 +7898,14 @@ (unspec:DF [(match_operand:IBM128 1 "gpc_reg_operand" "d")] UNSPEC_FIX_TRUNC_TF)) (clobber (match_operand:DF 2 "gpc_reg_operand" "=&d"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && FLOAT128_IBM_P (<MODE>mode)" + "TARGET_HARD_FLOAT && FLOAT128_IBM_P (<MODE>mode)" "mffs %2\n\tmtfsb1 31\n\tmtfsb0 30\n\tfadd %0,%1,%L1\n\tmtfsf 1,%2" [(set_attr "type" "fp") (set_attr "length" "20")]) (define_expand "fix_trunc<mode>si2" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:FLOAT128 1 "gpc_reg_operand" "")))] + [(set (match_operand:SI 0 "gpc_reg_operand") + (fix:SI (match_operand:FLOAT128 1 "gpc_reg_operand")))] "TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" { rtx op0 = operands[0]; @@ -7783,8 +7928,8 @@ }) (define_expand "fix_trunc<mode>si2_fprs" - [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" ""))) + [(parallel [(set (match_operand:SI 0 "gpc_reg_operand") + (fix:SI (match_operand:IBM128 1 "gpc_reg_operand"))) (clobber (match_dup 2)) (clobber (match_dup 3)) (clobber (match_dup 4)) @@ -7823,8 +7968,8 @@ }) (define_expand "fix_trunc<mode>di2" - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (fix:DI (match_operand:IEEE128 1 "gpc_reg_operand" "")))] + [(set (match_operand:DI 0 "gpc_reg_operand") + (fix:DI (match_operand:IEEE128 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { if (!TARGET_FLOAT128_HW) @@ -7835,8 +7980,8 @@ }) (define_expand "fixuns_trunc<IEEE128:mode><SDI:mode>2" - [(set (match_operand:SDI 0 "gpc_reg_operand" "") - (unsigned_fix:SDI (match_operand:IEEE128 1 "gpc_reg_operand" "")))] + [(set (match_operand:SDI 0 "gpc_reg_operand") + (unsigned_fix:SDI (match_operand:IEEE128 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rs6000_expand_float128_convert (operands[0], operands[1], true); @@ -7844,8 +7989,8 @@ }) (define_expand "floatdi<mode>2" - [(set (match_operand:IEEE128 0 "gpc_reg_operand" "") - (float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))] + [(set (match_operand:IEEE128 0 "gpc_reg_operand") + (float:IEEE128 (match_operand:DI 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { if (!TARGET_FLOAT128_HW) @@ -7856,8 +8001,8 @@ }) (define_expand "floatunsdi<IEEE128:mode>2" - [(set (match_operand:IEEE128 0 "gpc_reg_operand" "") - (unsigned_float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))] + [(set (match_operand:IEEE128 0 "gpc_reg_operand") + (unsigned_float:IEEE128 (match_operand:DI 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { if (!TARGET_FLOAT128_HW) @@ -7868,8 +8013,8 @@ }) (define_expand "floatuns<IEEE128:mode>2" - [(set (match_operand:IEEE128 0 "gpc_reg_operand" "") - (unsigned_float:IEEE128 (match_operand:SI 1 "gpc_reg_operand" "")))] + [(set (match_operand:IEEE128 0 "gpc_reg_operand") + (unsigned_float:IEEE128 (match_operand:SI 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rtx op0 = operands[0]; @@ -7883,11 +8028,10 @@ }) (define_expand "neg<mode>2" - [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "") - (neg:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand" "")))] + [(set (match_operand:FLOAT128 0 "gpc_reg_operand") + (neg:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand")))] "FLOAT128_IEEE_P (<MODE>mode) || (FLOAT128_IBM_P (<MODE>mode) && TARGET_HARD_FLOAT)" - " { if (FLOAT128_IEEE_P (<MODE>mode)) { @@ -7921,28 +8065,26 @@ } DONE; } -}") +}) (define_insn "neg<mode>2_internal" [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d") (neg:IBM128 (match_operand:IBM128 1 "gpc_reg_operand" "d")))] - "TARGET_HARD_FLOAT && FLOAT128_IBM_P (TFmode)" - "* + "TARGET_HARD_FLOAT && FLOAT128_IBM_P (<MODE>mode)" { if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"fneg %L0,%L1\;fneg %0,%1\"; - else - return \"fneg %0,%1\;fneg %L0,%L1\"; -}" + return "fneg %L0,%L1\;fneg %0,%1"; + else + return "fneg %0,%1\;fneg %L0,%L1"; +} [(set_attr "type" "fpsimple") (set_attr "length" "8")]) (define_expand "abs<mode>2" - [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "") - (abs:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand" "")))] + [(set (match_operand:FLOAT128 0 "gpc_reg_operand") + (abs:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand")))] "FLOAT128_IEEE_P (<MODE>mode) || (FLOAT128_IBM_P (<MODE>mode) && TARGET_HARD_FLOAT)" - " { rtx label; @@ -7975,26 +8117,25 @@ label = gen_label_rtx (); if (<MODE>mode == TFmode) emit_insn (gen_abstf2_internal (operands[0], operands[1], label)); - else if (<MODE>mode == TFmode) + else if (<MODE>mode == IFmode) emit_insn (gen_absif2_internal (operands[0], operands[1], label)); else FAIL; emit_label (label); DONE; -}") +}) (define_expand "abs<mode>2_internal" - [(set (match_operand:IBM128 0 "gpc_reg_operand" "") - (match_operand:IBM128 1 "gpc_reg_operand" "")) + [(set (match_operand:IBM128 0 "gpc_reg_operand") + (match_operand:IBM128 1 "gpc_reg_operand")) (set (match_dup 3) (match_dup 5)) (set (match_dup 5) (abs:DF (match_dup 5))) (set (match_dup 4) (compare:CCFP (match_dup 3) (match_dup 5))) (set (pc) (if_then_else (eq (match_dup 4) (const_int 0)) - (label_ref (match_operand 2 "" "")) + (label_ref (match_operand 2 "")) (pc))) (set (match_dup 6) (neg:DF (match_dup 6)))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" - " + "TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" { const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode); const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0; @@ -8002,14 +8143,14 @@ operands[4] = gen_reg_rtx (CCFPmode); operands[5] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word); operands[6] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word); -}") +}) ;; Generate IEEE 128-bit -0.0 (0x80000000000000000000000000000000) in a vector ;; register (define_expand "ieee_128bit_negative_zero" - [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))] + [(set (match_operand:V16QI 0 "register_operand") (match_dup 1))] "TARGET_FLOAT128_TYPE" { rtvec v = rtvec_alloc (16); @@ -8019,7 +8160,7 @@ RTVEC_ELT (v, i) = const0_rtx; high = (BYTES_BIG_ENDIAN) ? 0 : 15; - RTVEC_ELT (v, high) = GEN_INT (0x80); + RTVEC_ELT (v, high) = gen_int_mode (0x80, QImode); rs6000_expand_vector_init (operands[0], gen_rtx_PARALLEL (V16QImode, v)); DONE; @@ -8128,8 +8269,8 @@ ;; We use expand to convert from IBM double double to IEEE 128-bit ;; and trunc for the opposite. (define_expand "extendiftf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "")))] + [(set (match_operand:TF 0 "gpc_reg_operand") + (float_extend:TF (match_operand:IF 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rs6000_expand_float128_convert (operands[0], operands[1], false); @@ -8137,8 +8278,8 @@ }) (define_expand "extendifkf2" - [(set (match_operand:KF 0 "gpc_reg_operand" "") - (float_extend:KF (match_operand:IF 1 "gpc_reg_operand" "")))] + [(set (match_operand:KF 0 "gpc_reg_operand") + (float_extend:KF (match_operand:IF 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rs6000_expand_float128_convert (operands[0], operands[1], false); @@ -8146,8 +8287,17 @@ }) (define_expand "extendtfkf2" - [(set (match_operand:KF 0 "gpc_reg_operand" "") - (float_extend:KF (match_operand:TF 1 "gpc_reg_operand" "")))] + [(set (match_operand:KF 0 "gpc_reg_operand") + (float_extend:KF (match_operand:TF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "extendtfif2" + [(set (match_operand:IF 0 "gpc_reg_operand") + (float_extend:IF (match_operand:TF 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rs6000_expand_float128_convert (operands[0], operands[1], false); @@ -8155,8 +8305,8 @@ }) (define_expand "trunciftf2" - [(set (match_operand:IF 0 "gpc_reg_operand" "") - (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))] + [(set (match_operand:TF 0 "gpc_reg_operand") + (float_truncate:TF (match_operand:IF 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rs6000_expand_float128_convert (operands[0], operands[1], false); @@ -8164,8 +8314,8 @@ }) (define_expand "truncifkf2" - [(set (match_operand:IF 0 "gpc_reg_operand" "") - (float_truncate:IF (match_operand:KF 1 "gpc_reg_operand" "")))] + [(set (match_operand:KF 0 "gpc_reg_operand") + (float_truncate:KF (match_operand:IF 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rs6000_expand_float128_convert (operands[0], operands[1], false); @@ -8173,8 +8323,8 @@ }) (define_expand "trunckftf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (float_truncate:TF (match_operand:KF 1 "gpc_reg_operand" "")))] + [(set (match_operand:TF 0 "gpc_reg_operand") + (float_truncate:TF (match_operand:KF 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rs6000_expand_float128_convert (operands[0], operands[1], false); @@ -8182,14 +8332,40 @@ }) (define_expand "trunctfif2" - [(set (match_operand:IF 0 "gpc_reg_operand" "") - (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))] + [(set (match_operand:IF 0 "gpc_reg_operand") + (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand")))] "TARGET_FLOAT128_TYPE" { rs6000_expand_float128_convert (operands[0], operands[1], false); DONE; }) +(define_insn_and_split "*extend<mode>tf2_internal" + [(set (match_operand:TF 0 "gpc_reg_operand" "=<IFKF_reg>") + (float_extend:TF + (match_operand:IFKF 1 "gpc_reg_operand" "<IFKF_reg>")))] + "TARGET_FLOAT128_TYPE + && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (<MODE>mode)" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 2))] +{ + operands[2] = gen_rtx_REG (TFmode, REGNO (operands[1])); +}) + +(define_insn_and_split "*extendtf<mode>2_internal" + [(set (match_operand:IFKF 0 "gpc_reg_operand" "=<IFKF_reg>") + (float_extend:IFKF + (match_operand:TF 1 "gpc_reg_operand" "<IFKF_reg>")))] + "TARGET_FLOAT128_TYPE + && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (<MODE>mode)" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 2))] +{ + operands[2] = gen_rtx_REG (<MODE>mode, REGNO (operands[1])); +}) + ;; Reload helper functions used by rs6000_secondary_reload. The patterns all ;; must have 3 arguments, and scratch register constraint must be a single @@ -8362,8 +8538,8 @@ (set_attr "type" "three")]) (define_split - [(set (match_operand:FMOVE128_GPR 0 "nonimmediate_operand" "") - (match_operand:FMOVE128_GPR 1 "input_operand" ""))] + [(set (match_operand:FMOVE128_GPR 0 "nonimmediate_operand") + (match_operand:FMOVE128_GPR 1 "input_operand"))] "reload_completed && (int_reg_operand (operands[0], <MODE>mode) || int_reg_operand (operands[1], <MODE>mode)) @@ -8487,16 +8663,16 @@ (define_insn "*movdi_internal32" [(set (match_operand:DI 0 "nonimmediate_operand" - "=Y, r, r, ^m, ^d, ^d, - r, ^wY, $Z, ^wb, $wv, ^wi, + "=Y, r, r, m, ^d, ^d, + r, wY, Z, ^wb, $wv, ^wi, *wo, *wo, *wv, *wi, *wi, *wv, *wv") (match_operand:DI 1 "input_operand" - "r, Y, r, d, m, d, - IJKnGHF, wb, wv, wY, Z, wi, - Oj, wM, OjwM, Oj, wM, wS, - wB"))] + "r, Y, r, ^d, m, ^d, + IJKnGHF, ^wb, $wv, wY, Z, ^wi, + Oj, wM, OjwM, Oj, wM, wS, + wB"))] "! TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode) @@ -8529,14 +8705,13 @@ (set_attr "size" "64")]) (define_split - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (match_operand:DI 1 "const_int_operand" ""))] + [(set (match_operand:DI 0 "gpc_reg_operand") + (match_operand:DI 1 "const_int_operand"))] "! TARGET_POWERPC64 && reload_completed && gpr_or_gpr_p (operands[0], operands[1]) && !direct_move_p (operands[0], operands[1])" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 1))] - " { HOST_WIDE_INT value = INTVAL (operands[1]); operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0, @@ -8545,11 +8720,11 @@ DImode); operands[4] = GEN_INT (value >> 32); operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000); -}") +}) (define_split - [(set (match_operand:DIFD 0 "nonimmediate_operand" "") - (match_operand:DIFD 1 "input_operand" ""))] + [(set (match_operand:DIFD 0 "nonimmediate_operand") + (match_operand:DIFD 1 "input_operand"))] "reload_completed && !TARGET_POWERPC64 && gpr_or_gpr_p (operands[0], operands[1]) && !direct_move_p (operands[0], operands[1])" @@ -8563,18 +8738,18 @@ ;; FPR->GPR GPR->FPR VSX->GPR GPR->VSX (define_insn "*movdi_internal64" [(set (match_operand:DI 0 "nonimmediate_operand" - "=Y, r, r, r, r, r, - ^m, ^d, ^d, ^wY, $Z, $wb, + "=YZ, r, r, r, r, r, + m, ^d, ^d, wY, Z, $wb, $wv, ^wi, *wo, *wo, *wv, *wi, *wi, *wv, *wv, r, *h, *h, ?*r, ?*wg, ?*r, ?*wj") (match_operand:DI 1 "input_operand" - "r, Y, r, I, L, nF, - d, m, d, wb, wv, wY, - Z, wi, Oj, wM, OjwM, Oj, - wM, wS, wB, *h, r, 0, - wg, r, wj, r"))] + "r, YZ, r, I, L, nF, + ^d, m, ^d, ^wb, $wv, wY, + Z, ^wi, Oj, wM, OjwM, Oj, + wM, wS, wB, *h, r, 0, + wg, r, wj, r"))] "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode) @@ -8644,36 +8819,34 @@ ;; When non-easy constants can go in the TOC, this should use ;; easy_fp_constant predicate. (define_split - [(set (match_operand:DI 0 "int_reg_operand_not_pseudo" "") - (match_operand:DI 1 "const_int_operand" ""))] + [(set (match_operand:DI 0 "int_reg_operand_not_pseudo") + (match_operand:DI 1 "const_int_operand"))] "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1" [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] - " { if (rs6000_emit_set_const (operands[0], operands[1])) DONE; else FAIL; -}") +}) (define_split - [(set (match_operand:DI 0 "int_reg_operand_not_pseudo" "") - (match_operand:DI 1 "const_scalar_int_operand" ""))] + [(set (match_operand:DI 0 "int_reg_operand_not_pseudo") + (match_operand:DI 1 "const_scalar_int_operand"))] "TARGET_POWERPC64 && num_insns_constant (operands[1], DImode) > 1" [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] - " { if (rs6000_emit_set_const (operands[0], operands[1])) DONE; else FAIL; -}") +}) (define_split - [(set (match_operand:DI 0 "altivec_register_operand" "") - (match_operand:DI 1 "s5bit_cint_operand" ""))] + [(set (match_operand:DI 0 "altivec_register_operand") + (match_operand:DI 1 "s5bit_cint_operand"))] "TARGET_VSX && reload_completed" [(const_int 0)] { @@ -8694,8 +8867,8 @@ ;; Split integer constants that can be loaded with XXSPLTIB and a ;; sign extend operation. (define_split - [(set (match_operand:INT_ISA3 0 "altivec_register_operand" "") - (match_operand:INT_ISA3 1 "xxspltib_constant_split" ""))] + [(set (match_operand:INT_ISA3 0 "altivec_register_operand") + (match_operand:INT_ISA3 1 "xxspltib_constant_split"))] "TARGET_P9_VECTOR && reload_completed" [(const_int 0)] { @@ -8728,37 +8901,11 @@ && (<MODE>mode != TImode || VECTOR_MEM_NONE_P (TImode)) && (gpc_reg_operand (operands[0], <MODE>mode) || gpc_reg_operand (operands[1], <MODE>mode))" - "* -{ - switch (which_alternative) - { - default: - gcc_unreachable (); - case 0: - if (TARGET_STRING) - return \"stswi %1,%P0,16\"; - /* FALLTHRU */ - case 1: - return \"#\"; - case 2: - /* If the address is not used in the output, we can use lsi. Otherwise, - fall through to generating four loads. */ - if (TARGET_STRING - && ! reg_overlap_mentioned_p (operands[0], operands[1])) - return \"lswi %0,%P1,16\"; - /* fall through */ - case 3: - case 4: - case 5: - return \"#\"; - } -}" + "#" [(set_attr "type" "store,store,load,load,*,*") (set_attr "update" "yes") (set_attr "indexed" "yes") - (set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING") - (const_string "always") - (const_string "conditional")))]) + (set_attr "cell_micro" "conditional")]) (define_insn "*mov<mode>_ppc64" [(set (match_operand:TI2 0 "nonimmediate_operand" "=wQ,Y,r,r,r,r") @@ -8773,14 +8920,13 @@ (set_attr "length" "8")]) (define_split - [(set (match_operand:TI2 0 "int_reg_operand" "") - (match_operand:TI2 1 "const_scalar_int_operand" ""))] + [(set (match_operand:TI2 0 "int_reg_operand") + (match_operand:TI2 1 "const_scalar_int_operand"))] "TARGET_POWERPC64 && (VECTOR_MEM_NONE_P (<MODE>mode) || (reload_completed && INT_REGNO_P (REGNO (operands[0]))))" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] - " { operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0, <MODE>mode); @@ -8798,11 +8944,11 @@ } else FAIL; -}") +}) (define_split - [(set (match_operand:TI2 0 "nonimmediate_operand" "") - (match_operand:TI2 1 "input_operand" ""))] + [(set (match_operand:TI2 0 "nonimmediate_operand") + (match_operand:TI2 1 "input_operand"))] "reload_completed && gpr_or_gpr_p (operands[0], operands[1]) && !direct_move_p (operands[0], operands[1]) @@ -8810,344 +8956,12 @@ [(pc)] { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) -(define_expand "load_multiple" - [(match_par_dup 3 [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" "")) - (use (match_operand:SI 2 "" ""))])] - "TARGET_STRING && !TARGET_POWERPC64" - " -{ - int regno; - int count; - rtx op1; - int i; - - /* Support only loading a constant number of fixed-point registers from - memory and only bother with this if more than two; the machine - doesn't support more than eight. */ - if (GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) <= 2 - || INTVAL (operands[2]) > 8 - || GET_CODE (operands[1]) != MEM - || GET_CODE (operands[0]) != REG - || REGNO (operands[0]) >= 32) - FAIL; - - count = INTVAL (operands[2]); - regno = REGNO (operands[0]); - - operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); - op1 = replace_equiv_address (operands[1], - force_reg (SImode, XEXP (operands[1], 0))); - - for (i = 0; i < count; i++) - XVECEXP (operands[3], 0, i) - = gen_rtx_SET (gen_rtx_REG (SImode, regno + i), - adjust_address_nv (op1, SImode, i * 4)); -}") - -(define_insn "*ldmsi8" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 4)))) - (set (match_operand:SI 4 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 8)))) - (set (match_operand:SI 5 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 12)))) - (set (match_operand:SI 6 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 16)))) - (set (match_operand:SI 7 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 20)))) - (set (match_operand:SI 8 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 24)))) - (set (match_operand:SI 9 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 28))))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 8" - "* -{ return rs6000_output_load_multiple (operands); }" - [(set_attr "type" "load") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "length" "32")]) - -(define_insn "*ldmsi7" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 4)))) - (set (match_operand:SI 4 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 8)))) - (set (match_operand:SI 5 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 12)))) - (set (match_operand:SI 6 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 16)))) - (set (match_operand:SI 7 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 20)))) - (set (match_operand:SI 8 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 24))))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 7" - "* -{ return rs6000_output_load_multiple (operands); }" - [(set_attr "type" "load") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "length" "32")]) - -(define_insn "*ldmsi6" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 4)))) - (set (match_operand:SI 4 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 8)))) - (set (match_operand:SI 5 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 12)))) - (set (match_operand:SI 6 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 16)))) - (set (match_operand:SI 7 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 20))))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 6" - "* -{ return rs6000_output_load_multiple (operands); }" - [(set_attr "type" "load") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "length" "32")]) - -(define_insn "*ldmsi5" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 4)))) - (set (match_operand:SI 4 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 8)))) - (set (match_operand:SI 5 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 12)))) - (set (match_operand:SI 6 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 16))))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 5" - "* -{ return rs6000_output_load_multiple (operands); }" - [(set_attr "type" "load") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "length" "32")]) - -(define_insn "*ldmsi4" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 4)))) - (set (match_operand:SI 4 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 8)))) - (set (match_operand:SI 5 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 4" - "* -{ return rs6000_output_load_multiple (operands); }" - [(set_attr "type" "load") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "length" "32")]) - -(define_insn "*ldmsi3" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 4)))) - (set (match_operand:SI 4 "gpc_reg_operand" "") - (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 3" - "* -{ return rs6000_output_load_multiple (operands); }" - [(set_attr "type" "load") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "length" "32")]) - -(define_expand "store_multiple" - [(match_par_dup 3 [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" "")) - (clobber (scratch:SI)) - (use (match_operand:SI 2 "" ""))])] - "TARGET_STRING && !TARGET_POWERPC64" - " -{ - int regno; - int count; - rtx to; - rtx op0; - int i; - - /* Support only storing a constant number of fixed-point registers to - memory and only bother with this if more than two; the machine - doesn't support more than eight. */ - if (GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) <= 2 - || INTVAL (operands[2]) > 8 - || GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != REG - || REGNO (operands[1]) >= 32) - FAIL; - - count = INTVAL (operands[2]); - regno = REGNO (operands[1]); - - operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1)); - to = force_reg (SImode, XEXP (operands[0], 0)); - op0 = replace_equiv_address (operands[0], to); - - XVECEXP (operands[3], 0, 0) - = gen_rtx_SET (adjust_address_nv (op0, SImode, 0), operands[1]); - XVECEXP (operands[3], 0, 1) = gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (SImode)); - - for (i = 1; i < count; i++) - XVECEXP (operands[3], 0, i + 1) - = gen_rtx_SET (adjust_address_nv (op0, SImode, i * 4), - gen_rtx_REG (SImode, regno + i)); -}") - -(define_insn "*stmsi8" - [(match_parallel 0 "store_multiple_operation" - [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")) - (match_operand:SI 2 "gpc_reg_operand" "r")) - (clobber (match_scratch:SI 3 "=X")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) - (match_operand:SI 4 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) - (match_operand:SI 5 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) - (match_operand:SI 6 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) - (match_operand:SI 7 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) - (match_operand:SI 8 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) - (match_operand:SI 9 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) - (match_operand:SI 10 "gpc_reg_operand" "r"))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 9" - "stswi %2,%1,%O0" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always")]) - -(define_insn "*stmsi7" - [(match_parallel 0 "store_multiple_operation" - [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")) - (match_operand:SI 2 "gpc_reg_operand" "r")) - (clobber (match_scratch:SI 3 "=X")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) - (match_operand:SI 4 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) - (match_operand:SI 5 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) - (match_operand:SI 6 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) - (match_operand:SI 7 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) - (match_operand:SI 8 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) - (match_operand:SI 9 "gpc_reg_operand" "r"))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 8" - "stswi %2,%1,%O0" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always")]) - -(define_insn "*stmsi6" - [(match_parallel 0 "store_multiple_operation" - [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")) - (match_operand:SI 2 "gpc_reg_operand" "r")) - (clobber (match_scratch:SI 3 "=X")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) - (match_operand:SI 4 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) - (match_operand:SI 5 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) - (match_operand:SI 6 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) - (match_operand:SI 7 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) - (match_operand:SI 8 "gpc_reg_operand" "r"))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 7" - "stswi %2,%1,%O0" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always")]) - -(define_insn "*stmsi5" - [(match_parallel 0 "store_multiple_operation" - [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")) - (match_operand:SI 2 "gpc_reg_operand" "r")) - (clobber (match_scratch:SI 3 "=X")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) - (match_operand:SI 4 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) - (match_operand:SI 5 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) - (match_operand:SI 6 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) - (match_operand:SI 7 "gpc_reg_operand" "r"))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 6" - "stswi %2,%1,%O0" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always")]) - -(define_insn "*stmsi4" - [(match_parallel 0 "store_multiple_operation" - [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")) - (match_operand:SI 2 "gpc_reg_operand" "r")) - (clobber (match_scratch:SI 3 "=X")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) - (match_operand:SI 4 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) - (match_operand:SI 5 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) - (match_operand:SI 6 "gpc_reg_operand" "r"))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 5" - "stswi %2,%1,%O0" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always")]) - -(define_insn "*stmsi3" - [(match_parallel 0 "store_multiple_operation" - [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b")) - (match_operand:SI 2 "gpc_reg_operand" "r")) - (clobber (match_scratch:SI 3 "=X")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) - (match_operand:SI 4 "gpc_reg_operand" "r")) - (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) - (match_operand:SI 5 "gpc_reg_operand" "r"))])] - "TARGET_STRING && XVECLEN (operands[0], 0) == 4" - "stswi %2,%1,%O0" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always")]) - (define_expand "setmemsi" - [(parallel [(set (match_operand:BLK 0 "" "") - (match_operand 2 "const_int_operand" "")) - (use (match_operand:SI 1 "" "")) - (use (match_operand:SI 3 "" ""))])] - "" - " + [(parallel [(set (match_operand:BLK 0 "") + (match_operand 2 "const_int_operand")) + (use (match_operand:SI 1 "")) + (use (match_operand:SI 3 ""))])] + "" { /* If value to set is not zero, use the library routine. */ if (operands[2] != const0_rtx) @@ -9157,7 +8971,7 @@ DONE; else FAIL; -}") +}) ;; String compare N insn. ;; Argument 0 is the target (result) @@ -9233,198 +9047,17 @@ ;; Argument 3 is the alignment (define_expand "movmemsi" - [(parallel [(set (match_operand:BLK 0 "" "") - (match_operand:BLK 1 "" "")) - (use (match_operand:SI 2 "" "")) - (use (match_operand:SI 3 "" ""))])] - "" - " + [(parallel [(set (match_operand:BLK 0 "") + (match_operand:BLK 1 "")) + (use (match_operand:SI 2 "")) + (use (match_operand:SI 3 ""))])] + "" { if (expand_block_move (operands)) DONE; else FAIL; -}") - -;; Move up to 32 bytes at a time. The fixed registers are needed because the -;; register allocator doesn't have a clue about allocating 8 word registers. -;; rD/rS = r5 is preferred, efficient form. -(define_expand "movmemsi_8reg" - [(parallel [(set (match_operand 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" "")) - (clobber (reg:SI 5)) - (clobber (reg:SI 6)) - (clobber (reg:SI 7)) - (clobber (reg:SI 8)) - (clobber (reg:SI 9)) - (clobber (reg:SI 10)) - (clobber (reg:SI 11)) - (clobber (reg:SI 12)) - (clobber (match_scratch:SI 4 ""))])] - "TARGET_STRING" - "") - -(define_insn "" - [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b")) - (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b"))) - (use (match_operand:SI 2 "immediate_operand" "i")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (clobber (match_operand:SI 4 "gpc_reg_operand" "=&r")) - (clobber (reg:SI 6)) - (clobber (reg:SI 7)) - (clobber (reg:SI 8)) - (clobber (reg:SI 9)) - (clobber (reg:SI 10)) - (clobber (reg:SI 11)) - (clobber (reg:SI 12)) - (clobber (match_scratch:SI 5 "=X"))] - "TARGET_STRING - && ((INTVAL (operands[2]) > 24 && INTVAL (operands[2]) < 32) - || INTVAL (operands[2]) == 0) - && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 12) - && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 12) - && REGNO (operands[4]) == 5" - "lswi %4,%1,%2\;stswi %4,%0,%2" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always") - (set_attr "length" "8")]) - -;; Move up to 24 bytes at a time. The fixed registers are needed because the -;; register allocator doesn't have a clue about allocating 6 word registers. -;; rD/rS = r5 is preferred, efficient form. -(define_expand "movmemsi_6reg" - [(parallel [(set (match_operand 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" "")) - (clobber (reg:SI 5)) - (clobber (reg:SI 6)) - (clobber (reg:SI 7)) - (clobber (reg:SI 8)) - (clobber (reg:SI 9)) - (clobber (reg:SI 10)) - (clobber (match_scratch:SI 4 ""))])] - "TARGET_STRING" - "") - -(define_insn "" - [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b")) - (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b"))) - (use (match_operand:SI 2 "immediate_operand" "i")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (clobber (match_operand:SI 4 "gpc_reg_operand" "=&r")) - (clobber (reg:SI 6)) - (clobber (reg:SI 7)) - (clobber (reg:SI 8)) - (clobber (reg:SI 9)) - (clobber (reg:SI 10)) - (clobber (match_scratch:SI 5 "=X"))] - "TARGET_STRING - && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 32 - && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 10) - && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 10) - && REGNO (operands[4]) == 5" - "lswi %4,%1,%2\;stswi %4,%0,%2" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always") - (set_attr "length" "8")]) - -;; Move up to 16 bytes at a time, using 4 fixed registers to avoid spill -;; problems with TImode. -;; rD/rS = r5 is preferred, efficient form. -(define_expand "movmemsi_4reg" - [(parallel [(set (match_operand 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" "")) - (clobber (reg:SI 5)) - (clobber (reg:SI 6)) - (clobber (reg:SI 7)) - (clobber (reg:SI 8)) - (clobber (match_scratch:SI 4 ""))])] - "TARGET_STRING" - "") - -(define_insn "" - [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b")) - (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b"))) - (use (match_operand:SI 2 "immediate_operand" "i")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (clobber (match_operand:SI 4 "gpc_reg_operand" "=&r")) - (clobber (reg:SI 6)) - (clobber (reg:SI 7)) - (clobber (reg:SI 8)) - (clobber (match_scratch:SI 5 "=X"))] - "TARGET_STRING - && INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16 - && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 8) - && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 8) - && REGNO (operands[4]) == 5" - "lswi %4,%1,%2\;stswi %4,%0,%2" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always") - (set_attr "length" "8")]) - -;; Move up to 8 bytes at a time. -(define_expand "movmemsi_2reg" - [(parallel [(set (match_operand 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" "")) - (clobber (match_scratch:DI 4 "")) - (clobber (match_scratch:SI 5 ""))])] - "TARGET_STRING && ! TARGET_POWERPC64" - "") - -(define_insn "" - [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b")) - (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b"))) - (use (match_operand:SI 2 "immediate_operand" "i")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (clobber (match_scratch:DI 4 "=&r")) - (clobber (match_scratch:SI 5 "=X"))] - "TARGET_STRING && ! TARGET_POWERPC64 - && INTVAL (operands[2]) > 4 && INTVAL (operands[2]) <= 8" - "lswi %4,%1,%2\;stswi %4,%0,%2" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always") - (set_attr "length" "8")]) - -;; Move up to 4 bytes at a time. -(define_expand "movmemsi_1reg" - [(parallel [(set (match_operand 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" "")) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 ""))])] - "TARGET_STRING" - "") - -(define_insn "" - [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b")) - (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b"))) - (use (match_operand:SI 2 "immediate_operand" "i")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (clobber (match_scratch:SI 4 "=&r")) - (clobber (match_scratch:SI 5 "=X"))] - "TARGET_STRING && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4" - "lswi %4,%1,%2\;stswi %4,%0,%2" - [(set_attr "type" "store") - (set_attr "update" "yes") - (set_attr "indexed" "yes") - (set_attr "cell_micro" "always") - (set_attr "length" "8")]) +}) ;; Define insns that do load or store with update. Some of these we can ;; get by using pre-decrement or pre-increment, but the hardware can also @@ -9671,7 +9304,7 @@ (match_operand:SI 2 "reg_or_short_operand" "r,I")))) (set (match_operand:SI 0 "gpc_reg_operand" "=b,b") (plus:SI (match_dup 1) (match_dup 2)))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT && TARGET_UPDATE + "TARGET_HARD_FLOAT && TARGET_UPDATE && (!avoiding_indexed_address_p (SImode) || !gpc_reg_operand (operands[2], SImode))" "@ @@ -9687,7 +9320,7 @@ (match_operand:SF 3 "gpc_reg_operand" "f,f")) (set (match_operand:SI 0 "gpc_reg_operand" "=b,b") (plus:SI (match_dup 1) (match_dup 2)))] - "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT && TARGET_UPDATE + "TARGET_HARD_FLOAT && TARGET_UPDATE && (!avoiding_indexed_address_p (SImode) || !gpc_reg_operand (operands[2], SImode))" "@ @@ -9735,7 +9368,7 @@ (match_operand:SI 2 "reg_or_short_operand" "r,I")))) (set (match_operand:SI 0 "gpc_reg_operand" "=b,b") (plus:SI (match_dup 1) (match_dup 2)))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_UPDATE + "TARGET_HARD_FLOAT && TARGET_UPDATE && (!avoiding_indexed_address_p (SImode) || !gpc_reg_operand (operands[2], SImode))" "@ @@ -9752,7 +9385,7 @@ (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_DOUBLE_FLOAT && TARGET_UPDATE + "TARGET_HARD_FLOAT && TARGET_UPDATE && (!avoiding_indexed_address_p (SImode) || !gpc_reg_operand (operands[2], SImode))" "@ @@ -9772,18 +9405,18 @@ ;; Also this optimization interferes with scalars going into ;; altivec registers (the code does reloading through the FPRs). (define_peephole2 - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (match_operand:DF 1 "any_operand" "")) - (set (match_operand:DF 2 "gpc_reg_operand" "") + [(set (match_operand:DF 0 "gpc_reg_operand") + (match_operand:DF 1 "any_operand")) + (set (match_operand:DF 2 "gpc_reg_operand") (match_dup 0))] "!TARGET_VSX && peep2_reg_dead_p (2, operands[0])" [(set (match_dup 2) (match_dup 1))]) (define_peephole2 - [(set (match_operand:SF 0 "gpc_reg_operand" "") - (match_operand:SF 1 "any_operand" "")) - (set (match_operand:SF 2 "gpc_reg_operand" "") + [(set (match_operand:SF 0 "gpc_reg_operand") + (match_operand:SF 1 "any_operand")) + (set (match_operand:SF 2 "gpc_reg_operand") (match_dup 0))] "!TARGET_P8_VECTOR && peep2_reg_dead_p (2, operands[0])" @@ -9879,10 +9512,9 @@ (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))] - " { operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); -}" +} [(set (attr "length") (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL")) (const_int 8) @@ -9895,8 +9527,7 @@ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGD)))] "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" - "addis %0,%1,%2@got@tlsgd@ha" - [(set_attr "length" "4")]) + "addis %0,%1,%2@got@tlsgd@ha") (define_insn "*tls_gd_low<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") @@ -9905,8 +9536,7 @@ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGD)))] "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" - "addi %0,%1,%2@got@tlsgd@l" - [(set_attr "length" "4")]) + "addi %0,%1,%2@got@tlsgd@l") (define_insn "*tls_gd_call_aix<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") @@ -9938,8 +9568,7 @@ } return "bl %z1(%3@tlsgd)"; } - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn_and_split "tls_ld_aix<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") @@ -10016,10 +9645,9 @@ (set (match_dup 0) (lo_sum:TLSmode (match_dup 2) (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))] - " { operands[2] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); -}" +} [(set (attr "length") (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL")) (const_int 8) @@ -10032,8 +9660,7 @@ (match_operand:TLSmode 1 "gpc_reg_operand" "b")] UNSPEC_TLSLD)))] "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" - "addis %0,%1,%&@got@tlsld@ha" - [(set_attr "length" "4")]) + "addis %0,%1,%&@got@tlsld@ha") (define_insn "*tls_ld_low<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") @@ -10042,8 +9669,7 @@ (match_operand:TLSmode 2 "gpc_reg_operand" "b")] UNSPEC_TLSLD)))] "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" - "addi %0,%1,%&@got@tlsld@l" - [(set_attr "length" "4")]) + "addi %0,%1,%&@got@tlsld@l") (define_insn "*tls_ld_call_aix<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") @@ -10073,8 +9699,7 @@ } return "bl %z1(%&@tlsld)"; } - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "tls_dtprel_<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r") @@ -10114,10 +9739,9 @@ (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL)))] - " { operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); -}" +} [(set (attr "length") (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL")) (const_int 8) @@ -10130,8 +9754,7 @@ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGOTDTPREL)))] "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" - "addis %0,%1,%2@got@dtprel@ha" - [(set_attr "length" "4")]) + "addis %0,%1,%2@got@dtprel@ha") (define_insn "*tls_got_dtprel_low<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r") @@ -10140,8 +9763,7 @@ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGOTDTPREL)))] "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" - "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)" - [(set_attr "length" "4")]) + "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)") (define_insn "tls_tprel_<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r") @@ -10184,10 +9806,9 @@ (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL)))] - " { operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); -}" +} [(set (attr "length") (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL")) (const_int 8) @@ -10200,8 +9821,7 @@ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGOTTPREL)))] "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" - "addis %0,%1,%2@got@tprel@ha" - [(set_attr "length" "4")]) + "addis %0,%1,%2@got@tprel@ha") (define_insn "*tls_got_tprel_low<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r") @@ -10210,8 +9830,7 @@ (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] UNSPEC_TLSGOTTPREL)))] "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" - "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)" - [(set_attr "length" "4")]) + "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)") (define_insn "tls_tls_<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r") @@ -10222,15 +9841,14 @@ "add %0,%1,%2@tls") (define_expand "tls_get_tpointer" - [(set (match_operand:SI 0 "gpc_reg_operand" "") + [(set (match_operand:SI 0 "gpc_reg_operand") (unspec:SI [(const_int 0)] UNSPEC_TLSTLS))] "TARGET_XCOFF && HAVE_AS_TLS" - " { emit_insn (gen_tls_get_tpointer_internal ()); emit_move_insn (operands[0], gen_rtx_REG (SImode, 3)); DONE; -}") +}) (define_insn "tls_get_tpointer_internal" [(set (reg:SI 3) @@ -10240,18 +9858,17 @@ "bla __get_tpointer") (define_expand "tls_get_addr<mode>" - [(set (match_operand:P 0 "gpc_reg_operand" "") - (unspec:P [(match_operand:P 1 "gpc_reg_operand" "") - (match_operand:P 2 "gpc_reg_operand" "")] UNSPEC_TLSTLS))] + [(set (match_operand:P 0 "gpc_reg_operand") + (unspec:P [(match_operand:P 1 "gpc_reg_operand") + (match_operand:P 2 "gpc_reg_operand")] UNSPEC_TLSTLS))] "TARGET_XCOFF && HAVE_AS_TLS" - " { emit_move_insn (gen_rtx_REG (Pmode, 3), operands[1]); emit_move_insn (gen_rtx_REG (Pmode, 4), operands[2]); emit_insn (gen_tls_get_addr_internal<mode> ()); emit_move_insn (operands[0], gen_rtx_REG (Pmode, 3)); DONE; -}") +}) (define_insn "tls_get_addr_internal<mode>" [(set (reg:P 3) @@ -10281,13 +9898,13 @@ ;; the constant size. The value is forced into a register if necessary. ;; (define_expand "allocate_stack" - [(set (match_operand 0 "gpc_reg_operand" "") - (minus (reg 1) (match_operand 1 "reg_or_cint_operand" ""))) + [(set (match_operand 0 "gpc_reg_operand") + (minus (reg 1) (match_operand 1 "reg_or_cint_operand"))) (set (reg 1) (minus (reg 1) (match_dup 1)))] "" - " -{ rtx chain = gen_reg_rtx (Pmode); +{ + rtx chain = gen_reg_rtx (Pmode); rtx stack_bot = gen_rtx_MEM (Pmode, stack_pointer_rtx); rtx neg_op0; rtx insn, par, set, mem; @@ -10333,6 +9950,9 @@ { rtx loop_lab, end_loop; bool rotated = CONST_INT_P (rounded_size); + rtx update = GEN_INT (-probe_interval); + if (probe_interval > 32768) + update = force_reg (Pmode, update); emit_stack_clash_protection_probe_loop_start (&loop_lab, &end_loop, last_addr, rotated); @@ -10340,13 +9960,11 @@ if (Pmode == SImode) emit_insn (gen_movsi_update_stack (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-probe_interval), - chain)); + update, chain)); else emit_insn (gen_movdi_di_update_stack (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-probe_interval), - chain)); + update, chain)); emit_stack_clash_protection_probe_loop_end (loop_lab, end_loop, last_addr, rotated); } @@ -10354,14 +9972,12 @@ /* Now handle residuals. We just have to set operands[1] correctly and let the rest of the expander run. */ operands[1] = residual; - if (!CONST_INT_P (residual)) - operands[1] = force_reg (Pmode, operands[1]); - } - - if (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) < -32767 - || INTVAL (operands[1]) > 32768) - { + } + + if (!(CONST_INT_P (operands[1]) + && IN_RANGE (INTVAL (operands[1]), -32767, 32768))) + { + operands[1] = force_reg (Pmode, operands[1]); neg_op0 = gen_reg_rtx (Pmode); if (TARGET_32BIT) emit_insn (gen_negsi2 (neg_op0, operands[1])); @@ -10369,7 +9985,7 @@ emit_insn (gen_negdi2 (neg_op0, operands[1])); } else - neg_op0 = GEN_INT (- INTVAL (operands[1])); + neg_op0 = GEN_INT (-INTVAL (operands[1])); insn = emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update_stack : gen_movdi_di_update_stack)) @@ -10390,7 +10006,7 @@ emit_move_insn (operands[0], virtual_stack_dynamic_rtx); DONE; -}") +}) ;; These patterns say how to save and restore the stack pointer. We need not ;; save the stack pointer at function level since we are careful to @@ -10402,14 +10018,14 @@ ;; save area is a memory location. (define_expand "save_stack_function" - [(match_operand 0 "any_operand" "") - (match_operand 1 "any_operand" "")] + [(match_operand 0 "any_operand") + (match_operand 1 "any_operand")] "" "DONE;") (define_expand "restore_stack_function" - [(match_operand 0 "any_operand" "") - (match_operand 1 "any_operand" "")] + [(match_operand 0 "any_operand") + (match_operand 1 "any_operand")] "" "DONE;") @@ -10420,10 +10036,9 @@ [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 2)) (match_dup 5) - (set (match_operand 0 "register_operand" "") - (match_operand 1 "register_operand" ""))] - "" - " + (set (match_operand 0 "register_operand") + (match_operand 1 "register_operand"))] + "" { rtvec p; @@ -10435,14 +10050,13 @@ RTVEC_ELT (p, 0) = gen_rtx_SET (gen_frame_mem (BLKmode, operands[0]), const0_rtx); operands[5] = gen_rtx_PARALLEL (VOIDmode, p); -}") +}) (define_expand "save_stack_nonlocal" [(set (match_dup 3) (match_dup 4)) - (set (match_operand 0 "memory_operand" "") (match_dup 3)) - (set (match_dup 2) (match_operand 1 "register_operand" ""))] - "" - " + (set (match_operand 0 "memory_operand") (match_dup 3)) + (set (match_dup 2) (match_operand 1 "register_operand"))] + "" { int units_per_word = (TARGET_32BIT) ? 4 : 8; @@ -10451,16 +10065,15 @@ operands[2] = adjust_address_nv (operands[0], Pmode, units_per_word); operands[3] = gen_reg_rtx (Pmode); operands[4] = gen_frame_mem (Pmode, operands[1]); -}") +}) (define_expand "restore_stack_nonlocal" - [(set (match_dup 2) (match_operand 1 "memory_operand" "")) + [(set (match_dup 2) (match_operand 1 "memory_operand")) (set (match_dup 3) (match_dup 4)) (set (match_dup 5) (match_dup 2)) (match_dup 6) - (set (match_operand 0 "register_operand" "") (match_dup 3))] - "" - " + (set (match_operand 0 "register_operand") (match_dup 3))] + "" { int units_per_word = (TARGET_32BIT) ? 4 : 8; rtvec p; @@ -10475,7 +10088,7 @@ RTVEC_ELT (p, 0) = gen_rtx_SET (gen_frame_mem (BLKmode, operands[0]), const0_rtx); operands[6] = gen_rtx_PARALLEL (VOIDmode, p); -}") +}) ;; TOC register handling. @@ -10486,16 +10099,15 @@ (unspec:SI [(const_int 0)] UNSPEC_TOC)) (use (reg:SI 2))])] "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_32BIT" - "* { char buf[30]; extern int need_toc_init; need_toc_init = 1; - ASM_GENERATE_INTERNAL_LABEL (buf, \"LCTOC\", 1); + ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1); operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); operands[2] = gen_rtx_REG (Pmode, 2); - return \"lwz %0,%1(%2)\"; -}" + return "lwz %0,%1(%2)"; +} [(set_attr "type" "load") (set_attr "update" "no") (set_attr "indexed" "no")]) @@ -10505,19 +10117,18 @@ (unspec:DI [(const_int 0)] UNSPEC_TOC)) (use (reg:DI 2))])] "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && TARGET_64BIT" - "* { char buf[30]; extern int need_toc_init; need_toc_init = 1; - ASM_GENERATE_INTERNAL_LABEL (buf, \"LCTOC\", + ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", !TARGET_ELF || !TARGET_MINIMAL_TOC); if (TARGET_ELF) - strcat (buf, \"@toc\"); + strcat (buf, "@toc"); operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); operands[2] = gen_rtx_REG (Pmode, 2); - return \"ld %0,%1(%2)\"; -}" + return "ld %0,%1(%2)"; +} [(set_attr "type" "load") (set_attr "update" "no") (set_attr "indexed" "no")]) @@ -10527,8 +10138,7 @@ (unspec:SI [(const_int 0)] UNSPEC_TOC))] "DEFAULT_ABI == ABI_V4 && flag_pic == 1 && TARGET_32BIT" "bl _GLOBAL_OFFSET_TABLE_@local-4" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_expand "load_toc_v4_PIC_1" [(parallel [(set (reg:SI LR_REGNO) @@ -10544,9 +10154,8 @@ (use (unspec [(match_dup 0)] UNSPEC_TOC))] "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" - "bcl 20,31,%0\\n%0:" + "bcl 20,31,%0\n%0:" [(set_attr "type" "branch") - (set_attr "length" "4") (set_attr "cannot_copy" "yes")]) (define_insn "load_toc_v4_PIC_1_476" @@ -10555,23 +10164,21 @@ (use (unspec [(match_dup 0)] UNSPEC_TOC))] "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" - "* { char name[32]; static char templ[32]; get_ppc476_thunk_name (name); - sprintf (templ, \"bl %s\\n%%0:\", name); + sprintf (templ, "bl %s\n%%0:", name); return templ; -}" +} [(set_attr "type" "branch") - (set_attr "length" "4") (set_attr "cannot_copy" "yes")]) (define_expand "load_toc_v4_PIC_1b" [(parallel [(set (reg:SI LR_REGNO) (unspec:SI [(match_operand:SI 0 "immediate_operand" "s") - (label_ref (match_operand 1 "" ""))] + (label_ref (match_operand 1 ""))] UNSPEC_TOCPTR)) (match_dup 1)])] "TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2" @@ -10595,41 +10202,46 @@ UNSPEC_TOCPTR)) (match_dup 1)] "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2" - "* { char name[32]; static char templ[32]; get_ppc476_thunk_name (name); - sprintf (templ, \"bl %s\\n\\tb $+8\\n\\t.long %%0-$\", name); + sprintf (templ, "bl %s\;b $+8\;.long %%0-$", name); return templ; -}" +} [(set_attr "type" "branch") (set_attr "length" "16")]) (define_insn "load_toc_v4_PIC_2" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b") - (minus:SI (match_operand:SI 2 "immediate_operand" "s") - (match_operand:SI 3 "immediate_operand" "s")))))] + (mem:SI (plus:SI + (match_operand:SI 1 "gpc_reg_operand" "b") + (const + (minus:SI (match_operand:SI 2 "immediate_operand" "s") + (match_operand:SI 3 "immediate_operand" "s"))))))] "TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2" "lwz %0,%2-%3(%1)" [(set_attr "type" "load")]) (define_insn "load_toc_v4_PIC_3b" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b") - (high:SI - (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s") - (match_operand:SI 3 "symbol_ref_operand" "s")))))] + (plus:SI + (match_operand:SI 1 "gpc_reg_operand" "b") + (high:SI + (const + (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s") + (match_operand:SI 3 "symbol_ref_operand" "s"))))))] "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic" "addis %0,%1,%2-%3@ha") (define_insn "load_toc_v4_PIC_3c" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b") - (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s") - (match_operand:SI 3 "symbol_ref_operand" "s"))))] + (lo_sum:SI + (match_operand:SI 1 "gpc_reg_operand" "b") + (const + (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s") + (match_operand:SI 3 "symbol_ref_operand" "s")))))] "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic" "addi %0,%1,%2-%3@l") @@ -10639,11 +10251,10 @@ ;; On Darwin, we need to reload the picbase. (define_expand "builtin_setjmp_receiver" - [(use (label_ref (match_operand 0 "" "")))] + [(use (label_ref (match_operand 0 "")))] "(DEFAULT_ABI == ABI_V4 && flag_pic == 1) || (TARGET_TOC && TARGET_MINIMAL_TOC) || (DEFAULT_ABI == ABI_DARWIN && flag_pic)" - " { #if TARGET_MACHO if (DEFAULT_ABI == ABI_DARWIN) @@ -10654,7 +10265,7 @@ char tmplab[20]; crtl->uses_pic_offset_table = 1; - ASM_GENERATE_INTERNAL_LABEL(tmplab, \"LSJR\", + ASM_GENERATE_INTERNAL_LABEL(tmplab, "LSJR", CODE_LABEL_NUMBER (operands[0])); tmplabrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tmplab)); @@ -10666,7 +10277,7 @@ #endif rs6000_emit_load_toc_table (FALSE); DONE; -}") +}) ;; Largetoc support (define_insn "*largetoc_high" @@ -10751,12 +10362,11 @@ ;; Call and call_value insns (define_expand "call" - [(parallel [(call (mem:SI (match_operand 0 "address_operand" "")) - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) + [(parallel [(call (mem:SI (match_operand 0 "address_operand")) + (match_operand 1 "")) + (use (match_operand 2 "")) (clobber (reg:SI LR_REGNO))])] "" - " { #if TARGET_MACHO if (MACHOPIC_INDIRECT) @@ -10791,16 +10401,15 @@ gcc_unreachable (); } } -}") +}) (define_expand "call_value" - [(parallel [(set (match_operand 0 "" "") - (call (mem:SI (match_operand 1 "address_operand" "")) - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) + [(parallel [(set (match_operand 0 "") + (call (mem:SI (match_operand 1 "address_operand")) + (match_operand 2 ""))) + (use (match_operand 3 "")) (clobber (reg:SI LR_REGNO))])] "" - " { #if TARGET_MACHO if (MACHOPIC_INDIRECT) @@ -10835,7 +10444,7 @@ gcc_unreachable (); } } -}") +}) ;; Call to function in current module. No TOC pointer reload needed. ;; Operand2 is nonzero if we are using the V.4 calling sequence and @@ -10849,16 +10458,15 @@ (use (match_operand:SI 2 "immediate_operand" "O,n")) (clobber (reg:SI LR_REGNO))] "(INTVAL (operands[2]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); - - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@local\" : \"bl %z0\"; -}" + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@local" : "bl %z0"; +} [(set_attr "type" "branch") (set_attr "length" "4,8")]) @@ -10868,16 +10476,15 @@ (use (match_operand:SI 2 "immediate_operand" "O,n")) (clobber (reg:SI LR_REGNO))] "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); - - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@local\" : \"bl %z0\"; -}" + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@local" : "bl %z0"; +} [(set_attr "type" "branch") (set_attr "length" "4,8")]) @@ -10888,16 +10495,15 @@ (use (match_operand:SI 3 "immediate_operand" "O,n")) (clobber (reg:SI LR_REGNO))] "(INTVAL (operands[3]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); - - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@local\" : \"bl %z1\"; -}" + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@local" : "bl %z1"; +} [(set_attr "type" "branch") (set_attr "length" "4,8")]) @@ -10909,16 +10515,15 @@ (use (match_operand:SI 3 "immediate_operand" "O,n")) (clobber (reg:SI LR_REGNO))] "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); - - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@local\" : \"bl %z1\"; -}" + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@local" : "bl %z1"; +} [(set_attr "type" "branch") (set_attr "length" "4,8")]) @@ -10943,10 +10548,24 @@ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) output_asm_insn ("creqv 6,6,6", operands); - return "b%T0l"; + if (rs6000_speculate_indirect_jumps + || which_alternative == 1 || which_alternative == 3) + return "b%T0l"; + else + return "crset 2\;beq%T0l-"; } [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg") - (set_attr "length" "4,4,8,8")]) + (set_attr_alternative "length" + [(if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") + (const_int 0)) + (const_string "8") + (const_string "4")) + (const_string "4") + (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") + (const_int 0)) + (const_string "12") + (const_string "8")) + (const_string "8")])]) (define_insn_and_split "*call_nonlocal_sysv<mode>" [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s")) @@ -11031,10 +10650,24 @@ else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) output_asm_insn ("creqv 6,6,6", operands); - return "b%T1l"; + if (rs6000_speculate_indirect_jumps + || which_alternative == 1 || which_alternative == 3) + return "b%T1l"; + else + return "crset 2\;beq%T1l-"; } [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg") - (set_attr "length" "4,4,8,8")]) + (set_attr_alternative "length" + [(if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") + (const_int 0)) + (const_string "8") + (const_string "4")) + (const_string "4") + (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") + (const_int 0)) + (const_string "12") + (const_string "8")) + (const_string "8")])]) (define_insn_and_split "*call_value_nonlocal_sysv<mode>" [(set (match_operand 0 "" "") @@ -11113,8 +10746,7 @@ (clobber (reg:P LR_REGNO))] "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2" "bl %z0" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*call_value_local_aix<mode>" [(set (match_operand 0 "" "") @@ -11123,8 +10755,7 @@ (clobber (reg:P LR_REGNO))] "DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2" "bl %z1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) ;; Call to AIX abi function which may be in another module. ;; Restore the TOC pointer (r2) after the call. @@ -11159,11 +10790,22 @@ (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>")) (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX" + "DEFAULT_ABI == ABI_AIX && rs6000_speculate_indirect_jumps" "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3(1)" [(set_attr "type" "jmpreg") (set_attr "length" "12")]) +(define_insn "*call_indirect_aix<mode>_nospec" + [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + (match_operand 1 "" "g,g")) + (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>")) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX && !rs6000_speculate_indirect_jumps" + "crset 2\;<ptrload> 2,%2\;beq%T0l-\;<ptrload> 2,%3(1)" + [(set_attr "type" "jmpreg") + (set_attr "length" "16")]) + (define_insn "*call_value_indirect_aix<mode>" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) @@ -11171,11 +10813,23 @@ (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_AIX" + "DEFAULT_ABI == ABI_AIX && rs6000_speculate_indirect_jumps" "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4(1)" [(set_attr "type" "jmpreg") (set_attr "length" "12")]) +(define_insn "*call_value_indirect_aix<mode>_nospec" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (match_operand 2 "" "g,g"))) + (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_AIX && !rs6000_speculate_indirect_jumps" + "crset 2\;<ptrload> 2,%3\;beq%T1l-\;<ptrload> 2,%4(1)" + [(set_attr "type" "jmpreg") + (set_attr "length" "16")]) + ;; Call to indirect functions with the ELFv2 ABI. ;; Operand0 is the addresss of the function to call ;; Operand2 is the offset of the stack location holding the current TOC pointer @@ -11185,31 +10839,52 @@ (match_operand 1 "" "g,g")) (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_ELFv2" + "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps" "b%T0l\;<ptrload> 2,%2(1)" [(set_attr "type" "jmpreg") (set_attr "length" "8")]) +;; Variant with deliberate misprediction. +(define_insn "*call_indirect_elfv2<mode>_nospec" + [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + (match_operand 1 "" "g,g")) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps" + "crset 2\;beq%T0l-\;<ptrload> 2,%2(1)" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + (define_insn "*call_value_indirect_elfv2<mode>" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) (match_operand 2 "" "g,g"))) (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] - "DEFAULT_ABI == ABI_ELFv2" + "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps" "b%T1l\;<ptrload> 2,%3(1)" [(set_attr "type" "jmpreg") (set_attr "length" "8")]) +; Variant with deliberate misprediction. +(define_insn "*call_value_indirect_elfv2<mode>_nospec" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (match_operand 2 "" "g,g"))) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (clobber (reg:P LR_REGNO))] + "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps" + "crset 2\;beq%T1l-\;<ptrload> 2,%3(1)" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) ;; Call subroutine returning any type. (define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") + [(parallel [(call (match_operand 0 "") (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " + (match_operand 1 "") + (match_operand 2 "")])] + "" { int i; @@ -11228,16 +10903,15 @@ emit_insn (gen_blockage ()); DONE; -}") +}) ;; sibling call patterns (define_expand "sibcall" - [(parallel [(call (mem:SI (match_operand 0 "address_operand" "")) - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) + [(parallel [(call (mem:SI (match_operand 0 "address_operand")) + (match_operand 1 "")) + (use (match_operand 2 "")) (simple_return)])] "" - " { #if TARGET_MACHO if (MACHOPIC_INDIRECT) @@ -11254,16 +10928,15 @@ rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]); DONE; } -}") +}) (define_expand "sibcall_value" - [(parallel [(set (match_operand 0 "register_operand" "") - (call (mem:SI (match_operand 1 "address_operand" "")) - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) + [(parallel [(set (match_operand 0 "register_operand") + (call (mem:SI (match_operand 1 "address_operand")) + (match_operand 2 ""))) + (use (match_operand 3 "")) (simple_return)])] "" - " { #if TARGET_MACHO if (MACHOPIC_INDIRECT) @@ -11280,7 +10953,7 @@ rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]); DONE; } -}") +}) (define_insn "*sibcall_local32" [(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s")) @@ -11288,16 +10961,15 @@ (use (match_operand:SI 2 "immediate_operand" "O,n")) (simple_return)] "(INTVAL (operands[2]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); - - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@local\" : \"b %z0\"; -}" + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "b %z0@local" : "b %z0"; +} [(set_attr "type" "branch") (set_attr "length" "4,8")]) @@ -11307,16 +10979,15 @@ (use (match_operand:SI 2 "immediate_operand" "O,n")) (simple_return)] "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); - - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@local\" : \"b %z0\"; -}" + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "b %z0@local" : "b %z0"; +} [(set_attr "type" "branch") (set_attr "length" "4,8")]) @@ -11327,16 +10998,15 @@ (use (match_operand:SI 3 "immediate_operand" "O,n")) (simple_return)] "(INTVAL (operands[3]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); - - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@local\" : \"b %z1\"; -}" + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "b %z1@local" : "b %z1"; +} [(set_attr "type" "branch") (set_attr "length" "4,8")]) @@ -11347,16 +11017,15 @@ (use (match_operand:SI 3 "immediate_operand" "O,n")) (simple_return)] "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); - - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@local\" : \"b %z1\"; -}" + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "b %z1@local" : "b %z1"; +} [(set_attr "type" "branch") (set_attr "length" "4,8")]) @@ -11368,26 +11037,41 @@ "(DEFAULT_ABI == ABI_DARWIN || DEFAULT_ABI == ABI_V4) && (INTVAL (operands[2]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); + output_asm_insn ("creqv 6,6,6", operands); if (which_alternative >= 2) - return \"b%T0\"; + { + if (rs6000_speculate_indirect_jumps) + return "b%T0"; + else + /* Can use CR0 since it is volatile across sibcalls. */ + return "crset 2\;beq%T0-\;b $"; + } else if (DEFAULT_ABI == ABI_V4 && flag_pic) { gcc_assert (!TARGET_SECURE_PLT); - return \"b %z0@plt\"; - } - else - return \"b %z0\"; -}" + return "b %z0@plt"; + } + else + return "b %z0"; +} [(set_attr "type" "branch") - (set_attr "length" "4,8,4,8")]) + (set_attr_alternative "length" + [(const_string "4") + (const_string "8") + (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") + (const_int 0)) + (const_string "12") + (const_string "4")) + (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") + (const_int 0)) + (const_string "16") + (const_string "8"))])]) (define_insn "*sibcall_value_nonlocal_sysv<mode>" [(set (match_operand 0 "" "") @@ -11398,26 +11082,41 @@ "(DEFAULT_ABI == ABI_DARWIN || DEFAULT_ABI == ABI_V4) && (INTVAL (operands[3]) & CALL_LONG) == 0" - "* { if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); + output_asm_insn ("creqv 6,6,6", operands); if (which_alternative >= 2) - return \"b%T1\"; + { + if (rs6000_speculate_indirect_jumps) + return "b%T1"; + else + /* Can use CR0 since it is volatile across sibcalls. */ + return "crset 2\;beq%T1-\;b $"; + } else if (DEFAULT_ABI == ABI_V4 && flag_pic) { gcc_assert (!TARGET_SECURE_PLT); - return \"b %z1@plt\"; - } - else - return \"b %z1\"; -}" + return "b %z1@plt"; + } + else + return "b %z1"; +} [(set_attr "type" "branch") - (set_attr "length" "4,8,4,8")]) + (set_attr_alternative "length" + [(const_string "4") + (const_string "8") + (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") + (const_int 0)) + (const_string "12") + (const_string "4")) + (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") + (const_int 0)) + (const_string "16") + (const_string "8"))])]) ;; AIX ABI sibling call patterns. @@ -11429,8 +11128,7 @@ "@ b %z0 b%T0" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*sibcall_value_aix<mode>" [(set (match_operand 0 "" "") @@ -11441,8 +11139,7 @@ "@ b %z1 b%T1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) <<<<<<< local ======= @@ -11598,7 +11295,8 @@ (define_insn "blockage" [(unspec_volatile [(const_int 0)] UNSPECV_BLOCK)] "" - "") + "" + [(set_attr "length" "0")]) (define_expand "probe_stack_address" [(use (match_operand 0 "address_operand"))] @@ -11630,8 +11328,7 @@ (set (attr "indexed") (if_then_else (match_operand 0 "indexed_address_mem") (const_string "yes") - (const_string "no"))) - (set_attr "length" "4")]) + (const_string "no")))]) (define_insn "probe_stack_range<P:mode>" [(set (match_operand:P 0 "register_operand" "=&r") @@ -11651,11 +11348,10 @@ (define_expand "cbranch<mode>4" [(use (match_operator 0 "comparison_operator" - [(match_operand:GPR 1 "gpc_reg_operand" "") - (match_operand:GPR 2 "reg_or_short_operand" "")])) - (use (match_operand 3 ""))] - "" - " + [(match_operand:GPR 1 "gpc_reg_operand") + (match_operand:GPR 2 "reg_or_short_operand")])) + (use (match_operand 3))] + "" { /* Take care of the possibility that operands[2] might be negative but this might be a logical operation. That insn doesn't exist. */ @@ -11670,19 +11366,18 @@ rs6000_emit_cbranch (<MODE>mode, operands); DONE; -}") +}) (define_expand "cbranch<mode>4" [(use (match_operator 0 "comparison_operator" - [(match_operand:FP 1 "gpc_reg_operand" "") - (match_operand:FP 2 "gpc_reg_operand" "")])) - (use (match_operand 3 ""))] - "" - " + [(match_operand:FP 1 "gpc_reg_operand") + (match_operand:FP 2 "gpc_reg_operand")])) + (use (match_operand 3))] + "" { rs6000_emit_cbranch (<MODE>mode, operands); DONE; -}") +}) (define_expand "cstore<mode>4_signed" [(use (match_operator 1 "signed_comparison_operator" @@ -11909,13 +11604,9 @@ (clobber (match_operand:GPR 0 "gpc_reg_operand"))] "" { - /* Use ISEL if the user asked for it. */ - if (TARGET_ISEL) - rs6000_emit_sISEL (<MODE>mode, operands); - /* Expanding EQ and NE directly to some machine instructions does not help but does hurt combine. So don't. */ - else if (GET_CODE (operands[1]) == EQ) + if (GET_CODE (operands[1]) == EQ) emit_insn (gen_eq<mode>3 (operands[0], operands[2], operands[3])); else if (<MODE>mode == Pmode && GET_CODE (operands[1]) == NE) @@ -11927,7 +11618,11 @@ emit_insn (gen_xor<mode>3 (operands[0], tmp, const1_rtx)); } - /* Expanding the unsigned comparisons however helps a lot: all the neg_ltu + /* If ISEL is fast, expand to it. */ + else if (TARGET_ISEL) + rs6000_emit_int_cmove (operands[0], operands[1], const1_rtx, const0_rtx); + + /* Expanding the unsigned comparisons helps a lot: all the neg_ltu etc. combinations magically work out just right. */ else if (<MODE>mode == Pmode && unsigned_comparison_operator (operands[1], VOIDmode)) @@ -12094,18 +11789,18 @@ (define_peephole2 [(set (match_operand:SI 0 "register_operand") - (match_operand:SI 1 "logical_const_operand" "")) + (match_operand:SI 1 "logical_const_operand")) (set (match_dup 0) (match_operator:SI 3 "boolean_or_operator" [(match_dup 0) - (match_operand:SI 2 "logical_const_operand" "")])) - (set (match_operand:CC 4 "cc_reg_operand" "") - (compare:CC (match_operand:SI 5 "gpc_reg_operand" "") + (match_operand:SI 2 "logical_const_operand")])) + (set (match_operand:CC 4 "cc_reg_operand") + (compare:CC (match_operand:SI 5 "gpc_reg_operand") (match_dup 0))) (set (pc) (if_then_else (match_operator 6 "equality_operator" [(match_dup 4) (const_int 0)]) - (match_operand 7 "" "") - (match_operand 8 "" "")))] + (match_operand 7 "") + (match_operand 8 "")))] "peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (4, operands[4]) && REGNO (operands[0]) != REGNO (operands[5])" @@ -12128,58 +11823,13 @@ operands[10] = GEN_INT (sextc); }) -;; The following two insns don't exist as single insns, but if we provide -;; them, we can swap an add and compare, which will enable us to overlap more -;; of the required delay between a compare and branch. We generate code for -;; them by splitting. - -(define_insn "" - [(set (match_operand:CC 3 "cc_reg_operand" "=y") - (compare:CC (match_operand:SI 1 "gpc_reg_operand" "r") - (match_operand:SI 2 "short_cint_operand" "i"))) - (set (match_operand:SI 0 "gpc_reg_operand" "=r") - (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "i")))] - "" - "#" - [(set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:CCUNS 3 "cc_reg_operand" "=y") - (compare:CCUNS (match_operand:SI 1 "gpc_reg_operand" "r") - (match_operand:SI 2 "u_short_cint_operand" "i"))) - (set (match_operand:SI 0 "gpc_reg_operand" "=r") - (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "i")))] - "" - "#" - [(set_attr "length" "8")]) - -(define_split - [(set (match_operand:CC 3 "cc_reg_operand" "") - (compare:CC (match_operand:SI 1 "gpc_reg_operand" "") - (match_operand:SI 2 "short_cint_operand" ""))) - (set (match_operand:SI 0 "gpc_reg_operand" "") - (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "")))] - "" - [(set (match_dup 3) (compare:CC (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))]) - -(define_split - [(set (match_operand:CCUNS 3 "cc_reg_operand" "") - (compare:CCUNS (match_operand:SI 1 "gpc_reg_operand" "") - (match_operand:SI 2 "u_short_cint_operand" ""))) - (set (match_operand:SI 0 "gpc_reg_operand" "") - (plus:SI (match_dup 1) (match_operand:SI 4 "short_cint_operand" "")))] - "" - [(set (match_dup 3) (compare:CCUNS (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))]) - ;; Only need to compare second words if first words equal (define_insn "*cmp<mode>_internal1" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") (compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d") (match_operand:IBM128 2 "gpc_reg_operand" "d")))] "!TARGET_XL_COMPAT && FLOAT128_IBM_P (<MODE>mode) - && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" + && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" "fcmpu %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2" [(set_attr "type" "fpcompare") (set_attr "length" "12")]) @@ -12198,7 +11848,7 @@ (clobber (match_scratch:DF 10 "=d")) (clobber (match_scratch:GPR 11 "=b"))] "TARGET_XL_COMPAT && FLOAT128_IBM_P (<MODE>mode) - && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" + && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" "#" "&& reload_completed" [(set (match_dup 3) (match_dup 14)) @@ -12253,10 +11903,10 @@ ;; cases the insns below which don't use an intermediate CR field will ;; be used instead. (define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (match_operator:SI 1 "scc_comparison_operator" - [(match_operand 2 "cc_reg_operand" "y") - (const_int 0)]))] + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (match_operator:GPR 1 "scc_comparison_operator" + [(match_operand 2 "cc_reg_operand" "y") + (const_int 0)]))] "" "mfcr %0%Q2\;rlwinm %0,%0,%J1,1" [(set (attr "type") @@ -12266,31 +11916,7 @@ (const_string "mfcr"))) (set_attr "length" "8")]) -;; Same as above, but get the OV/ORDERED bit. -(define_insn "move_from_CR_ov_bit" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (unspec:SI [(match_operand:CC 1 "cc_reg_operand" "y")] - UNSPEC_MV_CR_OV))] - "TARGET_ISEL" - "mfcr %0\;rlwinm %0,%0,%t1,1" - [(set_attr "type" "mfcr") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (match_operator:DI 1 "scc_comparison_operator" - [(match_operand 2 "cc_reg_operand" "y") - (const_int 0)]))] - "TARGET_POWERPC64" - "mfcr %0%Q2\;rlwinm %0,%0,%J1,1" - [(set (attr "type") - (cond [(match_test "TARGET_MFCRF") - (const_string "mfcrf") - ] - (const_string "mfcr"))) - (set_attr "length" "8")]) - -(define_insn "" +(define_insn_and_split "" [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y") (compare:CC (match_operator:SI 1 "scc_comparison_operator" [(match_operand 2 "cc_reg_operand" "y,y") @@ -12302,25 +11928,16 @@ "@ mfcr %3%Q2\;rlwinm. %3,%3,%J1,1 #" - [(set_attr "type" "shift") - (set_attr "dot" "yes") - (set_attr "length" "8,16")]) - -(define_split - [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "") - (compare:CC (match_operator:SI 1 "scc_comparison_operator" - [(match_operand 2 "cc_reg_operand" "") - (const_int 0)]) - (const_int 0))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (match_op_dup 1 [(match_dup 2) (const_int 0)]))] - "TARGET_32BIT && reload_completed" + "&& reload_completed" [(set (match_dup 3) (match_op_dup 1 [(match_dup 2) (const_int 0)])) (set (match_dup 0) (compare:CC (match_dup 3) (const_int 0)))] - "") + "" + [(set_attr "type" "shift") + (set_attr "dot" "yes") + (set_attr "length" "8,16")]) (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") @@ -12329,7 +11946,6 @@ (const_int 0)]) (match_operand:SI 3 "const_int_operand" "n")))] "" - "* { int is_bit = ccr_bit (operands[1], 1); int put_bit = 31 - (INTVAL (operands[3]) & 31); @@ -12343,8 +11959,8 @@ operands[4] = GEN_INT (count); operands[5] = GEN_INT (put_bit); - return \"mfcr %0%Q2\;rlwinm %0,%0,%4,%5,%5\"; -}" + return "mfcr %0%Q2\;rlwinm %0,%0,%4,%5,%5"; +} [(set (attr "type") (cond [(match_test "TARGET_MFCRF") (const_string "mfcrf") @@ -12364,7 +11980,6 @@ (ashift:SI (match_op_dup 1 [(match_dup 2) (const_int 0)]) (match_dup 3)))] "" - "* { int is_bit = ccr_bit (operands[1], 1); int put_bit = 31 - (INTVAL (operands[3]) & 31); @@ -12372,7 +11987,7 @@ /* Force split for non-cc0 compare. */ if (which_alternative == 1) - return \"#\"; + return "#"; if (is_bit >= put_bit) count = is_bit - put_bit; @@ -12382,8 +11997,8 @@ operands[5] = GEN_INT (count); operands[6] = GEN_INT (put_bit); - return \"mfcr %4%Q2\;rlwinm. %4,%4,%5,%6,%6\"; -}" + return "mfcr %4%Q2\;rlwinm. %4,%4,%5,%6,%6"; +} [(set_attr "type" "shift") (set_attr "dot" "yes") (set_attr "length" "8,16")]) @@ -12409,18 +12024,130 @@ "") +(define_code_iterator cmp [eq ne lt ltu gt gtu le leu ge geu]) +(define_code_attr UNS [(eq "CC") + (ne "CC") + (lt "CC") (ltu "CCUNS") + (gt "CC") (gtu "CCUNS") + (le "CC") (leu "CCUNS") + (ge "CC") (geu "CCUNS")]) +(define_code_attr UNSu_ [(eq "") + (ne "") + (lt "") (ltu "u_") + (gt "") (gtu "u_") + (le "") (leu "u_") + (ge "") (geu "u_")]) +(define_code_attr UNSIK [(eq "I") + (ne "I") + (lt "I") (ltu "K") + (gt "I") (gtu "K") + (le "I") (leu "K") + (ge "I") (geu "K")]) + +(define_insn_and_split "<code><GPR:mode><GPR2:mode>2_isel" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (cmp:GPR (match_operand:GPR2 1 "gpc_reg_operand" "r") + (match_operand:GPR2 2 "reg_or_<cmp:UNSu_>short_operand" "r<cmp:UNSIK>"))) + (clobber (match_scratch:GPR 3 "=r")) + (clobber (match_scratch:GPR 4 "=r")) + (clobber (match_scratch:<UNS> 5 "=y"))] + "TARGET_ISEL + && !(<CODE> == EQ && operands[2] == const0_rtx) + && !(<CODE> == NE && operands[2] == const0_rtx + && <GPR:MODE>mode == Pmode && <GPR2:MODE>mode == Pmode)" + "#" + "&& 1" + [(pc)] +{ + rtx_code code = <CODE>; + if (CONST_INT_P (operands[2]) && code != EQ && code != NE) + { + HOST_WIDE_INT val = INTVAL (operands[2]); + if (code == LT && val != -0x8000) + { + code = LE; + val--; + } + if (code == GT && val != 0x7fff) + { + code = GE; + val++; + } + if (code == LTU && val != 0) + { + code = LEU; + val--; + } + if (code == GTU && val != 0xffff) + { + code = GEU; + val++; + } + operands[2] = GEN_INT (val); + } + + if (code == NE || code == LE || code == GE || code == LEU || code == GEU) + operands[3] = const0_rtx; + else + { + if (GET_CODE (operands[3]) == SCRATCH) + operands[3] = gen_reg_rtx (<GPR:MODE>mode); + emit_move_insn (operands[3], const0_rtx); + } + + if (GET_CODE (operands[4]) == SCRATCH) + operands[4] = gen_reg_rtx (<GPR:MODE>mode); + emit_move_insn (operands[4], const1_rtx); + + if (GET_CODE (operands[5]) == SCRATCH) + operands[5] = gen_reg_rtx (<UNS>mode); + + rtx c1 = gen_rtx_COMPARE (<UNS>mode, operands[1], operands[2]); + emit_insn (gen_rtx_SET (operands[5], c1)); + + rtx c2 = gen_rtx_fmt_ee (code, <GPR:MODE>mode, operands[5], const0_rtx); + rtx x = gen_rtx_IF_THEN_ELSE (<GPR:MODE>mode, c2, operands[4], operands[3]); + emit_move_insn (operands[0], x); + + DONE; +} + [(set (attr "cost") + (if_then_else (match_test "(CONST_INT_P (operands[2]) && <CODE> != EQ) + || <CODE> == NE + || <CODE> == LE || <CODE> == GE + || <CODE> == LEU || <CODE> == GEU") + (const_string "9") + (const_string "10")))]) + (define_mode_attr scc_eq_op2 [(SI "rKLI") (DI "rKJI")]) -(define_insn_and_split "eq<mode>3" +(define_expand "eq<mode>3" + [(parallel [ + (set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") + (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>"))) + (clobber (match_scratch:GPR 3 "=r")) + (clobber (match_scratch:GPR 4 "=r"))])] + "" +{ + if (TARGET_ISEL && operands[2] != const0_rtx) + { + emit_insn (gen_eq<mode><mode>2_isel (operands[0], operands[1], + operands[2])); + DONE; + } +}) + +(define_insn_and_split "*eq<mode>3" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>"))) (clobber (match_scratch:GPR 3 "=r")) (clobber (match_scratch:GPR 4 "=r"))] - "" - "#" - "" + "!(TARGET_ISEL && operands[2] != const0_rtx)" + "#" + "&& 1" [(set (match_dup 4) (clz:GPR (match_dup 3))) (set (match_dup 0) @@ -12440,16 +12167,34 @@ (const_string "8") (const_string "12")))]) -(define_insn_and_split "ne<mode>3" +(define_expand "ne<mode>3" + [(parallel [ + (set (match_operand:P 0 "gpc_reg_operand" "=r") + (ne:P (match_operand:P 1 "gpc_reg_operand" "r") + (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))) + (clobber (match_scratch:P 3 "=r")) + (clobber (match_scratch:P 4 "=r")) + (clobber (reg:P CA_REGNO))])] + "" +{ + if (TARGET_ISEL && operands[2] != const0_rtx) + { + emit_insn (gen_ne<mode><mode>2_isel (operands[0], operands[1], + operands[2])); + DONE; + } +}) + +(define_insn_and_split "*ne<mode>3" [(set (match_operand:P 0 "gpc_reg_operand" "=r") (ne:P (match_operand:P 1 "gpc_reg_operand" "r") (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))) (clobber (match_scratch:P 3 "=r")) (clobber (match_scratch:P 4 "=r")) (clobber (reg:P CA_REGNO))] - "!TARGET_ISEL" - "#" - "" + "!(TARGET_ISEL && operands[2] != const0_rtx)" + "#" + "&& 1" [(parallel [(set (match_dup 4) (plus:P (match_dup 3) (const_int -1))) @@ -12702,9 +12447,9 @@ (clobber (match_scratch:SI 3 "=r")) (clobber (match_scratch:SI 4 "=r")) (clobber (match_scratch:EXTSI 5 "=r"))] - "" - "#" - "" + "!TARGET_ISEL" + "#" + "&& 1" [(set (match_dup 4) (clz:SI (match_dup 3))) (set (match_dup 5) @@ -12728,11 +12473,10 @@ (const_string "12") (const_string "16")))]) -;; Define both directions of branch and return. If we need a reload -;; register, we'd rather use CR0 since it is much easier to copy a -;; register CC value to there. - -(define_insn "" +;; Conditional branches. +;; These either are a single bc insn, or a bc around a b. + +(define_insn "*cbranch" [(set (pc) (if_then_else (match_operator 1 "branch_comparison_operator" [(match_operand 2 "cc_reg_operand" "y") @@ -12743,9 +12487,17 @@ { return output_cbranch (operands[1], "%l0", 0, insn); } - [(set_attr "type" "branch")]) - -(define_insn "" + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (and (ge (minus (match_dup 0) (pc)) + (const_int -32768)) + (lt (minus (match_dup 0) (pc)) + (const_int 32764))) + (const_int 4) + (const_int 8)))]) + +;; Conditional return. +(define_insn "*creturn" [(set (pc) (if_then_else (match_operator 0 "branch_comparison_operator" [(match_operand 1 "cc_reg_operand" "y") @@ -12756,8 +12508,7 @@ { return output_cbranch (operands[0], NULL, 0, insn); } - [(set_attr "type" "jmpreg") - (set_attr "length" "4")]) + [(set_attr "type" "jmpreg")]) ;; Logic on condition register values. @@ -12768,7 +12519,7 @@ ; which are generated by the branch logic. ; Prefer destructive operations where BT = BB (for crXX BT,BA,BB) -(define_insn "*cceq_ior_compare" +(define_insn "cceq_ior_compare" [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y") (compare:CCEQ (match_operator:SI 1 "boolean_operator" [(match_operator:SI 2 @@ -12784,13 +12535,14 @@ (const_int 1)))] "" "cr%q1 %E0,%j2,%j4" - [(set_attr "type" "cr_logical,delayed_cr")]) + [(set_attr "type" "cr_logical") + (set_attr "cr_logical_3op" "no,yes")]) ; Why is the constant -1 here, but 1 in the previous pattern? ; Because ~1 has all but the low bit set. -(define_insn "" +(define_insn "cceq_ior_compare_complement" [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y") - (compare:CCEQ (match_operator:SI 1 "boolean_or_operator" + (compare:CCEQ (match_operator:SI 1 "boolean_operator" [(not:SI (match_operator:SI 2 "branch_positive_comparison_operator" [(match_operand 3 @@ -12804,7 +12556,8 @@ (const_int -1)))] "" "cr%q1 %E0,%j2,%j4" - [(set_attr "type" "cr_logical,delayed_cr")]) + [(set_attr "type" "cr_logical") + (set_attr "cr_logical_3op" "no,yes")]) (define_insn "*cceq_rev_compare" [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y") @@ -12816,7 +12569,8 @@ (const_int 0)))] "" "crnot %E0,%j1" - [(set_attr "type" "cr_logical,delayed_cr")]) + [(set_attr "type" "cr_logical") + (set_attr "cr_logical_3op" "no,yes")]) ;; If we are comparing the result of two comparisons, this can be done ;; using creqv or crxor. @@ -12834,7 +12588,6 @@ "" [(set (match_dup 0) (compare:CCEQ (xor:SI (match_dup 1) (match_dup 3)) (match_dup 5)))] - " { int positive_1, positive_2; @@ -12870,7 +12623,7 @@ { operands[5] = const1_rtx; } -}") +}) ;; Unconditional branch and return. @@ -12888,25 +12641,57 @@ [(set_attr "type" "jmpreg")]) (define_expand "indirect_jump" - [(set (pc) (match_operand 0 "register_operand"))]) + [(set (pc) (match_operand 0 "register_operand"))] + "" +{ + if (!rs6000_speculate_indirect_jumps) { + rtx ccreg = gen_reg_rtx (CCmode); + if (Pmode == DImode) + emit_jump_insn (gen_indirect_jumpdi_nospec (operands[0], ccreg)); + else + emit_jump_insn (gen_indirect_jumpsi_nospec (operands[0], ccreg)); + DONE; + } +}) (define_insn "*indirect_jump<mode>" [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))] - "" + "rs6000_speculate_indirect_jumps" "b%T0" [(set_attr "type" "jmpreg")]) +(define_insn "indirect_jump<mode>_nospec" + [(set (pc) (match_operand:P 0 "register_operand" "c,*l")) + (clobber (match_operand:CC 1 "cc_reg_operand" "=y,y"))] + "!rs6000_speculate_indirect_jumps" + "crset %E1\;beq%T0- %1\;b $" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + ;; Table jump for switch statements: (define_expand "tablejump" [(use (match_operand 0)) (use (label_ref (match_operand 1)))] "" { - if (TARGET_32BIT) - emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); - else - emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); + if (rs6000_speculate_indirect_jumps) + { + if (TARGET_32BIT) + emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); + else + emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); + } + else + { + rtx ccreg = gen_reg_rtx (CCmode); + rtx jump; + if (TARGET_32BIT) + jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg); + else + jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg); + emit_jump_insn (jump); + } DONE; }) @@ -12917,13 +12702,28 @@ (parallel [(set (pc) (match_dup 3)) (use (label_ref (match_operand 1)))])] - "TARGET_32BIT" + "TARGET_32BIT && rs6000_speculate_indirect_jumps" { operands[0] = force_reg (SImode, operands[0]); operands[2] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1])); operands[3] = gen_reg_rtx (SImode); }) +(define_expand "tablejumpsi_nospec" + [(set (match_dup 4) + (plus:SI (match_operand:SI 0) + (match_dup 3))) + (parallel [(set (pc) + (match_dup 4)) + (use (label_ref (match_operand 1))) + (clobber (match_operand 2))])] + "TARGET_32BIT && !rs6000_speculate_indirect_jumps" +{ + operands[0] = force_reg (SImode, operands[0]); + operands[3] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1])); + operands[4] = gen_reg_rtx (SImode); +}) + (define_expand "tablejumpdi" [(set (match_dup 4) (sign_extend:DI (match_operand:SI 0 "lwa_operand"))) @@ -12933,21 +12733,48 @@ (parallel [(set (pc) (match_dup 3)) (use (label_ref (match_operand 1)))])] - "TARGET_64BIT" + "TARGET_64BIT && rs6000_speculate_indirect_jumps" { operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1])); operands[3] = gen_reg_rtx (DImode); operands[4] = gen_reg_rtx (DImode); }) +(define_expand "tablejumpdi_nospec" + [(set (match_dup 5) + (sign_extend:DI (match_operand:SI 0 "lwa_operand"))) + (set (match_dup 4) + (plus:DI (match_dup 5) + (match_dup 3))) + (parallel [(set (pc) + (match_dup 4)) + (use (label_ref (match_operand 1))) + (clobber (match_operand 2))])] + "TARGET_64BIT && !rs6000_speculate_indirect_jumps" +{ + operands[3] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1])); + operands[4] = gen_reg_rtx (DImode); + operands[5] = gen_reg_rtx (DImode); +}) + (define_insn "*tablejump<mode>_internal1" [(set (pc) (match_operand:P 0 "register_operand" "c,*l")) (use (label_ref (match_operand 1)))] - "" + "rs6000_speculate_indirect_jumps" "b%T0" [(set_attr "type" "jmpreg")]) +(define_insn "*tablejump<mode>_internal1_nospec" + [(set (pc) + (match_operand:P 0 "register_operand" "c,*l")) + (use (label_ref (match_operand 1))) + (clobber (match_operand:CC 2 "cc_reg_operand" "=y,y"))] + "!rs6000_speculate_indirect_jumps" + "crset %E2\;beq%T0- %2\;b $" + [(set_attr "type" "jmpreg") + (set_attr "length" "12")]) + (define_insn "nop" [(unspec [(const_int 0)] UNSPEC_NOP)] "" @@ -12957,10 +12784,15 @@ [(unspec [(const_int 0)] UNSPEC_GRP_END_NOP)] "" { - if (rs6000_cpu_attr == CPU_POWER6) + if (rs6000_tune == PROCESSOR_POWER6) return "ori 1,1,0"; return "ori 2,2,0"; }) + +(define_insn "speculation_barrier" + [(unspec_volatile:BLK [(const_int 0)] UNSPECV_SPEC_BARRIER)] + "" + "ori 31,31,0") ;; Define the subtract-one-and-jump insns, starting with the template ;; so loop.c knows what to generate. @@ -13007,34 +12839,13 @@ ;; rs6000_legitimate_combined_insn prevents combine creating any of ;; the ctr<mode> insns. -(define_insn "ctr<mode>_internal1" +(define_code_iterator eqne [eq ne]) +(define_code_attr bd [(eq "bdz") (ne "bdnz")]) +(define_code_attr bd_neg [(eq "bdnz") (ne "bdz")]) + +(define_insn "<bd>_<mode>" [(set (pc) - (if_then_else (ne (match_operand:P 1 "register_operand" "c,*b,*b,*b") - (const_int 1)) - (label_ref (match_operand 0)) - (pc))) - (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l") - (plus:P (match_dup 1) - (const_int -1))) - (clobber (match_scratch:CC 3 "=X,&x,&x,&x")) - (clobber (match_scratch:P 4 "=X,X,&r,r"))] - "" -{ - if (which_alternative != 0) - return "#"; - else if (get_attr_length (insn) == 4) - return "bdnz %l0"; - else - return "bdz $+8\;b %l0"; -} - [(set_attr "type" "branch") - (set_attr "length" "*,16,20,20")]) - -;; Similar but use EQ - -(define_insn "ctr<mode>_internal2" - [(set (pc) - (if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b") + (if_then_else (eqne (match_operand:P 1 "register_operand" "c,*b,*b,*b") (const_int 1)) (label_ref (match_operand 0)) (pc))) @@ -13048,43 +12859,23 @@ if (which_alternative != 0) return "#"; else if (get_attr_length (insn) == 4) - return "bdz %l0"; - else - return "bdnz $+8\;b %l0"; + return "<bd> %l0"; + else + return "<bd_neg> $+8\;b %l0"; } [(set_attr "type" "branch") - (set_attr "length" "*,16,20,20")]) - -;; Now the splitters if we could not allocate the CTR register - -(define_split - [(set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(match_operand:P 1 "gpc_reg_operand") - (const_int 1)]) - (match_operand 5) - (match_operand 6))) - (set (match_operand:P 0 "int_reg_operand") - (plus:P (match_dup 1) - (const_int -1))) - (clobber (match_scratch:CC 3)) - (clobber (match_scratch:P 4))] - "reload_completed" - [(set (match_dup 3) - (compare:CC (match_dup 1) - (const_int 1))) - (set (match_dup 0) - (plus:P (match_dup 1) - (const_int -1))) - (set (pc) - (if_then_else (match_dup 7) - (match_dup 5) - (match_dup 6)))] -{ - operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode, operands[3], - const0_rtx); -}) - + (set_attr_alternative "length" + [(if_then_else (and (ge (minus (match_dup 0) (pc)) + (const_int -32768)) + (lt (minus (match_dup 0) (pc)) + (const_int 32764))) + (const_int 4) + (const_int 8)) + (const_string "16") + (const_string "20") + (const_string "20")])]) + +;; Now the splitter if we could not allocate the CTR register (define_split [(set (pc) (if_then_else (match_operator 2 "comparison_operator" @@ -13097,23 +12888,141 @@ (const_int -1))) (clobber (match_scratch:CC 3)) (clobber (match_scratch:P 4))] - "reload_completed && !gpc_reg_operand (operands[0], SImode)" - [(set (match_dup 3) - (compare:CC (match_dup 1) - (const_int 1))) - (set (match_dup 4) - (plus:P (match_dup 1) - (const_int -1))) - (set (match_dup 0) - (match_dup 4)) - (set (pc) + "reload_completed" + [(set (pc) (if_then_else (match_dup 7) (match_dup 5) (match_dup 6)))] { operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode, operands[3], const0_rtx); -}) + emit_insn (gen_rtx_SET (operands[3], + gen_rtx_COMPARE (CCmode, operands[1], const1_rtx))); + if (gpc_reg_operand (operands[0], <MODE>mode)) + emit_insn (gen_add<mode>3 (operands[0], operands[1], constm1_rtx)); + else + { + emit_insn (gen_add<mode>3 (operands[4], operands[1], constm1_rtx)); + emit_move_insn (operands[0], operands[4]); + } + /* No DONE so branch comes from the pattern. */ +}) + +;; patterns for bdnzt/bdnzf/bdzt/bdzf +;; Note that in the case of long branches we have to decompose this into +;; bdnz+bc. This is because bdnzt has an implied AND between the ctr condition +;; and the CR bit, which means there is no way to conveniently invert the +;; comparison as is done with plain bdnz/bdz. + +(define_insn "<bd>tf_<mode>" + [(set (pc) + (if_then_else + (and + (eqne (match_operand:P 1 "register_operand" "c,*b,*b,*b") + (const_int 1)) + (match_operator 3 "branch_comparison_operator" + [(match_operand 4 "cc_reg_operand" "y,y,y,y") + (const_int 0)])) + (label_ref (match_operand 0)) + (pc))) + (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l") + (plus:P (match_dup 1) + (const_int -1))) + (clobber (match_scratch:P 5 "=X,X,&r,r")) + (clobber (match_scratch:CC 6 "=X,&y,&y,&y")) + (clobber (match_scratch:CCEQ 7 "=X,&y,&y,&y"))] + "" +{ + if (which_alternative != 0) + return "#"; + else if (get_attr_length (insn) == 4) + { + if (branch_positive_comparison_operator (operands[3], + GET_MODE (operands[3]))) + return "<bd>t %j3,%l0"; + else + return "<bd>f %j3,%l0"; + } + else + { + static char seq[96]; + char *bcs = output_cbranch (operands[3], "$+8", 1, insn); + sprintf(seq, "<bd_neg> $+12\;%s;b %%l0", bcs); + return seq; + } +} + [(set_attr "type" "branch") + (set_attr_alternative "length" + [(if_then_else (and (ge (minus (match_dup 0) (pc)) + (const_int -32768)) + (lt (minus (match_dup 0) (pc)) + (const_int 32764))) + (const_int 4) + (const_int 8)) + (const_string "16") + (const_string "20") + (const_string "20")])]) + +;; Now the splitter if we could not allocate the CTR register +(define_split + [(set (pc) + (if_then_else + (and + (match_operator 1 "comparison_operator" + [(match_operand:P 0 "gpc_reg_operand") + (const_int 1)]) + (match_operator 3 "branch_comparison_operator" + [(match_operand 2 "cc_reg_operand") + (const_int 0)])) + (match_operand 4) + (match_operand 5))) + (set (match_operand:P 6 "int_reg_operand") + (plus:P (match_dup 0) + (const_int -1))) + (clobber (match_scratch:P 7)) + (clobber (match_scratch:CC 8)) + (clobber (match_scratch:CCEQ 9))] + "reload_completed" +[(pc)] +{ + rtx ctr = operands[0]; + rtx ctrcmp = operands[1]; + rtx ccin = operands[2]; + rtx cccmp = operands[3]; + rtx dst1 = operands[4]; + rtx dst2 = operands[5]; + rtx ctrout = operands[6]; + rtx ctrtmp = operands[7]; + enum rtx_code cmpcode = GET_CODE (ctrcmp); + bool ispos = branch_positive_comparison_operator (ctrcmp, GET_MODE (ctrcmp)); + if (!ispos) + cmpcode = reverse_condition (cmpcode); + /* Generate crand/crandc here. */ + emit_insn (gen_rtx_SET (operands[8], + gen_rtx_COMPARE (CCmode, ctr, const1_rtx))); + rtx ctrcmpcc = gen_rtx_fmt_ee (cmpcode, SImode, operands[8], const0_rtx); + + rtx andexpr = gen_rtx_AND (SImode, ctrcmpcc, cccmp); + if (ispos) + emit_insn (gen_cceq_ior_compare (operands[9], andexpr, ctrcmpcc, + operands[8], cccmp, ccin)); + else + emit_insn (gen_cceq_ior_compare_complement (operands[9], andexpr, ctrcmpcc, + operands[8], cccmp, ccin)); + if (gpc_reg_operand (operands[0], <MODE>mode)) + emit_insn (gen_add<mode>3 (ctrout, ctr, constm1_rtx)); + else + { + emit_insn (gen_add<mode>3 (ctrtmp, ctr, constm1_rtx)); + emit_move_insn (ctrout, ctrtmp); + } + rtx cmp = gen_rtx_EQ (CCEQmode, operands[9], const0_rtx); + emit_jump_insn (gen_rtx_SET (pc_rtx, + gen_rtx_IF_THEN_ELSE (VOIDmode, cmp, + dst1, dst2))); + DONE; +}) + (define_insn "trap" [(trap_if (const_int 1) (const_int 0))] @@ -13157,7 +13066,6 @@ (match_operand 3 "immediate_operand" "n")] UNSPEC_MOVESI_FROM_CR))])] "TARGET_MFCRF" - "* { int mask = 0; int i; @@ -13165,10 +13073,10 @@ { mask = INTVAL (XVECEXP (SET_SRC (XVECEXP (operands[0], 0, i)), 0, 1)); operands[4] = GEN_INT (mask); - output_asm_insn (\"mfcr %1,%4\", operands); + output_asm_insn ("mfcr %1,%4", operands); } - return \"\"; -}" + return ""; +} [(set_attr "type" "mfcrf")]) ;; Don't include the volatile CRs since their values are not used wrt CR save @@ -13226,8 +13134,7 @@ (match_operand:P 3 "gpc_reg_operand" "r"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*save_gpregs_<mode>_r12" [(match_parallel 0 "any_parallel_operand" @@ -13238,8 +13145,7 @@ (match_operand:P 3 "gpc_reg_operand" "r"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*save_gpregs_<mode>_r1" [(match_parallel 0 "any_parallel_operand" @@ -13250,8 +13156,7 @@ (match_operand:P 3 "gpc_reg_operand" "r"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*save_fpregs_<mode>_r11" [(match_parallel 0 "any_parallel_operand" @@ -13262,8 +13167,7 @@ (match_operand:DF 3 "gpc_reg_operand" "d"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*save_fpregs_<mode>_r12" [(match_parallel 0 "any_parallel_operand" @@ -13274,8 +13178,7 @@ (match_operand:DF 3 "gpc_reg_operand" "d"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*save_fpregs_<mode>_r1" [(match_parallel 0 "any_parallel_operand" @@ -13286,8 +13189,7 @@ (match_operand:DF 3 "gpc_reg_operand" "d"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) ; This is to explain that changes to the stack pointer should ; not be moved over loads from or stores to stack memory. @@ -13327,8 +13229,8 @@ ; faster; for instance, on the 601 and 750. (define_expand "movsi_to_cr_one" - [(set (match_operand:CC 0 "cc_reg_operand" "") - (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "") + [(set (match_operand:CC 0 "cc_reg_operand") + (unspec:CC [(match_operand:SI 1 "gpc_reg_operand") (match_dup 2)] UNSPEC_MOVESI_TO_CR))] "" "operands[2] = GEN_INT (1 << (75 - REGNO (operands[0])));") @@ -13340,15 +13242,14 @@ (match_operand 3 "immediate_operand" "n")] UNSPEC_MOVESI_TO_CR))])] "" - "* { int mask = 0; int i; for (i = 0; i < XVECLEN (operands[0], 0); i++) mask |= INTVAL (XVECEXP (SET_SRC (XVECEXP (operands[0], 0, i)), 0, 1)); operands[4] = GEN_INT (mask); - return \"mtcrf %4,%2\"; -}" + return "mtcrf %4,%2"; +} [(set_attr "type" "mtcr")]) (define_insn "*mtcrfsi" @@ -13378,8 +13279,7 @@ (set_attr "indexed" "yes") (set_attr "cell_micro" "always")]) -; FIXME: This would probably be somewhat simpler if the Cygnus sibcall -; stuff was in GCC. Oh, and "any_parallel_operand" is a bit flexible... +; FIXME: "any_parallel_operand" is a bit flexible... ; The following comment applies to: ; save_gpregs_* @@ -13405,8 +13305,7 @@ (match_operand:P 3 "memory_operand" "m"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*restore_gpregs_<mode>_r12" [(match_parallel 0 "any_parallel_operand" @@ -13417,8 +13316,7 @@ (match_operand:P 3 "memory_operand" "m"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*restore_gpregs_<mode>_r1" [(match_parallel 0 "any_parallel_operand" @@ -13429,8 +13327,7 @@ (match_operand:P 3 "memory_operand" "m"))])] "" "bl %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*return_and_restore_gpregs_<mode>_r11" [(match_parallel 0 "any_parallel_operand" @@ -13442,8 +13339,7 @@ (match_operand:P 3 "memory_operand" "m"))])] "" "b %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*return_and_restore_gpregs_<mode>_r12" [(match_parallel 0 "any_parallel_operand" @@ -13455,8 +13351,7 @@ (match_operand:P 3 "memory_operand" "m"))])] "" "b %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*return_and_restore_gpregs_<mode>_r1" [(match_parallel 0 "any_parallel_operand" @@ -13468,8 +13363,7 @@ (match_operand:P 3 "memory_operand" "m"))])] "" "b %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*return_and_restore_fpregs_<mode>_r11" [(match_parallel 0 "any_parallel_operand" @@ -13481,8 +13375,7 @@ (match_operand:DF 3 "memory_operand" "m"))])] "" "b %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*return_and_restore_fpregs_<mode>_r12" [(match_parallel 0 "any_parallel_operand" @@ -13494,8 +13387,7 @@ (match_operand:DF 3 "memory_operand" "m"))])] "" "b %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*return_and_restore_fpregs_<mode>_r1" [(match_parallel 0 "any_parallel_operand" @@ -13507,8 +13399,7 @@ (match_operand:DF 3 "memory_operand" "m"))])] "" "b %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*return_and_restore_fpregs_aix_<mode>_r11" [(match_parallel 0 "any_parallel_operand" @@ -13519,8 +13410,7 @@ (match_operand:DF 3 "memory_operand" "m"))])] "" "b %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) (define_insn "*return_and_restore_fpregs_aix_<mode>_r1" [(match_parallel 0 "any_parallel_operand" @@ -13531,21 +13421,19 @@ (match_operand:DF 3 "memory_operand" "m"))])] "" "b %1" - [(set_attr "type" "branch") - (set_attr "length" "4")]) + [(set_attr "type" "branch")]) ; This is used in compiling the unwind routines. (define_expand "eh_return" - [(use (match_operand 0 "general_operand" ""))] - "" - " + [(use (match_operand 0 "general_operand"))] + "" { if (TARGET_32BIT) emit_insn (gen_eh_set_lr_si (operands[0])); else emit_insn (gen_eh_set_lr_di (operands[0])); DONE; -}") +}) ; We can't expand this before we know where the link register is stored. (define_insn "eh_set_lr_<mode>" @@ -13556,27 +13444,44 @@ "#") (define_split - [(unspec_volatile [(match_operand 0 "register_operand" "")] UNSPECV_EH_RR) - (clobber (match_scratch 1 ""))] + [(unspec_volatile [(match_operand 0 "register_operand")] UNSPECV_EH_RR) + (clobber (match_scratch 1))] "reload_completed" [(const_int 0)] - " { rs6000_emit_eh_reg_restore (operands[0], operands[1]); DONE; -}") +}) (define_insn "prefetch" [(prefetch (match_operand 0 "indexed_or_indirect_address" "a") (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n"))] "" - "* -{ - if (GET_CODE (operands[0]) == REG) - return INTVAL (operands[1]) ? \"dcbtst 0,%0\" : \"dcbt 0,%0\"; - return INTVAL (operands[1]) ? \"dcbtst %a0\" : \"dcbt %a0\"; -}" +{ + + + /* dcbtstt, dcbtt and TH=0b10000 support starts with ISA 2.06 (Power7). + AIX does not support the dcbtstt and dcbtt extended mnemonics. + The AIX assembler does not support the three operand form of dcbt + and dcbtst on Power 7 (-mpwr7). */ + int inst_select = INTVAL (operands[2]) || !TARGET_DIRECT_MOVE; + + if (REG_P (operands[0])) + { + if (INTVAL (operands[1]) == 0) + return inst_select ? "dcbt 0,%0" : "dcbt 0,%0,16"; + else + return inst_select ? "dcbtst 0,%0" : "dcbtst 0,%0,16"; + } + else + { + if (INTVAL (operands[1]) == 0) + return inst_select ? "dcbt %a0" : "dcbt %a0,16"; + else + return inst_select ? "dcbtst %a0" : "dcbtst %a0,16"; + } +} [(set_attr "type" "load")]) ;; Handle -fsplit-stack. @@ -13623,7 +13528,7 @@ ;; Use r0 to stop regrename twiddling with lr restore insns emitted ;; after the call to __morestack. (define_insn "split_stack_return" - [(unspec_volatile [(use (reg:SI 0))] UNSPECV_SPLIT_STACK_RETURN)] + [(unspec_volatile [(reg:SI 0) (reg:SI LR_REGNO)] UNSPECV_SPLIT_STACK_RETURN)] "" "blr" [(set_attr "type" "jmpreg")]) @@ -13660,11 +13565,11 @@ ;; Note that the conditions for expansion are in the FMA_F iterator. (define_expand "fma<mode>4" - [(set (match_operand:FMA_F 0 "gpc_reg_operand" "") + [(set (match_operand:FMA_F 0 "gpc_reg_operand") (fma:FMA_F - (match_operand:FMA_F 1 "gpc_reg_operand" "") - (match_operand:FMA_F 2 "gpc_reg_operand" "") - (match_operand:FMA_F 3 "gpc_reg_operand" "")))] + (match_operand:FMA_F 1 "gpc_reg_operand") + (match_operand:FMA_F 2 "gpc_reg_operand") + (match_operand:FMA_F 3 "gpc_reg_operand")))] "" "") @@ -13674,21 +13579,20 @@ (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>,<Fv2>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0") (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>")))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fmadd<Ftrad> %0,%1,%2,%3 xsmadda<Fvsx> %x0,%x1,%x2 xsmaddm<Fvsx> %x0,%x1,%x3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_<Fs>")]) + [(set_attr "type" "fp")]) ; Altivec only has fma and nfms. (define_expand "fms<mode>4" - [(set (match_operand:FMA_F 0 "gpc_reg_operand" "") + [(set (match_operand:FMA_F 0 "gpc_reg_operand") (fma:FMA_F - (match_operand:FMA_F 1 "gpc_reg_operand" "") - (match_operand:FMA_F 2 "gpc_reg_operand" "") - (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand" ""))))] + (match_operand:FMA_F 1 "gpc_reg_operand") + (match_operand:FMA_F 2 "gpc_reg_operand") + (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand"))))] "!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)" "") @@ -13698,44 +13602,43 @@ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>,<Fv2>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0") (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>"))))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fmsub<Ftrad> %0,%1,%2,%3 xsmsuba<Fvsx> %x0,%x1,%x2 xsmsubm<Fvsx> %x0,%x1,%x3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_<Fs>")]) + [(set_attr "type" "fp")]) ;; If signed zeros are ignored, -(a * b - c) = -a * b + c. (define_expand "fnma<mode>4" - [(set (match_operand:FMA_F 0 "gpc_reg_operand" "") + [(set (match_operand:FMA_F 0 "gpc_reg_operand") (neg:FMA_F (fma:FMA_F - (match_operand:FMA_F 1 "gpc_reg_operand" "") - (match_operand:FMA_F 2 "gpc_reg_operand" "") - (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand" "")))))] + (match_operand:FMA_F 1 "gpc_reg_operand") + (match_operand:FMA_F 2 "gpc_reg_operand") + (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand")))))] "!HONOR_SIGNED_ZEROS (<MODE>mode)" "") ;; If signed zeros are ignored, -(a * b + c) = -a * b - c. (define_expand "fnms<mode>4" - [(set (match_operand:FMA_F 0 "gpc_reg_operand" "") + [(set (match_operand:FMA_F 0 "gpc_reg_operand") (neg:FMA_F (fma:FMA_F - (match_operand:FMA_F 1 "gpc_reg_operand" "") - (match_operand:FMA_F 2 "gpc_reg_operand" "") - (match_operand:FMA_F 3 "gpc_reg_operand" ""))))] + (match_operand:FMA_F 1 "gpc_reg_operand") + (match_operand:FMA_F 2 "gpc_reg_operand") + (match_operand:FMA_F 3 "gpc_reg_operand"))))] "!HONOR_SIGNED_ZEROS (<MODE>mode) && !VECTOR_UNIT_ALTIVEC_P (<MODE>mode)" "") ; Not an official optab name, but used from builtins. (define_expand "nfma<mode>4" - [(set (match_operand:FMA_F 0 "gpc_reg_operand" "") + [(set (match_operand:FMA_F 0 "gpc_reg_operand") (neg:FMA_F (fma:FMA_F - (match_operand:FMA_F 1 "gpc_reg_operand" "") - (match_operand:FMA_F 2 "gpc_reg_operand" "") - (match_operand:FMA_F 3 "gpc_reg_operand" ""))))] + (match_operand:FMA_F 1 "gpc_reg_operand") + (match_operand:FMA_F 2 "gpc_reg_operand") + (match_operand:FMA_F 3 "gpc_reg_operand"))))] "!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)" "") @@ -13746,22 +13649,21 @@ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>,<Fv2>") (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0") (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>"))))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fnmadd<Ftrad> %0,%1,%2,%3 xsnmadda<Fvsx> %x0,%x1,%x2 xsnmaddm<Fvsx> %x0,%x1,%x3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_<Fs>")]) + [(set_attr "type" "fp")]) ; Not an official optab name, but used from builtins. (define_expand "nfms<mode>4" - [(set (match_operand:FMA_F 0 "gpc_reg_operand" "") + [(set (match_operand:FMA_F 0 "gpc_reg_operand") (neg:FMA_F (fma:FMA_F - (match_operand:FMA_F 1 "gpc_reg_operand" "") - (match_operand:FMA_F 2 "gpc_reg_operand" "") - (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand" "")))))] + (match_operand:FMA_F 1 "gpc_reg_operand") + (match_operand:FMA_F 2 "gpc_reg_operand") + (neg:FMA_F (match_operand:FMA_F 3 "gpc_reg_operand")))))] "" "") @@ -13773,17 +13675,16 @@ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0") (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>")))))] - "TARGET_<MODE>_FPR" + "TARGET_HARD_FLOAT" "@ fnmsub<Ftrad> %0,%1,%2,%3 xsnmsuba<Fvsx> %x0,%x1,%x2 xsnmsubm<Fvsx> %x0,%x1,%x3" - [(set_attr "type" "fp") - (set_attr "fp_type" "fp_maddsub_<Fs>")]) + [(set_attr "type" "fp")]) (define_expand "rs6000_get_timebase" - [(use (match_operand:DI 0 "gpc_reg_operand" ""))] + [(use (match_operand:DI 0 "gpc_reg_operand"))] "" { if (TARGET_POWERPC64) @@ -13849,6 +13750,43 @@ }) +;; The ISA 3.0 mffsl instruction is a lower latency instruction +;; for reading bits [29:31], [45:51] and [56:63] of the FPSCR. +(define_insn "rs6000_mffsl_hw" + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFSL))] + "TARGET_HARD_FLOAT" + "mffsl %0") + +(define_expand "rs6000_mffsl" + [(set (match_operand:DF 0 "gpc_reg_operand") + (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFSL))] + "TARGET_HARD_FLOAT" +{ + /* If the low latency mffsl instruction (ISA 3.0) is available use it, + otherwise fall back to the older mffs instruction to emulate the mffsl + instruction. */ + + if (!TARGET_P9_MISC) + { + rtx tmp_di = gen_reg_rtx (DImode); + rtx tmp_df = gen_reg_rtx (DFmode); + + /* The mffs instruction reads the entire FPSCR. Emulate the mffsl + instruction using the mffs instruction and masking off the bits + the mmsl instruciton actually reads. */ + emit_insn (gen_rs6000_mffs (tmp_df)); + tmp_di = simplify_gen_subreg (DImode, tmp_df, DFmode, 0); + emit_insn (gen_anddi3 (tmp_di, tmp_di, GEN_INT (0x70007f0ffLL))); + + operands[0] = simplify_gen_subreg (DFmode, tmp_di, DImode, 0); + DONE; + } + + emit_insn (gen_rs6000_mffsl_hw (operands[0])); + DONE; +}) + (define_insn "rs6000_mffs" [(set (match_operand:DF 0 "gpc_reg_operand" "=d") (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFS))] @@ -13862,80 +13800,32 @@ "TARGET_HARD_FLOAT" "mtfsf %0,%1") +(define_insn "rs6000_mtfsf_hi" + [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n") + (match_operand:DF 1 "gpc_reg_operand" "d")] + UNSPECV_MTFSF_HI)] + "TARGET_HARD_FLOAT" + "mtfsf %0,%1,0,1") + ;; Power8 fusion support for fusing an addis instruction with a D-form load of ;; a GPR. The addis instruction must be adjacent to the load, and use the same ;; register that is being loaded. The fused ops must be physically adjacent. -;; There are two parts to addis fusion. The support for fused TOCs occur -;; before register allocation, and is meant to reduce the lifetime for the -;; tempoary register that holds the ADDIS result. On Power8 GPR loads, we try -;; to use the register that is being load. The peephole2 then gathers any -;; other fused possibilities that it can find after register allocation. If -;; power9 fusion is selected, we also fuse floating point loads/stores. - -;; Fused TOC support: Replace simple GPR loads with a fused form. This is done -;; before register allocation, so that we can avoid allocating a temporary base -;; register that won't be used, and that we try to load into base registers, -;; and not register 0. If we can't get a fused GPR load, generate a P9 fusion -;; (addis followed by load) even on power8. - -(define_split - [(set (match_operand:INT1 0 "toc_fusion_or_p9_reg_operand" "") - (match_operand:INT1 1 "toc_fusion_mem_raw" ""))] - "TARGET_TOC_FUSION_INT && can_create_pseudo_p ()" - [(parallel [(set (match_dup 0) (match_dup 2)) - (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS) - (use (match_dup 3)) - (clobber (scratch:DI))])] -{ - operands[2] = fusion_wrap_memory_address (operands[1]); - operands[3] = gen_rtx_REG (Pmode, TOC_REGISTER); -}) - -(define_insn "*toc_fusionload_<mode>" - [(set (match_operand:QHSI 0 "int_reg_operand" "=&b,??r") - (match_operand:QHSI 1 "toc_fusion_mem_wrapped" "wG,wG")) - (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS) - (use (match_operand:DI 2 "base_reg_operand" "r,r")) - (clobber (match_scratch:DI 3 "=X,&b"))] - "TARGET_TOC_FUSION_INT" -{ - if (base_reg_operand (operands[0], <MODE>mode)) - return emit_fusion_gpr_load (operands[0], operands[1]); - - return emit_fusion_p9_load (operands[0], operands[1], operands[3]); -} - [(set_attr "type" "load") - (set_attr "length" "8")]) - -(define_insn "*toc_fusionload_di" - [(set (match_operand:DI 0 "int_reg_operand" "=&b,??r,?d") - (match_operand:DI 1 "toc_fusion_mem_wrapped" "wG,wG,wG")) - (unspec [(const_int 0)] UNSPEC_FUSION_ADDIS) - (use (match_operand:DI 2 "base_reg_operand" "r,r,r")) - (clobber (match_scratch:DI 3 "=X,&b,&b"))] - "TARGET_TOC_FUSION_INT && TARGET_POWERPC64 - && (MEM_P (operands[1]) || int_reg_operand (operands[0], DImode))" -{ - if (base_reg_operand (operands[0], DImode)) - return emit_fusion_gpr_load (operands[0], operands[1]); - - return emit_fusion_p9_load (operands[0], operands[1], operands[3]); -} - [(set_attr "type" "load") - (set_attr "length" "8")]) - - +;; On Power8 GPR loads, we try to use the register that is being load. The +;; peephole2 then gathers any other fused possibilities that it can find after +;; register allocation. If power9 fusion is selected, we also fuse floating +;; point loads/stores. + ;; Find cases where the addis that feeds into a load instruction is either used ;; once or is the same as the target register, and replace it with the fusion ;; insn (define_peephole2 - [(set (match_operand:P 0 "base_reg_operand" "") - (match_operand:P 1 "fusion_gpr_addis" "")) - (set (match_operand:INT1 2 "base_reg_operand" "") - (match_operand:INT1 3 "fusion_gpr_mem_load" ""))] + [(set (match_operand:P 0 "base_reg_operand") + (match_operand:P 1 "fusion_gpr_addis")) + (set (match_operand:INT1 2 "base_reg_operand") + (match_operand:INT1 3 "fusion_gpr_mem_load"))] "TARGET_P8_FUSION && fusion_gpr_load_p (operands[0], operands[1], operands[2], operands[3])" @@ -13948,7 +13838,7 @@ ;; Fusion insn, created by the define_peephole2 above (and eventually by ;; reload) -(define_insn "fusion_gpr_load_<mode>" +(define_insn "*fusion_gpr_load_<mode>" [(set (match_operand:INT1 0 "base_reg_operand" "=b") (unspec:INT1 [(match_operand:INT1 1 "fusion_addis_mem_combo_load" "wF")] UNSPEC_FUSION_GPR))] @@ -13963,10 +13853,10 @@ ;; ISA 3.0 (power9) fusion support ;; Merge addis with floating load/store to FPRs (or GPRs). (define_peephole2 - [(set (match_operand:P 0 "base_reg_operand" "") - (match_operand:P 1 "fusion_gpr_addis" "")) - (set (match_operand:SFDF 2 "toc_fusion_or_p9_reg_operand" "") - (match_operand:SFDF 3 "fusion_offsettable_mem_operand" ""))] + [(set (match_operand:P 0 "base_reg_operand") + (match_operand:P 1 "fusion_gpr_addis")) + (set (match_operand:SFDF 2 "p9_fusion_reg_operand") + (match_operand:SFDF 3 "fusion_offsettable_mem_operand"))] "TARGET_P9_FUSION && peep2_reg_dead_p (2, operands[0]) && fusion_p9_p (operands[0], operands[1], operands[2], operands[3])" [(const_int 0)] @@ -13976,10 +13866,10 @@ }) (define_peephole2 - [(set (match_operand:P 0 "base_reg_operand" "") - (match_operand:P 1 "fusion_gpr_addis" "")) - (set (match_operand:SFDF 2 "offsettable_mem_operand" "") - (match_operand:SFDF 3 "toc_fusion_or_p9_reg_operand" ""))] + [(set (match_operand:P 0 "base_reg_operand") + (match_operand:P 1 "fusion_gpr_addis")) + (set (match_operand:SFDF 2 "offsettable_mem_operand") + (match_operand:SFDF 3 "p9_fusion_reg_operand"))] "TARGET_P9_FUSION && peep2_reg_dead_p (2, operands[0]) && fusion_p9_p (operands[0], operands[1], operands[2], operands[3]) && !rtx_equal_p (operands[0], operands[3])" @@ -13990,22 +13880,22 @@ }) (define_peephole2 - [(set (match_operand:SDI 0 "int_reg_operand" "") - (match_operand:SDI 1 "upper16_cint_operand" "")) + [(set (match_operand:SDI 0 "int_reg_operand") + (match_operand:SDI 1 "upper16_cint_operand")) (set (match_dup 0) (ior:SDI (match_dup 0) - (match_operand:SDI 2 "u_short_cint_operand" "")))] + (match_operand:SDI 2 "u_short_cint_operand")))] "TARGET_P9_FUSION" [(set (match_dup 0) (unspec:SDI [(match_dup 1) (match_dup 2)] UNSPEC_FUSION_P9))]) (define_peephole2 - [(set (match_operand:SDI 0 "int_reg_operand" "") - (match_operand:SDI 1 "upper16_cint_operand" "")) - (set (match_operand:SDI 2 "int_reg_operand" "") + [(set (match_operand:SDI 0 "int_reg_operand") + (match_operand:SDI 1 "upper16_cint_operand")) + (set (match_operand:SDI 2 "int_reg_operand") (ior:SDI (match_dup 0) - (match_operand:SDI 3 "u_short_cint_operand" "")))] + (match_operand:SDI 3 "u_short_cint_operand")))] "TARGET_P9_FUSION && !rtx_equal_p (operands[0], operands[2]) && peep2_reg_dead_p (2, operands[0])" @@ -14017,7 +13907,7 @@ ;; reload). Because we want to eventually have secondary_reload generate ;; these, they have to have a single alternative that gives the register ;; classes. This means we need to have separate gpr/fpr/altivec versions. -(define_insn "fusion_gpr_<P:mode>_<GPR_FUSION:mode>_load" +(define_insn "*fusion_gpr_<P:mode>_<GPR_FUSION:mode>_load" [(set (match_operand:GPR_FUSION 0 "int_reg_operand" "=r") (unspec:GPR_FUSION [(match_operand:GPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")] @@ -14035,7 +13925,7 @@ [(set_attr "type" "load") (set_attr "length" "8")]) -(define_insn "fusion_gpr_<P:mode>_<GPR_FUSION:mode>_store" +(define_insn "*fusion_gpr_<P:mode>_<GPR_FUSION:mode>_store" [(set (match_operand:GPR_FUSION 0 "fusion_addis_mem_combo_store" "=wF") (unspec:GPR_FUSION [(match_operand:GPR_FUSION 1 "int_reg_operand" "r")] @@ -14048,7 +13938,7 @@ [(set_attr "type" "store") (set_attr "length" "8")]) -(define_insn "fusion_vsx_<P:mode>_<FPR_FUSION:mode>_load" +(define_insn "*fusion_vsx_<P:mode>_<FPR_FUSION:mode>_load" [(set (match_operand:FPR_FUSION 0 "vsx_register_operand" "=dwb") (unspec:FPR_FUSION [(match_operand:FPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")] @@ -14061,7 +13951,7 @@ [(set_attr "type" "fpload") (set_attr "length" "8")]) -(define_insn "fusion_vsx_<P:mode>_<FPR_FUSION:mode>_store" +(define_insn "*fusion_vsx_<P:mode>_<FPR_FUSION:mode>_store" [(set (match_operand:FPR_FUSION 0 "fusion_addis_mem_combo_store" "=wF") (unspec:FPR_FUSION [(match_operand:FPR_FUSION 1 "vsx_register_operand" "dwb")] @@ -14081,7 +13971,7 @@ UNSPEC_FUSION_P9))] "TARGET_P9_FUSION" { - emit_fusion_addis (operands[0], operands[1], "constant", "<MODE>"); + emit_fusion_addis (operands[0], operands[1]); return "ori %0,%0,%2"; } [(set_attr "type" "two") @@ -14170,8 +14060,7 @@ UNSPEC_ADDG6S))] "TARGET_POPCNTD" "addg6s %0,%1,%2" - [(set_attr "type" "integer") - (set_attr "length" "4")]) + [(set_attr "type" "integer")]) (define_insn "cdtbcd" [(set (match_operand:SI 0 "register_operand" "=r") @@ -14179,8 +14068,7 @@ UNSPEC_CDTBCD))] "TARGET_POPCNTD" "cdtbcd %0,%1" - [(set_attr "type" "integer") - (set_attr "length" "4")]) + [(set_attr "type" "integer")]) (define_insn "cbcdtd" [(set (match_operand:SI 0 "register_operand" "=r") @@ -14188,18 +14076,13 @@ UNSPEC_CBCDTD))] "TARGET_POPCNTD" "cbcdtd %0,%1" - [(set_attr "type" "integer") - (set_attr "length" "4")]) + [(set_attr "type" "integer")]) (define_int_iterator UNSPEC_DIV_EXTEND [UNSPEC_DIVE - UNSPEC_DIVEO - UNSPEC_DIVEU - UNSPEC_DIVEUO]) + UNSPEC_DIVEU]) (define_int_attr div_extend [(UNSPEC_DIVE "e") - (UNSPEC_DIVEO "eo") - (UNSPEC_DIVEU "eu") - (UNSPEC_DIVEUO "euo")]) + (UNSPEC_DIVEU "eu")]) (define_insn "div<div_extend>_<mode>" [(set (match_operand:GPR 0 "register_operand" "=r") @@ -14221,10 +14104,10 @@ (KF "DI")]) (define_expand "unpack<mode>" - [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "") + [(set (match_operand:<FP128_64> 0 "nonimmediate_operand") (unspec:<FP128_64> - [(match_operand:FMOVE128 1 "register_operand" "") - (match_operand:QI 2 "const_0_to_1_operand" "")] + [(match_operand:FMOVE128 1 "register_operand") + (match_operand:QI 2 "const_0_to_1_operand")] UNSPEC_UNPACK_128BIT))] "FLOAT128_2REG_P (<MODE>mode)" "") @@ -14250,8 +14133,7 @@ operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno); } - [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store") - (set_attr "length" "4")]) + [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store")]) (define_insn_and_split "unpack<mode>_nodm" [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m") @@ -14274,20 +14156,17 @@ operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno); } - [(set_attr "type" "fp,fpstore") - (set_attr "length" "4")]) + [(set_attr "type" "fp,fpstore")]) (define_insn_and_split "pack<mode>" - [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d") + [(set (match_operand:FMOVE128 0 "register_operand" "=&d") (unspec:FMOVE128 - [(match_operand:<FP128_64> 1 "register_operand" "0,d") - (match_operand:<FP128_64> 2 "register_operand" "d,d")] + [(match_operand:<FP128_64> 1 "register_operand" "d") + (match_operand:<FP128_64> 2 "register_operand" "d")] UNSPEC_PACK_128BIT))] "FLOAT128_2REG_P (<MODE>mode)" - "@ - fmr %L0,%2 - #" - "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])" + "#" + "&& reload_completed" [(set (match_dup 3) (match_dup 1)) (set (match_dup 4) (match_dup 2))] { @@ -14300,8 +14179,8 @@ operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi); operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo); } - [(set_attr "type" "fpsimple,fp") - (set_attr "length" "4,8")]) + [(set_attr "type" "fp") + (set_attr "length" "8")]) (define_insn "unpack<mode>" [(set (match_operand:DI 0 "register_operand" "=wa,wa") @@ -14359,7 +14238,7 @@ (match_operand:IEEE128 2 "altivec_register_operand" "v")))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsmulqp %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "div<mode>3" @@ -14391,11 +14270,8 @@ emit_insn (gen_copysign<mode>3_hard (operands[0], operands[1], operands[2])); else - { - rtx tmp = gen_reg_rtx (<MODE>mode); - emit_insn (gen_copysign<mode>3_soft (operands[0], operands[1], - operands[2], tmp)); - } + emit_insn (gen_copysign<mode>3_soft (operands[0], operands[1], + operands[2])); DONE; }) @@ -14414,9 +14290,9 @@ [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") (unspec:IEEE128 [(match_operand:IEEE128 1 "altivec_register_operand" "v") - (match_operand:IEEE128 2 "altivec_register_operand" "v") - (match_operand:IEEE128 3 "altivec_register_operand" "+v")] - UNSPEC_COPYSIGN))] + (match_operand:IEEE128 2 "altivec_register_operand" "v")] + UNSPEC_COPYSIGN)) + (clobber (match_scratch:IEEE128 3 "=&v"))] "!TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xscpsgndp %x3,%x2,%x1\;xxpermdi %x0,%x3,%x1,1" [(set_attr "type" "veccomplex") @@ -14461,7 +14337,7 @@ (match_operand:IEEE128 3 "altivec_register_operand" "0")))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsmaddqp %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "*fms<mode>4_hw" @@ -14473,7 +14349,7 @@ (match_operand:IEEE128 3 "altivec_register_operand" "0"))))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsmsubqp %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "*nfma<mode>4_hw" @@ -14485,7 +14361,7 @@ (match_operand:IEEE128 3 "altivec_register_operand" "0"))))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsnmaddqp %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "*nfms<mode>4_hw" @@ -14498,7 +14374,7 @@ (match_operand:IEEE128 3 "altivec_register_operand" "0")))))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsnmsubqp %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "extend<SFDF:mode><IEEE128:mode>2_hw" @@ -14577,49 +14453,45 @@ (set_attr "length" "8")]) ;; Conversion between IEEE 128-bit and integer types -(define_insn "fix_<mode>di2_hw" - [(set (match_operand:DI 0 "altivec_register_operand" "=v") - (fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] - "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" - "xscvqpsdz %0,%1" - [(set_attr "type" "vecfloat") - (set_attr "size" "128")]) - -(define_insn "fixuns_<mode>di2_hw" - [(set (match_operand:DI 0 "altivec_register_operand" "=v") - (unsigned_fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] - "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" - "xscvqpudz %0,%1" + +;; The fix function for DImode and SImode was declared earlier as a +;; define_expand. It calls into rs6000_expand_float128_convert if we don't +;; have IEEE 128-bit hardware support. QImode and HImode are not provided +;; unless we have the IEEE 128-bit hardware. +;; +;; Unlike the code for converting SFmode/DFmode to QImode/HImode, we don't have +;; to provide a GPR target that used direct move and a conversion in the GPR +;; which works around QImode/HImode not being allowed in vector registers in +;; ISA 2.07 (power8). +(define_insn "fix<uns>_<IEEE128:mode><SDI:mode>2_hw" + [(set (match_operand:SDI 0 "altivec_register_operand" "=v") + (any_fix:SDI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<IEEE128:MODE>mode)" + "xscvqp<su><wd>z %0,%1" [(set_attr "type" "vecfloat") (set_attr "size" "128")]) -(define_insn "fix_<mode>si2_hw" - [(set (match_operand:SI 0 "altivec_register_operand" "=v") - (fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] - "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" - "xscvqpswz %0,%1" +(define_insn "fix<uns>_trunc<IEEE128:mode><QHI:mode>2" + [(set (match_operand:QHI 0 "altivec_register_operand" "=v") + (any_fix:QHI + (match_operand:IEEE128 1 "altivec_register_operand" "v")))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<IEEE128:MODE>mode)" + "xscvqp<su>wz %0,%1" [(set_attr "type" "vecfloat") (set_attr "size" "128")]) -(define_insn "fixuns_<mode>si2_hw" - [(set (match_operand:SI 0 "altivec_register_operand" "=v") - (unsigned_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] - "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" - "xscvqpuwz %0,%1" - [(set_attr "type" "vecfloat") - (set_attr "size" "128")]) - -;; Combiner pattern to prevent moving the result of converting an IEEE 128-bit -;; floating point value to 32-bit integer to GPR in order to save it. -(define_insn_and_split "*fix<uns>_<mode>_mem" - [(set (match_operand:SI 0 "memory_operand" "=Z") - (any_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v"))) - (clobber (match_scratch:SI 2 "=v"))] +;; Combiner patterns to prevent moving the result of converting an IEEE 128-bit +;; floating point value to 8/16/32-bit integer to GPR in order to save it. +(define_insn_and_split "*fix<uns>_trunc<IEEE128:mode><QHSI:mode>2_mem" + [(set (match_operand:QHSI 0 "memory_operand" "=Z") + (any_fix:QHSI + (match_operand:IEEE128 1 "altivec_register_operand" "v"))) + (clobber (match_scratch:QHSI 2 "=v"))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "#" "&& reload_completed" [(set (match_dup 2) - (any_fix:SI (match_dup 1))) + (any_fix:QHSI (match_dup 1))) (set (match_dup 0) (match_dup 2))]) @@ -14645,6 +14517,9 @@ { if (GET_CODE (operands[2]) == SCRATCH) operands[2] = gen_reg_rtx (DImode); + + if (MEM_P (operands[1])) + operands[1] = rs6000_address_for_fpconvert (operands[1]); }) (define_insn_and_split "float<QHI:mode><IEEE128:mode>2" @@ -14708,6 +14583,9 @@ { if (GET_CODE (operands[2]) == SCRATCH) operands[2] = gen_reg_rtx (DImode); + + if (MEM_P (operands[1])) + operands[1] = rs6000_address_for_fpconvert (operands[1]); }) (define_insn_and_split "floatuns<QHI:mode><IEEE128:mode>2" @@ -14742,6 +14620,47 @@ (set_attr "type" "vecfloat") (set_attr "size" "128")]) +;; IEEE 128-bit round to integer built-in functions +(define_insn "floor<mode>2" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unspec:IEEE128 + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] + UNSPEC_FRIM))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" + "xsrqpi 1,%0,%1,3" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + +(define_insn "ceil<mode>2" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unspec:IEEE128 + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] + UNSPEC_FRIP))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" + "xsrqpi 1,%0,%1,2" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + +(define_insn "btrunc<mode>2" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unspec:IEEE128 + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] + UNSPEC_FRIZ))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" + "xsrqpi 1,%0,%1,1" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + +(define_insn "round<mode>2" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unspec:IEEE128 + [(match_operand:IEEE128 1 "altivec_register_operand" "v")] + UNSPEC_FRIN))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" + "xsrqpi 0,%0,%1,0" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + ;; IEEE 128-bit instructions with round to odd semantics (define_insn "add<mode>3_odd" [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") @@ -14773,7 +14692,7 @@ UNSPEC_MUL_ROUND_TO_ODD))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsmulqpo %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "div<mode>3_odd" @@ -14806,7 +14725,7 @@ UNSPEC_FMA_ROUND_TO_ODD))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsmaddqpo %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "*fms<mode>4_odd" @@ -14819,7 +14738,7 @@ UNSPEC_FMA_ROUND_TO_ODD))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsmsubqpo %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "*nfma<mode>4_odd" @@ -14832,7 +14751,7 @@ UNSPEC_FMA_ROUND_TO_ODD)))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsnmaddqpo %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "*nfms<mode>4_odd" @@ -14846,7 +14765,7 @@ UNSPEC_FMA_ROUND_TO_ODD)))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)" "xsnmsubqpo %0,%1,%2" - [(set_attr "type" "vecfloat") + [(set_attr "type" "qmul") (set_attr "size" "128")]) (define_insn "trunc<mode>df2_odd" @@ -14875,6 +14794,5 @@ (include "vsx.md") (include "altivec.md") (include "dfp.md") -(include "paired.md") (include "crypto.md") (include "htm.md")