在 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

Reply via email to