Hello! Attached patch fixes corner case with reload, where reload propagates constant zero into zero_extended LEA instruction, creating invalid RTX:
(insn 4 15 52 2 (set (reg/v:SI 59 [ p_60 ]) (const_int 0 [0])) tt.c:24 64 {*movsi_internal} (nil)) ... (insn 29 28 30 3 (set (reg:DI 78) (zero_extend:DI (plus:SI (reg/v:SI 59 [ p_60 ]) (const_int 1 [0x1])))) tt.c:35 250 {*lea_4_zext} (expr_list:REG_DEAD (reg/v:SI 59 [ p_60 ]) (nil))) to: tt.c: In function ‘func_59’: tt.c:48:1: error: unrecognizable insn: (insn 29 28 30 3 (set (reg:DI 0 ax [78]) (zero_extend:DI (const_int 1 [0x1]))) tt.c:35 -1 (expr_list:REG_DEAD (reg/v:SI 59 [ p_60 ]) (nil))) To prevent this, we introduce new address constraint, so a register will be used instead of const_int. The fix uncovered a problem with "lea_address_operand", that was a converted from special predicate to normal one a while ago. For a brief moment, when fixing operand with address constraint, reload requires that the pattern accepts (const int 1). However, contrary to what documentation says, normal predicates don't provide any bypass for const_int operands, leaving mode-less const_int operands out by GET_MODE (op) == mode check. To fix this, attached patch converts lea_address_operand back to special_predicate. It was actually changed by me a couple of months ago to normal predicate, while Reading The (... ehm ...) Fine Manual. A followup patch will axe out wrong define_predicate blurb. For additional joy, I was not able to fix the testcase - some of its variables have to be left uninitialized to trigger this corner case. OTOH, the testcase is too ugly to live and could cause some psychological trauma to innocent readers. I suspect, that this problem triggers more often on x32 which depends on zero_extended addresses for sane code. 2011-11-10 Uros Bizjak <ubiz...@gmail.com> PR target/50762 * config/i386/constraints.md (j): New address constraint. * config/i386/predicates.md (lea_address_operand): Redefine as special predicate. * config/i386/i386.md (*lea_3_zext): Use "j" constraint for operand 1. (*lea_4_zext): Ditto. Patch was tested on x86_64-pc-linux-gnu {,-m32}. I will wait for a day for possible comments before committing the patch to SVN mainline. (Thanks go to Ulrich and Bernd for their help in heroic battle against reload). Uros.
Index: i386.md =================================================================== --- i386.md (revision 181258) +++ i386.md (working copy) @@ -5551,7 +5551,7 @@ (define_insn "*lea_3_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0)))] + (subreg:SI (match_operand:DI 1 "lea_address_operand" "j") 0)))] "TARGET_64BIT" "lea{l}\t{%a1, %k0|%k0, %a1}" [(set_attr "type" "lea") @@ -5560,7 +5560,7 @@ (define_insn "*lea_4_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (match_operand:SI 1 "lea_address_operand" "p")))] + (match_operand:SI 1 "lea_address_operand" "j")))] "TARGET_64BIT" "lea{l}\t{%a1, %k0|%k0, %a1}" [(set_attr "type" "lea") Index: constraints.md =================================================================== --- constraints.md (revision 181258) +++ constraints.md (working copy) @@ -19,7 +19,7 @@ ;;; Unused letters: ;;; B H T W -;;; h jk v +;;; h k v ;; Integer register constraints. ;; It is not necessary to define 'r' here. @@ -127,6 +127,11 @@ (and (not (match_test "TARGET_X32")) (match_operand 0 "memory_operand"))) +(define_address_constraint "j" + "@internal Address operand that can be zero extended in LEA instruction." + (and (not (match_code "const_int")) + (match_operand 0 "address_operand"))) + ;; Integer constant constraints. (define_constraint "I" "Integer constant in the range 0 @dots{} 31, for 32-bit shifts." Index: predicates.md =================================================================== --- predicates.md (revision 181258) +++ predicates.md (working copy) @@ -808,8 +808,9 @@ (match_operand 0 "const0_operand"))) ;; Return true if op if a valid address for LEA, and does not contain -;; a segment override. -(define_predicate "lea_address_operand" +;; a segment override. Defined as a special predicate to allow +;; mode-less const_int operands passed to address_operand. +(define_special_predicate "lea_address_operand" (match_operand 0 "address_operand") { struct ix86_address parts;