x86: don't suppress errors when optimizing

Message ID acb2dd7c-4c8d-4471-9ca2-646cfaac32fd@suse.com
State New
Headers
Series x86: don't suppress errors when optimizing |

Checks

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

Commit Message

Jan Beulich June 18, 2024, 6:33 a.m. UTC
  Blindly ignoring any mnemonic suffix can't be quite right: Bad suffix /
operand combinations still want flagging. Simply avoid optimizing in
such situations.
---
Introducing a new helper function right here, for it to be used in v2 of
"x86: a few more optimizations".
  

Comments

Sam James June 18, 2024, 6:52 a.m. UTC | #1
Jan Beulich <jbeulich@suse.com> writes:

> Blindly ignoring any mnemonic suffix can't be quite right: Bad suffix /
> operand combinations still want flagging. Simply avoid optimizing in
> such situations.
> ---
> Introducing a new helper function right here, for it to be used in v2 of
> "x86: a few more optimizations".
>
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -4573,6 +4573,20 @@ check_hle (void)
>      }
>  }
>  
> +/* Helper for optimization (running ahead of process_suffix()), to make sure we
> +   convert only well-formed insns.  @OP is the sized operand to cross check
> +   against (typically a register).  Checking against a single operand typically
> +   suffices, as match_template() has already honored CheckOperandSize.  */
> +
> +static bool is_plausible_suffix (unsigned int op)
> +{
> +  return !i.suffix
> +	 || (i.suffix == BYTE_MNEM_SUFFIX && i.types[op].bitfield.byte)
> +	 || (i.suffix == WORD_MNEM_SUFFIX && i.types[op].bitfield.word)
> +	 || (i.suffix == LONG_MNEM_SUFFIX && i.types[op].bitfield.dword)
> +	 || (i.suffix == QWORD_MNEM_SUFFIX && i.types[op].bitfield.qword);
> +}
> +
>  /* Encode aligned vector move as unaligned vector move.  */
>  
>  static void
> @@ -4758,6 +4772,7 @@ optimize_encoding (void)
>        && i.reg_operands == 1
>        && i.imm_operands == 1
>        && !i.types[1].bitfield.byte
> +      && is_plausible_suffix (1)
>        && i.op[0].imms->X_op == O_constant
>        && fits_in_imm7 (i.op[0].imms->X_add_number))
>      {
> @@ -4768,7 +4783,7 @@ optimize_encoding (void)
>        if (flag_code == CODE_64BIT || base_regnum < 4)
>  	{
>  	  i.types[1].bitfield.byte = 1;
> -	  /* Ignore the suffix.  */
> +	  /* Squash the suffix.  */
>  	  i.suffix = 0;
>  	  /* Convert to byte registers. 8-bit registers are special,
>  	     RegRex64 and non-RegRex64 each have 8 registers.  */
> --- a/gas/testsuite/gas/i386/i386.exp
> +++ b/gas/testsuite/gas/i386/i386.exp
> @@ -615,6 +615,7 @@ if [gas_32_check] then {
>      run_list_test "optimize-6a" "-I${srcdir}/$subdir -march=+noavx -al"
>      run_dump_test "optimize-6b"
>      run_list_test "optimize-7" "-I${srcdir}/$subdir -march=+noavx2 -al"
> +    run_list_test "optimize-8" "-Os"
>      run_dump_test "noopt"
>      run_dump_test "lea-optimize"
>      run_dump_test "lea16-optimize"
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/optimize-8.l
> @@ -0,0 +1,4 @@
> +.*: Assembler messages:
> +.*:5: Error: .* `%ecx' .* suffix
> +.*:6: Error: .* `%cx' .* suffix
> +#pass
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/optimize-8.s
> @@ -0,0 +1,6 @@
> +# Check bogus instructions are still rejected when optimitating

optimi(z|s)ing

> +
> +	.text
> +_start:
> +	testw	$4, %ecx
> +	testl	$4, %cx
  

Patch

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -4573,6 +4573,20 @@  check_hle (void)
     }
 }
 
+/* Helper for optimization (running ahead of process_suffix()), to make sure we
+   convert only well-formed insns.  @OP is the sized operand to cross check
+   against (typically a register).  Checking against a single operand typically
+   suffices, as match_template() has already honored CheckOperandSize.  */
+
+static bool is_plausible_suffix (unsigned int op)
+{
+  return !i.suffix
+	 || (i.suffix == BYTE_MNEM_SUFFIX && i.types[op].bitfield.byte)
+	 || (i.suffix == WORD_MNEM_SUFFIX && i.types[op].bitfield.word)
+	 || (i.suffix == LONG_MNEM_SUFFIX && i.types[op].bitfield.dword)
+	 || (i.suffix == QWORD_MNEM_SUFFIX && i.types[op].bitfield.qword);
+}
+
 /* Encode aligned vector move as unaligned vector move.  */
 
 static void
@@ -4758,6 +4772,7 @@  optimize_encoding (void)
       && i.reg_operands == 1
       && i.imm_operands == 1
       && !i.types[1].bitfield.byte
+      && is_plausible_suffix (1)
       && i.op[0].imms->X_op == O_constant
       && fits_in_imm7 (i.op[0].imms->X_add_number))
     {
@@ -4768,7 +4783,7 @@  optimize_encoding (void)
       if (flag_code == CODE_64BIT || base_regnum < 4)
 	{
 	  i.types[1].bitfield.byte = 1;
-	  /* Ignore the suffix.  */
+	  /* Squash the suffix.  */
 	  i.suffix = 0;
 	  /* Convert to byte registers. 8-bit registers are special,
 	     RegRex64 and non-RegRex64 each have 8 registers.  */
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -615,6 +615,7 @@  if [gas_32_check] then {
     run_list_test "optimize-6a" "-I${srcdir}/$subdir -march=+noavx -al"
     run_dump_test "optimize-6b"
     run_list_test "optimize-7" "-I${srcdir}/$subdir -march=+noavx2 -al"
+    run_list_test "optimize-8" "-Os"
     run_dump_test "noopt"
     run_dump_test "lea-optimize"
     run_dump_test "lea16-optimize"
--- /dev/null
+++ b/gas/testsuite/gas/i386/optimize-8.l
@@ -0,0 +1,4 @@ 
+.*: Assembler messages:
+.*:5: Error: .* `%ecx' .* suffix
+.*:6: Error: .* `%cx' .* suffix
+#pass
--- /dev/null
+++ b/gas/testsuite/gas/i386/optimize-8.s
@@ -0,0 +1,6 @@ 
+# Check bogus instructions are still rejected when optimitating
+
+	.text
+_start:
+	testw	$4, %ecx
+	testl	$4, %cx