| Submitter | Chung-Ju Wu |
|---|---|
| Date | Feb. 27, 2013, 4:30 p.m. |
| Message ID | <CADj25HMrO+PJ56EScQuW4irfO1__7M4fAwZy0ocyqgnHt2JhDQ@mail.gmail.com> |
| Download | mbox | patch |
| Permalink | /patch/223648/ |
| State | New |
| Headers | show |
Comments
> In other words, any 32-bit target with 'need_64bit_hwint=yes' in config.gcc > is not able to have benefit from this optimization because it never > passes the condition test. > > > My solution is to use GET_MODE_MASK(mode) to filter out all bits not > in target mode. The following is my patch: The patch is OK for 4.9 once stage #1 is open if it passes bootstrap/regtest. > gcc/ChangLog: > > * gcc/combine.c: Use GET_MODE_MASK() to filter out > unnecessary bits in simplify_compare_const(). This should be * combine.c (simplify_compare_const): Use GET_MODE_MASK to filter out unnecessary bits in the constant power of two case. > > diff --git a/gcc/combine.c b/gcc/combine.c > index 67bd776..8c8cb92 100644 > --- a/gcc/combine.c > +++ b/gcc/combine.c > @@ -10917,8 +10917,8 @@ simplify_compare_const (enum rtx_code code, > rtx op0, rtx *pop1) > && (code == EQ || code == NE || code == GE || code == GEU > > || code == LT || code == LTU) > > && mode_width <= HOST_BITS_PER_WIDE_INT > - && exact_log2 (const_op) >= 0 > - && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op) > + && exact_log2 (const_op & GET_MODE_MASK (mode)) >= 0 > + && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) > (const_op & GET_MODE_MASK (mode))) > { > code = (code == EQ || code == GE || code == GEU ? NE : EQ); > const_op = 0; The line is too long, write && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) (const_op & GET_MODE_MASK (mode))) instead.
Patch
diff --git a/gcc/combine.c b/gcc/combine.c index 67bd776..8c8cb92 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -10917,8 +10917,8 @@ simplify_compare_const (enum rtx_code code, rtx op0, rtx *pop1) && (code == EQ || code == NE || code == GE || code == GEU || code == LT || code == LTU) && mode_width <= HOST_BITS_PER_WIDE_INT - && exact_log2 (const_op) >= 0 - && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op) + && exact_log2 (const_op & GET_MODE_MASK (mode)) >= 0 + && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) (const_op & GET_MODE_MASK (mode))) {
Hi all, I notice the function simplify_compare_const() in gcc/combine.c presents different behavior between 32-bit host machine and 64-bit host machine, causing it to perform different RTL transformation for a 32-bit target. In the function: simplify_compare_const (enum rtx_code code, rtx op0, rtx *pop1), there is a statement "HOST_WIDE_INT const_op = INTVAL (*pop1);". Although it uses "trunc_int_for_mode()" to make const_op present the value for target machine mode, the subsequent condition checking does not filter out the unnecessary bits: if (... ... && exact_log2 (const_op) >= 0 && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op) { ... } For example, given that: op0: (and:SI (reg/v:SI 54) (const_int -2147483648)) *pop1: (const_int -2147483648) Since mode comes from GET_MODE (op0), we know that mode is SImode. on 32-bit host machine, rtx *pop1: (const_int -2147483648 [0x80000000]) const_op: 0x80000000 exact_log2 (const_op): 31 nonzero_bits (op0, mode) : 0x80000000 (unsigned HOST_WIDE_INT) const_op: 0x80000000 on 64-bit host machine, rtx *pop1: (const_int -2147483648 [0xffffffff80000000]) const_op: 0xffffffff80000000 exact_log2 (const_op): -1 nonzero_bits (op0, mode) : 0x0000000080000000 (unsigned HOST_WIDE_INT) const_op: 0xffffffff80000000 In this case, the condition results on 32-bit and 64-bit host machine are different. The result on 64-bit host machine cannot pass the condition test so that we have no chance to do optimization. In other words, any 32-bit target with 'need_64bit_hwint=yes' in config.gcc is not able to have benefit from this optimization because it never passes the condition test. My solution is to use GET_MODE_MASK(mode) to filter out all bits not in target mode. The following is my patch: gcc/ChangLog: * gcc/combine.c: Use GET_MODE_MASK() to filter out unnecessary bits in simplify_compare_const(). code = (code == EQ || code == GE || code == GEU ? NE : EQ); const_op = 0; Any comment for the patch? Thanks, jasonwucj