diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/builtins.c | 37 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 7 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 12 | ||||
-rw-r--r-- | gcc/genopinit.c | 1 | ||||
-rw-r--r-- | gcc/optabs.c | 1 | ||||
-rw-r--r-- | gcc/optabs.h | 3 |
7 files changed, 64 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 802135b..51c3df3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2007-07-09 Wolfgang Gellerich <gellerich@de.ibm.com> + + * 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_SIGNBIT_SET): New constant. + * config/s390/s390.md (signbit<mode>2): New expander. + 2007-07-09 Richard Guenther <rguenther@suse.de> PR middle-end/32698 diff --git a/gcc/builtins.c b/gcc/builtins.c index 45dea02..c01d4d0 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -240,6 +240,11 @@ static tree do_mpfr_remquo (tree, tree, tree); static tree do_mpfr_lgamma_r (tree, tree, tree); #endif +/* 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". */ @@ -5584,12 +5589,15 @@ expand_builtin_adjust_trampoline (tree exp) return tramp; } -/* Expand a call to the built-in signbit, signbitf, signbitl, signbitd32, - signbitd64, or signbitd128 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 the call EXP 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) { @@ -5598,6 +5606,7 @@ expand_builtin_signbit (tree exp, rtx target) 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)) @@ -5608,6 +5617,21 @@ expand_builtin_signbit (tree exp, rtx target) rmode = TYPE_MODE (TREE_TYPE (exp)); fmt = REAL_MODE_FORMAT (fmode); + arg = builtin_save_expr (arg); + + /* 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) + { + target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); + emit_unop_insn (signbit_insn_code, target, temp, UNKNOWN); + return target; + } + /* For floating point formats without a sign bit, implement signbit as "ARG < 0.0". */ bitpos = fmt->signbit_ro; @@ -5622,7 +5646,6 @@ expand_builtin_signbit (tree exp, rtx target) 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); diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index f95dae2..8336a8f 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -156,6 +156,13 @@ extern enum processor_flags s390_arch_flags; #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 ) + #define S390_TDC_INFINITY (S390_TDC_POSITIVE_INFINITY \ | S390_TDC_NEGATIVE_INFINITY ) diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 3fac610..eb05553 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -2308,6 +2308,18 @@ ; Test data class. ; +(define_expand "signbit<mode>2" + [(set (reg:CCZ CC_REGNUM) + (unspec:CCZ [(match_operand:BFP 1 "register_operand" "f") + (match_dup 2)] + UNSPEC_TDC_INSN)) + (set (match_operand:SI 0 "register_operand" "=d") + (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))] + "TARGET_HARD_FLOAT" +{ + operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET); +}) + (define_expand "isinf<mode>2" [(set (reg:CCZ CC_REGNUM) (unspec:CCZ [(match_operand:BFP 1 "register_operand" "f") diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 0838058..3ed772e 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -177,6 +177,7 @@ static const char * const optabs[] = "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$a2$)", "movmem_optab[$A] = CODE_FOR_$(movmem$a$)", "cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)", "cmpstrn_optab[$A] = CODE_FOR_$(cmpstrn$a$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index 9cd5507..1af4388 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5655,6 +5655,7 @@ init_optabs (void) 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; diff --git a/gcc/optabs.h b/gcc/optabs.h index c1d57f6..aed7a54 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -553,6 +553,9 @@ extern enum insn_code vcondu_gen_code[NUM_MACHINE_MODES]; /* 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]; |