1:识别的gimple
(1) VEC_COND_EXPR
(2) MASK_STORE
2: 找向量数学函数的方法
(1)VEC_COND_EXPR中有三个参数
vect_cstore_3623.1792_3442 = VEC_COND_EXPR <_3443, vect_cst__3446, vect__3624.1791_3445>;
参数1:mask的值,需要保证该mask在向量数学函数之前定义,不然插入的mask无法识别。如果在其之后定义,需要评估能不能移动到其之前。
参数2:mask 为 true 选择的元素,该操作数如果是SSA_NAME需要递归的找其定义的地方是否有向量数学函数,如果有,将参数1 插入向量数学函数中。
参数3:mask为false选择的元素,该操作数如果是SSA_NAME需要递归的找其定义的地方是否有向量数学函数,如果有,将参数1 取反插入向量数学函数中。
(2)MASK_STORE 有四个参数
MASK_STORE (vectp.232_1628, 64B, mask__847.221_1607, vect__839.231_1621);
参数3:mask的值,同上,定义需要在向量数学函数之前。否则考虑能否移动
参数4:运算的结果。在其定义中查找是否有vect-mathfunc。
#include "config.h" 2 #include "system.h" 3 #include "coretypes.h" 4 #include "backend.h" 5 #include "tree.h" 6 #include "gimple.h" 7 #include "predict.h" 8 #include "tree-pass.h" 9 #include "ssa.h" 10 #include "cgraph.h" 11 #include "fold-const.h" 12 #include "stor-layout.h" 13 #include "gimple-iterator.h" 14 #include "gimple-walk.h" 15 #include "tree-ssa-loop-manip.h" 16 #include "tree-ssa-loop-niter.h" 17 #include "tree-cfg.h" 18 #include "cfgloop.h" 19 #include "tree-vectorizer.h" 20 #include "tree-ssa-propagate.h" 21 #include "dbgcnt.h" 22 #include "tree-scalar-evolution.h" 23 #include "stringpool.h" 24 #include "attribs.h" 25 #include "gimple-pretty-print.h" 26 #include "opt-problem.h" 27 #include "internal-fn.h" 28 #include "tree-ssa-sccvn.h" 29 #include "gimple-expr.h" 30 #include <cstdio> 31 32 namespace 33 { 34 const pass_data pass_data_test = { 35 GIMPLE_PASS, /* type */ 36 "mask_vecmath_func", /* name */ 37 OPTGROUP_NONE, /* optinfo_flags */ 38 TV_TREE_VECT_MASK_VECMATH_FUNC, /* tv_id */ 39 (PROP_cfg | PROP_ssa), /* properties_required */ 40 0, /* properties_provided */ 41 0, /* properties_destroyed */ 42 0, /* todo_flags_start */ 43 0, /* todo_flags_finish */ 44 }; 46 class pass_mask_vecmath_func : public gimple_opt_pass 47 { 48 public: 49 pass_mask_vecmath_func (gcc::context *ctxt) : gimple_opt_pass (pass_data_test, ctxt) {} 50 virtual bool 51 gate (function *fun) 52 { 53 // printf ("gate function noipa.\n"); 54 return flag_tree_mask_vecmath_func; 55 } 56 57 virtual unsigned int execute (function *); 58 }; 59 60 61 static gimple *find_relate_operand(tree operand, gimple *stmt) 62 { 63 if (!stmt) 64 return NULL; 65 66 if (TREE_CODE (operand) == SSA_NAME && is_gimple_call(stmt)) { // operand is ssa && stmt is gimple call 67 tree fndecl = gimple_call_fndecl(stmt); // 获取函数声明 68 if (fndecl && DECL_P(fndecl)) { // 确保fndecl有效并且是一个声明 69 const char *func_name = IDENTIFIER_POINTER(DECL_NAME(fndecl)); // 获取函数名称 70 // if (strcmp(func_name, "vmldLn2") == 0) { 71 if (strcmp(func_name, "__svml_log4_mask_e9") == 0) { 72 return stmt; 73 } 74 } 75 } 76 if (TREE_CODE (operand) == SSA_NAME && is_gimple_assign(stmt)) { // only find gimple assign 77 78 for (unsigned i = 1; i < gimple_num_ops(stmt); ++i) { // get gimple assign right hand side operand 79 tree op = gimple_op(stmt, i); 80 if(TREE_CODE (op) == SSA_NAME) { 81 82 gimple *stmt_2 = SSA_NAME_DEF_STMT (op); 83 gimple *result = find_relate_operand(op,stmt_2); 84 if(result) return result; 85 } 86 } 87 } 88 return NULL; 89 } 90 91 static void add_mask_to_call(gimple *stmt, tree new_arg) { 92 if (!is_gimple_call(stmt)) { 93 // 如果不是函数调用语句,则不做任何操作 94 return; 95 } 96 97 // 获取原始函数调用的目标和参数列表 98 tree call_fn = gimple_call_fndecl(stmt); 99 100 // 获取或创建新的标识符节点来表示新的函数名称 101 // tree new_func_id = get_identifier("vmldLn2Mask"); 102 tree new_func_id = get_identifier("__svml_log4_mask_e9"); 103 tree fntype = TREE_TYPE(call_fn); 104 105 tree new_fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, new_func_id, fntype); 106 107 TREE_PUBLIC (new_fndecl) = 1; 108 DECL_EXTERNAL (new_fndecl) = 1; 109 DECL_IS_NOVOPS (new_fndecl) = 1; 110 TREE_READONLY (new_fndecl) = 1; 111 112 113 // 将新的标识符节点分配给函数声明的汇编名 114 // DECL_ASSEMBLER_NAME(call_fn) = new_func_id; 115 116 int num_args = gimple_call_num_args(stmt); 117 vec<tree> vargs = vNULL; 118 vargs.create (num_args+1); 119 120 // 创建一个新的参数列表,包含原始的参数和新的参数 121 for (int i = 0; i < num_args; i++) { 122 tree arg = gimple_call_arg(stmt, i); 123 vargs.safe_push(arg); 124 } 125 vargs.safe_push(new_arg); 126 127 tree lhs = gimple_call_lhs(stmt); 128 129 // 创建新的函数调用语句,包含新的参数 130 gimple *new_call = gimple_build_call_vec(new_fndecl,vargs); 131 gimple_call_set_lhs (new_call, lhs); 132 133 // 替换原始的函数调用语句 134 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 135 136 // printf ("-------------finish add mask to vecmath func call------------.\n"); 137 138 gsi_replace(&gsi, new_call,true); 139 stmt = new_call; 140 141 // 释放参数列表的内存 142 vargs.release (); 143 } 144 145 unsigned 146 pass_mask_vecmath_func::execute (function *fun) 147 { 148 unsigned ret = 0; 149 150 // printf ("-----------begin mask vecmath func------------.\n"); 151 // printf ("current function name:%s\n", function_name (fun)); 152 basic_block bb; 153 enum tree_code code; 154 155 // 遍历所有基本块 156 FOR_EACH_BB_FN(bb, fun) { 157 gimple_stmt_iterator gsi; 158 159 // 遍历基本块中的所有 GIMPLE 语句 160 for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) { 161 gimple *stmt = gsi_stmt(gsi); 162 if (is_gimple_assign(stmt)) { 163 164 gassign *stmt_assign = dyn_cast <gassign *> (gsi_stmt (gsi)); 165 code = gimple_assign_rhs_code (stmt_assign); 166 167 // 检查语句是否为 VEC_COND_EXPR 168 if (code == VEC_COND_EXPR) { 169 170 // printf ("-----------find out vec cond expr------------.\n"); 171 tree true_vector_operand = gimple_assign_rhs2(stmt_assign); // add wrong vec operand 172 tree mask_operand = gimple_assign_rhs1(stmt_assign); 173 if(TREE_CODE (true_vector_operand) == SSA_NAME) { 174 175 gimple *stmt_def = SSA_NAME_DEF_STMT (true_vector_operand); 176 gimple *stmt_vecmath = find_relate_operand(true_vector_operand,stmt_def); 177 if(stmt_vecmath) { 178 // printf ("-----------find out vecmath stmt------------.\n"); 179 add_mask_to_call(stmt_vecmath,mask_operand); 180 181 } 182 } 183 } 184 } 185 } 186 } 187 return ret; 188 } 189 } 190 191 gimple_opt_pass * 192 make_pass_mask_vecmath_func (gcc::context *ctxt) 193 { 194 return new pass_mask_vecmath_func (ctxt); 195 } |