[1/3] x86: Split REX/REX2 old registers judgment.

Message ID 20240520062202.1297234-2-lili.cui@intel.com
State New
Headers
Series Support APX zero-upper |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Testing passed

Commit Message

Cui, Lili May 20, 2024, 6:22 a.m. UTC
  Split "REX/REX2 old register checking" and "add empty rex prefix"
into two separate branches.

gas/ChangeLog:

        * config/tc-i386.c (establish_rex): Split the judgments.
---
 gas/config/tc-i386.c | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)
  

Comments

Jan Beulich May 21, 2024, 12:18 p.m. UTC | #1
On 20.05.2024 08:22, Cui, Lili wrote:
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -4303,22 +4303,20 @@ static void establish_rex (void)
>    /* Respect a user-specified REX prefix.  */
>    i.rex |= i.prefix[REX_PREFIX] & REX_OPCODE;
>  
> -  /* For 8 bit registers we need an empty rex prefix.  Also if the
> -     instruction already has a prefix, we need to convert old
> -     registers to new ones.  */
> -
> -  if ((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
> -       && ((i.op[first].regs->reg_flags & RegRex64) != 0 || i.rex != 0
> -	   || i.rex2 != 0))
> -      || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
> -	  && ((i.op[last].regs->reg_flags & RegRex64) != 0 || i.rex != 0
> -	      || i.rex2 != 0)))
> -    {
> -      unsigned int x;
> -
> -      if (!is_apx_rex2_encoding () && !is_any_vex_encoding(&i.tm))
> -	i.rex |= REX_OPCODE;
> -      for (x = first; x <= last; x++)
> +  /* For 8 bit registers without a prefix, we need an empty rex prefix.  */

As you're touching this comment, can you please also correct it? It's
not all 8-bit registers which are affected here (as expressed by the
RegRex64 checks).

> +  if (((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
> +	&& ((i.op[first].regs->reg_flags & RegRex64) != 0 ))

Nit: Please parenthesize this line and ...

> +       || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
> +	   && (i.op[last].regs->reg_flags & RegRex64) != 0 ))

... this one the same way, preferably like the latter. Also please omit
the blanks before the closing parentheses.

> +      && !is_apx_rex2_encoding () && !is_any_vex_encoding (&i.tm) && !i.rex)

Is the !i.rex part needed? It wasn't there before. If it's needed, it
would imo better come ahead of the APX/VEX checks.

> +    i.rex |= REX_OPCODE;
> +
> +  /* For REX/REX2 prefix instructions, we need to convert old registers
> +     (AL, CL, DL and BL) to new ones (AXL, CXL, DXL and BXL) and report bad
> +     for AH, CH, DH and BH.  */

"report bad for" is a little odd; how about simply "reject"?

Okay with respective adjustments.

Jan

