Hello! We only have to copy registers without upper parts to a pseudo in named patterns (extv, extzv and insv). Nowadays, it is the job of TARGET_LEGITIMATE_COMBINED_INSN target hook to prevent propagation of unwanted hard registers to a combined insn.
So, only check the supported mode in the predicate and let the target hook do its job. 2016-12-30 Uros Bizjak <ubiz...@gmail.com> * config/i386/predicates.md (ext_register_operand): Do not reject registers without upper parts here. * config/i386/i386.md (extv<mode>): Copy registers without upper parts in operand 1 to a pseudo. (extzv<mode>): Ditto. (insv<mode>): Ditto. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. The patch will be committed soon. Uros.
Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 243969) +++ config/i386/i386.md (working copy) @@ -2766,7 +2766,10 @@ if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8) FAIL; - if (! ext_register_operand (operands[1], VOIDmode)) + unsigned int regno = reg_or_subregno (operands[1]); + + /* Be careful to expand only with registers having upper parts. */ + if (regno <= LAST_VIRTUAL_REGISTER && !QI_REGNO_P (regno)) operands[1] = copy_to_reg (operands[1]); }) @@ -2794,7 +2797,10 @@ if (INTVAL (operands[2]) != 8 || INTVAL (operands[3]) != 8) FAIL; - if (! ext_register_operand (operands[1], VOIDmode)) + unsigned int regno = reg_or_subregno (operands[1]); + + /* Be careful to expand only with registers having upper parts. */ + if (regno <= LAST_VIRTUAL_REGISTER && !QI_REGNO_P (regno)) operands[1] = copy_to_reg (operands[1]); }) @@ -2878,11 +2884,14 @@ if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8) FAIL; - dst = operands[0]; - - if (!ext_register_operand (dst, VOIDmode)) - dst = copy_to_reg (dst); + unsigned int regno = reg_or_subregno (operands[0]); + /* Be careful to expand only with registers having upper parts. */ + if (regno <= LAST_VIRTUAL_REGISTER && !QI_REGNO_P (regno)) + dst = copy_to_reg (operands[0]); + else + dst = operands[0]; + emit_insn (gen_insv<mode>_1 (dst, operands[3])); /* Fix up the destination if needed. */ Index: config/i386/predicates.md =================================================================== --- config/i386/predicates.md (revision 243969) +++ config/i386/predicates.md (working copy) @@ -85,21 +85,14 @@ (and (match_code "reg") (match_test "REGNO (op) == FLAGS_REG"))) -;; Match an SI or HImode register for a zero_extract. +;; Match a DI, SI or HImode register for a zero_extract. (define_special_predicate "ext_register_operand" - (match_operand 0 "register_operand") -{ - if ((!TARGET_64BIT || GET_MODE (op) != DImode) - && GET_MODE (op) != SImode && GET_MODE (op) != HImode) - return false; - if (SUBREG_P (op)) - op = SUBREG_REG (op); + (and (match_operand 0 "register_operand") + (ior (and (match_test "TARGET_64BIT") + (match_test "GET_MODE (op) == DImode")) + (match_test "GET_MODE (op) == SImode") + (match_test "GET_MODE (op) == HImode")))) - /* Be careful to accept only registers having upper parts. */ - return (REG_P (op) - && (REGNO (op) > LAST_VIRTUAL_REGISTER || QI_REGNO_P (REGNO (op)))); -}) - ;; Match register operands, but include memory operands for TARGET_SSE_MATH. (define_predicate "register_ssemem_operand" (if_then_else