[i386] : Fix PR 50762, [4.7 Regression] ICE: in extract_insn, at recog.c:2137 (unrecognizable insn)

Message ID CAFULd4YcvTNhQb1gop5KqjootB_9xSvDXpCNV2JmX3L5KQ_=yQ@mail.gmail.com
State New
Headers show

Commit Message

Uros Bizjak Nov. 10, 2011, 7:14 p.m.

Attached patch fixes corner case with reload, where reload propagates
constant zero into zero_extended LEA instruction, creating invalid

(insn 4 15 52 2 (set (reg/v:SI 59 [ p_60 ])
        (const_int 0 [0])) tt.c:24 64 {*movsi_internal}


(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 ])


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 ])

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  <ubizjak@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).



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")
-	  (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0)))]
+	  (subreg:SI (match_operand:DI 1 "lea_address_operand" "j") 0)))]
   "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")
-	  (match_operand:SI 1 "lea_address_operand" "p")))]
+	  (match_operand:SI 1 "lea_address_operand" "j")))]
   "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;