1 /* Internal functions. 2 Copyright (C) 2011 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #include "config.h" 21 #include "system.h" 22 #include "coretypes.h" 23 #include "internal-fn.h" 24 #include "tree.h" 25 #include "expr.h" 26 #include "optabs.h" 27 #include "gimple.h" 28 29 /* The names of each internal function, indexed by function number. */ 30 const char *const internal_fn_name_array[] = { 31 #define DEF_INTERNAL_FN(CODE, FLAGS) #CODE, 32 #include "internal-fn.def" 33 #undef DEF_INTERNAL_FN 34 "<invalid-fn>" 35 }; 36 37 /* The ECF_* flags of each internal function, indexed by function number. */ 38 const int internal_fn_flags_array[] = { 39 #define DEF_INTERNAL_FN(CODE, FLAGS) FLAGS, 40 #include "internal-fn.def" 41 #undef DEF_INTERNAL_FN 42 0 43 }; 44 45 /* ARRAY_TYPE is an array of vector modes. Return the associated insn 46 for load-lanes-style optab OPTAB. The insn must exist. */ 47 48 static enum insn_code 49 get_multi_vector_move (tree array_type, convert_optab optab) 50 { 51 enum insn_code icode; 52 enum machine_mode imode; 53 enum machine_mode vmode; 54 55 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE); 56 imode = TYPE_MODE (array_type); 57 vmode = TYPE_MODE (TREE_TYPE (array_type)); 58 59 icode = convert_optab_handler (optab, imode, vmode); 60 gcc_assert (icode != CODE_FOR_nothing); 61 return icode; 62 } 63 64 /* Expand LOAD_LANES call STMT. */ 65 66 static void 67 expand_LOAD_LANES (gimple stmt) 68 { 69 struct expand_operand ops[2]; 70 tree type, lhs, rhs; 71 rtx target, mem; 72 73 lhs = gimple_call_lhs (stmt); 74 rhs = gimple_call_arg (stmt, 0); 75 type = TREE_TYPE (lhs); 76 77 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); 78 mem = expand_normal (rhs); 79 80 gcc_assert (MEM_P (mem)); 81 PUT_MODE (mem, TYPE_MODE (type)); 82 83 create_output_operand (&ops[0], target, TYPE_MODE (type)); 84 create_fixed_operand (&ops[1], mem); 85 expand_insn (get_multi_vector_move (type, vec_load_lanes_optab), 2, ops); 86 } 87 88 /* Expand STORE_LANES call STMT. */ 89 90 static void 91 expand_STORE_LANES (gimple stmt) 92 { 93 struct expand_operand ops[2]; 94 tree type, lhs, rhs; 95 rtx target, reg; 96 97 lhs = gimple_call_lhs (stmt); 98 rhs = gimple_call_arg (stmt, 0); 99 type = TREE_TYPE (rhs); 100 101 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); 102 reg = expand_normal (rhs); 103 104 gcc_assert (MEM_P (target)); 105 PUT_MODE (target, TYPE_MODE (type)); 106 107 create_fixed_operand (&ops[0], target); 108 create_input_operand (&ops[1], reg, TYPE_MODE (type)); 109 expand_insn (get_multi_vector_move (type, vec_store_lanes_optab), 2, ops); 110 } 111 112 /* Routines to expand each internal function, indexed by function number. 113 Each routine has the prototype: 114 115 expand_<NAME> (gimple stmt) 116 117 where STMT is the statement that performs the call. */ 118 static void (*const internal_fn_expanders[]) (gimple) = { 119 #define DEF_INTERNAL_FN(CODE, FLAGS) expand_##CODE, 120 #include "internal-fn.def" 121 #undef DEF_INTERNAL_FN 122 0 123 }; 124 125 /* Expand STMT, which is a call to internal function FN. */ 126 127 void 128 expand_internal_call (gimple stmt) 129 { 130 internal_fn_expanders[(int) gimple_call_internal_fn (stmt)] (stmt); 131 } 132