On Tue, Jul 7, 2026 at 10:38 AM Dusan Stojkovic
<[email protected]> wrote:
>
> This commit expands on the work by Jeff and Milan regarding generating
> more Zbs instructions for RISC-V (PR123884).
>
> For the testcase:
> void foo(unsigned char *data, unsigned int lo_bit) {
>   unsigned int mask = ((1UL << 1) - 1) << lo_bit;
>   *data = (*data & ~mask) | ((1 << lo_bit) & mask)
> }
>
> Without their patch the following assembly would be produced:
> foo(unsigned char*, unsigned int):
>     lbu     a4,0(a0)
>     li      a5,1
>     sllw    a5,a5,a1
>      xor     a5,a4,a5
>      bset    a1,x0,a1
>      and     a5,a5,a1
>      xor     a4,a4,a5
>      sb      a4,0(a0)
>      ret
>
> With this patch it would be transformed into:
> foo(unsigned char*, unsigned int):
>     lbu   a5,0(a0)
>     li    a4,1
>     sllw  a4,a4,a1
>     bclr  a5,a5,a1
>     or    a5,a5,a4
>     sb    a5,0(a0)
>     ret
>
> Thus, in the combine pass arises a new pattern to try:
> Trying 17, 18 -> 22:
>    17: r155:SI=0x1
>    18: r156:DI=sign_extend(r155:SI<<r143:DI#0)
>       REG_DEAD r155:SI
>       REG_DEAD r143:DI
>       REG_EQUAL sign_extend(0x1<<r143:DI#0)
>    22: r159:DI=r152:DI|r156:DI
>       REG_DEAD r156:DI
>       REG_DEAD r152:DI
> Failed to match this instruction:
> (set (reg:DI 159)
>     (ior:DI (sign_extend:DI (ashift:SI (const_int 1 [0x1])
>                 (subreg:QI (reg/v:DI 143 [ lo_bitD.2469 ]) 0)))
>         (reg:DI 152)))
> Splitting with gen_split_161 (bitmanip.md:796)  <- pattern added in PR123884
> Successfully matched this instruction:
> (set (reg:DI 159)
>     (ior:DI (ashift:DI (const_int 1 [0x1])
>             (subreg:QI (reg/v:DI 143 [ lo_bitD.2469 ]) 0))
>         (reg:DI 152)))
> Successfully matched this instruction:
> (set (reg:DI 159)
>     (sign_extend:DI (subreg:SI (reg:DI 159) 0)))
>
> And ultimately generates the following assembly:
> foo:
>         lbu     a5,0(a0)
>         bset    a5,a5,a1
>         sb      a5,0(a0)
>         ret
>
> The match.pd pattern is inspired by Jeff's notes in the bugreport.
>
> Not all testcases added by this patch simplify completely.
> *For rv32 the smaller type to ULL produces poor assembly still
> *For rv64 the UI to UL/ULL are still not clean.
>
> Regression tested on x86, rv64 and rv32.
>
>  2026-07-07  Dusan Stojkovic  <[email protected]>
>
>       PR target/123883
>
> gcc/ChangeLog:
>
>       * match.pd: New pattern.
>
> gcc/testsuite/ChangeLog:
>
>       * gcc.target/riscv/pr123883.c: New test.
>
> Co-authored-by: Jeff Law <[email protected]>

Some fixes:
+/* (T)(1 << x) & (T)(1 << x) -> (T)(1 << x),
+ *  but keep the shift in the wider type to avoid introducing
+ *  undefined behaviour.  */
+(simplify
+ (bit_and:c
+  (convert? (lshift@2 integer_onep@1 @0))
+  (convert? (lshift@3 integer_onep@4 @0)))
+ (with
+  {
+    tree ltype0 = TREE_TYPE (@2);
+    tree ltype1 = TREE_TYPE (@3);
+    tree largertype = ltype0;
+    tree largertypeone = build_one_cst (largertype);
Remove largertypeone.
+  }
+  (if (INTEGRAL_TYPE_P (type)
+       && INTEGRAL_TYPE_P (ltype0)
+       && INTEGRAL_TYPE_P (ltype1)
+       && element_precision (type) <= element_precision (ltype0)
+       && element_precision (type) <= element_precision (ltype1))

So the check should be:
 && element_precision (type) <= element_precision (ltype1)
 && element_precision (ltype1) <= element_precision (ltype0))

Such that  `type <= itype1 <= itype0`

+   (convert:type
+    (lshift:largertype { largertypeone; } @0)))))

Replace `{ largertypeone; }` with `@1`.
Even though INTEGER_CSTs are shared and small integers are kept
around; this makes the code slightly faster as you don't need to look
up the constant.

if you want a future expansion on this, a nice change would remove the
`:c` and add a check for the other way around; that is  `type <=
itype0 <= itype1` and using itype1 for the inner type.

Thanks,
Andrea



>
>
>
>
> CONFIDENTIALITY: The contents of this e-mail are confidential and intended 
> only for the above addressee(s). If you are not the intended recipient, or 
> the person responsible for delivering it to the intended recipient, copying 
> or delivering it to anyone else or using it in any unauthorized manner is 
> prohibited and may be unlawful. If you receive this e-mail by mistake, please 
> notify the sender and the systems administrator at [email protected] 
> immediately.

Reply via email to