https://gcc.gnu.org/g:05e70b322d9a5b3eda6f6ac5d255dbe6e1cf0d51
commit r17-1044-g05e70b322d9a5b3eda6f6ac5d255dbe6e1cf0d51 Author: Takayuki 'January June' Suwa <[email protected]> Date: Tue May 26 07:32:43 2026 +0900 xtensa: Optimize 'insvsi' insn pattern if TARGET_DEPBITS is not configured By default, the RTX generation pass conservatively expands bit-field insertion to an insn sequence consisting of the bit mask and shift of the inserted value, the bit-inversion mask of the destination, and finally a logical-OR. However, if the logical-AND operation on an inverted bit-field mask is relatively expensive, it is more advantageous to shift the inserted value without masking it and then follow the idiom '(A & M) | (B & ~M)' -> '((A ^ B) & M) ^ B'. /* example */ struct foo { unsigned int x:10; unsigned int y:11; unsigned int z:11; }; struct foo test0(struct foo a, unsigned int b) { a.x = b; return a; } struct foo test1(struct foo a, unsigned int b) { a.y = b; return a; } ;; before (-Os ; !BITS_BIG_ENDIAN | !TARGET_DEPBITS) test0: entry sp, 32 movi a8, -0x400 ;; = ~0x000003FF extui a3, a3, 0, 10 ;; mask and a2, a2, a8 ;; inverted mask or a2, a2, a3 ;; logical-OR retw.n .literal_position .literal .LC0, -2096129 ;; = ~0x001FFC00 test1: entry sp, 32 l32r a8, .LC0 extui a3, a3, 0, 11 ;; mask slli a3, a3, 10 ;; and a2, a2, a8 ;; inverted mask or a2, a2, a3 ;; logical-OR retw.n ;; after (-Os ; !BITS_BIG_ENDIAN | !TARGET_DEPBITS) test0: entry sp, 32 xor a3, a2, a3 extui a3, a3, 0, 10 ;; mask xor a2, a2, a3 retw.n test1: entry sp, 32 slli a3, a3, 10 ;; bit-position alignment xor a3, a2, a3 extui a3, a3, 10, 11 ;; mask slli a3, a3, 10 ;; xor a2, a2, a3 retw.n gcc/ChangeLog: * config/xtensa/xtensa.md (insvsi_intermal): Rename from 'insvsi'. (insvsi): New expansion pattern that also addresses situations where the DEPBITS machine instruction is unavailable. Diff: --- gcc/config/xtensa/xtensa.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 8354ab250a15..31abbc8aa2d1 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1079,7 +1079,35 @@ (set_attr "mode" "SI") (set_attr "length" "6")]) -(define_insn "insvsi" +(define_expand "insvsi" + [(set (zero_extract:SI (match_operand:SI 0 "register_operand") + (match_operand:SI 1 "extui_fldsz_operand") + (match_operand:SI 2 "const_int_operand")) + (match_operand:SI 3 "register_operand"))] + "" +{ + if (TARGET_DEPBITS) + emit_insn (gen_insvsi_internal (operands[0], operands[1], operands[2], + operands[3])); + else + { + int fldsz = INTVAL (operands[1]), shift; + rtx temp = gen_reg_rtx (SImode), mask; + if (BITS_BIG_ENDIAN) + shift = (32 - (fldsz + INTVAL (operands[2]))) & 0x1f; + else + shift = INTVAL (operands[2]) & 0x1f; + mask = GEN_INT (((1 << fldsz) - 1) << shift); + emit_insn (shift ? gen_ashlsi3 (temp, operands[3], GEN_INT (shift)) + : gen_rtx_SET (temp, operands[3])); + emit_insn (gen_xorsi3 (temp, operands[0], temp)); + emit_insn (gen_andsi3 (temp, temp, force_reg (SImode, mask))); + emit_insn (gen_xorsi3 (operands[0], operands[0], temp)); + } + DONE; +}) + +(define_insn "insvsi_internal" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+a") (match_operand:SI 1 "extui_fldsz_operand" "") (match_operand:SI 2 "const_int_operand" ""))
