Hi Richard, I have attached a WIP untested patch for PR96463. IIUC, the PR suggests to transform lhs = svld1rq ({-1, -1, ...}, &v[0]) into: lhs = vec_perm_expr<v, v, {0, 0, ...}> if v is vector of 4 elements, and each element is 32 bits on little endian target ?
I am sorry if this sounds like a silly question, but I am not sure how to convert a vector of type int32x4_t into svint32_t ? In the patch, I simply used NOP_EXPR (which I expected to fail), and gave type error during gimple verification: svint32_t foo (int32x4_t x) { return svld1rq (svptrue_b8 (), &x[0]); } transformed to: EMERGENCY DUMP: svint32_t foo (int32x4_t x) { svint32_t _3; __Int32x4_t _4; <bb 2> : _4 = VEC_PERM_EXPR <x_5(D), x_5(D), { 0, 0, 0, 0 }>; _3 = (svint32_t) _4; return _3; } and ICE's with: pr96463.c:8:1: error: invalid vector types in nop conversion 8 | } | ^ svint32_t __Int32x4_t _3 = (svint32_t) _4; during GIMPLE pass: ccp Could you please suggest how to proceed ? Thanks, Prathamesh
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc index 02e42a71e5e..3834f33443a 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc @@ -44,6 +44,13 @@ #include "aarch64-sve-builtins-shapes.h" #include "aarch64-sve-builtins-base.h" #include "aarch64-sve-builtins-functions.h" +#include "print-tree.h" +#include "gimple-pretty-print.h" + +/* ??? Including tree-ssanames.h requires including other header dependencies. + Just including the prototype for now. */ +extern tree make_ssa_name_fn (struct function *, tree, gimple *, + unsigned int version = 0); using namespace aarch64_sve; @@ -1207,6 +1214,52 @@ public: insn_code icode = code_for_aarch64_sve_ld1rq (e.vector_mode (0)); return e.use_contiguous_load_insn (icode); } + + gimple * + fold (gimple_folder &f) const OVERRIDE + { + tree arg0 = gimple_call_arg (f.call, 0); + tree arg1 = gimple_call_arg (f.call, 1); + + /* Transform: + lhs = svld1rq ({-1, -1, ... }, &v[0]) + into: + tmp = vec_perm_expr<v, v, {0, 0, ...}>. + lhs = nop_expr tmp + on little endian target. */ + + if (!BYTES_BIG_ENDIAN + && integer_all_onesp (arg0) + && TREE_CODE (arg1) == ADDR_EXPR) + { + tree t = TREE_OPERAND (arg1, 0); + if (TREE_CODE (t) == ARRAY_REF) + { + tree index = TREE_OPERAND (t, 1); + t = TREE_OPERAND (t, 0); + if (integer_zerop (index) && TREE_CODE (t) == VIEW_CONVERT_EXPR) + { + t = TREE_OPERAND (t, 0); + tree vectype = TREE_TYPE (t); + if (VECTOR_TYPE_P (vectype) + && known_eq (TYPE_VECTOR_SUBPARTS (vectype), 4u) + && wi::to_wide (TYPE_SIZE (vectype)) == 128) + { + tree new_temp = ::make_ssa_name_fn (cfun, vectype, NULL); + tree zero_vec = build_vector_from_val (vectype, index); + gimple *g = gimple_build_assign (new_temp, VEC_PERM_EXPR, t, t, zero_vec); + /* ??? How to convert between vector types if gimple_call_lhs (f.call) and + new_temp have different types ? */ + gimple *g2 = gimple_build_assign (gimple_call_lhs (f.call), NOP_EXPR, new_temp); + gsi_insert_before (f.gsi, g, GSI_SAME_STMT); + return g2; + } + } + } + } + + return NULL; + } }; class svld1ro_impl : public load_replicate