diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 17793bf41a2..db1d1c8d782 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2009-10-28 Paolo Bonzini + + PR rtl-optimization/39715 + * combine.c (simplify_comparison): Use extensions to + widen comparisons. Try an ANDing first. + 2009-10-28 Paolo Bonzini PR rtl-optimization/40741 diff --git a/gcc/combine.c b/gcc/combine.c index 2311755691c..80c538ec490 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -11467,6 +11467,22 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) { int zero_extended; + /* If this is a test for negative, we can make an explicit + test of the sign bit. Test this first so we can use + a paradoxical subreg to extend OP0. */ + + if (op1 == const0_rtx && (code == LT || code == GE) + && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) + { + op0 = simplify_gen_binary (AND, tmode, + gen_lowpart (tmode, op0), + GEN_INT ((HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (mode) + - 1))); + code = (code == LT) ? NE : EQ; + break; + } + /* If the only nonzero bits in OP0 and OP1 are those in the narrower mode and this is an equality or unsigned comparison, we can use the wider mode. Similarly for sign-extended @@ -11497,27 +11513,20 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) XEXP (op0, 0)), gen_lowpart (tmode, XEXP (op0, 1))); - - op0 = gen_lowpart (tmode, op0); - if (zero_extended && CONST_INT_P (op1)) - op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (mode)); - op1 = gen_lowpart (tmode, op1); - break; - } - - /* If this is a test for negative, we can make an explicit - test of the sign bit. */ - - if (op1 == const0_rtx && (code == LT || code == GE) - && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) - { - op0 = simplify_gen_binary (AND, tmode, - gen_lowpart (tmode, op0), - GEN_INT ((HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (mode) - - 1))); - code = (code == LT) ? NE : EQ; - break; + else + { + if (zero_extended) + { + op0 = simplify_gen_unary (ZERO_EXTEND, tmode, op0, mode); + op1 = simplify_gen_unary (ZERO_EXTEND, tmode, op1, mode); + } + else + { + op0 = simplify_gen_unary (SIGN_EXTEND, tmode, op0, mode); + op1 = simplify_gen_unary (SIGN_EXTEND, tmode, op1, mode); + } + break; + } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index aa64dab4ef4..1d59b71e4eb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-10-28 Paolo Bonzini + + PR rtl-optimization/39715 + * gcc.target/arm/thumb-bitfld1.c: New. + 2009-10-28 Paolo Bonzini PR rtl-optimization/40741 diff --git a/gcc/testsuite/gcc.target/arm/thumb-bitfld1.c b/gcc/testsuite/gcc.target/arm/thumb-bitfld1.c new file mode 100644 index 00000000000..7741b4f45f3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb-bitfld1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -mthumb -march=armv5t" } */ + +struct foo +{ + unsigned b31 : 1; + unsigned b30 : 1; + unsigned b29 : 1; + unsigned b28 : 1; + unsigned rest : 28; +}; +foo(a) + struct foo a; +{ + return a.b30; +} + +/* { dg-final { scan-assembler-times "lsl" 1 } } */ +/* { dg-final { scan-assembler-times "lsr" 1 } } */