Users might use explicit arithmetic operations to create a mask and then and it, in a sequence like cond = (bits >> SHIFT) & 1; mask = ~(cond - 1); val &= mask; which will present as a single-bit sign-extract.
Dependening on what combination of XVentanaCondOps and Zbs are available, this will map to the following sequences: - bexti + vt.maskc, if both Zbs and XVentanaCondOps are present - andi + vt.maskc, if only XVentanaCondOps is available and the sign-extract is operating on bits 10:0 (bit 11 can't be reached, as the immediate is sign-extended) - slli + srli + and, otherwise. gcc/ChangeLog: * config/riscv/xventanacondops.md: Recognize SIGN_EXTRACT of a single-bit followed by AND for XVentanaCondOps. Signed-off-by: Philipp Tomsich <philipp.toms...@vrull.eu> --- (no changes since v1) gcc/config/riscv/xventanacondops.md | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/gcc/config/riscv/xventanacondops.md b/gcc/config/riscv/xventanacondops.md index f23058b95b2..a4068e53c13 100644 --- a/gcc/config/riscv/xventanacondops.md +++ b/gcc/config/riscv/xventanacondops.md @@ -74,3 +74,48 @@ [(set (match_dup 5) (match_dup 1)) (set (match_dup 0) (and:X (neg:X (ne:X (match_dup 5) (const_int 0))) (match_dup 4)))]) + +;; Users might use explicit arithmetic operations to create a mask and +;; then and it, in a sequence like +;; cond = (bits >> SHIFT) & 1; +;; mask = ~(cond - 1); +;; val &= mask; +;; which will present as a single-bit sign-extract in the combiner. +;; +;; This will give rise to any of the following cases: +;; - with Zbs and XVentanaCondOps: bexti + vt.maskc +;; - with XVentanaCondOps (but w/o Zbs): +;; - andi + vt.maskc, if the mask is representable in the immediate +;; (which requires extra care due to the immediate +;; being sign-extended) +;; - slli + srli + and +;; - otherwise: slli + srli + and + +;; With Zbb, we have bexti for all possible bits... +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (sign_extract:X (match_operand:X 1 "register_operand") + (const_int 1) + (match_operand 2 "immediate_operand")) + (match_operand:X 3 "register_operand"))) + (clobber (match_operand:X 4 "register_operand"))] + "TARGET_XVENTANACONDOPS && TARGET_ZBS" + [(set (match_dup 4) (zero_extract:X (match_dup 1) (const_int 1) (match_dup 2))) + (set (match_dup 0) (and:X (neg:X (ne:X (match_dup 4) (const_int 0))) + (match_dup 3)))]) + +;; ...whereas RV64I only allows us access to bits 0..10 in a single andi. +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (sign_extract:X (match_operand:X 1 "register_operand") + (const_int 1) + (match_operand 2 "immediate_operand")) + (match_operand:X 3 "register_operand"))) + (clobber (match_operand:X 4 "register_operand"))] + "TARGET_XVENTANACONDOPS && !TARGET_ZBS && (UINTVAL (operands[2]) < 11)" + [(set (match_dup 4) (and:X (match_dup 1) (match_dup 2))) + (set (match_dup 0) (and:X (neg:X (ne:X (match_dup 4) (const_int 0))) + (match_dup 3)))] +{ + operands[2] = GEN_INT(1 << UINTVAL(operands[2])); +}) -- 2.34.1