aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/aarch64/aarch64-sve-builtins.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/aarch64/aarch64-sve-builtins.cc')
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins.cc32
1 files changed, 28 insertions, 4 deletions
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index 3651926..e394c9a 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -47,6 +47,8 @@
#include "langhooks.h"
#include "stringpool.h"
#include "attribs.h"
+#include "value-range.h"
+#include "tree-ssanames.h"
#include "aarch64-sve-builtins.h"
#include "aarch64-sve-builtins-base.h"
#include "aarch64-sve-builtins-sve2.h"
@@ -3664,7 +3666,8 @@ gimple_folder::fold_pfalse ()
/* Convert the lhs and all non-boolean vector-type operands to TYPE.
Pass the converted variables to the callback FP, and finally convert the
result back to the original type. Add the necessary conversion statements.
- Return the new call. */
+ Return the new call. Note the tree argument to the callback FP, can only
+ be set once; it will always be a SSA_NAME. */
gimple *
gimple_folder::convert_and_fold (tree type,
gimple *(*fp) (gimple_folder &,
@@ -3675,7 +3678,7 @@ gimple_folder::convert_and_fold (tree type,
tree old_ty = TREE_TYPE (lhs);
gimple_seq stmts = NULL;
bool convert_lhs_p = !useless_type_conversion_p (type, old_ty);
- tree lhs_conv = convert_lhs_p ? create_tmp_var (type) : lhs;
+ tree lhs_conv = convert_lhs_p ? make_ssa_name (type) : lhs;
unsigned int num_args = gimple_call_num_args (call);
auto_vec<tree, 16> args_conv;
args_conv.safe_grow (num_args);
@@ -4001,7 +4004,8 @@ rtx
function_expander::get_reg_target ()
{
machine_mode target_mode = result_mode ();
- if (!possible_target || GET_MODE (possible_target) != target_mode)
+ if (!possible_target
+ || !register_operand (possible_target, target_mode))
possible_target = gen_reg_rtx (target_mode);
return possible_target;
}
@@ -4589,7 +4593,27 @@ function_expander::expand ()
gcc_assert (args.last ()->mode == DImode);
emit_move_insn (gen_rtx_REG (DImode, FPM_REGNUM), args.last ());
}
- return base->expand (*this);
+ rtx result = base->expand (*this);
+ if (function_returns_void_p ())
+ gcc_assert (result == const0_rtx);
+ else
+ {
+ auto expected_mode = result_mode ();
+ if (GET_MODE_CLASS (expected_mode) == MODE_INT)
+ /* Scalar integer constants don't store a mode.
+
+ It's OK for a variable result to have a different mode from the
+ function return type. In particular, some functions that return int
+ expand into instructions that have a DImode result, with all 64 bits
+ of the DImode being well-defined (usually zero). */
+ gcc_assert (CONST_SCALAR_INT_P (result)
+ || GET_MODE_CLASS (GET_MODE (result)) == MODE_INT);
+ else
+ /* In other cases, the return value should have the same mode
+ as the return type. */
+ gcc_assert (GET_MODE (result) == expected_mode);
+ }
+ return result;
}
/* Return a structure type that contains a single field of type FIELD_TYPE.