Re: [PATCH] LoongArch: improve 64-bit bitwise AND operation

Xi Ruoyao <[email protected]> Sun, 02 Aug 2026 04:49:54 +0800
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
On Sat, 2026-08-01 at 05:54 -0600, Jeffrey Law wrote:
> 
> 
> On 7/31/2026 3:47 AM, Ben Shi wrote:
> > It usually costs 4-5 instructions for 64-bit bitwise AND with a large
> > immediate. For some immediates the operation can be simplified to two
> > 'BSTRINS.D' instructions if the immediate satisfies:
> > 1. its top bit is not zero.
> > 2. has two sections of consecutive zero bits.
> > 
> > gcc/ChangeLog:
> > 	* config/loongarch/loongarch.md: Add a new RTL expression
> > 	  (define_insn_and_split "bstrins_bstrins_for_and_imm").
> > 
> > 	* config/loongarch/loongarch.cc: Add a helper function
> > 	  'loongarch_use_bstrins_bstrins_for_and' for the above RTL expression.
> > 
> > 	* config/loongarch/loongarch-protos.h: Add prototype of function
> > 	  'loongarch_use_bstrins_bstrins_for_and'.
> > 
> > 	* testsuite/gcc.target/loongarch/la64/and-large-immediate-opt-2.c:
> > 	  Add a new test.
> You might want ot look at how RISC-V handles this.  There's all kinds of 
> primitives you can use to clear bits and you're usually better using 
> those primitives to synthesize the logical operation during initial 
> expansion without constructing the constant.    For example you can use 
> shifts in pairs or triplets, bit clear style instructions, zero 
> extensions, and-immediate if you have them, rotates in combination with 
> and-immediate, and so-on.  These are composable.
> 
> In general define_insn_and_split is not a great way to solve these 
> problems because it effectively lies about the cost of the patterns it
> matches and it will tend to inhibit further optimizations because of 
> those lies about the cost (and to be clear, I'm not talking about 
> rtx_cost or insn cost, but instead the internal costing done by combine 
> which relies solely on insn counts, particularly with regards to insn 
> splitting).
> 
> I'm not at all familiar with the details of the loongarch port and this 
> should not be considered a review.  Just some advice based on working in 
> this space on the RISC-V port.

I tried doing this in define_expand but then combine insists to
transform the bstrins pair back to materializing the mask.  The reason
is we have

      /* When not optimizing for size, we care more about the cost
         of hot code, and hot code is often in a loop.  If a constant
         operand needs to be forced into a register, we will often be
         able to hoist the constant load out of the loop, so the load
         should not contribute to the cost.  */
      if (speed || loongarch_immediate_operand_p (outer_code, INTVAL (x))) 
        {     
          *total = 0;
          return true; 
        }     

in loongarch_rtx_costs for CONST_INT, i.e. the cost for materializing
the immediate is considered 0 unless optimizing for size...

Perhaps this loongarch_rtx_costs logic is incorrect but I'm not sure.

-- 
Xi Ruoyao <[email protected]>