OSDN Git Service

gcc/
authorcarlos <carlos@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 30 Jan 2006 19:58:57 +0000 (19:58 +0000)
committercarlos <carlos@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 30 Jan 2006 19:58:57 +0000 (19:58 +0000)
2006-01-30  Carlos O'Donell  <carlos@codesourcery.com>

* optabs.c (prepare_cmp_insn): If unbaised and unsigned then bias
the comparison routine return.

gcc/testsuite/

2006-01-30  Carlos O'Donell  <carlos@codesourcery.com>

* gcc.dg/unsigned-long-compare.c: New test.

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

gcc/ChangeLog
gcc/optabs.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/unsigned-long-compare.c [new file with mode: 0644]

index 8209ec6..ede7d94 100644 (file)
@@ -1,3 +1,8 @@
+2006-01-30  Carlos O'Donell  <carlos@codesourcery.com>
+
+       * optabs.c (prepare_cmp_insn): If unbaised and unsigned then bias
+       the comparison routine return.
+
 2006-01-30  Michael Matz  <matz@suse.de>
 
        * global.c (find_reg): Only evict for global regs.
index 48a3406..bdbb88c 100644 (file)
@@ -3711,18 +3711,24 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
       result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
                                        word_mode, 2, x, mode, y, mode);
 
+      /* There are two kinds of comparison routines. Biased routines
+        return 0/1/2, and unbiased routines return -1/0/1. Other parts
+        of gcc expect that the comparison operation is equivalent
+        to the modified comparison. For signed comparisons compare the 
+        result against 1 in the biased case, and zero in the unbiased
+        case. For unsigned comparisons always compare against 1 after
+        biasing the unbased result by adding 1. This gives us a way to
+        represent LTU. */
       *px = result;
       *pmode = word_mode;
-      if (TARGET_LIB_INT_CMP_BIASED)
-       /* Integer comparison returns a result that must be compared
-          against 1, so that even if we do an unsigned compare
-          afterward, there is still a value that can represent the
-          result "less than".  */
-       *py = const1_rtx;
-      else
+      *py = const1_rtx;
+
+      if (!TARGET_LIB_INT_CMP_BIASED)
        {
-         *py = const0_rtx;
-         *punsignedp = 1;
+         if (*punsignedp)
+           *px = plus_constant (result, 1);  
+         else
+           *py = const0_rtx;
        }
       return;
     }
index 3a6d317..1aea281 100644 (file)
@@ -1,3 +1,7 @@
+2006-01-30  Carlos O'Donell  <carlos@codesourcery.com>
+
+       * gcc.dg/unsigned-long-compare.c: New test.
+
 2006-01-30  Steve Ellcey  <sje@cup.hp.com>
 
        PR testsuite/25318
diff --git a/gcc/testsuite/gcc.dg/unsigned-long-compare.c b/gcc/testsuite/gcc.dg/unsigned-long-compare.c
new file mode 100644 (file)
index 0000000..1c5c69c
--- /dev/null
@@ -0,0 +1,24 @@
+/* Copyright (C) 2006 Free Software Foundation, Inc. */
+/* Contributed by Carlos O'Donell on 2006-01-30 */
+
+/* Test a division corner case where the expression simplifies
+   to a comparison, and the optab expansion is wrong. The optab 
+   expansion emits a function whose return is unbiased and needs
+   adjustment. */
+/* Origin: Carlos O'Donell <carlos@codesourcery.com> */
+/* { dg-do run { target arm-*-*eabi* } } */
+/* { dg-options "" } */
+#include <stdlib.h>
+
+#define BIG_CONSTANT 0xFFFFFFFF80000000ULL
+
+int main (void)
+{
+  unsigned long long OneULL = 1ULL;
+  unsigned long long result;
+
+  result = OneULL / BIG_CONSTANT; 
+  if (result)
+    abort ();
+  exit (0);
+}