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, &reg_use_analyzer},
243 {BRIG_KIND_INST_MOD, &reg_use_analyzer},
244 {BRIG_KIND_INST_CMP, &reg_use_analyzer},
245 {BRIG_KIND_INST_MEM, &reg_use_analyzer},
246 {BRIG_KIND_INST_CVT, &reg_use_analyzer},
247 {BRIG_KIND_INST_SEG_CVT, &reg_use_analyzer},
248 {BRIG_KIND_INST_SEG, &reg_use_analyzer},
249 {BRIG_KIND_INST_ADDR, &reg_use_analyzer},
250 {BRIG_KIND_INST_SOURCE_TYPE, &reg_use_analyzer},
251 {BRIG_KIND_INST_ATOMIC, &reg_use_analyzer},
252 {BRIG_KIND_INST_SIGNAL, &reg_use_analyzer},
253 {BRIG_KIND_INST_BR, &reg_use_analyzer},
254 {BRIG_KIND_INST_LANE, &reg_use_analyzer},
255 {BRIG_KIND_INST_QUEUE, &reg_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 }