tree gimple_simplify (enum tree_code code, tree type, tree op0, tree op1, gimple_seq *seq, tree (*valueize)(tree)) { if (constant_for_folding (op0) && constant_for_folding (op1)) { tree res = const_binop (code, type, op0, op1); if (res != NULL_TREE && CONSTANT_CLASS_P (res)) return res; } /* Canonicalize operand order both for matching and fallback stmt generation. */ if ((commutative_tree_code (code) || TREE_CODE_CLASS (code) == tcc_comparison) && tree_swap_operands_p (op0, op1, false)) { tree tem = op0; op0 = op1; op1 = tem; if (TREE_CODE_CLASS (code) == tcc_comparison) code = swap_tree_comparison (code); } code_helper rcode; tree ops[3] = {}; if (!gimple_simplify (&rcode, ops, seq, valueize, code, type, op0, op1)) return NULL_TREE; return maybe_push_res_to_seq (rcode, type, ops, seq); }
bool gimple_resimplify2 (gimple_seq *seq, code_helper *res_code, tree type, tree *res_ops, tree (*valueize)(tree)) { if (constant_for_folding (res_ops[0]) && constant_for_folding (res_ops[1])) { tree tem = NULL_TREE; if (res_code->is_tree_code ()) tem = const_binop (*res_code, type, res_ops[0], res_ops[1]); else tem = fold_const_call (combined_fn (*res_code), type, res_ops[0], res_ops[1]); if (tem != NULL_TREE && CONSTANT_CLASS_P (tem)) { if (TREE_OVERFLOW_P (tem)) tem = drop_tree_overflow (tem); res_ops[0] = tem; res_ops[1] = NULL_TREE; res_ops[2] = NULL_TREE; *res_code = TREE_CODE (res_ops[0]); return true; } } /* Canonicalize operand order. */ bool canonicalized = false; if (res_code->is_tree_code () && (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison || commutative_tree_code (*res_code)) && tree_swap_operands_p (res_ops[0], res_ops[1])) { std::swap (res_ops[0], res_ops[1]); if (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison) *res_code = swap_tree_comparison (*res_code); canonicalized = true; } code_helper res_code2; tree res_ops2[3] = {}; if (gimple_simplify (&res_code2, res_ops2, seq, valueize, *res_code, type, res_ops[0], res_ops[1])) { *res_code = res_code2; res_ops[0] = res_ops2[0]; res_ops[1] = res_ops2[1]; res_ops[2] = res_ops2[2]; return true; } return canonicalized; }
static tree fold_const_reduction (tree type, tree arg, tree_code code) { unsigned HOST_WIDE_INT nelts; if (TREE_CODE (arg) != VECTOR_CST || !VECTOR_CST_NELTS (arg).is_constant (&nelts)) return NULL_TREE; tree res = VECTOR_CST_ELT (arg, 0); for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++) { res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i)); if (res == NULL_TREE || !CONSTANT_CLASS_P (res)) return NULL_TREE; } return res; }
static tree fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code) { if (TREE_CODE (arg1) != VECTOR_CST) return NULL_TREE; unsigned HOST_WIDE_INT nelts; if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts)) return NULL_TREE; for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++) { arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i)); if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0)) return NULL_TREE; } return arg0; }
static bool gimple_resimplify2 (gimple_seq *seq, code_helper *res_code, tree type, tree *res_ops, tree (*valueize)(tree)) { if (constant_for_folding (res_ops[0]) && constant_for_folding (res_ops[1])) { tree tem = NULL_TREE; if (res_code->is_tree_code ()) tem = const_binop (*res_code, type, res_ops[0], res_ops[1]); else { tree decl = builtin_decl_implicit (*res_code); if (decl) { tem = fold_builtin_n (UNKNOWN_LOCATION, decl, res_ops, 2, false); if (tem) { /* fold_builtin_n wraps the result inside a NOP_EXPR. */ STRIP_NOPS (tem); tem = fold_convert (type, tem); } } } if (tem != NULL_TREE && CONSTANT_CLASS_P (tem)) { res_ops[0] = tem; res_ops[1] = NULL_TREE; res_ops[2] = NULL_TREE; *res_code = TREE_CODE (res_ops[0]); return true; } } /* Canonicalize operand order. */ bool canonicalized = false; if (res_code->is_tree_code () && (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison || commutative_tree_code (*res_code)) && tree_swap_operands_p (res_ops[0], res_ops[1], false)) { tree tem = res_ops[0]; res_ops[0] = res_ops[1]; res_ops[1] = tem; if (TREE_CODE_CLASS ((enum tree_code) *res_code) == tcc_comparison) *res_code = swap_tree_comparison (*res_code); canonicalized = true; } code_helper res_code2; tree res_ops2[3] = {}; if (gimple_simplify (&res_code2, res_ops2, seq, valueize, *res_code, type, res_ops[0], res_ops[1])) { *res_code = res_code2; res_ops[0] = res_ops2[0]; res_ops[1] = res_ops2[1]; res_ops[2] = res_ops2[2]; return true; } return canonicalized; }