Hello! Attached patch fixes PR64882, where special predicate address_no_seg_operand allowed operands in DImode, as well as SImode. This resulted in invalid RTX, produced by *lea<mode>:
(insn 60 59 61 3 (set (reg:SI 2 cx [orig:103 D.1909 ] [103]) (plus:DI (reg:DI 0 ax [106]) (reg:DI 1 dx [orig:104 D.1912 ] [104]))) pr64882.c:27 213 {*leasi} (nil)) The patch tightens the predicate to account for non-VOID modes, while still allowing VOIDmode CONST_INTs. Additionally, the patch clears a mess around the mode of the address_operand (luckily, x86 ignores this mode, see ix86_legitimate_address_p) and changes all uses to explicitly pass VOIDmode. Please note that the mode of address_operand predicate means the mode at the pointed location, not the mode of the operand itself. 2015-01-31 Uros Bizjak <ubiz...@gmail.com> PR target/64882 * config/i386/predicates.md (address_no_seg_operand): Reject non-CONST_INT_P operands in invalid mode. 2015-01-31 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.md (*prefetch_prefetchw1): Remove mode of address_operand 0. Rename from *prefetch_prefetchwt1_<mode>. * config/i386/predicates.md (address_no_seg_operand): Call address_operand with VOIDmode. (vsib_address_operand): Ditto. (address_mpx_no_base_operand): Ditto. (address_mpx_no_index_operand): Ditto. testsuite/ChangeLog: 2015-01-31 Uros Bizjak <ubiz...@gmail.com> PR target/64882 * gcc.dg/torture/pr64882.c: New test. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Patch was committed to mainline SVN, and will be backported to other release branches. Uros.
Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 220302) +++ config/i386/i386.md (working copy) @@ -18117,8 +18117,8 @@ (symbol_ref "memory_address_length (operands[0], false)")) (set_attr "memory" "none")]) -(define_insn "*prefetch_prefetchwt1_<mode>" - [(prefetch (match_operand:P 0 "address_operand" "p") +(define_insn "*prefetch_prefetchwt1" + [(prefetch (match_operand 0 "address_operand" "p") (const_int 1) (const_int 2))] "TARGET_PREFETCHWT1" Index: config/i386/predicates.md =================================================================== --- config/i386/predicates.md (revision 220302) +++ config/i386/predicates.md (working copy) @@ -966,11 +966,16 @@ ;; a segment override. Defined as a special predicate to allow ;; mode-less const_int operands pass to address_operand. (define_special_predicate "address_no_seg_operand" - (match_operand 0 "address_operand") + (match_test "address_operand (op, VOIDmode)") { struct ix86_address parts; int ok; + if (!CONST_INT_P (op) + && mode != VOIDmode + && GET_MODE (op) != mode) + return false; + ok = ix86_decompose_address (op, &parts); gcc_assert (ok); return parts.seg == SEG_DEFAULT; @@ -979,7 +984,7 @@ ;; Return true if op if a valid base register, displacement or ;; sum of base register and displacement for VSIB addressing. (define_predicate "vsib_address_operand" - (match_operand 0 "address_operand") + (match_test "address_operand (op, VOIDmode)") { struct ix86_address parts; int ok; @@ -1020,7 +1025,7 @@ ;; Return true if op is valid MPX address operand without base (define_predicate "address_mpx_no_base_operand" - (match_operand 0 "address_operand") + (match_test "address_operand (op, VOIDmode)") { struct ix86_address parts; int ok; @@ -1052,7 +1057,7 @@ ;; Return true if op is valid MPX address operand without index (define_predicate "address_mpx_no_index_operand" - (match_operand 0 "address_operand") + (match_test "address_operand (op, VOIDmode)") { struct ix86_address parts; int ok; Index: testsuite/gcc.dg/torture/pr64882.c =================================================================== --- testsuite/gcc.dg/torture/pr64882.c (revision 0) +++ testsuite/gcc.dg/torture/pr64882.c (working copy) @@ -0,0 +1,33 @@ +/* PR target/64882 */ +/* { dg-do compile } */ + +int a, d, e; +long long b; +static long long *c = &b; + +void +fn1 (short p) +{ +} + +long long +fn2 (long long p1, long long p2) +{ + return (p1 && p1 > 26854775807LL - p2) || p1 < -p2 ? p1 : p1 + p2; +} + +void +fn3 () +{ + long long f; + int g = 3; + int *h = &a; + for (e = 0; e < 2; e++) + { + int *i = &g; + if (!fn2 (*c, 7 < d % (*i)--)) + f = fn2 ((*h <= 0) | b, 5278350700LL); + *h = f; + fn1 (*h); + } +}