Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-29 Thread H.J. Lu
On Thu, Mar 24, 2011 at 8:51 AM, Eric Botcazou  wrote:
>> Pointer is promoted to Pmode from ptr_mode.
>
> Indeed.  However the problem is the 2 in assign_parm_setup_reg:
>
>  /* Store the parm in a pseudoregister during the function, but we may
>     need to do it in a wider mode.  Using 2 here makes the result
>     consistent with promote_decl_mode and thus expand_expr_real_1.  */
>  promoted_nominal_mode
>   = promote_function_mode (data->nominal_type, data->nominal_mode, &unsignedp,
>                             TREE_TYPE (current_function_decl), 2);
>
> which is supposed to match the 2 in promote_decl_mode:
>
>  if (TREE_CODE (decl) == RESULT_DECL
>      || TREE_CODE (decl) == PARM_DECL)
>    pmode = promote_function_mode (type, mode, &unsignedp,
>                                   TREE_TYPE (current_function_decl), 2);
>  else
>    pmode = promote_mode (type, mode, &unsignedp);
>
> but doesn't match the 0 in assign_parm_find_data_types:
>
>  promoted_mode = promote_function_mode (passed_type, passed_mode, &unsignedp,
>                                         TREE_TYPE (current_function_decl), 0);
>
> so you get the redundant extension in the callee.  The solution is to define
> the promote_function_mode hook for x86 to something like:
>
> static enum machine_mode
> ix86_promote_function_mode (const_tree type,
>                            enum machine_mode mode,
>                            int *punsignedp,
>                            const_tree fntype ATTRIBUTE_UNUSED,
>                            int for_return ATTRIBUTE_UNUSED)
> {
>  if (POINTER_TYPE_P (type))
>    {
>      *punsignedp = POINTERS_EXTEND_UNSIGNED;
>      return Pmode;
>    }
>
>  return mode;
> }
>

Here is the patch.  precompute_register_parameters change is needed for

---
extern __thread int ttt;
extern void bar (void *);
void
foo1 ()
{
  bar (&ttt);
}
---

I used

/* Pointer function arguments and return values are promoted to
   Pmode.  */

static enum machine_mode
ix86_promote_function_mode (const_tree type, enum machine_mode mode,
int *punsignedp, const_tree fntype,
int for_return)
{
  if (for_return != 1 && POINTER_TYPE_P (type))
{
  *punsignedp = POINTERS_EXTEND_UNSIGNED;
  return Pmode;
}
  return default_promote_function_mode (type, mode, punsignedp, fntype,
for_return);
}

since for_return == 1 has to match function_value, which I want to keep
as is.  default_promote_function_mode handles i386 PROMOTE_MODE.
Tested it on Linux/ia32 and Linux/x86-64.  OK for trunk?

Thanks.

-- 
H.J.
--
2011-03-29  H.J. Lu  

PR middle-end/47725
PR target/48085
* calls.c (precompute_register_parameters): Convert pointer to
TLS symbol if needed.

* config/i386/i386.c (ix86_promote_function_mode): New.
(TARGET_PROMOTE_FUNCTION_MODE): Likewise.
diff --git a/gcc/ChangeLog.x32 b/gcc/ChangeLog.x32
index 303acd8..a7ff7e3 100644
--- a/gcc/ChangeLog.x32
+++ b/gcc/ChangeLog.x32
@@ -1,6 +1,16 @@
 2011-03-29  H.J. Lu  
 
PR middle-end/47725
+   PR target/48085
+   * calls.c (precompute_register_parameters): Convert pointer to
+   TLS symbol if needed.
+
+   * config/i386/i386.c (ix86_promote_function_mode): New.
+   (TARGET_PROMOTE_FUNCTION_MODE): Likewise.
+
+2011-03-29  H.J. Lu  
+
+   PR middle-end/47725
* combine.c (cant_combine_insn_p): Don't check zero/sign extended
hard registers.
 
