From: Will Schmidt Date: Thu, 11 Oct 2018 21:03:30 +0000 (+0000) Subject: rs6000.c (map_to_integral_tree_type): New helper function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ea010af6b4d780261b791999e43ba056edce2af0;p=gcc.git rs6000.c (map_to_integral_tree_type): New helper function. [gcc] 2018-10-09 Will Schmidt * config/rs6000/rs6000.c (map_to_integral_tree_type): New helper function. (fold_mergeeo_helper): New helper function. (rs6000_gimple_fold_builtin): Add hooks for vec_mergee and vec_mergeo intrinsics. Correct some whitespace indentation issues. From-SVN: r265063 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b908601ce03..d6a4cade483 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2018-10-11 Will Schmidt + + * config/rs6000/rs6000.c (map_to_integral_tree_type): New helper + function. + (fold_mergeeo_helper): New helper function. + (rs6000_gimple_fold_builtin): Add hooks for vec_mergee and vec_mergeo + intrinsics. Correct some whitespace indentation issues. + 2018-10-11 Wilco Dijkstra PR target/87511 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 7036fd71c1e..85b05f6618c 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -15238,6 +15238,25 @@ fold_compare_helper (gimple_stmt_iterator *gsi, tree_code code, gimple *stmt) gsi_replace (gsi, g, true); } +/* Helper function to map V2DF and V4SF types to their + integral equivalents (V2DI and V4SI). */ +tree map_to_integral_tree_type (tree input_tree_type) +{ + if (INTEGRAL_TYPE_P (TREE_TYPE (input_tree_type))) + return input_tree_type; + else + { + if (types_compatible_p (TREE_TYPE (input_tree_type), + TREE_TYPE (V2DF_type_node))) + return V2DI_type_node; + else if (types_compatible_p (TREE_TYPE (input_tree_type), + TREE_TYPE (V4SF_type_node))) + return V4SI_type_node; + else + gcc_unreachable (); + } +} + /* Helper function to handle the vector merge[hl] built-ins. The implementation difference between h and l versions for this code are in the values used when building of the permute vector for high word versus @@ -15260,19 +15279,7 @@ fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high) float types, the permute type needs to map to the V2 or V4 type that matches size. */ tree permute_type; - if (INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))) - permute_type = lhs_type; - else - { - if (types_compatible_p (TREE_TYPE (lhs_type), - TREE_TYPE (V2DF_type_node))) - permute_type = V2DI_type_node; - else if (types_compatible_p (TREE_TYPE (lhs_type), - TREE_TYPE (V4SF_type_node))) - permute_type = V4SI_type_node; - else - gcc_unreachable (); - } + permute_type = map_to_integral_tree_type (lhs_type); tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1); for (int i = 0; i < midpoint; i++) @@ -15290,6 +15297,40 @@ fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high) gsi_replace (gsi, g, true); } +/* Helper function to handle the vector merge[eo] built-ins. */ +static void +fold_mergeeo_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_odd) +{ + tree arg0 = gimple_call_arg (stmt, 0); + tree arg1 = gimple_call_arg (stmt, 1); + tree lhs = gimple_call_lhs (stmt); + tree lhs_type = TREE_TYPE (lhs); + int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type); + + /* The permute_type will match the lhs for integral types. For double and + float types, the permute type needs to map to the V2 or V4 type that + matches size. */ + tree permute_type; + permute_type = map_to_integral_tree_type (lhs_type); + + tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1); + + /* Build the permute vector. */ + for (int i = 0; i < n_elts / 2; i++) + { + elts.safe_push (build_int_cst (TREE_TYPE (permute_type), + 2*i + use_odd)); + elts.safe_push (build_int_cst (TREE_TYPE (permute_type), + 2*i + use_odd + n_elts)); + } + + tree permute = elts.build (); + + gimple *g = gimple_build_assign (lhs, VEC_PERM_EXPR, arg0, arg1, permute); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); +} + /* Fold a machine-dependent built-in in GIMPLE. (For folding into a constant, use rs6000_fold_builtin.) */ @@ -15765,34 +15806,34 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) case VSX_BUILTIN_LXVD2X_V2DF: case VSX_BUILTIN_LXVD2X_V2DI: { - arg0 = gimple_call_arg (stmt, 0); // offset - arg1 = gimple_call_arg (stmt, 1); // address - lhs = gimple_call_lhs (stmt); - location_t loc = gimple_location (stmt); - /* Since arg1 may be cast to a different type, just use ptr_type_node - here instead of trying to enforce TBAA on pointer types. */ - tree arg1_type = ptr_type_node; - tree lhs_type = TREE_TYPE (lhs); - /* In GIMPLE the type of the MEM_REF specifies the alignment. The - required alignment (power) is 4 bytes regardless of data type. */ - tree align_ltype = build_aligned_type (lhs_type, 4); - /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create - the tree using the value from arg0. The resulting type will match - the type of arg1. */ - gimple_seq stmts = NULL; - tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0); - tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, + arg0 = gimple_call_arg (stmt, 0); // offset + arg1 = gimple_call_arg (stmt, 1); // address + lhs = gimple_call_lhs (stmt); + location_t loc = gimple_location (stmt); + /* Since arg1 may be cast to a different type, just use ptr_type_node + here instead of trying to enforce TBAA on pointer types. */ + tree arg1_type = ptr_type_node; + tree lhs_type = TREE_TYPE (lhs); + /* In GIMPLE the type of the MEM_REF specifies the alignment. The + required alignment (power) is 4 bytes regardless of data type. */ + tree align_ltype = build_aligned_type (lhs_type, 4); + /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create + the tree using the value from arg0. The resulting type will match + the type of arg1. */ + gimple_seq stmts = NULL; + tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0); + tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, arg1_type, arg1, temp_offset); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - /* Use the build2 helper to set up the mem_ref. The MEM_REF could also - take an offset, but since we've already incorporated the offset - above, here we just pass in a zero. */ - gimple *g; - g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr, - build_int_cst (arg1_type, 0))); - gimple_set_location (g, loc); - gsi_replace (gsi, g, true); - return true; + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + /* Use the build2 helper to set up the mem_ref. The MEM_REF could also + take an offset, but since we've already incorporated the offset + above, here we just pass in a zero. */ + gimple *g; + g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr, + build_int_cst (arg1_type, 0))); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; } /* unaligned Vector stores. */ @@ -15803,29 +15844,29 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) case VSX_BUILTIN_STXVD2X_V2DF: case VSX_BUILTIN_STXVD2X_V2DI: { - arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */ - arg1 = gimple_call_arg (stmt, 1); /* Offset. */ - tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */ - location_t loc = gimple_location (stmt); - tree arg0_type = TREE_TYPE (arg0); - /* Use ptr_type_node (no TBAA) for the arg2_type. */ - tree arg2_type = ptr_type_node; - /* In GIMPLE the type of the MEM_REF specifies the alignment. The - required alignment (power) is 4 bytes regardless of data type. */ - tree align_stype = build_aligned_type (arg0_type, 4); - /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create - the tree using the value from arg1. */ - gimple_seq stmts = NULL; - tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1); - tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, + arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */ + arg1 = gimple_call_arg (stmt, 1); /* Offset. */ + tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */ + location_t loc = gimple_location (stmt); + tree arg0_type = TREE_TYPE (arg0); + /* Use ptr_type_node (no TBAA) for the arg2_type. */ + tree arg2_type = ptr_type_node; + /* In GIMPLE the type of the MEM_REF specifies the alignment. The + required alignment (power) is 4 bytes regardless of data type. */ + tree align_stype = build_aligned_type (arg0_type, 4); + /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create + the tree using the value from arg1. */ + gimple_seq stmts = NULL; + tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1); + tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, arg2_type, arg2, temp_offset); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - gimple *g; - g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr, - build_int_cst (arg2_type, 0)), arg0); - gimple_set_location (g, loc); - gsi_replace (gsi, g, true); - return true; + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + gimple *g; + g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr, + build_int_cst (arg2_type, 0)), arg0); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; } /* Vector Fused multiply-add (fma). */ @@ -15897,35 +15938,34 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) case ALTIVEC_BUILTIN_VSPLTISH: case ALTIVEC_BUILTIN_VSPLTISW: { - int size; - - if (fn_code == ALTIVEC_BUILTIN_VSPLTISB) - size = 8; - else if (fn_code == ALTIVEC_BUILTIN_VSPLTISH) - size = 16; - else - size = 32; - - arg0 = gimple_call_arg (stmt, 0); - lhs = gimple_call_lhs (stmt); - - /* Only fold the vec_splat_*() if the lower bits of arg 0 is a - 5-bit signed constant in range -16 to +15. */ - if (TREE_CODE (arg0) != INTEGER_CST - || !IN_RANGE (sext_hwi(TREE_INT_CST_LOW (arg0), size), - -16, 15)) - return false; - gimple_seq stmts = NULL; - location_t loc = gimple_location (stmt); - tree splat_value = gimple_convert (&stmts, loc, - TREE_TYPE (TREE_TYPE (lhs)), arg0); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - tree splat_tree = build_vector_from_val (TREE_TYPE (lhs), splat_value); - g = gimple_build_assign (lhs, splat_tree); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - } + int size; + if (fn_code == ALTIVEC_BUILTIN_VSPLTISB) + size = 8; + else if (fn_code == ALTIVEC_BUILTIN_VSPLTISH) + size = 16; + else + size = 32; + + arg0 = gimple_call_arg (stmt, 0); + lhs = gimple_call_lhs (stmt); + + /* Only fold the vec_splat_*() if the lower bits of arg 0 is a + 5-bit signed constant in range -16 to +15. */ + if (TREE_CODE (arg0) != INTEGER_CST + || !IN_RANGE (sext_hwi (TREE_INT_CST_LOW (arg0), size), + -16, 15)) + return false; + gimple_seq stmts = NULL; + location_t loc = gimple_location (stmt); + tree splat_value = gimple_convert (&stmts, loc, + TREE_TYPE (TREE_TYPE (lhs)), arg0); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + tree splat_tree = build_vector_from_val (TREE_TYPE (lhs), splat_value); + g = gimple_build_assign (lhs, splat_tree); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + } /* Flavors of vec_splat. */ /* a = vec_splat (b, 0x3) becomes a = { b[3],b[3],b[3],...}; */ @@ -15977,8 +16017,8 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) case VSX_BUILTIN_VEC_MERGEL_V2DI: case VSX_BUILTIN_XXMRGLW_4SF: case VSX_BUILTIN_VEC_MERGEL_V2DF: - fold_mergehl_helper (gsi, stmt, 1); - return true; + fold_mergehl_helper (gsi, stmt, 1); + return true; /* vec_mergeh (integrals). */ case ALTIVEC_BUILTIN_VMRGHH: case ALTIVEC_BUILTIN_VMRGHW: @@ -15987,55 +16027,70 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) case VSX_BUILTIN_VEC_MERGEH_V2DI: case VSX_BUILTIN_XXMRGHW_4SF: case VSX_BUILTIN_VEC_MERGEH_V2DF: - fold_mergehl_helper (gsi, stmt, 0); - return true; + fold_mergehl_helper (gsi, stmt, 0); + return true; + + /* Flavors of vec_mergee. */ + case P8V_BUILTIN_VMRGEW_V4SI: + case P8V_BUILTIN_VMRGEW_V2DI: + case P8V_BUILTIN_VMRGEW_V4SF: + case P8V_BUILTIN_VMRGEW_V2DF: + fold_mergeeo_helper (gsi, stmt, 0); + return true; + /* Flavors of vec_mergeo. */ + case P8V_BUILTIN_VMRGOW_V4SI: + case P8V_BUILTIN_VMRGOW_V2DI: + case P8V_BUILTIN_VMRGOW_V4SF: + case P8V_BUILTIN_VMRGOW_V2DF: + fold_mergeeo_helper (gsi, stmt, 1); + return true; /* d = vec_pack (a, b) */ case P8V_BUILTIN_VPKUDUM: case ALTIVEC_BUILTIN_VPKUHUM: case ALTIVEC_BUILTIN_VPKUWUM: { - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; } - /* d = vec_unpackh (a) */ - /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call - in this code is sensitive to endian-ness, and needs to be inverted to - handle both LE and BE targets. */ + /* d = vec_unpackh (a) */ + /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call + in this code is sensitive to endian-ness, and needs to be inverted to + handle both LE and BE targets. */ case ALTIVEC_BUILTIN_VUPKHSB: case ALTIVEC_BUILTIN_VUPKHSH: case P8V_BUILTIN_VUPKHSW: { - arg0 = gimple_call_arg (stmt, 0); - lhs = gimple_call_lhs (stmt); - if (BYTES_BIG_ENDIAN) - g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0); - else - g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; + arg0 = gimple_call_arg (stmt, 0); + lhs = gimple_call_lhs (stmt); + if (BYTES_BIG_ENDIAN) + g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0); + else + g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; } - /* d = vec_unpackl (a) */ + /* d = vec_unpackl (a) */ case ALTIVEC_BUILTIN_VUPKLSB: case ALTIVEC_BUILTIN_VUPKLSH: case P8V_BUILTIN_VUPKLSW: { - arg0 = gimple_call_arg (stmt, 0); - lhs = gimple_call_lhs (stmt); - if (BYTES_BIG_ENDIAN) - g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0); - else - g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; + arg0 = gimple_call_arg (stmt, 0); + lhs = gimple_call_lhs (stmt); + if (BYTES_BIG_ENDIAN) + g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0); + else + g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; } /* There is no gimple type corresponding with pixel, so just return. */ case ALTIVEC_BUILTIN_VUPKHPX: