mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
Fix PR 93044: extra cast is not removed
In this case we are not removing convert to a bigger size back to the same size (or smaller) if signedness does not match. For an example: ``` signed char _1; ... _1 = *a_4(D); b_5 = (short unsigned int) _1; _2 = (unsigned char) b_5; ``` The inner cast is not needed and can be removed but was not. The match pattern for removing the extra cast is overly complex so decided to add a new case for rather than trying to modify the current if statement here. Committed as approved. Bootstrapped and tested on x86_64-linux-gnu with no regressions. gcc/ChangeLog: PR tree-optimization/93044 * match.pd (nested int casts): A truncation (to the same size or smaller) can always remove the inner cast. gcc/testsuite/ChangeLog: PR tree-optimization/93044 * gcc.dg/tree-ssa/cast-1.c: New test. * gcc.dg/tree-ssa/cast-2.c: New test.
This commit is contained in:
10
gcc/match.pd
10
gcc/match.pd
@@ -4340,6 +4340,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|
||||
&& ! (final_ptr && inside_prec != inter_prec))
|
||||
(ocvt @0))
|
||||
|
||||
/* `(outer:M)(inter:N) a:O`
|
||||
can be converted to `(outer:M) a`
|
||||
if M <= O && N >= O. No matter what signedness of the casts,
|
||||
as the final is either a truncation from the original or just
|
||||
a sign change of the type. */
|
||||
(if (inside_int && inter_int && final_int
|
||||
&& final_prec <= inside_prec
|
||||
&& inter_prec >= inside_prec)
|
||||
(convert @0))
|
||||
|
||||
/* A truncation to an unsigned type (a zero-extension) should be
|
||||
canonicalized as bitwise and of a mask. */
|
||||
(if (GIMPLE /* PR70366: doing this in GENERIC breaks -Wconversion. */
|
||||
|
||||
12
gcc/testsuite/gcc.dg/tree-ssa/cast-1.c
Normal file
12
gcc/testsuite/gcc.dg/tree-ssa/cast-1.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -fdump-tree-optimized" } */
|
||||
|
||||
|
||||
void f(signed char *a, unsigned char *c)
|
||||
{
|
||||
unsigned short b = *a;
|
||||
*c = ((unsigned char)b);
|
||||
}
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "\\(short unsigned int\\)" "optimized"} } */
|
||||
12
gcc/testsuite/gcc.dg/tree-ssa/cast-2.c
Normal file
12
gcc/testsuite/gcc.dg/tree-ssa/cast-2.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -fdump-tree-optimized" } */
|
||||
|
||||
|
||||
void f(signed short *a, unsigned char *c)
|
||||
{
|
||||
unsigned long b = *a;
|
||||
*c = ((unsigned char)b);
|
||||
}
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "\\(long unsigned int\\)" "optimized"} } */
|
||||
Reference in New Issue
Block a user