Hello!

This patch is based on the discussion in PR88178. Apparently, MIPS
uses accessible_reg_set array to disable register sets, unsupported by
currently active ISAs. The patch implements the same approach for x86,
which also results in IMO better error messages. The middle-end misses
to error out in asm having inaccessible clobber registers, so the
patch implements the missing handling (the error message could
probably be improved...)

A couple of test cases now emit better diagnostics, e.g.:

* gcc.target/i386/asm-1.c:5:23: error: the register specified for
'EAX' cannot be accessed by the current target

* gcc.target/i386/pr62120.c:6:16: error: the register specified for
'zmm_var' cannot be accessed by the current target
* gcc.target/i386/pr62120.c:7:16: error: the register specified for
'zmm_var2' cannot be accessed by the current target

instead of "invalid register name" messages.

2018-11-27  Uros Bizjak  <ubiz...@gmail.com>

    * cfgexpand.c (expand_asm_stmt): Reject clobbers outside of
    accessible_reg_set.
    * config/i386/i386.c (ix86_conditional_register_usage):
    Disable register sets by clearing corresponding bits in
    accessible_reg_set.  Do not set corresponding bits in fixed_regs,
    call_used_regs and don't clear corresponding reg_names array members.

Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

This is gcc-10 material, so the patch is not committed to the repository.

Uros.
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 21bdcdaeaa35..691e0c7c1b0b 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2981,6 +2981,14 @@ expand_asm_stmt (gasm *stmt)
                           regname);
                    return;
                  }
+               else if (!in_hard_reg_set_p
+                        (accessible_reg_set, reg_raw_mode[reg], reg))
+                 {
+                   /* ??? Diagnose during gimplification?  */
+                   error ("the register %qs cannot be clobbered in %<asm%>"
+                          " for the current target", regname);
+                   return;
+                 }
 
                SET_HARD_REG_BIT (clobbered_regs, reg);
                rtx x = gen_rtx_REG (reg_raw_mode[reg], reg);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 95abde95f89d..9abd441930f4 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -4743,15 +4743,15 @@ ix86_conditional_register_usage (void)
       if (!fixed_regs[i] && !ix86_function_value_regno_p (i))
        call_used_regs[i] = 0;
 
-  /* For 32-bit targets, squash the REX registers.  */
+  /* For 32-bit targets, disable the REX registers.  */
   if (! TARGET_64BIT)
     {
       for (i = FIRST_REX_INT_REG; i <= LAST_REX_INT_REG; i++)
-       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+       CLEAR_HARD_REG_BIT (accessible_reg_set, i);
       for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++)
-       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+       CLEAR_HARD_REG_BIT (accessible_reg_set, i);
       for (i = FIRST_EXT_REX_SSE_REG; i <= LAST_EXT_REX_SSE_REG; i++)
-       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+       CLEAR_HARD_REG_BIT (accessible_reg_set, i);
     }
 
   /*  See the definition of CALL_USED_REGISTERS in i386.h.  */
@@ -4773,32 +4773,29 @@ ix86_conditional_register_usage (void)
        SET_HARD_REG_BIT (reg_class_contents[(int)CLOBBERED_REGS], i);
     }
 
-  /* If MMX is disabled, squash the registers.  */
+  /* If MMX is disabled, disable the registers.  */
   if (! TARGET_MMX)
-    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-      if (TEST_HARD_REG_BIT (reg_class_contents[(int)MMX_REGS], i))
-       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+    AND_COMPL_HARD_REG_SET (accessible_reg_set,
+                           reg_class_contents[(int) MMX_REGS]);
 
-  /* If SSE is disabled, squash the registers.  */
+  /* If SSE is disabled, disable the registers.  */
   if (! TARGET_SSE)
-    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-      if (TEST_HARD_REG_BIT (reg_class_contents[(int)SSE_REGS], i))
-       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+    AND_COMPL_HARD_REG_SET (accessible_reg_set,
+                           reg_class_contents[(int) ALL_SSE_REGS]);
 
-  /* If the FPU is disabled, squash the registers.  */
+  /* If the FPU is disabled, disable the registers.  */
   if (! (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387))
-    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-      if (TEST_HARD_REG_BIT (reg_class_contents[(int)FLOAT_REGS], i))
-       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+    AND_COMPL_HARD_REG_SET (accessible_reg_set,
+                           reg_class_contents[(int) FLOAT_REGS]);
 
-  /* If AVX512F is disabled, squash the registers.  */
+  /* If AVX512F is disabled, disable the registers.  */
   if (! TARGET_AVX512F)
     {
       for (i = FIRST_EXT_REX_SSE_REG; i <= LAST_EXT_REX_SSE_REG; i++)
-       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+       CLEAR_HARD_REG_BIT (accessible_reg_set, i);
 
-      for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++)
-       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+      AND_COMPL_HARD_REG_SET (accessible_reg_set,
+                             reg_class_contents[(int) ALL_MASK_REGS]);
     }
 }
 

Reply via email to