2007-07-09 Wolfgang Gellerich <gellerich@de.ibm.com>
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 9 Jul 2007 20:12:51 +0000 (20:12 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 9 Jul 2007 20:12:51 +0000 (20:12 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@126495 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h

index 802135b..51c3df3 100644 (file)
@@ -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
index 45dea02..c01d4d0 100644 (file)
@@ -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);
index f95dae2..8336a8f 100644 (file)
@@ -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 )
 
index 3fac610..eb05553 100644 (file)
 ; 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") 
index 0838058..3ed772e 100644 (file)
@@ -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$)",
index 9cd5507..1af4388 100644 (file)
@@ -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;
index c1d57f6..aed7a54 100644 (file)
@@ -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];