rtx gen_lowpart_general (machine_mode mode, rtx x) { rtx result = gen_lowpart_common (mode, x); if (result) return result; /* Handle SUBREGs and hard REGs that were rejected by simplify_gen_subreg. */ else if (REG_P (x) || GET_CODE (x) == SUBREG) { result = gen_lowpart_common (mode, copy_to_reg (x)); gcc_assert (result != 0); return result; } else { int offset = 0; /* The only additional case we can do is MEM. */ gcc_assert (MEM_P (x)); /* The following exposes the use of "x" to CSE. */ if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD && SCALAR_INT_MODE_P (GET_MODE (x)) && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x)) && !reload_completed) return gen_lowpart_general (mode, force_reg (GET_MODE (x), x)); if (WORDS_BIG_ENDIAN) offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)); if (BYTES_BIG_ENDIAN) /* Adjust the address so that the address-after-the-data is unchanged. */ offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)) - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))); return adjust_address (x, mode, offset); } }
rtx gen_lowpart_general (enum machine_mode mode, rtx x) { rtx result = gen_lowpart_common (mode, x); if (result) return result; else if (REG_P (x)) { /* Must be a hard reg that's not valid in MODE. */ result = gen_lowpart_common (mode, copy_to_reg (x)); gcc_assert (result != 0); return result; } else { int offset = 0; /* The only additional case we can do is MEM. */ gcc_assert (MEM_P (x)); /* The following exposes the use of "x" to CSE. */ if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD && SCALAR_INT_MODE_P (GET_MODE (x)) && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode), GET_MODE_BITSIZE (GET_MODE (x))) && ! no_new_pseudos) return gen_lowpart_general (mode, force_reg (GET_MODE (x), x)); if (WORDS_BIG_ENDIAN) offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)); if (BYTES_BIG_ENDIAN) /* Adjust the address so that the address-after-the-data is unchanged. */ offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)) - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))); return adjust_address (x, mode, offset); } }
static tree fold_const_call_1 (built_in_function fn, tree type, tree arg) { machine_mode mode = TYPE_MODE (type); machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg)); if (integer_cst_p (arg)) { if (SCALAR_INT_MODE_P (mode)) { wide_int result; if (fold_const_call_ss (&result, fn, arg, TYPE_PRECISION (type), TREE_TYPE (arg))) return wide_int_to_tree (type, result); } return NULL_TREE; } if (real_cst_p (arg)) { gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode)); if (mode == arg_mode) { /* real -> real. */ REAL_VALUE_TYPE result; if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg), REAL_MODE_FORMAT (mode))) return build_real (type, result); } else if (COMPLEX_MODE_P (mode) && GET_MODE_INNER (mode) == arg_mode) { /* real -> complex real. */ REAL_VALUE_TYPE result_real, result_imag; if (fold_const_call_cs (&result_real, &result_imag, fn, TREE_REAL_CST_PTR (arg), REAL_MODE_FORMAT (arg_mode))) return build_complex (type, build_real (TREE_TYPE (type), result_real), build_real (TREE_TYPE (type), result_imag)); } else if (INTEGRAL_TYPE_P (type)) { /* real -> int. */ wide_int result; if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg), TYPE_PRECISION (type), REAL_MODE_FORMAT (arg_mode))) return wide_int_to_tree (type, result); } return NULL_TREE; } if (complex_cst_p (arg)) { gcc_checking_assert (COMPLEX_MODE_P (arg_mode)); machine_mode inner_mode = GET_MODE_INNER (arg_mode); tree argr = TREE_REALPART (arg); tree argi = TREE_IMAGPART (arg); if (mode == arg_mode && real_cst_p (argr) && real_cst_p (argi)) { /* complex real -> complex real. */ REAL_VALUE_TYPE result_real, result_imag; if (fold_const_call_cc (&result_real, &result_imag, fn, TREE_REAL_CST_PTR (argr), TREE_REAL_CST_PTR (argi), REAL_MODE_FORMAT (inner_mode))) return build_complex (type, build_real (TREE_TYPE (type), result_real), build_real (TREE_TYPE (type), result_imag)); } if (mode == inner_mode && real_cst_p (argr) && real_cst_p (argi)) { /* complex real -> real. */ REAL_VALUE_TYPE result; if (fold_const_call_sc (&result, fn, TREE_REAL_CST_PTR (argr), TREE_REAL_CST_PTR (argi), REAL_MODE_FORMAT (inner_mode))) return build_real (type, result); } return NULL_TREE; } return NULL_TREE; }