> +  if (i.rex || i.rex2)
> +    {
> +      for (unsigned int x = first; x <= last; x++)
>  	{
>  	  /* Look for 8 bit operand that uses old registers.  */
>  	  if (i.types[x].bitfield.class == Reg && i.types[x].bitfield.byte
  
Cui, Lili May 22, 2024, 1:33 a.m. UTC | #2
> On 20.05.2024 08:22, Cui, Lili wrote:
> > --- a/gas/config/tc-i386.c
> > +++ b/gas/config/tc-i386.c
> > @@ -4303,22 +4303,20 @@ static void establish_rex (void)
> >    /* Respect a user-specified REX prefix.  */
> >    i.rex |= i.prefix[REX_PREFIX] & REX_OPCODE;
> >
> > -  /* For 8 bit registers we need an empty rex prefix.  Also if the
> > -     instruction already has a prefix, we need to convert old
> > -     registers to new ones.  */
> > -
> > -  if ((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
> > -       && ((i.op[first].regs->reg_flags & RegRex64) != 0 || i.rex != 0
> > -	   || i.rex2 != 0))
> > -      || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
> > -	  && ((i.op[last].regs->reg_flags & RegRex64) != 0 || i.rex != 0
> > -	      || i.rex2 != 0)))
> > -    {
> > -      unsigned int x;
> > -
> > -      if (!is_apx_rex2_encoding () && !is_any_vex_encoding(&i.tm))
> > -	i.rex |= REX_OPCODE;
> > -      for (x = first; x <= last; x++)
> > +  /* For 8 bit registers without a prefix, we need an empty rex
> > + prefix.  */
> 
> As you're touching this comment, can you please also correct it? It's not all 8-
> bit registers which are affected here (as expressed by the
> RegRex64 checks).
> 
Done.

> > +  if (((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
> > +	&& ((i.op[first].regs->reg_flags & RegRex64) != 0 ))
> 
> Nit: Please parenthesize this line and ...
> 
> > +       || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
> > +	   && (i.op[last].regs->reg_flags & RegRex64) != 0 ))
> 
> ... this one the same way, preferably like the latter. Also please omit the blanks
> before the closing parentheses.
> 
Done.

> > +      && !is_apx_rex2_encoding () && !is_any_vex_encoding (&i.tm) &&
> > + !i.rex)
> 
> Is the !i.rex part needed? It wasn't there before. If it's needed, it would imo
> better come ahead of the APX/VEX checks.
> 
Yes, I added it because there is already i.rex and we don't need to overwrite it. And I will put it ahead of the APX/VEX checks.

> > +    i.rex |= REX_OPCODE;
> > +
> > +  /* For REX/REX2 prefix instructions, we need to convert old registers
> > +     (AL, CL, DL and BL) to new ones (AXL, CXL, DXL and BXL) and report bad
> > +     for AH, CH, DH and BH.  */
> 
> "report bad for" is a little odd; how about simply "reject"?
> 
Done.

> Okay with respective adjustments.

Thanks,
Lili.
  
Jan Beulich May 22, 2024, 5:49 a.m. UTC | #3
On 22.05.2024 03:33, Cui, Lili wrote:
> 
>> On 20.05.2024 08:22, Cui, Lili wrote:
>>> --- a/gas/config/tc-i386.c
>>> +++ b/gas/config/tc-i386.c
>>> @@ -4303,22 +4303,20 @@ static void establish_rex (void)
>>>    /* Respect a user-specified REX prefix.  */
>>>    i.rex |= i.prefix[REX_PREFIX] & REX_OPCODE;
>>>
>>> -  /* For 8 bit registers we need an empty rex prefix.  Also if the
>>> -     instruction already has a prefix, we need to convert old
>>> -     registers to new ones.  */
>>> -
>>> -  if ((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
>>> -       && ((i.op[first].regs->reg_flags & RegRex64) != 0 || i.rex != 0
>>> -	   || i.rex2 != 0))
>>> -      || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
>>> -	  && ((i.op[last].regs->reg_flags & RegRex64) != 0 || i.rex != 0
>>> -	      || i.rex2 != 0)))
>>> -    {
>>> -      unsigned int x;
>>> -
>>> -      if (!is_apx_rex2_encoding () && !is_any_vex_encoding(&i.tm))
>>> -	i.rex |= REX_OPCODE;
>>> -      for (x = first; x <= last; x++)
>>> +  /* For 8 bit registers without a prefix, we need an empty rex
>>> + prefix.  */
>>
>> As you're touching this comment, can you please also correct it? It's not all 8-
>> bit registers which are affected here (as expressed by the
>> RegRex64 checks).
>>
> Done.
> 
>>> +  if (((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
>>> +	&& ((i.op[first].regs->reg_flags & RegRex64) != 0 ))
>>
>> Nit: Please parenthesize this line and ...
>>
>>> +       || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
>>> +	   && (i.op[last].regs->reg_flags & RegRex64) != 0 ))
>>
>> ... this one the same way, preferably like the latter. Also please omit the blanks
>> before the closing parentheses.
>>
> Done.
> 
>>> +      && !is_apx_rex2_encoding () && !is_any_vex_encoding (&i.tm) &&
>>> + !i.rex)
>>
>> Is the !i.rex part needed? It wasn't there before. If it's needed, it would imo
>> better come ahead of the APX/VEX checks.
>>
> Yes, I added it because there is already i.rex and we don't need to overwrite it. And I will put it ahead of the APX/VEX checks.

I don't think conditionals should be added in such cases. Resulting code
will do better without the extra conditional branch, when the update is
really benign in the case where (here) i.rex is already set. See, btw,
your own response to a pretty similar question of mine:
https://sourceware.org/pipermail/binutils/2024-May/134157.html

Jan
  
Cui, Lili May 22, 2024, 6:11 a.m. UTC | #4
> On 22.05.2024 03:33, Cui, Lili wrote:
> >
> >> On 20.05.2024 08:22, Cui, Lili wrote:
> >>> --- a/gas/config/tc-i386.c
> >>> +++ b/gas/config/tc-i386.c
> >>> @@ -4303,22 +4303,20 @@ static void establish_rex (void)
> >>>    /* Respect a user-specified REX prefix.  */
> >>>    i.rex |= i.prefix[REX_PREFIX] & REX_OPCODE;
> >>>
> >>> -  /* For 8 bit registers we need an empty rex prefix.  Also if the
> >>> -     instruction already has a prefix, we need to convert old
> >>> -     registers to new ones.  */
> >>> -
> >>> -  if ((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
> >>> -       && ((i.op[first].regs->reg_flags & RegRex64) != 0 || i.rex != 0
> >>> -	   || i.rex2 != 0))
> >>> -      || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
> >>> -	  && ((i.op[last].regs->reg_flags & RegRex64) != 0 || i.rex != 0
> >>> -	      || i.rex2 != 0)))
> >>> -    {
> >>> -      unsigned int x;
> >>> -
> >>> -      if (!is_apx_rex2_encoding () && !is_any_vex_encoding(&i.tm))
> >>> -	i.rex |= REX_OPCODE;
> >>> -      for (x = first; x <= last; x++)
> >>> +  /* For 8 bit registers without a prefix, we need an empty rex
> >>> + prefix.  */
> >>
> >> As you're touching this comment, can you please also correct it? It's
> >> not all 8- bit registers which are affected here (as expressed by the
> >> RegRex64 checks).
> >>
> > Done.
> >
> >>> +  if (((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
> >>> +	&& ((i.op[first].regs->reg_flags & RegRex64) != 0 ))
> >>
> >> Nit: Please parenthesize this line and ...
> >>
> >>> +       || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
> >>> +	   && (i.op[last].regs->reg_flags & RegRex64) != 0 ))
> >>
> >> ... this one the same way, preferably like the latter. Also please
> >> omit the blanks before the closing parentheses.
> >>
> > Done.
> >
> >>> +      && !is_apx_rex2_encoding () && !is_any_vex_encoding (&i.tm)
> >>> + &&
> >>> + !i.rex)
> >>
> >> Is the !i.rex part needed? It wasn't there before. If it's needed, it
> >> would imo better come ahead of the APX/VEX checks.
> >>
> > Yes, I added it because there is already i.rex and we don't need to overwrite
> it. And I will put it ahead of the APX/VEX checks.
> 
> I don't think conditionals should be added in such cases. Resulting code will do
> better without the extra conditional branch, when the update is really benign
> in the case where (here) i.rex is already set. See, btw, your own response to a
> pretty similar question of mine:
> https://sourceware.org/pipermail/binutils/2024-May/134157.html
> 
Yes, they are the similar issues. Since I just pushed it to the trunk, I'll create a patch to remove it.

