xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/epiphany/mode-switch-use.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
1 /* Insert USEs in instructions that require mode switching.
2    This should probably be merged into mode-switching.c .
3    Copyright (C) 2011-2015 Free Software Foundation, Inc.
4    Contributed by Embecosm on behalf of Adapteva, Inc.
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12 
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "hashtab.h"
28 #include "hash-set.h"
29 #include "vec.h"
30 #include "machmode.h"
31 #include "hard-reg-set.h"
32 #include "input.h"
33 #include "function.h"
34 #include "emit-rtl.h"
35 #include "tree-pass.h"
36 #include "insn-attr.h"
37 #include "insn-config.h"
38 #include "recog.h"
39 #include "tm_p.h"
40 #include "dominance.h"
41 #include "cfg.h"
42 #include "cfgrtl.h"
43 #include "cfganal.h"
44 #include "lcm.h"
45 #include "cfgbuild.h"
46 #include "cfgcleanup.h"
47 #include "predict.h"
48 #include "basic-block.h"
49 #include "df.h"
50 
51 #ifndef TARGET_INSERT_MODE_SWITCH_USE
52 #define TARGET_INSERT_MODE_SWITCH_USE NULL
53 #endif
54 
55 static unsigned int
56 insert_uses (void)
57 {
58   static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
59 #define N_ENTITIES ARRAY_SIZE (num_modes)
60   int e;
61   void (*target_insert_mode_switch_use) (rtx_insn *insn, int, int)
62     = TARGET_INSERT_MODE_SWITCH_USE;
63 
64   for (e = N_ENTITIES - 1; e >= 0; e--)
65     {
66       int no_mode = num_modes[e];
67       rtx_insn *insn;
68       int mode;
69 
70       if (!OPTIMIZE_MODE_SWITCHING (e))
71 	continue;
72       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
73 	{
74 	  if (!INSN_P (insn))
75 	    continue;
76 	  mode = epiphany_mode_needed (e, insn);
77 	  if (mode == no_mode)
78 	    continue;
79 	  if (target_insert_mode_switch_use)
80 	    {
81 	      target_insert_mode_switch_use (insn, e, mode);
82 	      df_insn_rescan (insn);
83 	    }
84 	}
85     }
86   return 0;
87 }
88 
89 namespace {
90 
91 const pass_data pass_data_mode_switch_use =
92 {
93   RTL_PASS, /* type */
94   "mode_switch_use", /* name */
95   OPTGROUP_NONE, /* optinfo_flags */
96   TV_NONE, /* tv_id */
97   0, /* properties_required */
98   0, /* properties_provided */
99   0, /* properties_destroyed */
100   0, /* todo_flags_start */
101   0, /* todo_flags_finish */
102 };
103 
104 class pass_mode_switch_use : public rtl_opt_pass
105 {
106 public:
107   pass_mode_switch_use(gcc::context *ctxt)
108     : rtl_opt_pass(pass_data_mode_switch_use, ctxt)
109   {}
110 
111   /* opt_pass methods: */
112   virtual unsigned int execute (function *) { return insert_uses (); }
113 
114 }; // class pass_mode_switch_use
115 
116 } // anon namespace
117 
118 rtl_opt_pass *
119 make_pass_mode_switch_use (gcc::context *ctxt)
120 {
121   return new pass_mode_switch_use (ctxt);
122 }
123