Hi,

This patch fixes PIC with external symbol and updates
x86_64_immediate_operand/x86_64_zext_immediate_operand/x86_64_movabs_operand
for x32.

H.J.
----
2011-07-26  H.J. Lu  <hongjiu...@intel.com>

        PR target/49853
        * config/i386/i386.c (ix86_expand_move): Call convert_to_mode
        on legitimize_tls_address return if needed.  Allow ptr_mode for
        symbolic operand with PIC.

        * config/i386/predicates.md (x86_64_immediate_operand): Always
        allow the offsetted memory references for TARGET_X32.
        (x86_64_zext_immediate_operand): Likewise.
        (x86_64_movabs_operand): Don't allow nonmemory_operand for
        TARGET_X32.

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 3668357..fd00667 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -14985,6 +14985,7 @@ void
 ix86_expand_move (enum machine_mode mode, rtx operands[])
 {
   rtx op0, op1;
+  rtx symbol1 = NULL;
   enum tls_model model;
 
   op0 = operands[0];
@@ -15012,27 +15013,35 @@ ix86_expand_move (enum machine_mode mode, rtx 
operands[])
     {
       rtx addend = XEXP (XEXP (op1, 0), 1);
       rtx symbol = XEXP (XEXP (op1, 0), 0);
-      rtx tmp = NULL;
 
       model = SYMBOL_REF_TLS_MODEL (symbol);
       if (model)
-       tmp = legitimize_tls_address (symbol, model, true);
+       symbol1 = legitimize_tls_address (symbol, model, true);
       else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
               && SYMBOL_REF_DLLIMPORT_P (symbol))
-       tmp = legitimize_dllimport_symbol (symbol, true);
+       symbol1 = legitimize_dllimport_symbol (symbol, true);
 
-      if (tmp)
+      if (symbol1)
        {
-         tmp = force_operand (tmp, NULL);
-         tmp = expand_simple_binop (Pmode, PLUS, tmp, addend,
-                                    op0, 1, OPTAB_DIRECT);
-         if (tmp == op0)
+         symbol1 = force_operand (symbol1, NULL);
+         symbol1 = expand_simple_binop (Pmode, PLUS, symbol1, addend,
+                                        op0, 1, OPTAB_DIRECT);
+         if (symbol1 == op0)
            return;
        }
     }
 
+  if (symbol1)
+    {
+      if (GET_MODE (symbol1) != mode)
+       symbol1 = convert_to_mode (mode, symbol1, 1);
+      emit_insn (gen_rtx_SET (VOIDmode, op0, symbol1));
+      return;
+    }
+
   if ((flag_pic || MACHOPIC_INDIRECT) 
-       && mode == Pmode && symbolic_operand (op1, Pmode))
+       && (mode == Pmode || mode == ptr_mode)
+       && symbolic_operand (op1, mode))
     {
       if (TARGET_MACHO && !TARGET_64BIT)
        {
@@ -15073,13 +15082,15 @@ ix86_expand_move (enum machine_mode mode, rtx 
operands[])
       else
        {
          if (MEM_P (op0))
-           op1 = force_reg (Pmode, op1);
-         else if (!TARGET_64BIT || !x86_64_movabs_operand (op1, Pmode))
+           op1 = force_reg (mode, op1);
+         else if (!TARGET_64BIT || !x86_64_movabs_operand (op1, mode))
            {
              rtx reg = can_create_pseudo_p () ? NULL_RTX : op0;
              op1 = legitimize_pic_address (op1, reg);
              if (op0 == op1)
                return;
+             if (GET_MODE (op1) != mode)
+               op1 = convert_to_mode (mode, op1, 1);
            }
        }
     }
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 0515519..7dc690a 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -197,8 +197,10 @@
              if ((ix86_cmodel == CM_SMALL
                   || (ix86_cmodel == CM_MEDIUM
                       && !SYMBOL_REF_FAR_ADDR_P (op1)))
-                 && offset < 16*1024*1024
-                 && trunc_int_for_mode (offset, SImode) == offset)
+                 && (TARGET_X32
+                     || (offset < 16*1024*1024
+                         && (trunc_int_for_mode (offset, SImode)
+                             == offset))))
                return true;
              /* For CM_KERNEL we know that all object resist in the
                 negative half of 32bits address space.  We may not
@@ -302,8 +304,11 @@
                   || (ix86_cmodel == CM_MEDIUM
                       && !SYMBOL_REF_FAR_ADDR_P (op1)))
                  && CONST_INT_P (op2)
-                 && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
-                 && trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
+                 && (TARGET_X32
+                     || ((trunc_int_for_mode (INTVAL (op2), DImode)
+                          > -0x10000)
+                         && (trunc_int_for_mode (INTVAL (op2), SImode)
+                             == INTVAL (op2)))))
                return true;
              /* ??? For the kernel, we may accept adjustment of
                 -0x10000000, since we know that it will just convert
@@ -393,7 +398,8 @@
 ;; Return true if OP is nonmemory operand acceptable by movabs patterns.
 (define_predicate "x86_64_movabs_operand"
   (if_then_else (not (and (match_test "TARGET_64BIT")
-                         (match_test "flag_pic")))
+                         (ior (match_test "flag_pic")
+                              (match_test "TARGET_X32"))))
     (match_operand 0 "nonmemory_operand")
     (ior (match_operand 0 "register_operand")
         (and (match_operand 0 "const_double_operand")

Reply via email to