在 2025/6/12 6:46, Jeff Law 写道:
On 6/11/25 9:53 AM, Richard Sandiford wrote:
+ into B | (1 << A). */
+ if (GET_CODE (op0) == AND
+ && GET_CODE (XEXP (op0, 0)) == ROTATE
+ && CONST_INT_P (XEXP (XEXP (op0, 0), 0))
+ && INTVAL (XEXP (XEXP (op0, 0), 0)) == -2
+ && GET_CODE (op1) == ASHIFT
+ && CONST_INT_P (XEXP (op1, 0))
+ && INTVAL (XEXP (op1, 0)) == 1
+ && rtx_equal_p (XEXP (XEXP (op0, 0), 1), XEXP (op1, 1))
I think you also need to check !side_effects_p on XEXP (op1, 1),
since we'll be dropping one instance of the expression.
Yes. Thanks for catching this. I likely would have missed it.
+ && rtx_equal_p (XEXP (op0, 1), XEXP (op0, 1)))
Is this last line a typo? It should always be true.
Certainly looks weird. The prior test is checking the shift/rotate
counts are the same. It's not obvious that any other objects need to
be equal in this transformation.
I suppose the main question is whether we can safely apply this for
!SHIFT_COUNT_TRUNCATED targets.
It's probably best to be safe, though it'd be a real surprise to see
the shift count being truncated on a shift, but not on a rotate or
vice-versa
Jaiwei, can you also see if (ior (and (rotate ...)) gets simplified in
the combine dump? During the recent logical op rework I saw multiple
cases where we doing redundant bitmanip operations. It's worth double
checking.
Thanks!
jeff
I checked with an example after apply the new patch, using a case like:
void setBit(char &b, int a) {
char c = 0x1UL << a;
b &= ~c;
b |= c;
}
It seems the (ior (and (rotate ...)) is simplified into (ior (ashift
...)) in the combine dump, it is correct?
(insn 17 14 18 2 (set (reg:DI 146)
(ior:DI (ashift:DI (const_int 1 [0x1])
(subreg:QI (reg:DI 148 [ a ]) 0))
(reg:DI 144 [ *b_7(D) ]))) "/app/example.cpp":5:7 582 {*bsetdi}
(expr_list:REG_DEAD (reg:DI 148 [ a ])
(expr_list:REG_DEAD (reg:DI 144 [ *b_7(D) ])
(nil))))
BR,
Jiawei