Lili.
  
Jan Beulich May 22, 2024, 6:22 a.m. UTC | #5
On 22.05.2024 08:11, Cui, Lili wrote:
>> On 22.05.2024 03:33, Cui, Lili wrote:
>>>> On 20.05.2024 08:22, Cui, Lili wrote:
>>>>> --- a/gas/config/tc-i386.c
>>>>> +++ b/gas/config/tc-i386.c
>>>>> @@ -4303,22 +4303,20 @@ static void establish_rex (void)
>>>>>    /* Respect a user-specified REX prefix.  */
>>>>>    i.rex |= i.prefix[REX_PREFIX] & REX_OPCODE;
>>>>>
>>>>> -  /* For 8 bit registers we need an empty rex prefix.  Also if the
>>>>> -     instruction already has a prefix, we need to convert old
>>>>> -     registers to new ones.  */
>>>>> -
>>>>> -  if ((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
>>>>> -       && ((i.op[first].regs->reg_flags & RegRex64) != 0 || i.rex != 0
>>>>> -	   || i.rex2 != 0))
>>>>> -      || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
>>>>> -	  && ((i.op[last].regs->reg_flags & RegRex64) != 0 || i.rex != 0
>>>>> -	      || i.rex2 != 0)))
>>>>> -    {
>>>>> -      unsigned int x;
>>>>> -
>>>>> -      if (!is_apx_rex2_encoding () && !is_any_vex_encoding(&i.tm))
>>>>> -	i.rex |= REX_OPCODE;
>>>>> -      for (x = first; x <= last; x++)
>>>>> +  /* For 8 bit registers without a prefix, we need an empty rex
>>>>> + prefix.  */
>>>>
>>>> As you're touching this comment, can you please also correct it? It's
>>>> not all 8- bit registers which are affected here (as expressed by the
>>>> RegRex64 checks).
>>>>
>>> Done.
>>>
>>>>> +  if (((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
>>>>> +	&& ((i.op[first].regs->reg_flags & RegRex64) != 0 ))
>>>>
>>>> Nit: Please parenthesize this line and ...
>>>>
>>>>> +       || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
>>>>> +	   && (i.op[last].regs->reg_flags & RegRex64) != 0 ))
>>>>
>>>> ... this one the same way, preferably like the latter. Also please
>>>> omit the blanks before the closing parentheses.
>>>>
>>> Done.
>>>
>>>>> +      && !is_apx_rex2_encoding () && !is_any_vex_encoding (&i.tm)
>>>>> + &&
>>>>> + !i.rex)
>>>>
>>>> Is the !i.rex part needed? It wasn't there before. If it's needed, it
>>>> would imo better come ahead of the APX/VEX checks.
>>>>
>>> Yes, I added it because there is already i.rex and we don't need to overwrite
>> it. And I will put it ahead of the APX/VEX checks.
>>
>> I don't think conditionals should be added in such cases. Resulting code will do
>> better without the extra conditional branch, when the update is really benign
>> in the case where (here) i.rex is already set. See, btw, your own response to a
>> pretty similar question of mine:
>> https://sourceware.org/pipermail/binutils/2024-May/134157.html
>>
> Yes, they are the similar issues. Since I just pushed it to the trunk, I'll create a patch to remove it.

