[PATCH, i386, take 2]: Rewrite LEA handling (was:Re: PATCH [10/n] X32: Support x32 LEA insns)
Uros Bizjak
ubizjak@gmail.com
Mon Jul 25 21:16:00 GMT 2011
On Mon, Jul 25, 2011 at 3:30 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> Attached patch implements -fpic handling for x32. In x32 mode, we now
>> use x86_64_general_operand and corresponding "e" constraints for adds
>> in SImode, since it looks that invalid addresses can only be generated
>> through adds. This avoids a whole bunch of new predicates and
>> constraints.
> X32 glibc is miscompiled:
>
> CPP='/export/build/gnu/gcc-x32/release/usr/gcc-4.7.0-x32/bin/gcc -mx32
> -E -x c-header'
> /export/build/gnu/glibc-x32/build-x86_64-linux/elf/ld-linux-x32.so.2
> --library-path /export/build/gnu/glibc-x32/build-x86_64-linux:/export/build/gnu/glibc-x32/build-x86_64-linux/math:/export/build/gnu/glibc-x32/build-x86_64-linux/elf:/export/build/gnu/glibc-x32/build-x86_64-linux/dlfcn:/export/build/gnu/glibc-x32/build-x86_64-linux/nss:/export/build/gnu/glibc-x32/build-x86_64-linux/nis:/export/build/gnu/glibc-x32/build-x86_64-linux/rt:/export/build/gnu/glibc-x32/build-x86_64-linux/resolv:/export/build/gnu/glibc-x32/build-x86_64-linux/crypt:/export/build/gnu/glibc-x32/build-x86_64-linux/nptl
> /export/build/gnu/glibc-x32/build-x86_64-linux/sunrpc/rpcgen -Y
> ../scripts -h rpcsvc/yppasswd.x -o
> /export/build/gnu/glibc-x32/build-x86_64-linux/sunrpc/rpcsvc/yppasswd.T
> make[5]: *** [/export/build/gnu/glibc-x32/build-x86_64-linux/sunrpc/rpcsvc/yppasswd.stmp]
> Segmentation fault (core dumped)
>
> Some LEA patterns are wrong for x32. I will investigate.
We have to prevent symbols from entering general_operand predicated
SImode operands. Fortunatelly, x86_64_general_operand works OK for
x32, while both for i686 and x86_64 are unaffected due to early bypass
(i686) and due to the fact that all symbols are DImode (x86_64).
2011-07-25 Uros Bizjak <ubizjak@gmail.com>
H.J. Lu <hongjiu.lu@intel.com>
PR target/47381
PR target/49832
PR target/49833
* config/i386/i386.md (i): Change SImode attribute to "e".
(g): Change SImode attribute to "rme".
(di): Change SImode attribute to "nF".
(general_operand): Change SImode attribute to x86_64_general_operand.
(general_szext_operand): Change SImode attribute to
x86_64_szext_general_operand.
(immediate_operand): Change SImode attribute to
x86_64_immediate_operand-
(*movdi_internal_rex64): Remove mode from pic_32bit_operand check.
(*movsi_internal): Ditto. Use "e" constraint in alternative 2.
(*lea_1): Use SWI48 mode iterator.
(*lea_1_zext): New insn pattern.
(*add<mode>1): Use x86_64_general_operand predicate for operand 2.
Update operand constraints.
(addsi_1_zext): Ditto.
(*add<mode>2): Ditto.
(*addsi_3_zext): Ditto.
(*subsi_1_zext): Ditto.
(*subsi_2_zext): Ditto.
(*subsi_3_zext): Ditto.
(*addsi3_carry_zext): Ditto.
(*<plusminus_insn>si3_zext_cc_overflow): Ditto.
(*mulsi3_1_zext): Ditto.
(*andsi_1): Ditto.
(*andsi_1_zext): Ditto.
(*andsi_2_zext): Ditto.
(*<any_or:code>si_1_zext): Ditto.
(*<any_or:code>si_2_zext): Ditto.
(*test<mode>_1): Use <general_operand> predicate for operand 1.
(*and<mode>_2): Ditto.
(add->lea splitter): Check operand modes in insn constraint. Extend
operands less than SImode wide to SImode.
(add->lea zext splitter): Do not extend input operands to DImode.
(*lea_general_1): Handle only QImode and HImode operands.
(*lea_general_2): Ditto.
(*lea_general_3): Ditto.
(*lea_general_1_zext): Remove.
(*lea_general_2_zext): Ditto.
(*lea_general_3_zext): Ditto.
(*lea_general_4): Check operand modes in insn constraint. Extend
operands less than SImode wide to SImode.
(ashift->lea splitter): Ditto.
* config/i386/i386.c (ix86_print_operand_address): Print address
registers with 'q' modifier on 64bit targets.
* config/i386/predicates.md (pic_32bit_opreand): Define as special
predicate. Reject non-SI and non-DI modes.
Bootstrapped and regression ested on x86_64-pc-linux-gnu {,-m32}.
Uros.
-------------- next part --------------
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md (revision 176748)
+++ config/i386/i386.md (working copy)
@@ -861,13 +861,13 @@
(define_mode_attr r [(QI "q") (HI "r") (SI "r") (DI "r")])
;; Immediate operand constraint for integer modes.
-(define_mode_attr i [(QI "n") (HI "n") (SI "i") (DI "e")])
+(define_mode_attr i [(QI "n") (HI "n") (SI "e") (DI "e")])
;; General operand constraint for word modes.
-(define_mode_attr g [(QI "qmn") (HI "rmn") (SI "g") (DI "rme")])
+(define_mode_attr g [(QI "qmn") (HI "rmn") (SI "rme") (DI "rme")])
;; Immediate operand constraint for double integer modes.
-(define_mode_attr di [(SI "iF") (DI "e")])
+(define_mode_attr di [(SI "nF") (DI "e")])
;; Immediate operand constraint for shifts.
(define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")])
@@ -876,7 +876,7 @@
(define_mode_attr general_operand
[(QI "general_operand")
(HI "general_operand")
- (SI "general_operand")
+ (SI "x86_64_general_operand")
(DI "x86_64_general_operand")
(TI "x86_64_general_operand")])
@@ -884,14 +884,14 @@
(define_mode_attr general_szext_operand
[(QI "general_operand")
(HI "general_operand")
- (SI "general_operand")
+ (SI "x86_64_szext_general_operand")
(DI "x86_64_szext_general_operand")])
;; Immediate operand predicate for integer modes.
(define_mode_attr immediate_operand
[(QI "immediate_operand")
(HI "immediate_operand")
- (SI "immediate_operand")
+ (SI "x86_64_immediate_operand")
(DI "x86_64_immediate_operand")])
;; Nonmemory operand predicate for integer modes.
@@ -2039,7 +2039,7 @@
(const_string "ssemov")
(eq_attr "alternative" "16,17")
(const_string "ssecvt")
- (match_operand:DI 1 "pic_32bit_operand" "")
+ (match_operand 1 "pic_32bit_operand" "")
(const_string "lea")
]
(const_string "imov")))
@@ -2184,7 +2184,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand"
"=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x")
(match_operand:SI 1 "general_operand"
- "g ,ri,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m "))]
+ "g ,re,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m "))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
@@ -2232,7 +2232,7 @@
(const_string "sselog1")
(eq_attr "alternative" "7,8,9,10,11")
(const_string "ssemov")
- (match_operand:DI 1 "pic_32bit_operand" "")
+ (match_operand 1 "pic_32bit_operand" "")
(const_string "lea")
]
(const_string "imov")))
@@ -5425,13 +5425,22 @@
(set_attr "mode" "QI")])
(define_insn "*lea_1"
- [(set (match_operand:P 0 "register_operand" "=r")
- (match_operand:P 1 "no_seg_address_operand" "p"))]
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (match_operand:SWI48 1 "no_seg_address_operand" "p"))]
""
"lea{<imodesuffix>}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "lea")
(set_attr "mode" "<MODE>")])
+(define_insn "*lea_1_zext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (match_operand:SI 1 "no_seg_address_operand" "p")))]
+ "TARGET_64BIT"
+ "lea{l}\t{%a1, %k0|%k0, %a1}"
+ [(set_attr "type" "lea")
+ (set_attr "mode" "SI")])
+
(define_insn "*lea_2"
[(set (match_operand:SI 0 "register_operand" "=r")
(subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
@@ -5453,7 +5462,7 @@
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r")
(plus:SWI48
(match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r")
- (match_operand:SWI48 2 "<general_operand>" "<g>,r<i>,0,l<i>")))
+ (match_operand:SWI48 2 "x86_64_general_operand" "rme,re,0,le")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
{
@@ -5512,7 +5521,7 @@
[(set (match_operand:DI 0 "register_operand" "=r,r,r")
(zero_extend:DI
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r")
- (match_operand:SI 2 "general_operand" "g,0,li"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rme,0,le"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
{
@@ -5794,39 +5803,36 @@
(const_string "none")))
(set_attr "mode" "QI")])
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert add to the lea pattern to avoid flags dependency.
(define_split
[(set (match_operand 0 "register_operand" "")
(plus (match_operand 1 "register_operand" "")
(match_operand 2 "nonmemory_operand" "")))
(clobber (reg:CC FLAGS_REG))]
- "reload_completed && ix86_lea_for_add_ok (insn, operands)"
+ "GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && (GET_MODE (operands[0]) == GET_MODE (operands[2])
+ || GET_MODE (operands[2]) == VOIDmode)
+ && reload_completed && ix86_lea_for_add_ok (insn, operands)"
[(const_int 0)]
{
- rtx pat;
enum machine_mode mode = GET_MODE (operands[0]);
-
- /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
- may confuse gen_lowpart. */
- if (mode != Pmode)
- {
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_lowpart (Pmode, operands[2]);
- }
-
- pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
+ rtx pat;
if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
- operands[0] = gen_lowpart (SImode, operands[0]);
+ {
+ mode = SImode;
+ operands[0] = gen_lowpart (mode, operands[0]);
+ operands[1] = gen_lowpart (mode, operands[1]);
+ operands[2] = gen_lowpart (mode, operands[2]);
+ }
- if (TARGET_64BIT && mode != Pmode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
+ pat = gen_rtx_PLUS (mode, operands[1], operands[2]);
emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
DONE;
})
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert add to the lea pattern to avoid flags dependency.
;; ??? This pattern handles immediate operands that do not satisfy immediate
;; operand predicate (TARGET_LEGITIMATE_CONSTANT_P) in the previous pattern.
(define_split
@@ -5839,7 +5845,7 @@
[(set (match_dup 0)
(plus:DI (match_dup 1) (match_dup 2)))])
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert add to the lea pattern to avoid flags dependency.
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI
@@ -5849,11 +5855,7 @@
"TARGET_64BIT && reload_completed
&& ix86_lea_for_add_ok (insn, operands)"
[(set (match_dup 0)
- (zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
-{
- operands[1] = gen_lowpart (DImode, operands[1]);
- operands[2] = gen_lowpart (DImode, operands[2]);
-})
+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))])
(define_insn "*add<mode>_2"
[(set (reg FLAGS_REG)
@@ -5901,7 +5903,7 @@
[(set (reg FLAGS_REG)
(compare
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 2 "x86_64_general_operand" "rme"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
@@ -5979,7 +5981,7 @@
(define_insn "*addsi_3_zext"
[(set (reg FLAGS_REG)
(compare
- (neg:SI (match_operand:SI 2 "general_operand" "g"))
+ (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rme"))
(match_operand:SI 1 "nonimmediate_operand" "%0")))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
@@ -6233,7 +6235,7 @@
[(set_attr "type" "alu")
(set_attr "mode" "QI")])
-;; The lea patterns for non-Pmodes needs to be matched by
+;; The lea patterns for modes less than 32 bits need to be matched by
;; several insns converted to real lea by splitters.
(define_insn_and_split "*lea_general_1"
@@ -6241,8 +6243,7 @@
(plus (plus (match_operand 1 "index_register_operand" "l")
(match_operand 2 "register_operand" "r"))
(match_operand 3 "immediate_operand" "i")))]
- "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
- || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
+ "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
&& (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])
&& GET_MODE (operands[0]) == GET_MODE (operands[2])
@@ -6252,53 +6253,30 @@
"&& reload_completed"
[(const_int 0)]
{
+ enum machine_mode mode = SImode;
rtx pat;
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_lowpart (Pmode, operands[2]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
- pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
+
+ operands[0] = gen_lowpart (mode, operands[0]);
+ operands[1] = gen_lowpart (mode, operands[1]);
+ operands[2] = gen_lowpart (mode, operands[2]);
+ operands[3] = gen_lowpart (mode, operands[3]);
+
+ pat = gen_rtx_PLUS (mode, gen_rtx_PLUS (mode, operands[1], operands[2]),
operands[3]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
+
emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
DONE;
}
[(set_attr "type" "lea")
(set_attr "mode" "SI")])
-(define_insn_and_split "*lea_general_1_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (plus:SI (plus:SI
- (match_operand:SI 1 "index_register_operand" "l")
- (match_operand:SI 2 "register_operand" "r"))
- (match_operand:SI 3 "immediate_operand" "i"))))]
- "TARGET_64BIT"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1)
- (match_dup 2))
- (match_dup 3)) 0)))]
-{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_lowpart (Pmode, operands[2]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
-}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
-
(define_insn_and_split "*lea_general_2"
[(set (match_operand 0 "register_operand" "=r")
(plus (mult (match_operand 1 "index_register_operand" "l")
(match_operand 2 "const248_operand" "i"))
(match_operand 3 "nonmemory_operand" "ri")))]
- "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
- || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
- && (!TARGET_PARTIAL_REG_STALL
- || GET_MODE (operands[0]) == SImode
- || optimize_function_for_size_p (cfun))
+ "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+ && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])
&& (GET_MODE (operands[0]) == GET_MODE (operands[3])
|| GET_MODE (operands[3]) == VOIDmode)"
@@ -6306,110 +6284,68 @@
"&& reload_completed"
[(const_int 0)]
{
+ enum machine_mode mode = SImode;
rtx pat;
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
- pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
- operands[3]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
+
+ operands[0] = gen_lowpart (mode, operands[0]);
+ operands[1] = gen_lowpart (mode, operands[1]);
+ operands[3] = gen_lowpart (mode, operands[3]);
+
+ pat = gen_rtx_PLUS (mode, gen_rtx_MULT (mode, operands[1], operands[2]),
+ operands[3]);
+
emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
DONE;
}
[(set_attr "type" "lea")
(set_attr "mode" "SI")])
-(define_insn_and_split "*lea_general_2_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (plus:SI (mult:SI
- (match_operand:SI 1 "index_register_operand" "l")
- (match_operand:SI 2 "const248_operand" "n"))
- (match_operand:SI 3 "nonmemory_operand" "ri"))))]
- "TARGET_64BIT"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1)
- (match_dup 2))
- (match_dup 3)) 0)))]
-{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
-}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
-
(define_insn_and_split "*lea_general_3"
[(set (match_operand 0 "register_operand" "=r")
(plus (plus (mult (match_operand 1 "index_register_operand" "l")
(match_operand 2 "const248_operand" "i"))
(match_operand 3 "register_operand" "r"))
(match_operand 4 "immediate_operand" "i")))]
- "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
- || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
- && (!TARGET_PARTIAL_REG_STALL
- || GET_MODE (operands[0]) == SImode
- || optimize_function_for_size_p (cfun))
+ "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+ && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])
&& GET_MODE (operands[0]) == GET_MODE (operands[3])"
"#"
"&& reload_completed"
[(const_int 0)]
{
+ enum machine_mode mode = SImode;
rtx pat;
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
- operands[4] = gen_lowpart (Pmode, operands[4]);
- pat = gen_rtx_PLUS (Pmode,
- gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
- operands[2]),
+
+ operands[0] = gen_lowpart (mode, operands[0]);
+ operands[1] = gen_lowpart (mode, operands[1]);
+ operands[3] = gen_lowpart (mode, operands[3]);
+ operands[4] = gen_lowpart (mode, operands[4]);
+
+ pat = gen_rtx_PLUS (mode,
+ gen_rtx_PLUS (mode,
+ gen_rtx_MULT (mode, operands[1],
+ operands[2]),
operands[3]),
operands[4]);
- if (Pmode != SImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
+
emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
DONE;
}
[(set_attr "type" "lea")
(set_attr "mode" "SI")])
-(define_insn_and_split "*lea_general_3_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (plus:SI (plus:SI
- (mult:SI
- (match_operand:SI 1 "index_register_operand" "l")
- (match_operand:SI 2 "const248_operand" "n"))
- (match_operand:SI 3 "register_operand" "r"))
- (match_operand:SI 4 "immediate_operand" "i"))))]
- "TARGET_64BIT"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1)
- (match_dup 2))
- (match_dup 3))
- (match_dup 4)) 0)))]
-{
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[3] = gen_lowpart (Pmode, operands[3]);
- operands[4] = gen_lowpart (Pmode, operands[4]);
-}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
-
(define_insn_and_split "*lea_general_4"
- [(set (match_operand:SWI 0 "register_operand" "=r")
- (any_or:SWI (ashift:SWI (match_operand:SWI 1 "index_register_operand" "l")
- (match_operand:SWI 2 "const_int_operand" "n"))
- (match_operand 3 "const_int_operand" "n")))]
- "(<MODE>mode == DImode
- || <MODE>mode == SImode
- || !TARGET_PARTIAL_REG_STALL
- || optimize_function_for_size_p (cfun))
+ [(set (match_operand 0 "register_operand" "=r")
+ (any_or (ashift
+ (match_operand 1 "index_register_operand" "l")
+ (match_operand 2 "const_int_operand" "n"))
+ (match_operand 3 "const_int_operand" "n")))]
+ "(((GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+ && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)))
+ || GET_MODE (operands[0]) == SImode
+ || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
&& ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) - 1 < 3
&& ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
< ((unsigned HOST_WIDE_INT) 1 << INTVAL (operands[2])))"
@@ -6417,23 +6353,29 @@
"&& reload_completed"
[(const_int 0)]
{
+ enum machine_mode mode = GET_MODE (operands[0]);
rtx pat;
- if (<MODE>mode != DImode)
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (Pmode, operands[1]);
+
+ if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
+ {
+ mode = SImode;
+ operands[0] = gen_lowpart (mode, operands[0]);
+ operands[1] = gen_lowpart (mode, operands[1]);
+ }
+
operands[2] = GEN_INT (1 << INTVAL (operands[2]));
- pat = plus_constant (gen_rtx_MULT (Pmode, operands[1], operands[2]),
+
+ pat = plus_constant (gen_rtx_MULT (mode, operands[1], operands[2]),
INTVAL (operands[3]));
- if (Pmode != SImode && <MODE>mode != DImode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
+
emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
DONE;
}
[(set_attr "type" "lea")
(set (attr "mode")
- (if_then_else (eq (symbol_ref "<MODE>mode == DImode") (const_int 0))
- (const_string "SI")
- (const_string "DI")))])
+ (if_then_else (match_operand:DI 0 "" "")
+ (const_string "DI")
+ (const_string "SI")))])
;; Subtract instructions
@@ -6481,7 +6423,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "general_operand" "g"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rme"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sub{l}\t{%2, %k0|%k0, %2}"
@@ -6518,7 +6460,7 @@
[(set (reg FLAGS_REG)
(compare
(minus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 2 "x86_64_general_operand" "rme"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
@@ -6545,7 +6487,7 @@
(define_insn "*subsi_3_zext"
[(set (reg FLAGS_REG)
(compare (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "general_operand" "g")))
+ (match_operand:SI 2 "x86_64_general_operand" "rme")))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_dup 1)
@@ -6592,7 +6534,7 @@
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
(plus:SI (match_operator 3 "ix86_carry_flag_operator"
[(reg FLAGS_REG) (const_int 0)])
- (match_operand:SI 2 "general_operand" "g")))))
+ (match_operand:SI 2 "x86_64_general_operand" "rme")))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
"adc{l}\t{%2, %k0|%k0, %2}"
@@ -6607,7 +6549,7 @@
(minus:SI (match_operand:SI 1 "register_operand" "0")
(plus:SI (match_operator 3 "ix86_carry_flag_operator"
[(reg FLAGS_REG) (const_int 0)])
- (match_operand:SI 2 "general_operand" "g")))))
+ (match_operand:SI 2 "x86_64_general_operand" "rme")))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
"sbb{l}\t{%2, %k0|%k0, %2}"
@@ -6661,7 +6603,7 @@
(compare:CCC
(plusminus:SI
(match_operand:SI 1 "nonimmediate_operand" "<comm>0")
- (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 2 "x86_64_general_operand" "rme"))
(match_dup 1)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))]
@@ -6748,7 +6690,7 @@
[(set (match_operand:DI 0 "register_operand" "=r,r,r")
(zero_extend:DI
(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
- (match_operand:SI 2 "general_operand" "K,i,mr"))))
+ (match_operand:SI 2 "x86_64_general_operand" "K,e,mr"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& !(MEM_P (operands[1]) && MEM_P (operands[2]))"
@@ -7440,7 +7382,7 @@
(compare
(and:SWI124
(match_operand:SWI124 0 "nonimmediate_operand" "%!*a,<r>,<r>m")
- (match_operand:SWI124 1 "general_operand" "<i>,<i>,<r><i>"))
+ (match_operand:SWI124 1 "<general_operand>" "<i>,<i>,<r><i>"))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))"
@@ -7730,7 +7672,7 @@
(define_insn "*andsi_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r")
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm")
- (match_operand:SI 2 "general_operand" "ri,rm,L")))
+ (match_operand:SI 2 "x86_64_general_operand" "re,rm,L")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (AND, SImode, operands)"
{
@@ -7777,7 +7719,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "g"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rme"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
"and{l}\t{%2, %k0|%k0, %2}"
@@ -7925,7 +7867,7 @@
[(set (reg FLAGS_REG)
(compare (and:SWI124
(match_operand:SWI124 1 "nonimmediate_operand" "%0,0")
- (match_operand:SWI124 2 "general_operand" "<g>,<r><i>"))
+ (match_operand:SWI124 2 "<general_operand>" "<g>,<r><i>"))
(const_int 0)))
(set (match_operand:SWI124 0 "nonimmediate_operand" "=<r>,<r>m")
(and:SWI124 (match_dup 1) (match_dup 2)))]
@@ -7940,7 +7882,7 @@
[(set (reg FLAGS_REG)
(compare (and:SI
(match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 2 "x86_64_general_operand" "rme"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
@@ -8157,7 +8099,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "g"))))
+ (match_operand:SI 2 "x86_64_general_operand" "rme"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
"<logic>{l}\t{%2, %k0|%k0, %2}"
@@ -8205,7 +8147,7 @@
(define_insn "*<code>si_2_zext"
[(set (reg FLAGS_REG)
(compare (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
- (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 2 "x86_64_general_operand" "rme"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (any_or:SI (match_dup 1) (match_dup 2))))]
@@ -9395,36 +9337,36 @@
(const_string "*")))
(set_attr "mode" "QI")])
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert ashift to the lea pattern to avoid flags dependency.
(define_split
[(set (match_operand 0 "register_operand" "")
(ashift (match_operand 1 "index_register_operand" "")
(match_operand:QI 2 "const_int_operand" "")))
(clobber (reg:CC FLAGS_REG))]
- "reload_completed
+ "GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && reload_completed
&& true_regnum (operands[0]) != true_regnum (operands[1])"
[(const_int 0)]
{
- rtx pat;
enum machine_mode mode = GET_MODE (operands[0]);
-
- if (mode != Pmode)
- operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
-
- pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
+ rtx pat;
if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
- operands[0] = gen_lowpart (SImode, operands[0]);
+ {
+ mode = SImode;
+ operands[0] = gen_lowpart (mode, operands[0]);
+ operands[1] = gen_lowpart (mode, operands[1]);
+ }
+
+ operands[2] = gen_int_mode (1 << INTVAL (operands[2]), mode);
- if (TARGET_64BIT && mode != Pmode)
- pat = gen_rtx_SUBREG (SImode, pat, 0);
+ pat = gen_rtx_MULT (mode, operands[1], operands[2]);
emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
DONE;
})
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert ashift to the lea pattern to avoid flags dependency.
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md (revision 176748)
+++ config/i386/predicates.md (working copy)
@@ -366,9 +366,13 @@
;; Return true when operand is PIC expression that can be computed by lea
;; operation.
-(define_predicate "pic_32bit_operand"
+(define_special_predicate "pic_32bit_operand"
(match_code "const,symbol_ref,label_ref")
{
+ if (GET_MODE (op) != SImode
+ && GET_MODE (op) != DImode)
+ return false;
+
if (!flag_pic)
return false;
/* Rule out relocations that translate into 64bit constants. */
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c (revision 176748)
+++ config/i386/i386.c (working copy)
@@ -14122,6 +14122,9 @@ ix86_print_operand_address (FILE *file,
}
else
{
+ /* Use DImode registers in address on 64bit target. */
+ int code = TARGET_64BIT ? 'q' : 0;
+
if (ASSEMBLER_DIALECT == ASM_ATT)
{
if (disp)
@@ -14136,11 +14139,11 @@ ix86_print_operand_address (FILE *file,
putc ('(', file);
if (base)
- print_reg (base, 0, file);
+ print_reg (base, code, file);
if (index)
{
putc (',', file);
- print_reg (index, 0, file);
+ print_reg (index, code, file);
if (scale != 1)
fprintf (file, ",%d", scale);
}
@@ -14175,7 +14178,7 @@ ix86_print_operand_address (FILE *file,
putc ('[', file);
if (base)
{
- print_reg (base, 0, file);
+ print_reg (base, code, file);
if (offset)
{
if (INTVAL (offset) >= 0)
@@ -14191,7 +14194,7 @@ ix86_print_operand_address (FILE *file,
if (index)
{
putc ('+', file);
- print_reg (index, 0, file);
+ print_reg (index, code, file);
if (scale != 1)
fprintf (file, "*%d", scale);
}
More information about the Gcc-patches
mailing list