On 02/03/15 05:23, Joseph Myers wrote:
On Tue, 3 Feb 2015, Jeff Law wrote:
+/* Given a bit-wise operation performed in mode P1 on operands
+ in some narrower type P2 that feeds an outer masking operation.
+ See if the mask turns off all the bits outside P2, and if so
+ perform the all the operations in P2 and just convert the final
+ result from P1 to P2. */
+(for inner_op (bit_and bit_ior bit_xor)
+ (simplify
+ (bit_and (inner_op (convert @0) (convert @1)) INTEGER_CST@3)
+ (if ((TREE_INT_CST_LOW (@3) & ~GET_MODE_MASK (TYPE_MODE (TREE_TYPE (@0))))
== 0
Are you sure about checking TREE_INT_CST_LOW here? What if the inner type
is wider than HOST_WIDE_INT? (That could occur with bit-fields of type
__int128, for example.) I think the check for what bits are set needs to
be written in a wide-int-safe way - maybe something like tree_int_cst_sgn
(@3) > 0 && tree_int_cst_min_precision (@3, UNSIGNED) <= TYPE_PRECISION
(TREE_TYPE (@1)).
It's a WIP :-)
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1))
+ && TYPE_UNSIGNED (TREE_TYPE (@0)) == TYPE_UNSIGNED (TREE_TYPE (@1))
+ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0)))
+ (convert (bit_and (inner_op @0 @1) (convert @3))))))
I still don't think this is safe. Suppose @0 and @1 are -128 in type
int8_t and @3 is 128 in a wider type and the operation is AND. Then the
original expression has result 128. But if you convert @3 to int8_t you
get -128 and this would result in -128 from the simplified expression.
Agreed.
If the inner values are signed and the mask includes the sign bit of the
inner type, you have to zero-extend to the wider type (e.g. convert the
inner values to unsigned), not sign-extend.
FWIW I did figure out how to get at an expression's type (you can
capture them just like individual operands). This is important because
if we introduce that signed->unsigned conversions, we have to avoid
infinite recursion of the pattern and the easiest way is actually to
look at the various types.
(If the inner values are signed, it's *also* valid to optimize with a mask
where both the sign bit of the inner type and all higher bits are set,
such as a mask of -128 above; in that case, you do need to sign-extend.
If the inner values are unsigned, no check on the mask value is needed at
all as all higher bits in the mask can just be discarded. Both of these
statements only apply for bitwise operations, not arithmetic.)
Noted.
Thanks. I'm going to go through another iteration on this stuff. I'm
less concerned about this particular PR, but the knowledge gained here
looks to be helpful for 45397 which looks like it might be solveable
with match.pd patterns too.
jeff