/usr/src/gcc-4.4/debian/patches/pr43323.diff is in gcc-4.4-source 4.4.7-8ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | # DP: Fix PR middle-end/43323 wrong-code for bitfields
This patch fixes PR middle-end/43323, wrong-code for bitfields
and type casts. This is a 4.4 regression, 4.3 and 4.5 work.
For 4.5 the bug was fixed by r148631, Adam Nemet's STRIP_NOPS
conversion patch. This patch backports that patch to 4.4, and
adds the new PR43323 test case.
Bootstrapped and regression tested with all default languages
on {i686,x86_64,sparc64,powerpc64}-unknown-linux and
armv5tel-unknown-linux-gnueabi. Both Adam's original test case
and the new PR43323 one pass with this patch but fail without it.
Ok for 4.4? (I don't have svn write access.)
gcc/
2010-03-13 Mikael Pettersson <mikpe@it.uu.se>
PR middle-end/43323
Backport from mainline:
2009-06-17 Adam Nemet <anemet@caviumnetworks.com>
* tree.h (STRIP_NOPS, STRIP_SIGN_NOPS,
STRIP_USELESS_TYPE_CONVERSION): Use tree_strip_nop_conversions,
tree_strip_sign_nop_conversions and
tree_ssa_strip_useless_type_conversions rather than stripping
the operations here.
(tree_strip_nop_conversions, tree_strip_sign_nop_conversions):
Declare them.
* gimple.h (tree_ssa_strip_useless_type_conversions): Declare it.
* tree-ssa.c (tree_ssa_strip_useless_type_conversions): New function.
* tree.c (tree_nop_conversion, tree_sign_nop_conversion,
tree_strip_nop_conversions, tree_strip_sign_nop_conversions): New
functions.
gcc/testsuite/
2010-03-13 Mikael Pettersson <mikpe@it.uu.se>
PR middle-end/43323
* gcc.c-torture/execute/pr43323.c: New test.
Backport from mainline:
2009-06-17 Adam Nemet <anemet@caviumnetworks.com>
* gcc.c-torture/execute/bitfld-5.c: New test.
diff -rupN a/src/gcc/gimple.h b/src/gcc/gimple.h
--- a/src/gcc/gimple.h 2009-05-18 12:13:43.000000000 +0200
+++ b/src/gcc/gimple.h 2010-03-13 10:59:57.000000000 +0100
@@ -1020,6 +1020,7 @@ extern void gimple_add_to_addresses_take
/* In tree-ssa.c */
extern bool tree_ssa_useless_type_conversion (tree);
+extern tree tree_ssa_strip_useless_type_conversions (tree);
extern bool useless_type_conversion_p (tree, tree);
extern bool types_compatible_p (tree, tree);
diff -rupN a/src/gcc/testsuite/gcc.c-torture/execute/bitfld-5.c b/src/gcc/testsuite/gcc.c-torture/execute/bitfld-5.c
--- a/src/gcc/testsuite/gcc.c-torture/execute/bitfld-5.c 1970-01-01 01:00:00.000000000 +0100
+++ b/src/gcc/testsuite/gcc.c-torture/execute/bitfld-5.c 2010-03-13 10:59:57.000000000 +0100
@@ -0,0 +1,35 @@
+/* See http://gcc.gnu.org/ml/gcc/2009-06/msg00072.html. */
+
+extern void abort (void);
+
+struct s
+{
+ unsigned long long a:2;
+ unsigned long long b:40;
+ unsigned long long c:22;
+};
+
+__attribute__ ((noinline)) void
+g (unsigned long long a, unsigned long long b)
+{
+ asm ("");
+ if (a != b)
+ abort ();
+}
+
+__attribute__ ((noinline)) void
+f (struct s s, unsigned long long b)
+{
+ asm ("");
+ g (((unsigned long long) (s.b-8)) + 8, b);
+}
+
+int
+main ()
+{
+ struct s s = {1, 10, 3};
+ struct s t = {1, 2, 3};
+ f (s, 10);
+ f (t, 0x10000000002);
+ return 0;
+}
diff -rupN a/src/gcc/testsuite/gcc.c-torture/execute/pr43323.c b/src/gcc/testsuite/gcc.c-torture/execute/pr43323.c
--- a/src/gcc/testsuite/gcc.c-torture/execute/pr43323.c 1970-01-01 01:00:00.000000000 +0100
+++ b/src/gcc/testsuite/gcc.c-torture/execute/pr43323.c 2010-03-13 10:59:57.000000000 +0100
@@ -0,0 +1,14 @@
+/* PR middle-end/43323 */
+
+extern void abort (void);
+
+int main()
+{
+ struct { unsigned bar:1; } foo;
+ foo.bar = 0x1;
+ if ((unsigned char)(foo.bar * 0xfe) != 0xfeu)
+ abort ();
+ if ((unsigned char)(foo.bar * 0xff) != 0xffu)
+ abort ();
+ return 0;
+}
diff -rupN a/src/gcc/tree-ssa.c b/src/gcc/tree-ssa.c
--- a/src/gcc/tree-ssa.c 2009-08-03 21:27:32.000000000 +0200
+++ b/src/gcc/tree-ssa.c 2010-03-13 10:59:57.000000000 +0100
@@ -1271,6 +1271,18 @@ tree_ssa_useless_type_conversion (tree e
return false;
}
+/* Strip conversions from EXP according to
+ tree_ssa_useless_type_conversion and return the resulting
+ expression. */
+
+tree
+tree_ssa_strip_useless_type_conversions (tree exp)
+{
+ while (tree_ssa_useless_type_conversion (exp))
+ exp = TREE_OPERAND (exp, 0);
+ return exp;
+}
+
/* Internal helper for walk_use_def_chains. VAR, FN and DATA are as
described in walk_use_def_chains.
diff -rupN a/src/gcc/tree.c b/src/gcc/tree.c
--- a/src/gcc/tree.c 2009-07-20 16:39:32.000000000 +0200
+++ b/src/gcc/tree.c 2010-03-13 10:59:57.000000000 +0100
@@ -9094,6 +9094,79 @@ tree_nonartificial_location (tree exp)
return EXPR_LOCATION (exp);
}
+/* Return true iff conversion in EXP generates no instruction. Mark
+ it inline so that we fully inline into the stripping functions even
+ though we have two uses of this function. */
+
+static inline bool
+tree_nop_conversion (const_tree exp)
+{
+ tree outer_type, inner_type;
+
+ if (!CONVERT_EXPR_P (exp)
+ && TREE_CODE (exp) != NON_LVALUE_EXPR)
+ return false;
+ if (TREE_OPERAND (exp, 0) == error_mark_node)
+ return false;
+
+ outer_type = TREE_TYPE (exp);
+ inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+
+ /* Use precision rather then machine mode when we can, which gives
+ the correct answer even for submode (bit-field) types. */
+ if ((INTEGRAL_TYPE_P (outer_type)
+ || POINTER_TYPE_P (outer_type)
+ || TREE_CODE (outer_type) == OFFSET_TYPE)
+ && (INTEGRAL_TYPE_P (inner_type)
+ || POINTER_TYPE_P (inner_type)
+ || TREE_CODE (inner_type) == OFFSET_TYPE))
+ return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
+
+ /* Otherwise fall back on comparing machine modes (e.g. for
+ aggregate types, floats). */
+ return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
+}
+
+/* Return true iff conversion in EXP generates no instruction. Don't
+ consider conversions changing the signedness. */
+
+static bool
+tree_sign_nop_conversion (const_tree exp)
+{
+ tree outer_type, inner_type;
+
+ if (!tree_nop_conversion (exp))
+ return false;
+
+ outer_type = TREE_TYPE (exp);
+ inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+
+ return (TYPE_UNSIGNED (outer_type) == TYPE_UNSIGNED (inner_type)
+ && POINTER_TYPE_P (outer_type) == POINTER_TYPE_P (inner_type));
+}
+
+/* Strip conversions from EXP according to tree_nop_conversion and
+ return the resulting expression. */
+
+tree
+tree_strip_nop_conversions (tree exp)
+{
+ while (tree_nop_conversion (exp))
+ exp = TREE_OPERAND (exp, 0);
+ return exp;
+}
+
+/* Strip conversions from EXP according to tree_sign_nop_conversion
+ and return the resulting expression. */
+
+tree
+tree_strip_sign_nop_conversions (tree exp)
+{
+ while (tree_sign_nop_conversion (exp))
+ exp = TREE_OPERAND (exp, 0);
+ return exp;
+}
+
/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq
nodes. */
diff -rupN a/src/gcc/tree.h b/src/gcc/tree.h
--- a/src/gcc/tree.h 2009-06-02 09:18:16.000000000 +0200
+++ b/src/gcc/tree.h 2010-03-13 10:59:57.000000000 +0100
@@ -974,30 +974,17 @@ extern void omp_clause_range_check_faile
case NOP_EXPR: \
case CONVERT_EXPR
-/* Given an expression as a tree, strip any NON_LVALUE_EXPRs and NOP_EXPRs
- that don't change the machine mode. */
+/* Given an expression as a tree, strip any conversion that generates
+ no instruction. Accepts both tree and const_tree arguments since
+ we are not modifying the tree itself. */
-#define STRIP_NOPS(EXP) \
- while ((CONVERT_EXPR_P (EXP) \
- || TREE_CODE (EXP) == NON_LVALUE_EXPR) \
- && TREE_OPERAND (EXP, 0) != error_mark_node \
- && (TYPE_MODE (TREE_TYPE (EXP)) \
- == TYPE_MODE (TREE_TYPE (TREE_OPERAND (EXP, 0))))) \
- (EXP) = TREE_OPERAND (EXP, 0)
+#define STRIP_NOPS(EXP) \
+ (EXP) = tree_strip_nop_conversions (CONST_CAST_TREE (EXP))
/* Like STRIP_NOPS, but don't let the signedness change either. */
#define STRIP_SIGN_NOPS(EXP) \
- while ((CONVERT_EXPR_P (EXP) \
- || TREE_CODE (EXP) == NON_LVALUE_EXPR) \
- && TREE_OPERAND (EXP, 0) != error_mark_node \
- && (TYPE_MODE (TREE_TYPE (EXP)) \
- == TYPE_MODE (TREE_TYPE (TREE_OPERAND (EXP, 0)))) \
- && (TYPE_UNSIGNED (TREE_TYPE (EXP)) \
- == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (EXP, 0)))) \
- && (POINTER_TYPE_P (TREE_TYPE (EXP)) \
- == POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (EXP, 0))))) \
- (EXP) = TREE_OPERAND (EXP, 0)
+ (EXP) = tree_strip_sign_nop_conversions (CONST_CAST_TREE (EXP))
/* Like STRIP_NOPS, but don't alter the TREE_TYPE either. */
@@ -1012,9 +999,8 @@ extern void omp_clause_range_check_faile
/* Remove unnecessary type conversions according to
tree_ssa_useless_type_conversion. */
-#define STRIP_USELESS_TYPE_CONVERSION(EXP) \
- while (tree_ssa_useless_type_conversion (EXP)) \
- EXP = TREE_OPERAND (EXP, 0)
+#define STRIP_USELESS_TYPE_CONVERSION(EXP) \
+ (EXP) = tree_ssa_strip_useless_type_conversions (EXP)
/* Nonzero if TYPE represents an integral type. Note that we do not
include COMPLEX types here. Keep these checks in ascending code
@@ -4702,6 +4688,8 @@ extern bool stdarg_p (tree);
extern bool prototype_p (tree);
extern int function_args_count (tree);
extern bool auto_var_in_fn_p (const_tree, const_tree);
+extern tree tree_strip_nop_conversions (tree);
+extern tree tree_strip_sign_nop_conversions (tree);
/* In gimplify.c */
extern tree unshare_expr (tree);
|