Thanks, and pre-approved.

Jan
  

Patch

diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 339e849a971..2fbd90bedb8 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -4303,22 +4303,20 @@  static void establish_rex (void)
   /* Respect a user-specified REX prefix.  */
   i.rex |= i.prefix[REX_PREFIX] & REX_OPCODE;
 
-  /* For 8 bit registers we need an empty rex prefix.  Also if the
-     instruction already has a prefix, we need to convert old
-     registers to new ones.  */
-
-  if ((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
-       && ((i.op[first].regs->reg_flags & RegRex64) != 0 || i.rex != 0
-	   || i.rex2 != 0))
-      || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
-	  && ((i.op[last].regs->reg_flags & RegRex64) != 0 || i.rex != 0
-	      || i.rex2 != 0)))
-    {
-      unsigned int x;
-
-      if (!is_apx_rex2_encoding () && !is_any_vex_encoding(&i.tm))
-	i.rex |= REX_OPCODE;
-      for (x = first; x <= last; x++)
+  /* For 8 bit registers without a prefix, we need an empty rex prefix.  */
+  if (((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte
+	&& ((i.op[first].regs->reg_flags & RegRex64) != 0 ))
+       || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte
+	   && (i.op[last].regs->reg_flags & RegRex64) != 0 ))
+      && !is_apx_rex2_encoding () && !is_any_vex_encoding (&i.tm) && !i.rex)
+    i.rex |= REX_OPCODE;
+
+  /* For REX/REX2 prefix instructions, we need to convert old registers
+     (AL, CL, DL and BL) to new ones (AXL, CXL, DXL and BXL) and report bad
+     for AH, CH, DH and BH.  */
+  if (i.rex || i.rex2)
+    {
+      for (unsigned int x = first; x <= last; x++)
 	{
 	  /* Look for 8 bit operand that uses old registers.  */
 	  if (i.types[x].bitfield.class == Reg && i.types[x].bitfield.byte