From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21196 invoked by alias); 3 Apr 2007 13:35:43 -0000 Received: (qmail 21185 invoked by uid 22791); 3 Apr 2007 13:35:42 -0000 X-Spam-Check-By: sourceware.org Received: from mtagate2.de.ibm.com (HELO mtagate2.de.ibm.com) (195.212.29.151) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 03 Apr 2007 14:35:32 +0100 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate2.de.ibm.com (8.13.8/8.13.8) with ESMTP id l33DZT97115896 for ; Tue, 3 Apr 2007 13:35:29 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v8.3) with ESMTP id l33DZSc92113712 for ; Tue, 3 Apr 2007 15:35:29 +0200 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id l33DZQpU011848 for ; Tue, 3 Apr 2007 15:35:27 +0200 Received: from tuxmkge1.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id l33DZPP6011681; Tue, 3 Apr 2007 15:35:25 +0200 Received: from tuxmkge1.boeblingen.de.ibm.com (localhost.localdomain [127.0.0.1]) by tuxmkge1.boeblingen.de.ibm.com (8.13.1/8.12.11) with ESMTP id l33DZOVk020697; Tue, 3 Apr 2007 15:35:25 +0200 Received: (from gelleric@localhost) by tuxmkge1.boeblingen.de.ibm.com (8.13.1/8.13.1/Submit) id l33DZOvv020696; Tue, 3 Apr 2007 15:35:24 +0200 Date: Tue, 03 Apr 2007 13:35:00 -0000 From: Gellerich Message-Id: <200704031335.l33DZOvv020696@tuxmkge1.boeblingen.de.ibm.com> To: gcc-patches@gcc.gnu.org, gellerich@de.ibm.com Subject: Re: [PATCH] add insn implementing signbit to middle end and s390 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-04/txt/msg00097.txt.bz2 Here is the reworked version. Concerning documentation: I would provide a description for the "Standard Pattern Names..." section in a separate patch. However, I saw that a quite similar pattern named isinf is not mentioned there. Is this pattern intentionally omitted, or should I add a description for that one, too? Regards, Wolfgang --- Dr. Wolfgang Gellerich IBM Deutschland Entwicklung GmbH Schönaicher Strasse 220 71032 Böblingen, Germany Tel. +49 / 7031 / 162598 gellerich@de.ibm.com ======================= IBM Deutschland Entwicklung GmbH Vorsitzender des Aufsichtsrats: Johann Weihen Geschäftsführung: Herbert Kircher Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294 ---------------------------------------------------------------------------------- Changelog: 2007-04-02 Wolfgang Gellerich * optabs.h: Added declaration for signbit_optab. * optabs.c: (init_optabs): Added initialization for signbit_optab. * genoptinit.c (optabs): Added entry for signbit insns. * builtins.c (expand_builtin_signbit): Added code to use a signbit insn, if available. * config/s390/s390.h (S390_TDC_POSITIVE_ZERO):New constant. (S390_TDC_NEGATIVE_ZERO): New constant. (S390_TDC_POSITIVE_NORMALIZED_NUMBER): New constant. (S390_TDC_NEGATIVE_NORMALIZED_NUMBER): New constant. (S390_TDC_POSITIVE_DENORMALIZED_NUMBER): New constant. (S390_TDC_NEGATIVE_DENORMALIZED_NUMBER): New constant. (S390_TDC_POSITIVE_INFINITY): New constant. (S390_TDC_NEGATIVE_INFINITY): New constant. (S390_TDC_POSITIVE_QUIET_NAN): New constant. (S390_TDC_NEGATIVE_QUIET_NAN): New constant. (S390_TDC_POSITIVE_SIGNALING_NAN): New constant. (S390_TDC_NEGATIVE_SIGNALING_NAN): New constant. (S390_TDC_SIGNBIT_SET): New constant. * config/s390/s390.c (s390_canonicalize_comparison): Renamed UNSPEC_CMPINT to UNSPEC_CCU_TO_INT, added a CCU-like optimization for UNSPEC_CCZ_TO_INT. * config/s390/s390.md (signbit_): New expander. (TDC_insn_): New insn. (*ccz_to_int): New insn. (UNSPEC_CMPINT): Renamed to UNSPEC_CCU_TO_INT. (UNSPEC_CCU_TO_INT): New constant, replaces UNSPEC_CMPINT. (UNSPEC_CCZ_TO_INT): New constant. ---------------------------------------------------------------------------------- Index: gcc/optabs.c =================================================================== --- gcc/optabs.c (Revision 123425) +++ gcc/optabs.c (Arbeitskopie) @@ -5584,6 +5584,7 @@ for (i = 0; i < NUM_MACHINE_MODES; i++) { movmem_optab[i] = CODE_FOR_nothing; + signbit_optab[i] = CODE_FOR_nothing; cmpstr_optab[i] = CODE_FOR_nothing; cmpstrn_optab[i] = CODE_FOR_nothing; cmpmem_optab[i] = CODE_FOR_nothing; Index: gcc/optabs.h =================================================================== --- gcc/optabs.h (Revision 123425) +++ gcc/optabs.h (Arbeitskopie) @@ -513,6 +513,9 @@ /* This array records the insn_code of insns to perform block moves. */ extern enum insn_code movmem_optab[NUM_MACHINE_MODES]; +/* This array records the insn_code of insns to implement the signbit function. */ +extern enum insn_code signbit_optab[NUM_MACHINE_MODES]; + /* This array records the insn_code of insns to perform block sets. */ extern enum insn_code setmem_optab[NUM_MACHINE_MODES]; Index: gcc/genopinit.c =================================================================== --- gcc/genopinit.c (Revision 123425) +++ gcc/genopinit.c (Arbeitskopie) @@ -172,6 +172,7 @@ "push_optab->handlers[$A].insn_code = CODE_FOR_$(push$a1$)", "reload_in_optab[$A] = CODE_FOR_$(reload_in$a$)", "reload_out_optab[$A] = CODE_FOR_$(reload_out$a$)", + "signbit_optab[$A] = CODE_FOR_$(signbit_$F$a$)", "movmem_optab[$A] = CODE_FOR_$(movmem$a$)", "cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)", "cmpstrn_optab[$A] = CODE_FOR_$(cmpstrn$a$)", Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (Revision 123425) +++ gcc/builtins.c (Arbeitskopie) @@ -230,6 +230,11 @@ int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t)); static tree do_mpfr_sincos (tree, tree, tree); +/* This array records the insn_code of insns to imlement the signbit + function. */ +enum insn_code signbit_optab[NUM_MACHINE_MODES]; + + /* Return true if NODE should be considered for inline expansion regardless of the optimization level. This means whenever a function is invoked with its "internal" name, which normally contains the prefix "__builtin". */ @@ -5553,11 +5558,15 @@ return tramp; } -/* Expand a call to the built-in signbit, signbitf or signbitl function. - Return NULL_RTX if a normal call should be emitted rather than expanding - the function in-line. EXP is the expression that is a call to the builtin - function; if convenient, the result should be placed in TARGET. */ +/* Expand a call to the built-in signbit, signbitf or signbitl function. The + function first checks whether the back end provides an insn to implement + signbit for the respective mode. If not, it checks whether the floating + point format of the value is such that the sign bit can be extracted. If + that is not the case, the function returns NULL_RTX to indicate that a + normal call should be emitted rather than expanding the function in-line. + EXP is the expression that is a call to the builtin function; if + convenient, the result should be placed in TARGET. */ static rtx expand_builtin_signbit (tree exp, rtx target) { @@ -5566,6 +5575,7 @@ HOST_WIDE_INT hi, lo; tree arg; int word, bitpos; + enum insn_code signbit_insn_code; rtx temp; if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) @@ -5576,6 +5586,28 @@ rmode = TYPE_MODE (TREE_TYPE (exp)); fmt = REAL_MODE_FORMAT (fmode); + /* Expand the argument yielding a RTX expression. */ + temp = expand_normal (arg); + + /* Check if the back end provides an insn that handles signbit for the + argument's mode. */ + signbit_insn_code = signbit_optab [(int) fmode]; + if (signbit_insn_code != CODE_FOR_nothing) + { + rtx result = gen_reg_rtx (SImode); + rtx signbit_insn; + + if (!insn_data[(int) signbit_insn_code].operand[1].predicate (temp, fmode)) + temp = force_reg (fmode, temp); + + signbit_insn = GEN_FCN (signbit_insn_code) (temp, result); + if (signbit_insn == NULL_RTX) + gcc_unreachable (); + emit_insn (signbit_insn); + + return result; + } + /* For floating point formats without a sign bit, implement signbit as "ARG < 0.0". */ bitpos = fmt->signbit_ro; @@ -5590,7 +5622,6 @@ return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL); } - temp = expand_normal (arg); if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD) { imode = int_mode_for_mode (fmode); @@ -5649,7 +5680,6 @@ temp = expand_binop (rmode, and_optab, temp, const1_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN); } - return temp; } Index: gcc/config/s390/s390.c =================================================================== --- gcc/config/s390/s390.c (Revision 123426) +++ gcc/config/s390/s390.c (Arbeitskopie) @@ -700,9 +700,9 @@ } - /* Remove redundant UNSPEC_CMPINT conversions if possible. */ + /* Remove redundant UNSPEC_CCU_TO_INT conversions if possible. */ if (GET_CODE (*op0) == UNSPEC - && XINT (*op0, 1) == UNSPEC_CMPINT + && XINT (*op0, 1) == UNSPEC_CCU_TO_INT && XVECLEN (*op0, 0) == 1 && GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode && GET_CODE (XVECEXP (*op0, 0, 0)) == REG @@ -728,6 +728,32 @@ } } + + /* Remove redundant UNSPEC_CCZ_TO_INT conversions if possible. */ + if (GET_CODE (*op0) == UNSPEC + && XINT (*op0, 1) == UNSPEC_CCZ_TO_INT + && XVECLEN (*op0, 0) == 1 + && GET_MODE (XVECEXP (*op0, 0, 0)) == CCZmode + && GET_CODE (XVECEXP (*op0, 0, 0)) == REG + && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM + && *op1 == const0_rtx) + { + enum rtx_code new_code = UNKNOWN; + switch (*code) + { + case EQ: new_code = EQ; break; + case NE: new_code = NE; break; + default: break; + } + + if (new_code != UNKNOWN) + { + *op0 = XVECEXP (*op0, 0, 0); + *code = new_code; + } + } + + /* Simplify cascaded EQ, NE with const0_rtx. */ if ((*code == NE || *code == EQ) && (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE) @@ -753,6 +779,8 @@ } } + + /* Emit a compare instruction suitable to implement the comparison OP0 CODE OP1. Return the correct condition RTL to be placed in the IF_THEN_ELSE of the conditional branch testing the result. */ Index: gcc/config/s390/s390.h =================================================================== --- gcc/config/s390/s390.h (Revision 123426) +++ gcc/config/s390/s390.h (Arbeitskopie) @@ -146,7 +146,27 @@ /* Frame pointer is not used for debugging. */ #define CAN_DEBUG_WITHOUT_FP +/* Constants needed to control the TEST DATA CLASS (TDC) instruction. */ +#define S390_TDC_POSITIVE_ZERO (1 << 11) +#define S390_TDC_NEGATIVE_ZERO (1 << 10) +#define S390_TDC_POSITIVE_NORMALIZED_NUMBER (1 << 9) +#define S390_TDC_NEGATIVE_NORMALIZED_NUMBER (1 << 8) +#define S390_TDC_POSITIVE_DENORMALIZED_NUMBER (1 << 7) +#define S390_TDC_NEGATIVE_DENORMALIZED_NUMBER (1 << 6) +#define S390_TDC_POSITIVE_INFINITY (1 << 5) +#define S390_TDC_NEGATIVE_INFINITY (1 << 4) +#define S390_TDC_POSITIVE_QUIET_NAN (1 << 3) +#define S390_TDC_NEGATIVE_QUIET_NAN (1 << 2) +#define S390_TDC_POSITIVE_SIGNALING_NAN (1 << 1) +#define S390_TDC_NEGATIVE_SIGNALING_NAN (1 << 0) +#define S390_TDC_SIGNBIT_SET (S390_TDC_NEGATIVE_ZERO \ + | S390_TDC_NEGATIVE_NORMALIZED_NUMBER \ + | S390_TDC_NEGATIVE_DENORMALIZED_NUMBER\ + | S390_TDC_NEGATIVE_INFINITY \ + | S390_TDC_NEGATIVE_QUIET_NAN \ + | S390_TDC_NEGATIVE_SIGNALING_NAN ) + /* In libgcc2, determine target settings as compile-time constants. */ #ifdef IN_LIBGCC2 #undef TARGET_64BIT Index: gcc/config/s390/s390.md =================================================================== --- gcc/config/s390/s390.md (Revision 123426) +++ gcc/config/s390/s390.md (Arbeitskopie) @@ -59,7 +59,8 @@ (define_constants [; Miscellaneous (UNSPEC_ROUND 1) - (UNSPEC_CMPINT 2) + (UNSPEC_CCU_TO_INT 2) + (UNSPEC_CCZ_TO_INT 3) (UNSPEC_ICM 10) ; GOT/PLT and lt-relative accesses @@ -97,11 +98,15 @@ ; Stack Smashing Protector (UNSPEC_SP_SET 700) (UNSPEC_SP_TEST 701) - + ; Copy sign instructions (UNSPEC_COPYSIGN 800) + + ; Test Data Class (TDC) + (UNSPEC_TDC_INSN 900) ]) + ;; ;; UNSPEC_VOLATILE usage ;; @@ -2090,7 +2095,7 @@ (use (reg:SI 0))]) (parallel [(set (match_operand:SI 0 "register_operand" "=d") - (unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_CMPINT)) + (unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_CCU_TO_INT)) (clobber (reg:CC CC_REGNUM))])] "" { @@ -2288,7 +2293,50 @@ [(set_attr "length" "8") (set_attr "type" "vs")]) + + ; +; Test data class. +; + +(define_expand "signbit_" + [(set (reg:CCZ CC_REGNUM) + (unspec:CCZ [(match_operand:BFP 0 "register_operand" "f") + (match_dup 2)] + UNSPEC_TDC_INSN)) + (set (match_operand:SI 1 "register_operand" "=d") + (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))] + "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT" +{ + operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET); +}) + + +; This insn is used to generate all variants of the Test Data Class +; instruction. The insn's first operand is the register to be tested +; and the second one is the bit mask specifying the required test(s). +; +(define_insn "*TDC_insn_" + [(set (reg:CCZ CC_REGNUM) + (unspec:CCZ [(match_operand:BFP 0 "register_operand" "f") + (match_operand:SI 1 "const_int_operand")] UNSPEC_TDC_INSN))] + "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT" + "tcb\t%0,%1" + [(set_attr "op_type" "RXE") + (set_attr "type" "fsimp")]) + + +(define_insn_and_split "*ccz_to_int" + [(set (match_operand:SI 0 "register_operand" "=d") + (unspec:SI [(match_operand:CCZ 1 "register_operand" "0")] + UNSPEC_CCZ_TO_INT))] + "" + "#" + "reload_completed" + [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 28)))]) + + +; ; setmemM instruction pattern(s). ; @@ -2564,7 +2612,7 @@ (define_insn_and_split "cmpint" [(set (match_operand:SI 0 "register_operand" "=d") (unspec:SI [(match_operand:CCU 1 "register_operand" "0")] - UNSPEC_CMPINT)) + UNSPEC_CCU_TO_INT)) (clobber (reg:CC CC_REGNUM))] "" "#" @@ -2577,10 +2625,10 @@ (define_insn_and_split "*cmpint_cc" [(set (reg CC_REGNUM) (compare (unspec:SI [(match_operand:CCU 1 "register_operand" "0")] - UNSPEC_CMPINT) + UNSPEC_CCU_TO_INT) (const_int 0))) (set (match_operand:SI 0 "register_operand" "=d") - (unspec:SI [(match_dup 1)] UNSPEC_CMPINT))] + (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT))] "s390_match_ccmode (insn, CCSmode)" "#" "&& reload_completed" @@ -2597,7 +2645,7 @@ (define_insn_and_split "*cmpint_sign" [(set (match_operand:DI 0 "register_operand" "=d") (sign_extend:DI (unspec:SI [(match_operand:CCU 1 "register_operand" "0")] - UNSPEC_CMPINT))) + UNSPEC_CCU_TO_INT))) (clobber (reg:CC CC_REGNUM))] "TARGET_64BIT" "#" @@ -2611,11 +2659,11 @@ [(set (reg CC_REGNUM) (compare (ashiftrt:DI (ashift:DI (subreg:DI (unspec:SI [(match_operand:CCU 1 "register_operand" "0")] - UNSPEC_CMPINT) 0) + UNSPEC_CCU_TO_INT) 0) (const_int 32)) (const_int 32)) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_CMPINT)))] + (sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT)))] "s390_match_ccmode (insn, CCSmode) && TARGET_64BIT" "#" "&& reload_completed"