summaryrefslogtreecommitdiff
path: root/packages/gcc/gcc-csl-arm/gcc_optab_arm.patch
blob: fa21b26554b7a3562c4e7d3e7abc97e0e7cea4f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
ARM is the only architecture that has a helper function that returns
an unbiased result. This fix is trivial enough that we can show it
doesn't effect any of the other arches. Can we consider this a
regression fix since it used to work until the helper was added :}

Tested with no regressions on x86_64-pc-linux-gnu and arm-none-eabi.

Cheers,
Carlos.
-- 
Carlos O'Donell
CodeSourcery
carlos@codesourcery.com
(650) 331-3385 x716

gcc/

2006-01-27  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-27  Carlos O'Donell  <carlos@codesourcery.com>

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

Index: gcc/optabs.c
===================================================================
--- 1/gcc/optabs.c	(revision 110300)
+++ 2/gcc/optabs.c	(working copy)
@@ -3711,18 +3711,24 @@
       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 unbiased case, and zero in the biased
+	 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: gcc/testsuite/gcc.dg/unsigned-long-compare.c
===================================================================
--- 1/gcc/testsuite/gcc.dg/unsigned-long-compare.c	(revision 0)
+++ 2/gcc/testsuite/gcc.dg/unsigned-long-compare.c	(revision 0)
@@ -0,0 +1,24 @@
+/* Copyright (C) 2006 Free Software Foundation, Inc. */
+/* Contributed by Carlos O'Donell on 2006-01-27 */
+
+/* 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);
+}