]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR rtl-optimization/42269 (Extra sign extension instructions generated)
authorRichard Henderson <rth@redhat.com>
Tue, 8 Dec 2009 00:44:28 +0000 (16:44 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 8 Dec 2009 00:44:28 +0000 (16:44 -0800)
        PR rtl-opt/42269
        * combine.c (setup_incoming_promotions): Improve the conditions
        under which we respect the promotions applied.

From-SVN: r155071

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/gcc.c-torture/execute/pr42269-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/alpha/pr42269-1.c [new file with mode: 0644]

index b91b6383faf1d71c67bf694f126691394db02bc0..bcccc3a2bf97c3a9eb600611f267a158a1603269 100644 (file)
@@ -1,3 +1,9 @@
+2009-12-07  Richard Henderson  <rth@redhat.com>
+
+       PR rtl-opt/42269
+       * combine.c (setup_incoming_promotions): Improve the conditions
+       under which we respect the promotions applied.
+
 2009-12-07  Eric Botcazou  <ebotcazou@adacore.com>
 
        * config/sparc/linux.h (ASM_SPEC): Pass -K PIC if -findirect-dispatch.
index 7f3f6da2cea188e71acfa87e3ec4004cc0c434e3..f26b9e50abc841fcea49b9b2b01278348632bf16 100644 (file)
@@ -1377,19 +1377,23 @@ setup_incoming_promotions (rtx first)
 
       /* Eliminate sign extensions in the callee when possible.  Only
          do this when:
-        (a) a mode promotion has occurred;
-        (b) the mode of the register is the same as the mode of
+        (a) A mode promotion has occurred;
+        (b) The mode of the register is the same as the mode of
             the argument as it is passed; and
-        (c) the signedness does not change across any of the promotions; and
-        (d) when no language-level promotions (which we cannot guarantee
+        (c) Either there's no language level extension, or the extension
+            from source to end result is valid.  The later case is true
+            when the signedness of the extensions match, or when the 
+            language level extension is unsigned.  In the later case,
+            a zero extension followed by a sign extension is the same
+            as one big zero extension.
+        (d) When no language-level promotions (which we cannot guarantee
             will have been done by an external caller) are necessary,
             unless we know that this function is only ever called from
             the current compilation unit -- all of whose call sites will
             do the mode1 --> mode2 promotion.  */
       if (mode1 != mode3
           && mode3 == mode4
-          && uns1 == uns3
-         && (mode1 == mode2 || strictly_local))
+         && (mode1 == mode2 || ((uns1 || !uns3) && strictly_local)))
         {
          /* Record that the value was promoted from mode1 to mode3,
             so that any sign extension at the head of the current
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr42269-2.c b/gcc/testsuite/gcc.c-torture/execute/pr42269-2.c
new file mode 100644 (file)
index 0000000..a9410d4
--- /dev/null
@@ -0,0 +1,15 @@
+/* Make sure that language + abi extensions in passing S interoperate.  */
+
+static long long __attribute__((noinline))
+foo (unsigned short s)
+{
+  return (short) s;
+}
+
+unsigned short s = 0xFFFF;
+
+int
+main (void)
+{
+  return foo (s) + 1 != 0;
+}
diff --git a/gcc/testsuite/gcc.target/alpha/pr42269-1.c b/gcc/testsuite/gcc.target/alpha/pr42269-1.c
new file mode 100644 (file)
index 0000000..5d4ef1c
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "addl" } } */
+
+unsigned
+parity (unsigned x)
+{
+  x ^= x >> 16;
+  x ^= x >> 8;
+  x ^= x >> 4;
+  x &= 0xf;
+  return (0x6996 >> x) & 1;
+}