So the next step in Shreya's work. In the prior patch we used two
shifts to clear bits at the high or low end of an object. In this patch
we use 3 shifts to clear bits on both ends.
Nothing really special here. With mvconst_internal still in the tree
it's of marginal value, though Shreya and I have confirmed the code
coming out of expand looks good. It's just that combine reconstitutes
the operation via mvconst_internal+and which looks cheaper.
When I was playing in this space earlier I definitely saw testsuite
cases that need this case handled to not regress with mvconst_internal
removed.
This has spun in my tester on rv32 and rv64 and it's bootstrap + testing
on my BPI with a mere 23 hours to go. Waiting on pre-commit testing to
render a verdict before moving forward.
Jeff
gcc/
* config/riscv/riscv.cc (synthesize_and): When profitable, use a three
shift sequence to clear bits at both upper and lower bits rather than
synthesizing the constant mask.
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 41a164bc778..358d1ec5d32 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -14562,6 +14562,34 @@ synthesize_and (rtx operands[3])
return true;
}
+ /* If there are all zeros, except for a run of 1s somewhere in the middle
+ of the constant, then this is at worst 3 shifts. */
+ t = INTVAL (operands[2]);
+ if (budget >= 3
+ && consecutive_bits_operand (GEN_INT (t), word_mode)
+ && popcount_hwi (t) > 3)
+ {
+ /* Shift right to clear the low order bits. */
+ int count = ctz_hwi (INTVAL (operands[2]));
+ rtx x = gen_rtx_LSHIFTRT (word_mode, operands[1], GEN_INT (count));
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* Shift left to clear the high order bits. */
+ count += clz_hwi (INTVAL (operands[2])) % BITS_PER_WORD;
+ x = gen_rtx_ASHIFT (word_mode, input, GEN_INT (count));
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* And shift back right to put the bits into position. */
+ count = clz_hwi (INTVAL (operands[2])) % BITS_PER_WORD;
+ x = gen_rtx_LSHIFTRT (word_mode, input, GEN_INT (count));
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
/* If the remaining budget has gone to less than zero, it
forces the value into a register and performs the AND
operation. It returns TRUE to the caller so the caller