Mercurial > hg > CbC > CbC_gcc
comparison gcc/brig/brigfrontend/brig-to-generic.cc @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* brig2tree.cc -- brig to gcc generic/gimple tree conversion | 1 /* brig2tree.cc -- brig to gcc generic/gimple tree conversion |
2 Copyright (C) 2016-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2016-2018 Free Software Foundation, Inc. |
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com> | 3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com> |
4 for General Processor Tech. | 4 for General Processor Tech. |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
50 #include "errors.h" | 50 #include "errors.h" |
51 #include "fold-const.h" | 51 #include "fold-const.h" |
52 #include "cgraph.h" | 52 #include "cgraph.h" |
53 #include "dumpfile.h" | 53 #include "dumpfile.h" |
54 #include "tree-pretty-print.h" | 54 #include "tree-pretty-print.h" |
55 #include "attribs.h" | |
55 | 56 |
56 extern int gccbrig_verbose; | 57 extern int gccbrig_verbose; |
57 | 58 |
58 tree brig_to_generic::s_fp16_type; | 59 tree brig_to_generic::s_fp16_type; |
59 tree brig_to_generic::s_fp32_type; | 60 tree brig_to_generic::s_fp32_type; |
120 size_t | 121 size_t |
121 operator () (const BrigBase *base) | 122 operator () (const BrigBase *base) |
122 { | 123 { |
123 return base->byteCount; | 124 return base->byteCount; |
124 } | 125 } |
126 }; | |
127 | |
128 class brig_reg_use_analyzer : public brig_code_entry_handler | |
129 { | |
130 public: | |
131 brig_reg_use_analyzer (brig_to_generic &parent) | |
132 : brig_code_entry_handler (parent) | |
133 { | |
134 } | |
135 | |
136 size_t | |
137 operator () (const BrigBase *base) | |
138 { | |
139 const BrigInstBase *brig_inst = (const BrigInstBase *) base; | |
140 analyze_operands (*brig_inst); | |
141 return base->byteCount; | |
142 } | |
143 | |
125 }; | 144 }; |
126 | 145 |
127 /* Helper struct for pairing a BrigKind and a BrigCodeEntryHandler that | 146 /* Helper struct for pairing a BrigKind and a BrigCodeEntryHandler that |
128 should handle its data. */ | 147 should handle its data. */ |
129 | 148 |
208 find_brig_sections (); | 227 find_brig_sections (); |
209 | 228 |
210 brig_directive_variable_handler var_handler (*this); | 229 brig_directive_variable_handler var_handler (*this); |
211 brig_directive_fbarrier_handler fbar_handler (*this); | 230 brig_directive_fbarrier_handler fbar_handler (*this); |
212 brig_directive_function_handler func_handler (*this); | 231 brig_directive_function_handler func_handler (*this); |
232 brig_reg_use_analyzer reg_use_analyzer (*this); | |
213 | 233 |
214 /* Need this for grabbing the module names for mangling the | 234 /* Need this for grabbing the module names for mangling the |
215 group variable names. */ | 235 group variable names. */ |
216 brig_directive_module_handler module_handler (*this); | 236 brig_directive_module_handler module_handler (*this); |
217 skipped_entry_handler skipped_handler (*this); | 237 skipped_entry_handler skipped_handler (*this); |
218 | 238 |
219 const BrigSectionHeader *csection_header = (const BrigSectionHeader *) m_code; | 239 const BrigSectionHeader *csection_header = (const BrigSectionHeader *) m_code; |
220 | 240 |
221 code_entry_handler_info handlers[] | 241 code_entry_handler_info handlers[] |
222 = {{BRIG_KIND_DIRECTIVE_VARIABLE, &var_handler}, | 242 = {{BRIG_KIND_INST_BASIC, ®_use_analyzer}, |
243 {BRIG_KIND_INST_MOD, ®_use_analyzer}, | |
244 {BRIG_KIND_INST_CMP, ®_use_analyzer}, | |
245 {BRIG_KIND_INST_MEM, ®_use_analyzer}, | |
246 {BRIG_KIND_INST_CVT, ®_use_analyzer}, | |
247 {BRIG_KIND_INST_SEG_CVT, ®_use_analyzer}, | |
248 {BRIG_KIND_INST_SEG, ®_use_analyzer}, | |
249 {BRIG_KIND_INST_ADDR, ®_use_analyzer}, | |
250 {BRIG_KIND_INST_SOURCE_TYPE, ®_use_analyzer}, | |
251 {BRIG_KIND_INST_ATOMIC, ®_use_analyzer}, | |
252 {BRIG_KIND_INST_SIGNAL, ®_use_analyzer}, | |
253 {BRIG_KIND_INST_BR, ®_use_analyzer}, | |
254 {BRIG_KIND_INST_LANE, ®_use_analyzer}, | |
255 {BRIG_KIND_INST_QUEUE, ®_use_analyzer}, | |
256 {BRIG_KIND_DIRECTIVE_VARIABLE, &var_handler}, | |
223 {BRIG_KIND_DIRECTIVE_FBARRIER, &fbar_handler}, | 257 {BRIG_KIND_DIRECTIVE_FBARRIER, &fbar_handler}, |
224 {BRIG_KIND_DIRECTIVE_KERNEL, &func_handler}, | 258 {BRIG_KIND_DIRECTIVE_KERNEL, &func_handler}, |
225 {BRIG_KIND_DIRECTIVE_MODULE, &module_handler}, | 259 {BRIG_KIND_DIRECTIVE_MODULE, &module_handler}, |
226 {BRIG_KIND_DIRECTIVE_FUNCTION, &func_handler}}; | 260 {BRIG_KIND_DIRECTIVE_FUNCTION, &func_handler}}; |
227 | 261 |
452 | 486 |
453 tree ptype = build_pointer_type (TREE_TYPE (var_decl)); | 487 tree ptype = build_pointer_type (TREE_TYPE (var_decl)); |
454 tree var_addr = build1 (ADDR_EXPR, ptype, var_decl); | 488 tree var_addr = build1 (ADDR_EXPR, ptype, var_decl); |
455 | 489 |
456 DECL_INITIAL (host_def_var) = var_addr; | 490 DECL_INITIAL (host_def_var) = var_addr; |
457 TREE_PUBLIC (host_def_var) = 0; | 491 TREE_PUBLIC (host_def_var) = 1; |
492 | |
493 set_externally_visible (host_def_var); | |
458 } | 494 } |
459 | 495 |
460 /* Adds an indirection pointer for a potential host-defined program scope | 496 /* Adds an indirection pointer for a potential host-defined program scope |
461 variable declaration. */ | 497 variable declaration. */ |
462 | 498 |
475 TREE_PUBLIC (ptr_var) = 1; | 511 TREE_PUBLIC (ptr_var) = 1; |
476 TREE_USED (ptr_var) = 1; | 512 TREE_USED (ptr_var) = 1; |
477 TREE_ADDRESSABLE (ptr_var) = 1; | 513 TREE_ADDRESSABLE (ptr_var) = 1; |
478 TREE_STATIC (ptr_var) = 1; | 514 TREE_STATIC (ptr_var) = 1; |
479 | 515 |
516 set_externally_visible (ptr_var); | |
517 | |
480 append_global (ptr_var); | 518 append_global (ptr_var); |
481 m_global_variables[var_name] = ptr_var; | 519 m_global_variables[var_name] = ptr_var; |
520 } | |
521 | |
522 void | |
523 brig_to_generic::add_decl_call (tree call) | |
524 { | |
525 m_decl_call.push_back (call); | |
482 } | 526 } |
483 | 527 |
484 /* Produce a "mangled name" for the given brig function or kernel. | 528 /* Produce a "mangled name" for the given brig function or kernel. |
485 The mangling is used to make unique global symbol name in case of | 529 The mangling is used to make unique global symbol name in case of |
486 module scope functions. Program scope functions are not mangled | 530 module scope functions. Program scope functions are not mangled |
553 /* BRIG regs are untyped, but GENERIC is not. We need to add implicit casts | 597 /* BRIG regs are untyped, but GENERIC is not. We need to add implicit casts |
554 in case treating the operand with an instruction with a type different | 598 in case treating the operand with an instruction with a type different |
555 than the created reg var type in order to select correct instruction type | 599 than the created reg var type in order to select correct instruction type |
556 later on. This function creates the necessary reinterpret type cast from | 600 later on. This function creates the necessary reinterpret type cast from |
557 a source variable to the destination type. In case no cast is needed to | 601 a source variable to the destination type. In case no cast is needed to |
558 the same type, SOURCE is returned directly. */ | 602 the same type, SOURCE is returned directly. |
603 | |
604 In case of mismatched type sizes, casting: | |
605 - to narrower type the upper bits are clipped and | |
606 - to wider type the source value is zero extended. */ | |
559 | 607 |
560 tree | 608 tree |
561 build_reinterpret_cast (tree destination_type, tree source) | 609 build_resize_convert_view (tree destination_type, tree source) |
562 { | 610 { |
563 | 611 |
564 gcc_assert (source && destination_type && TREE_TYPE (source) != NULL_TREE | 612 gcc_assert (source && destination_type && TREE_TYPE (source) != NULL_TREE |
565 && destination_type != NULL_TREE); | 613 && destination_type != NULL_TREE); |
566 | 614 |
576 | 624 |
577 size_t src_size = int_size_in_bytes (source_type); | 625 size_t src_size = int_size_in_bytes (source_type); |
578 size_t dst_size = int_size_in_bytes (destination_type); | 626 size_t dst_size = int_size_in_bytes (destination_type); |
579 if (src_size == dst_size) | 627 if (src_size == dst_size) |
580 return build1 (VIEW_CONVERT_EXPR, destination_type, source); | 628 return build1 (VIEW_CONVERT_EXPR, destination_type, source); |
581 else if (src_size < dst_size) | 629 else /* src_size != dst_size */ |
582 { | 630 { |
583 /* The src_size can be smaller at least with f16 scalars which are | 631 /* The src_size can be smaller at least with f16 scalars which are |
584 stored to 32b register variables. First convert to an equivalent | 632 stored to 32b register variables. First convert to an equivalent |
585 size unsigned type, then extend to an unsigned type of the | 633 size unsigned type, then extend to an unsigned type of the |
586 target width, after which VIEW_CONVERT_EXPR can be used to | 634 target width, after which VIEW_CONVERT_EXPR can be used to |
587 force to the target type. */ | 635 force to the target type. */ |
588 tree unsigned_temp = build1 (VIEW_CONVERT_EXPR, | 636 tree resized = convert (get_scalar_unsigned_int_type (destination_type), |
589 get_unsigned_int_type (source_type), | 637 build_reinterpret_to_uint (source)); |
590 source); | 638 gcc_assert ((size_t)int_size_in_bytes (TREE_TYPE (resized)) == dst_size); |
591 return build1 (VIEW_CONVERT_EXPR, destination_type, | 639 return build_resize_convert_view (destination_type, resized); |
592 convert (get_unsigned_int_type (destination_type), | 640 } |
593 unsigned_temp)); | 641 } |
594 } | 642 |
595 else | 643 /* Reinterprets SOURCE as a scalar unsigned int with the size |
596 gcc_unreachable (); | 644 corresponding to the orignal. */ |
597 return NULL_TREE; | 645 |
646 tree build_reinterpret_to_uint (tree source) | |
647 { | |
648 tree src_type = TREE_TYPE (source); | |
649 if (INTEGRAL_TYPE_P (src_type) && TYPE_UNSIGNED (src_type)) | |
650 return source; | |
651 tree dest_type = get_scalar_unsigned_int_type (src_type); | |
652 return build1 (VIEW_CONVERT_EXPR, dest_type, source); | |
598 } | 653 } |
599 | 654 |
600 /* Returns the finished brig_function for the given generic FUNC_DECL, | 655 /* Returns the finished brig_function for the given generic FUNC_DECL, |
601 or NULL, if not found. */ | 656 or NULL, if not found. */ |
602 | 657 |
655 tree bind_expr = m_cf->m_current_bind_expr; | 710 tree bind_expr = m_cf->m_current_bind_expr; |
656 tree stmts = BIND_EXPR_BODY (bind_expr); | 711 tree stmts = BIND_EXPR_BODY (bind_expr); |
657 m_cf->finish (); | 712 m_cf->finish (); |
658 m_cf->emit_metadata (stmts); | 713 m_cf->emit_metadata (stmts); |
659 dump_function (m_dump_file, m_cf); | 714 dump_function (m_dump_file, m_cf); |
660 gimplify_function_tree (m_cf->m_func_decl); | |
661 cgraph_node::finalize_function (m_cf->m_func_decl, true); | |
662 } | 715 } |
663 else | 716 else |
664 /* Emit the kernel only at the very end so we can analyze the total | 717 /* Emit the kernel only at the very end so we can analyze the total |
665 group and private memory usage. */ | 718 group and private memory usage. */ |
666 m_kernels.push_back (m_cf); | 719 m_kernels.push_back (m_cf); |
773 va_start (ap, rettype); | 826 va_start (ap, rettype); |
774 for (int i = 0; i < nargs; ++i) | 827 for (int i = 0; i < nargs; ++i) |
775 { | 828 { |
776 types[i] = va_arg (ap, tree); | 829 types[i] = va_arg (ap, tree); |
777 tree arg = va_arg (ap, tree); | 830 tree arg = va_arg (ap, tree); |
778 args[i] = build_reinterpret_cast (types[i], arg); | 831 args[i] = build_resize_convert_view (types[i], arg); |
779 if (types[i] == error_mark_node || args[i] == error_mark_node) | 832 if (types[i] == error_mark_node || args[i] == error_mark_node) |
780 { | 833 { |
781 delete[] types; | 834 delete[] types; |
782 delete[] args; | 835 delete[] args; |
783 va_end (ap); | 836 va_end (ap); |
800 BRIG has been fed in. */ | 853 BRIG has been fed in. */ |
801 | 854 |
802 void | 855 void |
803 brig_to_generic::write_globals () | 856 brig_to_generic::write_globals () |
804 { | 857 { |
858 | |
859 /* Replace calls to declarations with calls to definitions. Otherwise | |
860 inlining will fail to find the definition to inline from. */ | |
861 | |
862 for (size_t i = 0; i < m_decl_call.size(); ++i) | |
863 { | |
864 tree decl_call = m_decl_call.at(i); | |
865 tree func_decl = get_callee_fndecl (decl_call); | |
866 brig_function *brig_function = get_finished_function (func_decl); | |
867 | |
868 if (brig_function && brig_function->m_func_decl | |
869 && DECL_EXTERNAL (brig_function->m_func_decl) == 0 | |
870 && brig_function->m_func_decl != func_decl) | |
871 { | |
872 | |
873 decl_call = CALL_EXPR_FN (decl_call); | |
874 STRIP_NOPS (decl_call); | |
875 if (TREE_CODE (decl_call) == ADDR_EXPR | |
876 && TREE_CODE (TREE_OPERAND (decl_call, 0)) == FUNCTION_DECL) | |
877 TREE_OPERAND (decl_call, 0) = brig_function->m_func_decl; | |
878 } | |
879 } | |
880 | |
881 for (std::map<std::string, brig_function *>::iterator i | |
882 = m_finished_functions.begin(), e = m_finished_functions.end(); | |
883 i != e; ++i) | |
884 { | |
885 brig_function *brig_f = (*i).second; | |
886 if (brig_f->m_is_kernel) | |
887 continue; | |
888 | |
889 /* Finalize only at this point to allow the cgraph analysis to | |
890 see definitions to calls to later functions. */ | |
891 gimplify_function_tree (brig_f->m_func_decl); | |
892 cgraph_node::finalize_function (brig_f->m_func_decl, true); | |
893 } | |
894 | |
805 /* Now that the whole BRIG module has been processed, build a launcher | 895 /* Now that the whole BRIG module has been processed, build a launcher |
806 and a metadata section for each built kernel. */ | 896 and a metadata section for each built kernel. */ |
807 for (size_t i = 0; i < m_kernels.size (); ++i) | 897 for (size_t i = 0; i < m_kernels.size (); ++i) |
808 { | 898 { |
809 brig_function *f = m_kernels[i]; | 899 brig_function *f = m_kernels[i]; |
834 | 924 |
835 tree launcher = f->emit_launcher_and_metadata (); | 925 tree launcher = f->emit_launcher_and_metadata (); |
836 | 926 |
837 append_global (launcher); | 927 append_global (launcher); |
838 | 928 |
929 if (m_dump_file) | |
930 { | |
931 std::string kern_name = f->m_name.substr (1); | |
932 fprintf (m_dump_file, "\n;; Function %s", kern_name.c_str()); | |
933 fprintf (m_dump_file, "\n;; enabled by -%s\n\n", | |
934 dump_flag_name (TDI_original)); | |
935 print_generic_decl (m_dump_file, launcher, TDF_NONE); | |
936 print_generic_expr (m_dump_file, DECL_SAVED_TREE (launcher), | |
937 TDF_NONE); | |
938 fprintf (m_dump_file, "\n"); | |
939 } | |
940 | |
839 gimplify_function_tree (launcher); | 941 gimplify_function_tree (launcher); |
840 cgraph_node::finalize_function (launcher, true); | 942 cgraph_node::finalize_function (launcher, true); |
841 pop_cfun (); | 943 pop_cfun (); |
842 } | 944 } |
843 | 945 |
867 { | 969 { |
868 if (VECTOR_TYPE_P (original_type)) | 970 if (VECTOR_TYPE_P (original_type)) |
869 { | 971 { |
870 size_t esize | 972 size_t esize |
871 = int_size_in_bytes (TREE_TYPE (original_type)) * BITS_PER_UNIT; | 973 = int_size_in_bytes (TREE_TYPE (original_type)) * BITS_PER_UNIT; |
872 size_t ecount = TYPE_VECTOR_SUBPARTS (original_type); | 974 poly_uint64 ecount = TYPE_VECTOR_SUBPARTS (original_type); |
873 return build_vector_type (build_nonstandard_integer_type (esize, true), | 975 return build_vector_type (build_nonstandard_integer_type (esize, true), |
874 ecount); | 976 ecount); |
875 } | 977 } |
876 else | 978 else |
877 return build_nonstandard_integer_type (int_size_in_bytes (original_type) | 979 return build_nonstandard_integer_type (int_size_in_bytes (original_type) |
878 * BITS_PER_UNIT, | 980 * BITS_PER_UNIT, |
879 true); | 981 true); |
880 } | 982 } |
881 | 983 |
984 /* Returns a type with unsigned int corresponding to the size | |
985 ORIGINAL_TYPE. */ | |
986 | |
987 tree | |
988 get_scalar_unsigned_int_type (tree original_type) | |
989 { | |
990 return build_nonstandard_integer_type (int_size_in_bytes (original_type) | |
991 * BITS_PER_UNIT, true); | |
992 } | |
993 | |
994 /* Set the declaration externally visible so it won't get removed by | |
995 whole program optimizations. */ | |
996 | |
997 void | |
998 set_externally_visible (tree decl) | |
999 { | |
1000 if (!lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) | |
1001 DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("externally_visible"), | |
1002 NULL, DECL_ATTRIBUTES (decl)); | |
1003 } | |
1004 | |
1005 void | |
1006 set_inline (tree decl) | |
1007 { | |
1008 if (!lookup_attribute ("inline", DECL_ATTRIBUTES (decl))) | |
1009 DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("inline"), | |
1010 NULL, DECL_ATTRIBUTES (decl)); | |
1011 } | |
1012 | |
882 void | 1013 void |
883 dump_function (FILE *dump_file, brig_function *f) | 1014 dump_function (FILE *dump_file, brig_function *f) |
884 { | 1015 { |
885 /* Dump the BRIG-specific tree IR. */ | 1016 /* Dump the BRIG-specific tree IR. */ |
886 if (dump_file) | 1017 if (dump_file) |
887 { | 1018 { |
888 fprintf (dump_file, "\n;; Function %s", f->m_name.c_str ()); | 1019 fprintf (dump_file, "\n;; Function %s", f->m_name.c_str ()); |
889 fprintf (dump_file, "\n;; enabled by -%s\n\n", | 1020 fprintf (dump_file, "\n;; enabled by -%s\n\n", |
890 dump_flag_name (TDI_original)); | 1021 dump_flag_name (TDI_original)); |
891 print_generic_decl (dump_file, f->m_func_decl, 0); | 1022 print_generic_decl (dump_file, f->m_func_decl, TDF_NONE); |
892 print_generic_expr (dump_file, f->m_current_bind_expr, 0); | 1023 print_generic_expr (dump_file, f->m_current_bind_expr, TDF_NONE); |
893 fprintf (dump_file, "\n"); | 1024 fprintf (dump_file, "\n"); |
894 } | 1025 } |
895 } | 1026 } |
1027 | |
1028 /* Records use of the BRIG_REG as a TYPE in the current function. */ | |
1029 | |
1030 void | |
1031 brig_to_generic::add_reg_used_as_type (const BrigOperandRegister &brig_reg, | |
1032 tree type) | |
1033 { | |
1034 gcc_assert (m_cf); | |
1035 reg_use_info &info | |
1036 = m_fn_regs_use_index[m_cf->m_name][gccbrig_hsa_reg_id (brig_reg)]; | |
1037 | |
1038 if (info.m_type_refs_lookup.count (type)) | |
1039 info.m_type_refs[info.m_type_refs_lookup[type]].second++; | |
1040 else | |
1041 { | |
1042 info.m_type_refs.push_back (std::make_pair (type, 1)); | |
1043 info.m_type_refs_lookup[type] = info.m_type_refs.size () - 1; | |
1044 } | |
1045 } |