diff --git a/gcc/calls.c b/gcc/calls.c
index 2e79777..7357241 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -691,7 +691,13 @@ precompute_register_parameters (int num_actuals, struct 
arg_data *args,
   pseudo now.  TLS symbols sometimes need a call to resolve.  */
if (CONSTANT_P (args[i].value)
&& !LEGITIMATE_CONSTANT_P (args[i].value))
- args[i].value = force_reg (args[i].mode, args[i].value);
+ {
+   if (GET_MODE (args[i].value) != args[i].mode)
+ args[i].value = convert_to_mode (args[i].mode,
+  args[i].value,
+  args[i].unsignedp);
+   args[i].value = force_reg (args[i].mode, args[i].value);
+ }
 
/* If we are to promote the function arg to a wider mode,
   do it now.  */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index d7a5c02..6cffab2 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7636,6 +7636,23 @@ ix86_function_value (const_tree valtype, const_tree 
fntype_or_decl,
   return ix86_function_value_1 (valtype, fntype_or_decl, orig_mode, mode);
 }
 
+/* Pointer function arguments and return values are promoted to
+   Pmode.  */
+
+static enum machine_mode
+ix86_promote_function_mode (const_tree type, enum machine_mode mode,
+   int *punsignedp, const_tree fntype,
+   int for_return)
+{
+  i

Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-24 Thread Eric Botcazou
> Pointer is promoted to Pmode from ptr_mode.

Indeed.  However the problem is the 2 in assign_parm_setup_reg:

  /* Store the parm in a pseudoregister during the function, but we may
 need to do it in a wider mode.  Using 2 here makes the result
 consistent with promote_decl_mode and thus expand_expr_real_1.  */
 promoted_nominal_mode
   = promote_function_mode (data->nominal_type, data->nominal_mode, &unsignedp,
 TREE_TYPE (current_function_decl), 2);

which is supposed to match the 2 in promote_decl_mode:

  if (TREE_CODE (decl) == RESULT_DECL
  || TREE_CODE (decl) == PARM_DECL)
pmode = promote_function_mode (type, mode, &unsignedp,
   TREE_TYPE (current_function_decl), 2);
  else
pmode = promote_mode (type, mode, &unsignedp);

but doesn't match the 0 in assign_parm_find_data_types:

  promoted_mode = promote_function_mode (passed_type, passed_mode, &unsignedp,
 TREE_TYPE (current_function_decl), 0);

so you get the redundant extension in the callee.  The solution is to define 
the promote_function_mode hook for x86 to something like:

static enum machine_mode
ix86_promote_function_mode (const_tree type,
enum machine_mode mode,
int *punsignedp,
const_tree fntype ATTRIBUTE_UNUSED,
int for_return ATTRIBUTE_UNUSED)
{
  if (POINTER_TYPE_P (type))
{
  *punsignedp = POINTERS_EXTEND_UNSIGNED;
  return Pmode;
}

  return mode;
}

-- 
Eric Botcazou


Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-23 Thread H.J. Lu
On Wed, Mar 23, 2011 at 1:22 AM, Eric Botcazou  wrote:
>> It is:
>>
>>       op0 = parmreg;
>>       op1 = validated_mem;
>>       if (icode != CODE_FOR_nothing
>>           && insn_data[icode].operand[0].predicate (op0,
>> promoted_nominal_mode) && insn_data[icode].operand[1].predicate (op1,
>> data->passed_mode)) {
>>           enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND;
>>           rtx insn, insns;
>>           HARD_REG_SET hardregs;
>>
>>           start_sequence ();
>>           insn = gen_extend_insn (op0, op1, promoted_nominal_mode,
>>                                   data->passed_mode, unsignedp);
>>           emit_insn (insn);
>>           insns = get_insns ();
>
> Sure, but why is need_conversion set to true?
>

Pointer is promoted to Pmode from ptr_mode.


-- 
H.J.
---
#0  promote_mode (type=0x70e05540, mode=SImode, punsignedp=0x7fffd76c)
at /export/gnu/import/git/gcc-x32/gcc/explow.c:808
#1  0x009ef004 in default_promote_function_mode (type=0x70e05540,
mode=SImode, punsignedp=0x7fffd76c, funtype=0x70cec3f0,
for_return=2) at /export/gnu/import/git/gcc-x32/gcc/targhooks.c:128
#2  0x006d7155 in promote_function_mode (type=0x70e05540,
mode=SImode, punsignedp=0x7fffd76c, funtype=0x70cec3f0,
for_return=2) at /export/gnu/import/git/gcc-x32/gcc/explow.c:774
#3  0x007cf7de in assign_parm_setup_reg (all=0x7fffda10,
parm=0x70dec880, data=0x7fffd980)
at /export/gnu/import/git/gcc-x32/gcc/function.c:2941


Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-23 Thread Eric Botcazou
> It is:
>
>   op0 = parmreg;
>   op1 = validated_mem;
>   if (icode != CODE_FOR_nothing
>   && insn_data[icode].operand[0].predicate (op0,
> promoted_nominal_mode) && insn_data[icode].operand[1].predicate (op1,
> data->passed_mode)) {
>   enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND;
>   rtx insn, insns;
>   HARD_REG_SET hardregs;
>
>   start_sequence ();
>   insn = gen_extend_insn (op0, op1, promoted_nominal_mode,
>   data->passed_mode, unsignedp);
>   emit_insn (insn);
>   insns = get_insns ();

Sure, but why is need_conversion set to true?

-- 
Eric Botcazou


Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-22 Thread H.J. Lu
On Tue, Mar 22, 2011 at 1:05 PM, Eric Botcazou  wrote:
>> It leads 2 problems:
>>
>> 1. Redundant zero-extension at function entry.
>> 2. combine doesn't check zero-extension on hard register and leads to
>> internal compiler error.
>>
>> Is there a way to avoid redundant zero-extension at function entry to
>> solve both problems?
>
> Eliminating the redundant extension in the callee seems indeed to be 
> appealing.
> You need to find out who decides that the incoming parameter needs to be zero-
> extended.  Is that the call to promote_function_mode in assign_parm_setup_reg?
>

It is:

  op0 = parmreg;
  op1 = validated_mem;
  if (icode != CODE_FOR_nothing
  && insn_data[icode].operand[0].predicate (op0, promoted_nominal_mode)
  && insn_data[icode].operand[1].predicate (op1, data->passed_mode))
{
  enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND;
  rtx insn, insns;
  HARD_REG_SET hardregs;

  start_sequence ();
  insn = gen_extend_insn (op0, op1, promoted_nominal_mode,
  data->passed_mode, unsignedp);
  emit_insn (insn);
  insns = get_insns ();

in assign_parm_setup_reg.

-- 
H.J.


Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-22 Thread Eric Botcazou
> It leads 2 problems:
>
> 1. Redundant zero-extension at function entry.
> 2. combine doesn't check zero-extension on hard register and leads to
> internal compiler error.
>
> Is there a way to avoid redundant zero-extension at function entry to
> solve both problems?

Eliminating the redundant extension in the callee seems indeed to be appealing.
You need to find out who decides that the incoming parameter needs to be zero- 
extended.  Is that the call to promote_function_mode in assign_parm_setup_reg?

-- 
Eric Botcazou


Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-20 Thread H.J. Lu
On Thu, Mar 17, 2011 at 9:00 PM, H.J. Lu  wrote:
> On Thu, Mar 17, 2011 at 5:30 PM, H.J. Lu  wrote:
>> On Tue, Feb 15, 2011 at 2:55 PM, Bernd Schmidt  
>> wrote:
>>> On 02/14/2011 08:46 PM, Eric Botcazou wrote:
> I agree with Jeff that combine would be the correct place to fix this.
> At least it takes class_likely_spilled_p into account, so it will
> restrict only those machines where extending the lifetime of hard regs
> is dangerous.

 OK, but I don't see how copying to a new pseudo would interfere with that.
>>>
>>> For one thing, the set no longer matches the REG_EQUIV note we make
>>> here, and that does seem to interfere with the optimization. I've tested
>>> both patches on ARM, -march=armv7-a. The combiner patch produced no code
>>> changes. The function.c patch produced regressions (increased register
>>> pressure). Both results are as expected.
>>>
>>> To put it another way: the combiner change is conservatively correct,
>>> and necessary if we're going to have extends of hard registers in the
>>> RTL. The function.c change is demonstrably incorrect as shown by the ARM
>>> codegen regressions.
>>>
>>
>> I checked in my patch into trunk.
>>
>
> I noticed that for x32, all pointers passed in registers are zero-extended
> by caller. If we can fix
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48085
>
> by avoiding zero-extension in callee, this issue won't happen for x32.  I will
> revert the combine change for now and try to implement this approach.
>

The issues are

1. When passing a 32bit integer parameter in a register, hardware
always zero-extends
it to 64bit.  I can update x32 psABI to document it, which costs
nothing to implement
in GCC.
2. assign_parm_setup_reg zero-extends 32bit pointer in register to
64bit, which is
redundant.

It leads 2 problems:

1. Redundant zero-extension at function entry.
2. combine doesn't check zero-extension on hard register and leads to
internal compiler error.

Is there a way to avoid redundant zero-extension at function entry to
solve both problems?

Thanks.


-- 
H.J.


Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-17 Thread H.J. Lu
On Thu, Mar 17, 2011 at 5:30 PM, H.J. Lu  wrote:
> On Tue, Feb 15, 2011 at 2:55 PM, Bernd Schmidt  
> wrote:
>> On 02/14/2011 08:46 PM, Eric Botcazou wrote:
 I agree with Jeff that combine would be the correct place to fix this.
 At least it takes class_likely_spilled_p into account, so it will
 restrict only those machines where extending the lifetime of hard regs
 is dangerous.
>>>
>>> OK, but I don't see how copying to a new pseudo would interfere with that.
>>
>> For one thing, the set no longer matches the REG_EQUIV note we make
>> here, and that does seem to interfere with the optimization. I've tested
>> both patches on ARM, -march=armv7-a. The combiner patch produced no code
>> changes. The function.c patch produced regressions (increased register
>> pressure). Both results are as expected.
>>
>> To put it another way: the combiner change is conservatively correct,
>> and necessary if we're going to have extends of hard registers in the
>> RTL. The function.c change is demonstrably incorrect as shown by the ARM
>> codegen regressions.
>>
>
> I checked in my patch into trunk.
>

I noticed that for x32, all pointers passed in registers are zero-extended
by caller. If we can fix

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48085

by avoiding zero-extension in callee, this issue won't happen for x32.  I will
revert the combine change for now and try to implement this approach.

Thanks.

-- 
H.J.


Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG

2011-03-17 Thread H.J. Lu
On Tue, Feb 15, 2011 at 2:55 PM, Bernd Schmidt  wrote:
> On 02/14/2011 08:46 PM, Eric Botcazou wrote:
>>> I agree with Jeff that combine would be the correct place to fix this.
>>> At least it takes class_likely_spilled_p into account, so it will
>>> restrict only those machines where extending the lifetime of hard regs
>>> is dangerous.
>>
>> OK, but I don't see how copying to a new pseudo would interfere with that.
>
> For one thing, the set no longer matches the REG_EQUIV note we make
> here, and that does seem to interfere with the optimization. I've tested
> both patches on ARM, -march=armv7-a. The combiner patch produced no code
> changes. The function.c patch produced regressions (increased register
> pressure). Both results are as expected.
>
> To put it another way: the combiner change is conservatively correct,
> and necessary if we're going to have extends of hard registers in the
> RTL. The function.c change is demonstrably incorrect as shown by the ARM
> codegen regressions.
>

I checked in my patch into trunk.

Thanks.

-- 
H.J.