1  /* Copyright (C) 1988-2023 Free Software Foundation, Inc.
       2  
       3  This file is part of GCC.
       4  
       5  GCC is free software; you can redistribute it and/or modify
       6  it under the terms of the GNU General Public License as published by
       7  the Free Software Foundation; either version 3, or (at your option)
       8  any later version.
       9  
      10  GCC is distributed in the hope that it will be useful,
      11  but WITHOUT ANY WARRANTY; without even the implied warranty of
      12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13  GNU General Public License for more details.
      14  
      15  You should have received a copy of the GNU General Public License
      16  along with GCC; see the file COPYING3.  If not see
      17  <http://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef GCC_I386_FEATURES_H
      20  #define GCC_I386_FEATURES_H
      21  
      22  enum xlogue_stub {
      23    XLOGUE_STUB_SAVE,
      24    XLOGUE_STUB_RESTORE,
      25    XLOGUE_STUB_RESTORE_TAIL,
      26    XLOGUE_STUB_SAVE_HFP,
      27    XLOGUE_STUB_RESTORE_HFP,
      28    XLOGUE_STUB_RESTORE_HFP_TAIL,
      29  
      30    XLOGUE_STUB_COUNT
      31  };
      32  
      33  enum xlogue_stub_sets {
      34    XLOGUE_SET_ALIGNED,
      35    XLOGUE_SET_ALIGNED_PLUS_8,
      36    XLOGUE_SET_HFP_ALIGNED_OR_REALIGN,
      37    XLOGUE_SET_HFP_ALIGNED_PLUS_8,
      38  
      39    XLOGUE_SET_COUNT
      40  };
      41  
      42  /* Register save/restore layout used by out-of-line stubs.  */
      43  class xlogue_layout {
      44  public:
      45    struct reginfo
      46    {
      47      unsigned regno;
      48      HOST_WIDE_INT offset;	/* Offset used by stub base pointer (rax or
      49  				   rsi) to where each register is stored.  */
      50    };
      51  
      52    unsigned get_nregs () const			{return m_nregs;}
      53    HOST_WIDE_INT get_stack_align_off_in () const	{return m_stack_align_off_in;}
      54  
      55    const reginfo &get_reginfo (unsigned reg) const
      56    {
      57      gcc_assert (reg < m_nregs);
      58      return m_regs[reg];
      59    }
      60  
      61    static const char *get_stub_name (enum xlogue_stub stub,
      62  				    unsigned n_extra_args);
      63  
      64    /* Returns an rtx for the stub's symbol based upon
      65         1.) the specified stub (save, restore or restore_ret) and
      66         2.) the value of cfun->machine->call_ms2sysv_extra_regs and
      67         3.) rather or not stack alignment is being performed.  */
      68    static rtx get_stub_rtx (enum xlogue_stub stub);
      69  
      70    /* Returns the amount of stack space (including padding) that the stub
      71       needs to store registers based upon data in the machine_function.  */
      72    HOST_WIDE_INT get_stack_space_used () const
      73    {
      74      const struct machine_function *m = cfun->machine;
      75      unsigned last_reg = m->call_ms2sysv_extra_regs + MIN_REGS - 1;
      76  
      77      gcc_assert (m->call_ms2sysv_extra_regs <= MAX_EXTRA_REGS);
      78      return m_regs[last_reg].offset + STUB_INDEX_OFFSET;
      79    }
      80  
      81    /* Returns the offset for the base pointer used by the stub.  */
      82    HOST_WIDE_INT get_stub_ptr_offset () const
      83    {
      84      return STUB_INDEX_OFFSET + m_stack_align_off_in;
      85    }
      86  
      87    static const class xlogue_layout &get_instance ();
      88    static unsigned count_stub_managed_regs ();
      89    static bool is_stub_managed_reg (unsigned regno, unsigned count);
      90  
      91    static const HOST_WIDE_INT STUB_INDEX_OFFSET = 0x70;
      92    static const unsigned MIN_REGS = NUM_X86_64_MS_CLOBBERED_REGS;
      93    static const unsigned MAX_REGS = 18;
      94    static const unsigned MAX_EXTRA_REGS = MAX_REGS - MIN_REGS;
      95    static const unsigned VARIANT_COUNT = MAX_EXTRA_REGS + 1;
      96    static const unsigned STUB_NAME_MAX_LEN = 20;
      97    static const char * const STUB_BASE_NAMES[XLOGUE_STUB_COUNT];
      98    static const unsigned REG_ORDER[MAX_REGS];
      99    static const unsigned REG_ORDER_REALIGN[MAX_REGS];
     100  
     101  private:
     102    xlogue_layout ();
     103    xlogue_layout (HOST_WIDE_INT stack_align_off_in, bool hfp);
     104    xlogue_layout (const xlogue_layout &);
     105  
     106    /* True if hard frame pointer is used.  */
     107    bool m_hfp;
     108  
     109    /* Max number of register this layout manages.  */
     110    unsigned m_nregs;
     111  
     112    /* Incoming offset from 16-byte alignment.  */
     113    HOST_WIDE_INT m_stack_align_off_in;
     114  
     115    /* Register order and offsets.  */
     116    struct reginfo m_regs[MAX_REGS];
     117  
     118    /* Lazy-inited cache of symbol names for stubs.  */
     119    static char s_stub_names[2][XLOGUE_STUB_COUNT][VARIANT_COUNT]
     120  			  [STUB_NAME_MAX_LEN];
     121  
     122    static const xlogue_layout s_instances[XLOGUE_SET_COUNT];
     123  };
     124  
     125  namespace {
     126  
     127  class scalar_chain
     128  {
     129   public:
     130    scalar_chain (enum machine_mode, enum machine_mode);
     131    virtual ~scalar_chain ();
     132  
     133    static unsigned max_id;
     134  
     135    /* Scalar mode.  */
     136    enum machine_mode smode;
     137    /* Vector mode.  */
     138    enum machine_mode vmode;
     139  
     140    /* ID of a chain.  */
     141    unsigned int chain_id;
     142    /* A queue of instructions to be included into a chain.  */
     143    bitmap queue;
     144    /* Instructions included into a chain.  */
     145    bitmap insns;
     146    /* All registers defined by a chain.  */
     147    bitmap defs;
     148    /* Registers used in both vector and sclar modes.  */
     149    bitmap defs_conv;
     150  
     151    /* Limit on chain discovery.  */
     152    unsigned max_visits;
     153  
     154    bitmap insns_conv;
     155    hash_map<rtx, rtx> defs_map;
     156    unsigned n_sse_to_integer;
     157    unsigned n_integer_to_sse;
     158  
     159    bool build (bitmap candidates, unsigned insn_uid, bitmap disallowed);
     160    virtual int compute_convert_gain () = 0;
     161    int convert ();
     162  
     163   protected:
     164    void add_to_queue (unsigned insn_uid);
     165    void emit_conversion_insns (rtx insns, rtx_insn *pos);
     166    rtx convert_compare (rtx op1, rtx op2, rtx_insn *insn);
     167    void mark_dual_mode_def (df_ref def);
     168    void convert_reg (rtx_insn *insn, rtx dst, rtx src);
     169    void convert_insn_common (rtx_insn *insn);
     170    void make_vector_copies (rtx_insn *, rtx);
     171    void convert_registers ();
     172  
     173   private:
     174    bool add_insn (bitmap candidates, unsigned insn_uid, bitmap disallowed);
     175    bool analyze_register_chain (bitmap candidates, df_ref ref,
     176  			       bitmap disallowed);
     177    virtual void convert_insn (rtx_insn *insn) = 0;
     178    virtual void convert_op (rtx *op, rtx_insn *insn) = 0;
     179  };
     180  
     181  class general_scalar_chain : public scalar_chain
     182  {
     183   public:
     184    general_scalar_chain (enum machine_mode smode_, enum machine_mode vmode_)
     185      : scalar_chain (smode_, vmode_) {}
     186    int compute_convert_gain () final override;
     187  
     188   private:
     189    void convert_insn (rtx_insn *insn) final override;
     190    void convert_op (rtx *op, rtx_insn *insn) final override;
     191    int vector_const_cost (rtx exp);
     192  };
     193  
     194  class timode_scalar_chain : public scalar_chain
     195  {
     196   public:
     197    timode_scalar_chain () : scalar_chain (TImode, V1TImode) {}
     198    int compute_convert_gain () final override;
     199  
     200   private:
     201    void fix_debug_reg_uses (rtx reg);
     202    void convert_insn (rtx_insn *insn) final override;
     203    void convert_op (rtx *op, rtx_insn *insn) final override;
     204  };
     205  
     206  } // anon namespace
     207  
     208  bool ix86_save_reg (unsigned int regno, bool maybe_eh_return,
     209  		    bool ignore_outlined);
     210  int ix86_compare_version_priority (tree decl1, tree decl2);
     211  tree ix86_generate_version_dispatcher_body (void *node_p);
     212  tree ix86_get_function_versions_dispatcher (void *decl);
     213  tree ix86_mangle_decl_assembler_name (tree decl, tree id);
     214  
     215  
     216  #endif  /* GCC_I386_FEATURES_H */