Brig front-end

2017-01-24  Pekka Jääskeläinen <pekka@parmance.com>
	    Martin Jambor  <mjambor@suse.cz>

	* Makefile.def (target_modules): Added libhsail-rt.
	(languages): Added language brig.
	* Makefile.in: Regenerated.
	* configure.ac (TOPLEVEL_CONFIGURE_ARGUMENTS): Added
	tgarget-libhsail-rt.  Make brig unsupported on untested architectures.
	* configure: Regenerated.

gcc/
	* brig-builtins.def: New file.
	* builtins.def (DEF_HSAIL_BUILTIN): New macro.
	(DEF_HSAIL_ATOMIC_BUILTIN): Likewise.
	(DEF_HSAIL_SAT_BUILTIN): Likewise.
	(DEF_HSAIL_INTR_BUILTIN): Likewise.
	(DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN): Likewise.
	* builtin-types.def (BT_INT8): New.
	(BT_INT16): Likewise.
	(BT_UINT8): Likewise.
	(BT_UINT16): Likewise.
	(BT_FN_ULONG): Likewise.
	(BT_FN_UINT_INT): Likewise.
	(BT_FN_UINT_ULONG): Likewise.
	(BT_FN_UINT_LONG): Likewise.
	(BT_FN_UINT_PTR): Likewise.
	(BT_FN_ULONG_PTR): Likewise.
	(BT_FN_INT8_FLOAT): Likewise.
	(BT_FN_INT16_FLOAT): Likewise.
	(BT_FN_UINT32_FLOAT): Likewise.
	(BT_FN_UINT16_FLOAT): Likewise.
	(BT_FN_UINT8_FLOAT): Likewise.
	(BT_FN_UINT64_FLOAT): Likewise.
	(BT_FN_UINT16_UINT32): Likewise.
	(BT_FN_UINT32_UINT16): Likewise.
	(BT_FN_UINT16_UINT16_UINT16): Likewise.
	(BT_FN_INT_PTR_INT): Likewise.
	(BT_FN_UINT_PTR_UINT): Likewise.
	(BT_FN_LONG_PTR_LONG): Likewise.
	(BT_FN_ULONG_PTR_ULONG): Likewise.
	(BT_FN_VOID_UINT64_UINT64): Likewise.
	(BT_FN_UINT8_UINT8_UINT8): Likewise.
	(BT_FN_INT8_INT8_INT8): Likewise.
	(BT_FN_INT16_INT16_INT16): Likewise.
	(BT_FN_INT_INT_INT): Likewise.
	(BT_FN_UINT_FLOAT_UINT): Likewise.
	(BT_FN_FLOAT_UINT_UINT): Likewise.
	(BT_FN_ULONG_UINT_UINT): Likewise.
	(BT_FN_ULONG_UINT_PTR): Likewise.
	(BT_FN_ULONG_ULONG_ULONG): Likewise.
	(BT_FN_UINT_UINT_UINT): Likewise.
	(BT_FN_VOID_UINT_PTR): Likewise.
	(BT_FN_UINT_UINT_PTR: Likewise.
	(BT_FN_UINT32_UINT64_PTR): Likewise.
	(BT_FN_INT_INT_UINT_UINT): Likewise.
	(BT_FN_UINT_UINT_UINT_UINT): Likewise.
	(BT_FN_UINT_UINT_UINT_PTR): Likewise.
	(BT_FN_UINT_ULONG_ULONG_UINT): Likewise.
	(BT_FN_ULONG_ULONG_ULONG_ULONG): Likewise.
	(BT_FN_LONG_LONG_UINT_UINT): Likewise.
	(BT_FN_ULONG_ULONG_UINT_UINT): Likewise.
	(BT_FN_VOID_UINT32_UINT64_PTR): Likewise.
	(BT_FN_VOID_UINT32_UINT32_PTR): Likewise.
	(BT_FN_UINT_UINT_UINT_UINT_UINT): Likewise.
	(BT_FN_UINT_FLOAT_FLOAT_FLOAT_FLOAT): Likewise.
	(BT_FN_ULONG_ULONG_ULONG_UINT_UINT): Likewise.
	* doc/frontends.texi: List BRIG FE.
	* doc/install.texi (Testing): Add BRIG tesring requirements.
	* doc/invoke.texi (Overall Options): Mention BRIG.
	* doc/standards.texi (Standards): Doucment BRIG HSA version.

gcc/brig/

	* Make-lang.in: New file.
	* brig-builtins.h: Likewise.
	* brig-c.h: Likewise.
	* brig-lang.c: Likewise.
	* brigspec.c: Likewise.
	* config-lang.in: Likewise.
	* lang-specs.h: Likewise.
	* lang.opt: Likewise.
	* brigfrontend/brig-arg-block-handler.cc: Likewise.
	* brigfrontend/brig-atomic-inst-handler.cc: Likewise.
	* brigfrontend/brig-basic-inst-handler.cc: Likewise.
	* brigfrontend/brig-branch-inst-handler.cc: Likewise.
	* brigfrontend/brig-cmp-inst-handler.cc: Likewise.
	* brigfrontend/brig-code-entry-handler.cc: Likewise.
	* brigfrontend/brig-code-entry-handler.h: Likewise.
	* brigfrontend/brig-comment-handler.cc: Likewise.
	* brigfrontend/brig-control-handler.cc: Likewise.
	* brigfrontend/brig-copy-move-inst-handler.cc: Likewise.
	* brigfrontend/brig-cvt-inst-handler.cc: Likewise.
	* brigfrontend/brig-fbarrier-handler.cc: Likewise.
	* brigfrontend/brig-function-handler.cc: Likewise.
	* brigfrontend/brig-function.cc: Likewise.
	* brigfrontend/brig-function.h: Likewise.
	* brigfrontend/brig-inst-mod-handler.cc: Likewise.
	* brigfrontend/brig-label-handler.cc: Likewise.
	* brigfrontend/brig-lane-inst-handler.cc: Likewise.
	* brigfrontend/brig-machine.c: Likewise.
	* brigfrontend/brig-machine.h: Likewise.
	* brigfrontend/brig-mem-inst-handler.cc: Likewise.
	* brigfrontend/brig-module-handler.cc: Likewise.
	* brigfrontend/brig-queue-inst-handler.cc: Likewise.
	* brigfrontend/brig-seg-inst-handler.cc: Likewise.
	* brigfrontend/brig-signal-inst-handler.cc: Likewise.
	* brigfrontend/brig-to-generic.cc: Likewise.
	* brigfrontend/brig-to-generic.h: Likewise.
	* brigfrontend/brig-util.cc: Likewise.
	* brigfrontend/brig-util.h: Likewise.
	* brigfrontend/brig-variable-handler.cc: Likewise.
	* brigfrontend/phsa.h: Likewise.


gcc/testsuite/

	* lib/brig-dg.exp: New file.
	* lib/brig.exp: Likewise.
	* brig.dg/README: Likewise.
	* brig.dg/dg.exp: Likewise.
	* brig.dg/test/gimple/alloca.hsail: Likewise.
	* brig.dg/test/gimple/atomics.hsail: Likewise.
	* brig.dg/test/gimple/branches.hsail: Likewise.
	* brig.dg/test/gimple/fbarrier.hsail: Likewise.
	* brig.dg/test/gimple/function_calls.hsail: Likewise.
	* brig.dg/test/gimple/kernarg.hsail: Likewise.
	* brig.dg/test/gimple/mem.hsail: Likewise.
	* brig.dg/test/gimple/mulhi.hsail: Likewise.
	* brig.dg/test/gimple/packed.hsail: Likewise.
	* brig.dg/test/gimple/smoke_test.hsail: Likewise.
	* brig.dg/test/gimple/variables.hsail: Likewise.
	* brig.dg/test/gimple/vector.hsail: Likewise.

include/

	* hsa.h: Moved here from libgomp/plugin/hsa.h.

libgomp/

	* plugin/hsa.h: Moved to top level include.
	* plugin/plugin-hsa.c: Chanfgd include of hsa.h accordingly.

libhsail-rt/

	* Makefile.am: New file.
	* target-config.h.in: Likewise.
	* configure.ac: Likewise.
	* configure: Likewise.
	* config.h.in: Likewise.
	* aclocal.m4: Likewise.
	* README: Likewise.
	* Makefile.in: Likewise.
	* include/internal/fibers.h: Likewise.
	* include/internal/phsa-queue-interface.h: Likewise.
	* include/internal/phsa-rt.h: Likewise.
	* include/internal/workitems.h: Likewise.
	* rt/arithmetic.c: Likewise.
	* rt/atomics.c: Likewise.
	* rt/bitstring.c: Likewise.
	* rt/fbarrier.c: Likewise.
	* rt/fibers.c: Likewise.
	* rt/fp16.c: Likewise.
	* rt/misc.c: Likewise.
	* rt/multimedia.c: Likewise.
	* rt/queue.c: Likewise.
	* rt/sat_arithmetic.c: Likewise.
	* rt/segment.c: Likewise.
	* rt/workitems.c: Likewise.


Co-Authored-By: Martin Jambor <mjambor@suse.cz>

From-SVN: r244867
This commit is contained in:
Pekka Jääskeläinen 2017-01-24 12:45:56 +00:00 committed by Martin Jambor
parent e1e41b6f10
commit 5fd1486ce5
99 changed files with 34461 additions and 4 deletions

View file

@ -1,3 +1,14 @@
2017-01-24 Pekka Jääskeläinen <pekka@parmance.com>
Martin Jambor <mjambor@suse.cz>
* Makefile.def (target_modules): Added libhsail-rt.
(languages): Added language brig.
* Makefile.in: Regenerated.
* configure.ac (TOPLEVEL_CONFIGURE_ARGUMENTS): Added
tgarget-libhsail-rt. Make brig unsupported on untested architectures.
* configure: Regenerated.
2017-01-19 Uros Bizjak <ubizjak@gmail.com>
PR target/78478

View file

@ -157,6 +157,7 @@ target_modules = { module= libquadmath; };
target_modules = { module= libgfortran; };
target_modules = { module= libobjc; };
target_modules = { module= libgo; };
target_modules = { module= libhsail-rt; };
target_modules = { module= libtermcap; no_check=true;
missing=mostlyclean;
missing=clean;
@ -601,6 +602,8 @@ languages = { language=objc; gcc-check-target=check-objc;
languages = { language=obj-c++; gcc-check-target=check-obj-c++; };
languages = { language=go; gcc-check-target=check-go;
lib-check-target=check-target-libgo; };
languages = { language=brig; gcc-check-target=check-brig;
lib-check-target=check-target-libhsail-rt; };
// Toplevel bootstrap
bootstrap_stage = { id=1 ; };

View file

@ -993,6 +993,7 @@ configure-target: \
maybe-configure-target-libgfortran \
maybe-configure-target-libobjc \
maybe-configure-target-libgo \
maybe-configure-target-libhsail-rt \
maybe-configure-target-libtermcap \
maybe-configure-target-winsup \
maybe-configure-target-libgloss \
@ -1158,6 +1159,7 @@ all-target: maybe-all-target-libquadmath
all-target: maybe-all-target-libgfortran
all-target: maybe-all-target-libobjc
all-target: maybe-all-target-libgo
all-target: maybe-all-target-libhsail-rt
all-target: maybe-all-target-libtermcap
all-target: maybe-all-target-winsup
all-target: maybe-all-target-libgloss
@ -1250,6 +1252,7 @@ info-target: maybe-info-target-libquadmath
info-target: maybe-info-target-libgfortran
info-target: maybe-info-target-libobjc
info-target: maybe-info-target-libgo
info-target: maybe-info-target-libhsail-rt
info-target: maybe-info-target-libtermcap
info-target: maybe-info-target-winsup
info-target: maybe-info-target-libgloss
@ -1335,6 +1338,7 @@ dvi-target: maybe-dvi-target-libquadmath
dvi-target: maybe-dvi-target-libgfortran
dvi-target: maybe-dvi-target-libobjc
dvi-target: maybe-dvi-target-libgo
dvi-target: maybe-dvi-target-libhsail-rt
dvi-target: maybe-dvi-target-libtermcap
dvi-target: maybe-dvi-target-winsup
dvi-target: maybe-dvi-target-libgloss
@ -1420,6 +1424,7 @@ pdf-target: maybe-pdf-target-libquadmath
pdf-target: maybe-pdf-target-libgfortran
pdf-target: maybe-pdf-target-libobjc
pdf-target: maybe-pdf-target-libgo
pdf-target: maybe-pdf-target-libhsail-rt
pdf-target: maybe-pdf-target-libtermcap
pdf-target: maybe-pdf-target-winsup
pdf-target: maybe-pdf-target-libgloss
@ -1505,6 +1510,7 @@ html-target: maybe-html-target-libquadmath
html-target: maybe-html-target-libgfortran
html-target: maybe-html-target-libobjc
html-target: maybe-html-target-libgo
html-target: maybe-html-target-libhsail-rt
html-target: maybe-html-target-libtermcap
html-target: maybe-html-target-winsup
html-target: maybe-html-target-libgloss
@ -1590,6 +1596,7 @@ TAGS-target: maybe-TAGS-target-libquadmath
TAGS-target: maybe-TAGS-target-libgfortran
TAGS-target: maybe-TAGS-target-libobjc
TAGS-target: maybe-TAGS-target-libgo
TAGS-target: maybe-TAGS-target-libhsail-rt
TAGS-target: maybe-TAGS-target-libtermcap
TAGS-target: maybe-TAGS-target-winsup
TAGS-target: maybe-TAGS-target-libgloss
@ -1675,6 +1682,7 @@ install-info-target: maybe-install-info-target-libquadmath
install-info-target: maybe-install-info-target-libgfortran
install-info-target: maybe-install-info-target-libobjc
install-info-target: maybe-install-info-target-libgo
install-info-target: maybe-install-info-target-libhsail-rt
install-info-target: maybe-install-info-target-libtermcap
install-info-target: maybe-install-info-target-winsup
install-info-target: maybe-install-info-target-libgloss
@ -1760,6 +1768,7 @@ install-pdf-target: maybe-install-pdf-target-libquadmath
install-pdf-target: maybe-install-pdf-target-libgfortran
install-pdf-target: maybe-install-pdf-target-libobjc
install-pdf-target: maybe-install-pdf-target-libgo
install-pdf-target: maybe-install-pdf-target-libhsail-rt
install-pdf-target: maybe-install-pdf-target-libtermcap
install-pdf-target: maybe-install-pdf-target-winsup
install-pdf-target: maybe-install-pdf-target-libgloss
@ -1845,6 +1854,7 @@ install-html-target: maybe-install-html-target-libquadmath
install-html-target: maybe-install-html-target-libgfortran
install-html-target: maybe-install-html-target-libobjc
install-html-target: maybe-install-html-target-libgo
install-html-target: maybe-install-html-target-libhsail-rt
install-html-target: maybe-install-html-target-libtermcap
install-html-target: maybe-install-html-target-winsup
install-html-target: maybe-install-html-target-libgloss
@ -1930,6 +1940,7 @@ installcheck-target: maybe-installcheck-target-libquadmath
installcheck-target: maybe-installcheck-target-libgfortran
installcheck-target: maybe-installcheck-target-libobjc
installcheck-target: maybe-installcheck-target-libgo
installcheck-target: maybe-installcheck-target-libhsail-rt
installcheck-target: maybe-installcheck-target-libtermcap
installcheck-target: maybe-installcheck-target-winsup
installcheck-target: maybe-installcheck-target-libgloss
@ -2015,6 +2026,7 @@ mostlyclean-target: maybe-mostlyclean-target-libquadmath
mostlyclean-target: maybe-mostlyclean-target-libgfortran
mostlyclean-target: maybe-mostlyclean-target-libobjc
mostlyclean-target: maybe-mostlyclean-target-libgo
mostlyclean-target: maybe-mostlyclean-target-libhsail-rt
mostlyclean-target: maybe-mostlyclean-target-libtermcap
mostlyclean-target: maybe-mostlyclean-target-winsup
mostlyclean-target: maybe-mostlyclean-target-libgloss
@ -2100,6 +2112,7 @@ clean-target: maybe-clean-target-libquadmath
clean-target: maybe-clean-target-libgfortran
clean-target: maybe-clean-target-libobjc
clean-target: maybe-clean-target-libgo
clean-target: maybe-clean-target-libhsail-rt
clean-target: maybe-clean-target-libtermcap
clean-target: maybe-clean-target-winsup
clean-target: maybe-clean-target-libgloss
@ -2185,6 +2198,7 @@ distclean-target: maybe-distclean-target-libquadmath
distclean-target: maybe-distclean-target-libgfortran
distclean-target: maybe-distclean-target-libobjc
distclean-target: maybe-distclean-target-libgo
distclean-target: maybe-distclean-target-libhsail-rt
distclean-target: maybe-distclean-target-libtermcap
distclean-target: maybe-distclean-target-winsup
distclean-target: maybe-distclean-target-libgloss
@ -2270,6 +2284,7 @@ maintainer-clean-target: maybe-maintainer-clean-target-libquadmath
maintainer-clean-target: maybe-maintainer-clean-target-libgfortran
maintainer-clean-target: maybe-maintainer-clean-target-libobjc
maintainer-clean-target: maybe-maintainer-clean-target-libgo
maintainer-clean-target: maybe-maintainer-clean-target-libhsail-rt
maintainer-clean-target: maybe-maintainer-clean-target-libtermcap
maintainer-clean-target: maybe-maintainer-clean-target-winsup
maintainer-clean-target: maybe-maintainer-clean-target-libgloss
@ -2411,6 +2426,7 @@ check-target: \
maybe-check-target-libgfortran \
maybe-check-target-libobjc \
maybe-check-target-libgo \
maybe-check-target-libhsail-rt \
maybe-check-target-libtermcap \
maybe-check-target-winsup \
maybe-check-target-libgloss \
@ -2592,6 +2608,7 @@ install-target: \
maybe-install-target-libgfortran \
maybe-install-target-libobjc \
maybe-install-target-libgo \
maybe-install-target-libhsail-rt \
maybe-install-target-libtermcap \
maybe-install-target-winsup \
maybe-install-target-libgloss \
@ -2697,6 +2714,7 @@ install-strip-target: \
maybe-install-strip-target-libgfortran \
maybe-install-strip-target-libobjc \
maybe-install-strip-target-libgo \
maybe-install-strip-target-libhsail-rt \
maybe-install-strip-target-libtermcap \
maybe-install-strip-target-winsup \
maybe-install-strip-target-libgloss \
@ -46096,6 +46114,464 @@ maintainer-clean-target-libgo:
.PHONY: configure-target-libhsail-rt maybe-configure-target-libhsail-rt
maybe-configure-target-libhsail-rt:
@if gcc-bootstrap
configure-target-libhsail-rt: stage_current
@endif gcc-bootstrap
@if target-libhsail-rt
maybe-configure-target-libhsail-rt: configure-target-libhsail-rt
configure-target-libhsail-rt:
@: $(MAKE); $(unstage)
@r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
echo "Checking multilib configuration for libhsail-rt..."; \
$(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libhsail-rt; \
$(CC_FOR_TARGET) --print-multi-lib > $(TARGET_SUBDIR)/libhsail-rt/multilib.tmp 2> /dev/null; \
if test -r $(TARGET_SUBDIR)/libhsail-rt/multilib.out; then \
if cmp -s $(TARGET_SUBDIR)/libhsail-rt/multilib.tmp $(TARGET_SUBDIR)/libhsail-rt/multilib.out; then \
rm -f $(TARGET_SUBDIR)/libhsail-rt/multilib.tmp; \
else \
rm -f $(TARGET_SUBDIR)/libhsail-rt/Makefile; \
mv $(TARGET_SUBDIR)/libhsail-rt/multilib.tmp $(TARGET_SUBDIR)/libhsail-rt/multilib.out; \
fi; \
else \
mv $(TARGET_SUBDIR)/libhsail-rt/multilib.tmp $(TARGET_SUBDIR)/libhsail-rt/multilib.out; \
fi; \
test ! -f $(TARGET_SUBDIR)/libhsail-rt/Makefile || exit 0; \
$(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libhsail-rt; \
$(NORMAL_TARGET_EXPORTS) \
echo Configuring in $(TARGET_SUBDIR)/libhsail-rt; \
cd "$(TARGET_SUBDIR)/libhsail-rt" || exit 1; \
case $(srcdir) in \
/* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
*) topdir=`echo $(TARGET_SUBDIR)/libhsail-rt/ | \
sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
esac; \
module_srcdir=libhsail-rt; \
rm -f no-such-file || : ; \
CONFIG_SITE=no-such-file $(SHELL) \
$$s/$$module_srcdir/configure \
--srcdir=$${topdir}/$$module_srcdir \
$(TARGET_CONFIGARGS) --build=${build_alias} --host=${target_alias} \
--target=${target_alias} \
|| exit 1
@endif target-libhsail-rt
.PHONY: all-target-libhsail-rt maybe-all-target-libhsail-rt
maybe-all-target-libhsail-rt:
@if gcc-bootstrap
all-target-libhsail-rt: stage_current
@endif gcc-bootstrap
@if target-libhsail-rt
TARGET-target-libhsail-rt=all
maybe-all-target-libhsail-rt: all-target-libhsail-rt
all-target-libhsail-rt: configure-target-libhsail-rt
@: $(MAKE); $(unstage)
@r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS) \
$(TARGET-target-libhsail-rt))
@endif target-libhsail-rt
.PHONY: check-target-libhsail-rt maybe-check-target-libhsail-rt
maybe-check-target-libhsail-rt:
@if target-libhsail-rt
maybe-check-target-libhsail-rt: check-target-libhsail-rt
check-target-libhsail-rt:
@: $(MAKE); $(unstage)
@r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(TARGET_FLAGS_TO_PASS) check)
@endif target-libhsail-rt
.PHONY: install-target-libhsail-rt maybe-install-target-libhsail-rt
maybe-install-target-libhsail-rt:
@if target-libhsail-rt
maybe-install-target-libhsail-rt: install-target-libhsail-rt
install-target-libhsail-rt: installdirs
@: $(MAKE); $(unstage)
@r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(TARGET_FLAGS_TO_PASS) install)
@endif target-libhsail-rt
.PHONY: install-strip-target-libhsail-rt maybe-install-strip-target-libhsail-rt
maybe-install-strip-target-libhsail-rt:
@if target-libhsail-rt
maybe-install-strip-target-libhsail-rt: install-strip-target-libhsail-rt
install-strip-target-libhsail-rt: installdirs
@: $(MAKE); $(unstage)
@r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(TARGET_FLAGS_TO_PASS) install-strip)
@endif target-libhsail-rt
# Other targets (info, dvi, pdf, etc.)
.PHONY: maybe-info-target-libhsail-rt info-target-libhsail-rt
maybe-info-target-libhsail-rt:
@if target-libhsail-rt
maybe-info-target-libhsail-rt: info-target-libhsail-rt
info-target-libhsail-rt: \
configure-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing info in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
info) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-dvi-target-libhsail-rt dvi-target-libhsail-rt
maybe-dvi-target-libhsail-rt:
@if target-libhsail-rt
maybe-dvi-target-libhsail-rt: dvi-target-libhsail-rt
dvi-target-libhsail-rt: \
configure-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing dvi in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
dvi) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-pdf-target-libhsail-rt pdf-target-libhsail-rt
maybe-pdf-target-libhsail-rt:
@if target-libhsail-rt
maybe-pdf-target-libhsail-rt: pdf-target-libhsail-rt
pdf-target-libhsail-rt: \
configure-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing pdf in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
pdf) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-html-target-libhsail-rt html-target-libhsail-rt
maybe-html-target-libhsail-rt:
@if target-libhsail-rt
maybe-html-target-libhsail-rt: html-target-libhsail-rt
html-target-libhsail-rt: \
configure-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing html in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
html) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-TAGS-target-libhsail-rt TAGS-target-libhsail-rt
maybe-TAGS-target-libhsail-rt:
@if target-libhsail-rt
maybe-TAGS-target-libhsail-rt: TAGS-target-libhsail-rt
TAGS-target-libhsail-rt: \
configure-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing TAGS in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
TAGS) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-install-info-target-libhsail-rt install-info-target-libhsail-rt
maybe-install-info-target-libhsail-rt:
@if target-libhsail-rt
maybe-install-info-target-libhsail-rt: install-info-target-libhsail-rt
install-info-target-libhsail-rt: \
configure-target-libhsail-rt \
info-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing install-info in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
install-info) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-install-pdf-target-libhsail-rt install-pdf-target-libhsail-rt
maybe-install-pdf-target-libhsail-rt:
@if target-libhsail-rt
maybe-install-pdf-target-libhsail-rt: install-pdf-target-libhsail-rt
install-pdf-target-libhsail-rt: \
configure-target-libhsail-rt \
pdf-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing install-pdf in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
install-pdf) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-install-html-target-libhsail-rt install-html-target-libhsail-rt
maybe-install-html-target-libhsail-rt:
@if target-libhsail-rt
maybe-install-html-target-libhsail-rt: install-html-target-libhsail-rt
install-html-target-libhsail-rt: \
configure-target-libhsail-rt \
html-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing install-html in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
install-html) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-installcheck-target-libhsail-rt installcheck-target-libhsail-rt
maybe-installcheck-target-libhsail-rt:
@if target-libhsail-rt
maybe-installcheck-target-libhsail-rt: installcheck-target-libhsail-rt
installcheck-target-libhsail-rt: \
configure-target-libhsail-rt
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing installcheck in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
installcheck) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-mostlyclean-target-libhsail-rt mostlyclean-target-libhsail-rt
maybe-mostlyclean-target-libhsail-rt:
@if target-libhsail-rt
maybe-mostlyclean-target-libhsail-rt: mostlyclean-target-libhsail-rt
mostlyclean-target-libhsail-rt:
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing mostlyclean in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
mostlyclean) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-clean-target-libhsail-rt clean-target-libhsail-rt
maybe-clean-target-libhsail-rt:
@if target-libhsail-rt
maybe-clean-target-libhsail-rt: clean-target-libhsail-rt
clean-target-libhsail-rt:
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing clean in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
clean) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-distclean-target-libhsail-rt distclean-target-libhsail-rt
maybe-distclean-target-libhsail-rt:
@if target-libhsail-rt
maybe-distclean-target-libhsail-rt: distclean-target-libhsail-rt
distclean-target-libhsail-rt:
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing distclean in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
distclean) \
|| exit 1
@endif target-libhsail-rt
.PHONY: maybe-maintainer-clean-target-libhsail-rt maintainer-clean-target-libhsail-rt
maybe-maintainer-clean-target-libhsail-rt:
@if target-libhsail-rt
maybe-maintainer-clean-target-libhsail-rt: maintainer-clean-target-libhsail-rt
maintainer-clean-target-libhsail-rt:
@: $(MAKE); $(unstage)
@[ -f $(TARGET_SUBDIR)/libhsail-rt/Makefile ] || exit 0; \
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(NORMAL_TARGET_EXPORTS) \
echo "Doing maintainer-clean in $(TARGET_SUBDIR)/libhsail-rt"; \
for flag in $(EXTRA_TARGET_FLAGS); do \
eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
done; \
(cd $(TARGET_SUBDIR)/libhsail-rt && \
$(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
"CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
"RANLIB=$${RANLIB}" \
"DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
maintainer-clean) \
|| exit 1
@endif target-libhsail-rt
.PHONY: configure-target-libtermcap maybe-configure-target-libtermcap
maybe-configure-target-libtermcap:
@if gcc-bootstrap
@ -51382,6 +51858,14 @@ check-gcc-go:
(cd gcc && $(MAKE) $(GCC_FLAGS_TO_PASS) check-go);
check-go: check-gcc-go check-target-libgo
.PHONY: check-gcc-brig check-brig
check-gcc-brig:
r=`${PWD_COMMAND}`; export r; \
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(HOST_EXPORTS) \
(cd gcc && $(MAKE) $(GCC_FLAGS_TO_PASS) check-brig);
check-brig: check-gcc-brig check-target-libhsail-rt
# The gcc part of install-no-fixedincludes, which relies on an intimate
# knowledge of how a number of gcc internal targets (inter)operate. Delegate.
@ -54259,6 +54743,7 @@ configure-target-libquadmath: stage_last
configure-target-libgfortran: stage_last
configure-target-libobjc: stage_last
configure-target-libgo: stage_last
configure-target-libhsail-rt: stage_last
configure-target-libtermcap: stage_last
configure-target-winsup: stage_last
configure-target-libgloss: stage_last
@ -54293,6 +54778,7 @@ configure-target-libquadmath: maybe-all-gcc
configure-target-libgfortran: maybe-all-gcc
configure-target-libobjc: maybe-all-gcc
configure-target-libgo: maybe-all-gcc
configure-target-libhsail-rt: maybe-all-gcc
configure-target-libtermcap: maybe-all-gcc
configure-target-winsup: maybe-all-gcc
configure-target-libgloss: maybe-all-gcc
@ -55445,6 +55931,7 @@ configure-target-libquadmath: maybe-all-target-libgcc
configure-target-libgfortran: maybe-all-target-libgcc
configure-target-libobjc: maybe-all-target-libgcc
configure-target-libgo: maybe-all-target-libgcc
configure-target-libhsail-rt: maybe-all-target-libgcc
configure-target-libtermcap: maybe-all-target-libgcc
configure-target-winsup: maybe-all-target-libgcc
configure-target-libgloss: maybe-all-target-libgcc
@ -55486,6 +55973,8 @@ configure-target-libobjc: maybe-all-target-newlib maybe-all-target-libgloss
configure-target-libgo: maybe-all-target-newlib maybe-all-target-libgloss
configure-target-libhsail-rt: maybe-all-target-newlib maybe-all-target-libgloss
configure-target-libtermcap: maybe-all-target-newlib maybe-all-target-libgloss
configure-target-winsup: maybe-all-target-newlib maybe-all-target-libgloss

14
configure vendored
View file

@ -2754,6 +2754,7 @@ target_libraries="target-libgcc \
target-libgomp \
target-libcilkrts \
target-liboffloadmic \
target-libhsail-rt \
target-libatomic \
target-libitm \
target-libstdc++-v3 \
@ -3482,6 +3483,19 @@ if test x$enable_libgo = x; then
esac
fi
# Disable the BRIG frontend and libhsail-rt on untested or known
# broken systems. Currently it has been tested only on x86_64 Linux
# of the upstream gcc targets. More targets shall be added after testing.
case "${target}" in
x86_64-*-linux*)
;;
*)
unsupported_languages="$unsupported_languages brig"
# This implicitly disables also target-libhsail-rt as it won't
# get added to the build without BRIG FE.
;;
esac
# Default libgloss CPU subdirectory.
libgloss_dir="$target_cpu"

View file

@ -152,6 +152,7 @@ target_libraries="target-libgcc \
target-libgomp \
target-libcilkrts \
target-liboffloadmic \
target-libhsail-rt \
target-libatomic \
target-libitm \
target-libstdc++-v3 \
@ -812,6 +813,19 @@ if test x$enable_libgo = x; then
esac
fi
# Disable the BRIG frontend and libhsail-rt on untested or known
# broken systems. Currently it has been tested only on x86_64 Linux
# of the upstream gcc targets. More targets shall be added after testing.
case "${target}" in
x86_64-*-linux*)
;;
*)
unsupported_languages="$unsupported_languages brig"
# This implicitly disables also target-libhsail-rt as it won't
# get added to the build without BRIG FE.
;;
esac
# Default libgloss CPU subdirectory.
libgloss_dir="$target_cpu"

View file

@ -1,3 +1,66 @@
2017-01-24 Pekka Jääskeläinen <pekka@parmance.com>
Martin Jambor <mjambor@suse.cz>
* brig-builtins.def: New file.
* builtins.def (DEF_HSAIL_BUILTIN): New macro.
(DEF_HSAIL_ATOMIC_BUILTIN): Likewise.
(DEF_HSAIL_SAT_BUILTIN): Likewise.
(DEF_HSAIL_INTR_BUILTIN): Likewise.
(DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN): Likewise.
* builtin-types.def (BT_INT8): New.
(BT_INT16): Likewise.
(BT_UINT8): Likewise.
(BT_UINT16): Likewise.
(BT_FN_ULONG): Likewise.
(BT_FN_UINT_INT): Likewise.
(BT_FN_UINT_ULONG): Likewise.
(BT_FN_UINT_LONG): Likewise.
(BT_FN_UINT_PTR): Likewise.
(BT_FN_ULONG_PTR): Likewise.
(BT_FN_INT8_FLOAT): Likewise.
(BT_FN_INT16_FLOAT): Likewise.
(BT_FN_UINT32_FLOAT): Likewise.
(BT_FN_UINT16_FLOAT): Likewise.
(BT_FN_UINT8_FLOAT): Likewise.
(BT_FN_UINT64_FLOAT): Likewise.
(BT_FN_UINT16_UINT32): Likewise.
(BT_FN_UINT32_UINT16): Likewise.
(BT_FN_UINT16_UINT16_UINT16): Likewise.
(BT_FN_INT_PTR_INT): Likewise.
(BT_FN_UINT_PTR_UINT): Likewise.
(BT_FN_LONG_PTR_LONG): Likewise.
(BT_FN_ULONG_PTR_ULONG): Likewise.
(BT_FN_VOID_UINT64_UINT64): Likewise.
(BT_FN_UINT8_UINT8_UINT8): Likewise.
(BT_FN_INT8_INT8_INT8): Likewise.
(BT_FN_INT16_INT16_INT16): Likewise.
(BT_FN_INT_INT_INT): Likewise.
(BT_FN_UINT_FLOAT_UINT): Likewise.
(BT_FN_FLOAT_UINT_UINT): Likewise.
(BT_FN_ULONG_UINT_UINT): Likewise.
(BT_FN_ULONG_UINT_PTR): Likewise.
(BT_FN_ULONG_ULONG_ULONG): Likewise.
(BT_FN_UINT_UINT_UINT): Likewise.
(BT_FN_VOID_UINT_PTR): Likewise.
(BT_FN_UINT_UINT_PTR: Likewise.
(BT_FN_UINT32_UINT64_PTR): Likewise.
(BT_FN_INT_INT_UINT_UINT): Likewise.
(BT_FN_UINT_UINT_UINT_UINT): Likewise.
(BT_FN_UINT_UINT_UINT_PTR): Likewise.
(BT_FN_UINT_ULONG_ULONG_UINT): Likewise.
(BT_FN_ULONG_ULONG_ULONG_ULONG): Likewise.
(BT_FN_LONG_LONG_UINT_UINT): Likewise.
(BT_FN_ULONG_ULONG_UINT_UINT): Likewise.
(BT_FN_VOID_UINT32_UINT64_PTR): Likewise.
(BT_FN_VOID_UINT32_UINT32_PTR): Likewise.
(BT_FN_UINT_UINT_UINT_UINT_UINT): Likewise.
(BT_FN_UINT_FLOAT_FLOAT_FLOAT_FLOAT): Likewise.
(BT_FN_ULONG_ULONG_ULONG_UINT_UINT): Likewise.
* doc/frontends.texi: List BRIG FE.
* doc/install.texi (Testing): Add BRIG tesring requirements.
* doc/invoke.texi (Overall Options): Mention BRIG.
* doc/standards.texi (Standards): Doucment BRIG HSA version.
2017-01-24 Richard Biener <rguenther@suse.de>
PR translation/79208

659
gcc/brig-builtins.def Normal file
View file

@ -0,0 +1,659 @@
/* This file contains the definitions and documentation for the
HSAIL builtins used in the GNU compiler.
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* Following builtins are used by the BRIG (the binary representation of
HSAIL) frontend. Software implementations are available in libhsail-rt.
Use leading double underscore in the name to avoid name space clashes
with kernel program symbols in case the builtin is implemented as
a function call. */
/* Work-item ID related builtins are not constant in the work-group function
mode (each WI has a different return value). */
#ifndef DEF_HSAIL_BUILTIN
#define DEF_HSAIL_BUILTIN(ENUM, HSAIL_OPCODE, HSAIL_TYPE, \
NAME, TYPE, ATTRS)
#endif
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WORKITEMABSID, BRIG_OPCODE_WORKITEMABSID,
BRIG_TYPE_U32, "__hsail_workitemabsid", BT_FN_UINT_UINT_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_GRIDSIZE, BRIG_OPCODE_GRIDSIZE,
BRIG_TYPE_U32, "__hsail_gridsize", BT_FN_UINT_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WORKITEMFLATABSID_U32,
BRIG_OPCODE_WORKITEMFLATABSID, BRIG_TYPE_U32,
"__hsail_workitemflatabsid_u32", BT_FN_UINT_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WORKITEMFLATABSID_U64,
BRIG_OPCODE_WORKITEMFLATABSID, BRIG_TYPE_U64,
"__hsail_workitemflatabsid_u64", BT_FN_ULONG_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WORKITEMFLATID, BRIG_OPCODE_WORKITEMFLATID,
BRIG_TYPE_U32, "__hsail_workitemflatid", BT_FN_UINT_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WORKITEMID, BRIG_OPCODE_WORKITEMID,
BRIG_TYPE_U32, "__hsail_workitemid", BT_FN_UINT_UINT_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WORKGROUPID, BRIG_OPCODE_WORKGROUPID,
BRIG_TYPE_U32, "__hsail_workgroupid", BT_FN_UINT_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CURRENTWORKITEMFLATID,
BRIG_OPCODE_CURRENTWORKITEMFLATID,
BRIG_TYPE_U32, "__hsail_currentworkitemflatid",
BT_FN_UINT_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WORKITEMABSID_U64, BRIG_OPCODE_WORKITEMABSID,
BRIG_TYPE_U64, "__hsail_workitemabsid_u64",
BT_FN_ULONG_UINT_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_PACKETID, BRIG_OPCODE_PACKETID,
BRIG_TYPE_U64, "__hsail_packetid", BT_FN_ULONG_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_PACKETCOMPLETIONSIG_SIG64,
BRIG_OPCODE_PACKETCOMPLETIONSIG, BRIG_TYPE_SIG64,
"__hsail_packetcompletionsig_sig64", BT_FN_ULONG_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_PACKETCOMPLETIONSIG_SIG32,
BRIG_OPCODE_PACKETCOMPLETIONSIG, BRIG_TYPE_SIG32,
"__hsail_packetcompletionsig_sig32", BT_FN_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CURRENTWORKGROUPSIZE,
BRIG_OPCODE_CURRENTWORKGROUPSIZE, BRIG_TYPE_U32,
"__hsail_currentworkgroupsize", BT_FN_UINT_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WORKGROUPSIZE, BRIG_OPCODE_WORKGROUPSIZE,
BRIG_TYPE_U32, "__hsail_workgroupsize", BT_FN_UINT_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_DIM, BRIG_OPCODE_DIM,
BRIG_TYPE_U32, "__hsail_dim", BT_FN_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_GRIDGROUPS, BRIG_OPCODE_GRIDGROUPS,
BRIG_TYPE_U32, "__hsail_gridgroups", BT_FN_UINT_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITEXTRACT_S32, BRIG_OPCODE_BITEXTRACT,
BRIG_TYPE_S32, "__hsail_bitextract_s32",
BT_FN_INT_INT_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITEXTRACT_U32, BRIG_OPCODE_BITEXTRACT,
BRIG_TYPE_U32, "__hsail_bitextract_u32",
BT_FN_UINT_UINT_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITEXTRACT_S64, BRIG_OPCODE_BITEXTRACT,
BRIG_TYPE_S64, "__hsail_bitextract_s64",
BT_FN_LONG_LONG_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITEXTRACT_U64, BRIG_OPCODE_BITEXTRACT,
BRIG_TYPE_U64, "__hsail_bitextract_u64",
BT_FN_ULONG_ULONG_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITINSERT_U32, BRIG_OPCODE_BITINSERT,
BRIG_TYPE_U32, "__hsail_bitinsert_u32",
BT_FN_UINT_UINT_UINT_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITINSERT_U64, BRIG_OPCODE_BITINSERT,
BRIG_TYPE_U64, "__hsail_bitinsert_u64",
BT_FN_ULONG_ULONG_ULONG_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITMASK_B32, BRIG_OPCODE_BITMASK,
BRIG_TYPE_B32, "__hsail_bitmask_u32", BT_FN_UINT_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITMASK_B64, BRIG_OPCODE_BITMASK,
BRIG_TYPE_B64, "__hsail_bitmask_u64", BT_FN_ULONG_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITREV_B32, BRIG_OPCODE_BITREV,
BRIG_TYPE_B32, "__hsail_bitrev_u32", BT_FN_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITREV_B64, BRIG_OPCODE_BITREV,
BRIG_TYPE_B64, "__hsail_bitrev_u64", BT_FN_ULONG_ULONG,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITSELECT_B32, BRIG_OPCODE_BITSELECT,
BRIG_TYPE_B32, "__hsail_bitselect_u32",
BT_FN_UINT_UINT_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITSELECT_U64, BRIG_OPCODE_BITSELECT,
BRIG_TYPE_B64, "__hsail_bitselect_u64",
BT_FN_ULONG_ULONG_ULONG_ULONG, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_FIRSTBIT_U32, BRIG_OPCODE_FIRSTBIT,
BRIG_TYPE_U32, "__hsail_firstbit_u32", BT_FN_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_FIRSTBIT_S32, BRIG_OPCODE_FIRSTBIT,
BRIG_TYPE_S32, "__hsail_firstbit_s32", BT_FN_UINT_INT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_FIRSTBIT_U64, BRIG_OPCODE_FIRSTBIT,
BRIG_TYPE_U64, "__hsail_firstbit_u64", BT_FN_UINT_ULONG,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_FIRSTBIT_S64, BRIG_OPCODE_FIRSTBIT,
BRIG_TYPE_S64, "__hsail_firstbit_s64", BT_FN_UINT_LONG,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_LASTBIT_U32, BRIG_OPCODE_LASTBIT,
BRIG_TYPE_U32, "__hsail_lastbit_u32", BT_FN_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_LASTBIT_U64, BRIG_OPCODE_LASTBIT,
BRIG_TYPE_U64, "__hsail_lastbit_u64", BT_FN_UINT_ULONG,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BORROW_U32, BRIG_OPCODE_BORROW,
BRIG_TYPE_U32, "__hsail_borrow_u32", BT_FN_UINT_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BORROW_U64, BRIG_OPCODE_BORROW,
BRIG_TYPE_U64, "__hsail_borrow_u64", BT_FN_ULONG_ULONG_ULONG,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CARRY_U32, BRIG_OPCODE_CARRY,
BRIG_TYPE_U32, "__hsail_carry_u32", BT_FN_UINT_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CARRY_U64, BRIG_OPCODE_CARRY,
BRIG_TYPE_U64, "__hsail_carry_u64", BT_FN_ULONG_ULONG_ULONG,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_REM_S32, BRIG_OPCODE_REM,
BRIG_TYPE_S32, "__hsail_rem_s32", BT_FN_INT_INT_INT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_REM_S64, BRIG_OPCODE_REM,
BRIG_TYPE_S64, "__hsail_rem_s64", BT_FN_LONG_LONG_LONG,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_MIN_F32, BRIG_OPCODE_MIN,
BRIG_TYPE_F32, "__hsail_min_f32", BT_FN_FLOAT_FLOAT_FLOAT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_MAX_F32, BRIG_OPCODE_MAX,
BRIG_TYPE_F32, "__hsail_max_f32", BT_FN_FLOAT_FLOAT_FLOAT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_MIN_F64, BRIG_OPCODE_MIN,
BRIG_TYPE_F64, "__hsail_min_f64", BT_FN_DOUBLE_DOUBLE_DOUBLE,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_MAX_F64, BRIG_OPCODE_MAX,
BRIG_TYPE_F64, "__hsail_max_f64", BT_FN_DOUBLE_DOUBLE_DOUBLE,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CLASS_F32, BRIG_OPCODE_CLASS,
BRIG_TYPE_F32, "__hsail_class_f32", BT_FN_UINT_FLOAT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CLASS_F32_F16, BRIG_OPCODE_CLASS,
BRIG_TYPE_F16, "__hsail_class_f32_f16", BT_FN_UINT_FLOAT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_FRACT_F32, BRIG_OPCODE_FRACT,
BRIG_TYPE_F32, "__hsail_fract_f32", BT_FN_FLOAT_FLOAT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_FRACT_F64, BRIG_OPCODE_FRACT,
BRIG_TYPE_F64, "__hsail_fract_f64", BT_FN_DOUBLE_DOUBLE,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BARRIER, BRIG_OPCODE_BARRIER,
BRIG_TYPE_NONE, "__hsail_barrier", BT_FN_VOID_PTR,
ATTR_NOTHROW_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_INITFBAR, BRIG_OPCODE_INITFBAR,
BRIG_TYPE_NONE, "__hsail_initfbar", BT_FN_VOID_UINT_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_JOINFBAR, BRIG_OPCODE_JOINFBAR,
BRIG_TYPE_NONE, "__hsail_joinfbar", BT_FN_VOID_UINT_PTR,
ATTR_NOTHROW_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_WAITFBAR, BRIG_OPCODE_WAITFBAR,
BRIG_TYPE_NONE, "__hsail_waitfbar", BT_FN_VOID_UINT_PTR,
ATTR_NOTHROW_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_ARRIVEFBAR, BRIG_OPCODE_ARRIVEFBAR,
BRIG_TYPE_NONE, "__hsail_arrivefbar", BT_FN_VOID_UINT_PTR,
ATTR_NOTHROW_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_LEAVEFBAR, BRIG_OPCODE_LEAVEFBAR,
BRIG_TYPE_NONE, "__hsail_leavefbar", BT_FN_VOID_UINT_PTR,
ATTR_NOTHROW_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_RELEASEFBAR, BRIG_OPCODE_RELEASEFBAR,
BRIG_TYPE_NONE, "__hsail_releasefbar", BT_FN_VOID_UINT_PTR,
ATTR_NOTHROW_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BITALIGN, BRIG_OPCODE_BITALIGN,
BRIG_TYPE_B32, "__hsail_bitalign",
BT_FN_UINT_ULONG_ULONG_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_BYTEALIGN, BRIG_OPCODE_BYTEALIGN,
BRIG_TYPE_B32, "__hsail_bytealign",
BT_FN_UINT_ULONG_ULONG_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_LERP, BRIG_OPCODE_LERP,
BRIG_TYPE_U8X4, "__hsail_lerp", BT_FN_UINT_UINT_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_PACKCVT, BRIG_OPCODE_PACKCVT,
BRIG_TYPE_U8X4, "__hsail_packcvt",
BT_FN_UINT_FLOAT_FLOAT_FLOAT_FLOAT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_UNPACKCVT, BRIG_OPCODE_UNPACKCVT,
BRIG_TYPE_F32, "__hsail_unpackcvt", BT_FN_FLOAT_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_SAD_U16X2, BRIG_OPCODE_SAD,
BRIG_TYPE_U16X2, "__hsail_sad_u16x2",
BT_FN_UINT_UINT_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_SAD_U32, BRIG_OPCODE_SAD,
BRIG_TYPE_U32, "__hsail_sad_u32", BT_FN_UINT_UINT_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_SAD_U8X4, BRIG_OPCODE_SAD,
BRIG_TYPE_U8X4, "__hsail_sad_u8x4", BT_FN_UINT_UINT_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_SADHI_U8X4, BRIG_OPCODE_SADHI,
BRIG_TYPE_U16X2, "__hsail_sadhi_u16x2_u8x4",
BT_FN_UINT_UINT_UINT_UINT,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CLOCK, BRIG_OPCODE_CLOCK,
BRIG_TYPE_U64, "__hsail_clock", BT_FN_ULONG,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CUID, BRIG_OPCODE_CUID,
BRIG_TYPE_U32, "__hsail_cuid", BT_FN_UINT_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_MAXCUID, BRIG_OPCODE_MAXCUID,
BRIG_TYPE_U32, "__hsail_maxcuid", BT_FN_UINT_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_DEBUGTRAP, BRIG_OPCODE_DEBUGTRAP,
BRIG_TYPE_U32, "__hsail_debugtrap", BT_FN_VOID_UINT_PTR,
ATTR_NORETURN_NOTHROW_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_GROUPBASEPTR, BRIG_OPCODE_GROUPBASEPTR,
BRIG_TYPE_U32, "__hsail_groupbaseptr", BT_FN_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_KERNARGBASEPTR_U64,
BRIG_OPCODE_KERNARGBASEPTR, BRIG_TYPE_U64,
"__hsail_kernargbaseptr_u64", BT_FN_ULONG_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_KERNARGBASEPTR_U32,
BRIG_OPCODE_KERNARGBASEPTR, BRIG_TYPE_U32,
"__hsail_kernargbaseptr_u32", BT_FN_UINT_PTR,
ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_ALLOCA, BRIG_OPCODE_ALLOCA,
BRIG_TYPE_U32, "__hsail_alloca", BT_FN_UINT_UINT_UINT_PTR,
ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_LDQUEUEWRITEINDEX,
BRIG_OPCODE_LDQUEUEWRITEINDEX,
BRIG_TYPE_U64, "__hsail_ldqueuewriteindex",
BT_FN_ULONG_ULONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_LDQUEUEREADINDEX,
BRIG_OPCODE_LDQUEUEREADINDEX,
BRIG_TYPE_U64, "__hsail_ldqueuereadindex",
BT_FN_ULONG_ULONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_STQUEUEWRITEINDEX,
BRIG_OPCODE_STQUEUEWRITEINDEX,
BRIG_TYPE_U64, "__hsail_stqueuewriteindex",
BT_FN_VOID_UINT64_UINT64, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_STQUEUEREADINDEX,
BRIG_OPCODE_STQUEUEREADINDEX,
BRIG_TYPE_U64, "__hsail_stqueuereadindex",
BT_FN_VOID_UINT64_UINT64, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_ADDQUEUEWRITEINDEX,
BRIG_OPCODE_ADDQUEUEWRITEINDEX,
BRIG_TYPE_U64, "__hsail_addqueuewriteindex",
BT_FN_ULONG_ULONG_ULONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_CASQUEUEWRITEINDEX,
BRIG_OPCODE_CASQUEUEWRITEINDEX,
BRIG_TYPE_U64, "__hsail_casqueuewriteindex",
BT_FN_ULONG_ULONG_ULONG_ULONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_SEGMENTP_GLOBAL,
BRIG_OPCODE_SEGMENTP,
BRIG_TYPE_U32, "__hsail_segmentp_global",
BT_FN_UINT32_UINT64_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_SEGMENTP_GROUP,
BRIG_OPCODE_SEGMENTP,
BRIG_TYPE_U32, "__hsail_segmentp_group",
BT_FN_UINT32_UINT64_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_BUILTIN (BUILT_IN_HSAIL_SEGMENTP_PRIVATE,
BRIG_OPCODE_SEGMENTP,
BRIG_TYPE_U32, "__hsail_segmentp_private",
BT_FN_UINT32_UINT64_PTR, ATTR_NOTHROW_LEAF_LIST)
#ifndef DEF_HSAIL_ATOMIC_BUILTIN
#define DEF_HSAIL_ATOMIC_BUILTIN(ENUM, ATOMIC_OPCODE, HSAIL_TYPE, \
NAME, TYPE, ATTRS)
#endif
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_MIN_S32, BRIG_ATOMIC_MIN,
BRIG_TYPE_S32, "__hsail_atomic_min_s32",
BT_FN_INT_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_MIN_S64, BRIG_ATOMIC_MIN,
BRIG_TYPE_S64, "__hsail_atomic_min_s64",
BT_FN_LONG_PTR_LONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_MIN_U32, BRIG_ATOMIC_MIN,
BRIG_TYPE_U32, "__hsail_atomic_min_u32",
BT_FN_UINT_PTR_UINT, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_MIN_U64, BRIG_ATOMIC_MIN,
BRIG_TYPE_U64, "__hsail_atomic_min_u64",
BT_FN_ULONG_PTR_ULONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_MAX_S32, BRIG_ATOMIC_MAX,
BRIG_TYPE_S32, "__hsail_atomic_max_s32",
BT_FN_INT_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_MAX_S64, BRIG_ATOMIC_MAX,
BRIG_TYPE_S64, "__hsail_atomic_max_s64",
BT_FN_LONG_PTR_LONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_MAX_U32, BRIG_ATOMIC_MAX,
BRIG_TYPE_U32, "__hsail_atomic_max_u32",
BT_FN_UINT_PTR_UINT, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_MAX_U64, BRIG_ATOMIC_MAX,
BRIG_TYPE_U64, "__hsail_atomic_max_u64",
BT_FN_ULONG_PTR_ULONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_WRAPDEC_U32,
BRIG_ATOMIC_WRAPDEC, BRIG_TYPE_U32,
"__hsail_atomic_wrapdec_u32",
BT_FN_UINT_PTR_UINT, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_WRAPDEC_U64,
BRIG_ATOMIC_WRAPDEC, BRIG_TYPE_U64,
"__hsail_atomic_wrapdec_u64",
BT_FN_ULONG_PTR_ULONG, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_WRAPINC_U32,
BRIG_ATOMIC_WRAPINC, BRIG_TYPE_U32,
"__hsail_atomic_wrapinc_u32",
BT_FN_UINT_PTR_UINT, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_ATOMIC_BUILTIN (BUILT_IN_HSAIL_ATOMIC_WRAPINC_U64,
BRIG_ATOMIC_WRAPINC, BRIG_TYPE_U64,
"__hsail_atomic_wrapinc_u64",
BT_FN_ULONG_PTR_ULONG, ATTR_NOTHROW_LEAF_LIST)
#ifndef DEF_HSAIL_SAT_BUILTIN
#define DEF_HSAIL_SAT_BUILTIN(ENUM, HSAIL_OPCODE, HSAIL_TYPE, \
NAME, TYPE, ATTRS)
#endif
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_ADD_U64, BRIG_OPCODE_ADD,
BRIG_TYPE_U64, "__hsail_sat_add_u64",
BT_FN_ULONG_ULONG_ULONG, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_ADD_S64, BRIG_OPCODE_ADD,
BRIG_TYPE_S64, "__hsail_sat_add_s64",
BT_FN_LONG_LONG_LONG, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_ADD_U32, BRIG_OPCODE_ADD,
BRIG_TYPE_U32, "__hsail_sat_add_u32",
BT_FN_UINT_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_ADD_S32, BRIG_OPCODE_ADD,
BRIG_TYPE_S32, "__hsail_sat_add_s32",
BT_FN_INT_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_ADD_U16, BRIG_OPCODE_ADD,
BRIG_TYPE_U16, "__hsail_sat_add_u16",
BT_FN_UINT16_UINT16_UINT16, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_ADD_S16, BRIG_OPCODE_ADD,
BRIG_TYPE_S16, "__hsail_sat_add_s16",
BT_FN_INT16_INT16_INT16, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_ADD_U8, BRIG_OPCODE_ADD,
BRIG_TYPE_U8, "__hsail_sat_add_u8",
BT_FN_UINT8_UINT8_UINT8, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_ADD_S8, BRIG_OPCODE_ADD,
BRIG_TYPE_S8, "__hsail_sat_add_s8",
BT_FN_INT8_INT8_INT8, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_SUB_U64, BRIG_OPCODE_SUB,
BRIG_TYPE_U64, "__hsail_sat_sub_u64",
BT_FN_ULONG_ULONG_ULONG, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_SUB_S64, BRIG_OPCODE_SUB,
BRIG_TYPE_S64, "__hsail_sat_sub_s64",
BT_FN_LONG_LONG_LONG, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_SUB_U32, BRIG_OPCODE_SUB,
BRIG_TYPE_U32, "__hsail_sat_sub_u32",
BT_FN_UINT_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_SUB_S32, BRIG_OPCODE_SUB,
BRIG_TYPE_S32, "__hsail_sat_sub_s32",
BT_FN_INT_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_SUB_U16, BRIG_OPCODE_SUB,
BRIG_TYPE_U16, "__hsail_sat_sub_u16",
BT_FN_UINT16_UINT16_UINT16, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_SUB_S16, BRIG_OPCODE_SUB,
BRIG_TYPE_S16, "__hsail_sat_sub_s16",
BT_FN_INT16_INT16_INT16, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_SUB_U8, BRIG_OPCODE_SUB,
BRIG_TYPE_U8, "__hsail_sat_sub_u8",
BT_FN_UINT8_UINT8_UINT8, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_SUB_S8, BRIG_OPCODE_SUB,
BRIG_TYPE_S8, "__hsail_sat_sub_s8",
BT_FN_INT8_INT8_INT8, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_MUL_U64, BRIG_OPCODE_MUL,
BRIG_TYPE_U64, "__hsail_sat_mul_u64",
BT_FN_ULONG_ULONG_ULONG, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_MUL_S64, BRIG_OPCODE_MUL,
BRIG_TYPE_S64, "__hsail_sat_mul_s64",
BT_FN_LONG_LONG_LONG, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_MUL_U32, BRIG_OPCODE_MUL,
BRIG_TYPE_U32, "__hsail_sat_mul_u32",
BT_FN_UINT_UINT_UINT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_MUL_S32, BRIG_OPCODE_MUL,
BRIG_TYPE_S32, "__hsail_sat_mul_s32",
BT_FN_INT_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_MUL_U16, BRIG_OPCODE_MUL,
BRIG_TYPE_U16, "__hsail_sat_mul_u16",
BT_FN_UINT16_UINT16_UINT16, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_MUL_S16, BRIG_OPCODE_MUL,
BRIG_TYPE_S16, "__hsail_sat_mul_s16",
BT_FN_INT16_INT16_INT16, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_MUL_U8, BRIG_OPCODE_MUL,
BRIG_TYPE_U8, "__hsail_sat_mul_u8",
BT_FN_UINT8_UINT8_UINT8, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_SAT_BUILTIN (BUILT_IN_HSAIL_SAT_MUL_S8, BRIG_OPCODE_MUL,
BRIG_TYPE_S8, "__hsail_sat_mul_s8",
BT_FN_INT8_INT8_INT8, ATTR_PURE_NOTHROW_LEAF_LIST)
#ifndef DEF_HSAIL_INTR_BUILTIN
#define DEF_HSAIL_INTR_BUILTIN(ENUM, NAME, TYPE, ATTRS)
#endif
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_FTZ_F32_F16, "__hsail_ftz_f32_f16",
BT_FN_FLOAT_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_FTZ_F32, "__hsail_ftz_f32",
BT_FN_FLOAT_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_FTZ_F64, "__hsail_ftz_f64",
BT_FN_DOUBLE_DOUBLE, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_PUSH_FRAME, "__hsail_alloca_push_frame",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_POP_FRAME, "__hsail_alloca_pop_frame",
BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_SETWORKITEMID, "__hsail_setworkitemid",
BT_FN_VOID_UINT32_UINT32_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_LAUNCH_WG_FUNC,
"__hsail_launch_wg_function",
BT_FN_VOID_PTR_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_LAUNCH_KERNEL,
"__hsail_launch_kernel",
BT_FN_VOID_PTR_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_F32_TO_F16, "__hsail_f32_to_f16",
BT_FN_UINT16_UINT32, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_INTR_BUILTIN (BUILT_IN_HSAIL_F16_TO_F32, "__hsail_f16_to_f32",
BT_FN_UINT32_UINT16, ATTR_PURE_NOTHROW_LEAF_LIST)
#ifndef DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN
#define DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN(ENUM, HSAIL_DEST_TYPE, HSAIL_SRC_TYPE, \
NAME, TYPE, ATTRS)
#endif
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_U8_F32,
BRIG_TYPE_U8, BRIG_TYPE_F32,
"__hsail_cvt_zeroi_sat_u8_f32",
BT_FN_UINT8_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_S8_F32,
BRIG_TYPE_S8, BRIG_TYPE_F32,
"__hsail_cvt_zeroi_sat_s8_f32",
BT_FN_INT8_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_U16_F32,
BRIG_TYPE_U16, BRIG_TYPE_F32,
"__hsail_cvt_zeroi_sat_u16_f32",
BT_FN_UINT16_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_S16_F32,
BRIG_TYPE_S16, BRIG_TYPE_F32,
"__hsail_cvt_zeroi_sat_s16_f32",
BT_FN_INT16_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_U32_F32,
BRIG_TYPE_U32, BRIG_TYPE_F32,
"__hsail_cvt_zeroi_sat_u32_f32",
BT_FN_UINT32_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_S32_F32,
BRIG_TYPE_S32, BRIG_TYPE_F32,
"__hsail_cvt_zeroi_sat_s32_f32",
BT_FN_INT_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_U64_F32,
BRIG_TYPE_U64, BRIG_TYPE_F32,
"__hsail_cvt_zeroi_sat_u64_f32",
BT_FN_UINT64_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_S64_F32,
BRIG_TYPE_S64, BRIG_TYPE_F32,
"__hsail_cvt_zeroi_sat_s64_f32",
BT_FN_LONG_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_U8_F64,
BRIG_TYPE_U8, BRIG_TYPE_F64,
"__hsail_cvt_zeroi_sat_u8_f64",
BT_FN_UINT8_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_S8_F64,
BRIG_TYPE_S8, BRIG_TYPE_F64,
"__hsail_cvt_zeroi_sat_s8_f64",
BT_FN_INT8_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_U16_F64,
BRIG_TYPE_U16, BRIG_TYPE_F64,
"__hsail_cvt_zeroi_sat_u16_f64",
BT_FN_UINT16_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_S16_F64,
BRIG_TYPE_S16, BRIG_TYPE_F64,
"__hsail_cvt_zeroi_sat_s16_f64",
BT_FN_INT16_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_U32_F64,
BRIG_TYPE_U32, BRIG_TYPE_F64,
"__hsail_cvt_zeroi_sat_u32_f64",
BT_FN_UINT32_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_S32_F64,
BRIG_TYPE_S32, BRIG_TYPE_F64,
"__hsail_cvt_zeroi_sat_s32_f64",
BT_FN_INT_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_U64_F64,
BRIG_TYPE_U64, BRIG_TYPE_F64,
"__hsail_cvt_zeroi_sat_u64_f64",
BT_FN_UINT64_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)
DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN (BUILT_IN_HSAIL_CVT_ZEROI_SAT_S64_F64,
BRIG_TYPE_S64, BRIG_TYPE_F64,
"__hsail_cvt_zeroi_sat_s64_f64",
BT_FN_LONG_FLOAT, ATTR_PURE_NOTHROW_LEAF_LIST)

42
gcc/brig/ChangeLog Normal file
View file

@ -0,0 +1,42 @@
2017-01-24 Pekka Jääskeläinen <pekka@parmance.com>
Martin Jambor <mjambor@suse.cz>
* Make-lang.in: New file.
* brig-builtins.h: Likewise.
* brig-c.h: Likewise.
* brig-lang.c: Likewise.
* brigspec.c: Likewise.
* config-lang.in: Likewise.
* lang-specs.h: Likewise.
* lang.opt: Likewise.
* brigfrontend/brig-arg-block-handler.cc: Likewise.
* brigfrontend/brig-atomic-inst-handler.cc: Likewise.
* brigfrontend/brig-basic-inst-handler.cc: Likewise.
* brigfrontend/brig-branch-inst-handler.cc: Likewise.
* brigfrontend/brig-cmp-inst-handler.cc: Likewise.
* brigfrontend/brig-code-entry-handler.cc: Likewise.
* brigfrontend/brig-code-entry-handler.h: Likewise.
* brigfrontend/brig-comment-handler.cc: Likewise.
* brigfrontend/brig-control-handler.cc: Likewise.
* brigfrontend/brig-copy-move-inst-handler.cc: Likewise.
* brigfrontend/brig-cvt-inst-handler.cc: Likewise.
* brigfrontend/brig-fbarrier-handler.cc: Likewise.
* brigfrontend/brig-function-handler.cc: Likewise.
* brigfrontend/brig-function.cc: Likewise.
* brigfrontend/brig-function.h: Likewise.
* brigfrontend/brig-inst-mod-handler.cc: Likewise.
* brigfrontend/brig-label-handler.cc: Likewise.
* brigfrontend/brig-lane-inst-handler.cc: Likewise.
* brigfrontend/brig-machine.c: Likewise.
* brigfrontend/brig-machine.h: Likewise.
* brigfrontend/brig-mem-inst-handler.cc: Likewise.
* brigfrontend/brig-module-handler.cc: Likewise.
* brigfrontend/brig-queue-inst-handler.cc: Likewise.
* brigfrontend/brig-seg-inst-handler.cc: Likewise.
* brigfrontend/brig-signal-inst-handler.cc: Likewise.
* brigfrontend/brig-to-generic.cc: Likewise.
* brigfrontend/brig-to-generic.h: Likewise.
* brigfrontend/brig-util.cc: Likewise.
* brigfrontend/brig-util.h: Likewise.
* brigfrontend/brig-variable-handler.cc: Likewise.
* brigfrontend/phsa.h: Likewise.

247
gcc/brig/Make-lang.in Normal file
View file

@ -0,0 +1,247 @@
# Make-lang.in -- Top level -*- makefile -*- fragment for gcc BRIG (HSAIL)
# frontend.
# Copyright (C) 2015 Free Software Foundation, Inc.
# This file is part of GCC.
# GCC is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# GCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# This file provides the language dependent support in the main Makefile.
# Installation name.
GCCBRIG_INSTALL_NAME := $(shell echo gccbrig|sed '$(program_transform_name)')
GCCBRIG_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccbrig|sed \
'$(program_transform_name)')
# The name for selecting brig in LANGUAGES.
brig: brig1$(exeext)
.PHONY: brig
CFLAGS-brig/brigspec.o += $(DRIVER_DEFINES)
GCCBRIG_OBJS = $(GCC_OBJS) brig/brigspec.o
gccbrig$(exeext): $(GCCBRIG_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
$(LIBDEPS)
+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(GCCBRIG_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
$(EXTRA_GCC_LIBS) $(LIBS)
# The cross-compiler version. This is built mainly as a signal to the
# brig.install-common target. If this executable exists, it means that
# brig.all.cross was run.
gccbrig-cross$(exeext): gccbrig$(exeext)
-rm -f gccbrig-cross$(exeext)
cp gccbrig$(exeext) gccbrig-cross$(exeext)
# Use strict warnings.
brig-warn = $(STRICT_WARN)
BRIG_OBJS = \
brig/brig-lang.o \
brig/brig-code-entry-handler.o \
brig/brig-function-handler.o \
brig/brig-variable-handler.o \
brig/brig-fbarrier-handler.o \
brig/brig-label-handler.o \
brig/brig-comment-handler.o \
brig/brig-basic-inst-handler.o \
brig/brig-cvt-inst-handler.o \
brig/brig-seg-inst-handler.o \
brig/brig-lane-inst-handler.o \
brig/brig-queue-inst-handler.o \
brig/brig-copy-move-inst-handler.o \
brig/brig-signal-inst-handler.o \
brig/brig-atomic-inst-handler.o \
brig/brig-arg-block-handler.o \
brig/brig-control-handler.o \
brig/brig-cmp-inst-handler.o \
brig/brig-branch-inst-handler.o \
brig/brig-mem-inst-handler.o \
brig/brig-module-handler.o \
brig/brig-inst-mod-handler.o \
brig/brig-function.o \
brig/brig-to-generic.o \
brig/brig-machine.o \
brig/brig-util.o
brig_OBJS = $(BRIG_OBJS) brig/brigspec.o
# brig1$(exeext): $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
# +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
# $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
brig1$(exeext): $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(BRIG_OBJS) attribs.o $(BACKEND) $(LIBS) \
$(BACKENDLIBS)
# Documentation.
GO_TEXI_FILES = \
brig/gccbrig.texi \
$(gcc_docdir)/include/fdl.texi \
$(gcc_docdir)/include/gpl_v3.texi \
$(gcc_docdir)/include/gcc-common.texi \
gcc-vers.texi
# doc/gccbrig.info: $(BRIG_TEXI_FILES)
# if test "x$(BUILD_INFO)" = xinfo; then \
# rm -f doc/gccbrig.info*; \
# $(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \
# -I $(gcc_docdir)/include -o $@ $<; \
# else true; fi
# doc/gccbrig.dvi: $(BRIG_TEXI_FILES)
# $(TEXI2DVI) -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
# doc/gccbrig.pdf: $(BRIG_TEXI_FILES)
# $(TEXI2PDF) -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
$(build_htmldir)/brig/index.html: $(BRIG_TEXI_FILES)
$(mkinstalldirs) $(@D)
rm -f $(@D)/*
$(TEXI2HTML) -I $(gcc_docdir) -I $(gcc_docdir)/include \
-I $(srcdir)/brig -o $(@D) $<
# Build hooks.
brig.all.cross: gccbrig-cross$(exeext)
brig.start.encap: gccbrig$(exeext)
brig.rest.encap:
#brig.info: doc/gccbrig.info
brig.info:
brig.dvi: doc/gccbrig.dvi
brig.pdf: doc/gccbrig.pdf
brig.html: $(build_htmldir)/brig/index.html
brig.srcinfo: #doc/gccbrig.info
# -cp -p $^ $(srcdir)/doc
brig.srcextra:
brig.tags: force
cd $(srcdir)/brig; \
etags -o TAGS.sub *.c *.h; \
etags --include TAGS.sub --include ../TAGS.sub
brig.man:
#brig.srcman: doc/gccbrig.1
# -cp -p $^ $(srcdir)/doc
lang_checks += check-brig
# Install hooks.
brig.install-common: installdirs
-rm -f $(DESTDIR)$(bindir)/$(GCCBRIG_INSTALL_NAME)$(exeext)
$(INSTALL_PROGRAM) gccbrig$(exeext) \
$(DESTDIR)$(bindir)/$(GCCBRIG_INSTALL_NAME)$(exeext)
-if test -f brig1$(exeext); then \
if test -f gccbrig-cross$(exeext); then \
:; \
else \
rm -f $(DESTDIR)$(bindir)/$(GCCBRIG_TARGET_INSTALL_NAME)$(exeext); \
( cd $(DESTDIR)$(bindir) && \
$(LN) $(GCCBRIG_INSTALL_NAME)$(exeext) \
$(GCCBRIG_TARGET_INSTALL_NAME)$(exeext) ); \
fi; \
fi
brig.install-plugin:
brig.install-info: #$(DESTDIR)$(infodir)/gccbrig.info
brig.install-pdf: doc/gccbrig.pdf
@$(NORMAL_INSTALL)
test -z "$(pdfdir)" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)/gcc"
@for p in doc/gccbrig.pdf; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(pdf__strip_dir) \
echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(pdfdir)/gcc/$$f'"; \
$(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/gcc/$$f"; \
done
brig.install-html: $(build_htmldir)/brig
@$(NORMAL_INSTALL)
test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
@for p in $(build_htmldir)/brig; do \
if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; \
fi; \
f=$(html__strip_dir) \
if test -d "$$d$$p"; then \
echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \
$(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \
$(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \
else \
echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \
$(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \
fi; \
done
brig.install-man: #$(DESTDIR)$(man1dir)/$(GCCBRIG_INSTALL_NAME)$(man1ext)
#$(DESTDIR)$(man1dir)/$(GCCBRIG_INSTALL_NAME)$(man1ext): doc/gccbrig.1 \
# installdirs
# -rm -f $@
# -$(INSTALL_DATA) $< $@
# -chmod a-x $@
brig.uninstall:
rm -rf $(DESTDIR)$(bindir)/$(GCCBRIG_INSTALL_NAME)$(exeext)
rm -rf $(DESTDIR)$(man1dir)/$(GCCBRIG_INSTALL_NAME)$(man1ext)
rm -rf $(DESTDIR)$(bindir)/$(GCCBRIG_TARGET_INSTALL_NAME)$(exeext)
rm -rf $(DESTDIR)$(infodir)/gccbrig.info*
# Clean hooks.
brig.mostlyclean:
-rm -f brig/*$(objext)
-rm -f brig/*$(coverageexts)
brig.clean:
brig.distclean:
brig.maintainer-clean:
-rm -f $(docobjdir)/gccbrig.1
# Stage hooks.
brig.stage1: stage1-start
-mv brig/*$(objext) stage1/brig
brig.stage2: stage2-start
-mv brig/*$(objext) stage2/brig
brig.stage3: stage3-start
-mv brig/*$(objext) stage3/brig
brig.stage4: stage4-start
-mv brig/*$(objext) stage4/brig
brig.stageprofile: stageprofile-start
-mv brig/*$(objext) stageprofile/brig
brig.stagefeedback: stagefeedback-start
-mv brig/*$(objext) stagefeedback/brig
CFLAGS-brig/brig-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \
-DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\"
BRIGINCLUDES = -I $(srcdir)/brig -I ${HOME}/local/include \
-I $(srcdir)/brig/brigfrontend
brig/brig-machine.o: brig/brigfrontend/brig-machine.c
$(COMPILE) $(BRIGINCLUDES) $<
$(POSTCOMPILE)
brig/%.o: brig/brigfrontend/%.cc
$(COMPILE) $(BRIGINCLUDES) $<
$(POSTCOMPILE)

99
gcc/brig/brig-builtins.h Normal file
View file

@ -0,0 +1,99 @@
/* brig-builtins.h -- brig builtin definitions
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
enum built_in_attribute
{
#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
#define DEF_ATTR_STRING(ENUM, VALUE) ENUM,
#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
#include "builtin-attrs.def"
#undef DEF_ATTR_NULL_TREE
#undef DEF_ATTR_INT
#undef DEF_ATTR_STRING
#undef DEF_ATTR_IDENT
#undef DEF_ATTR_TREE_LIST
ATTR_LAST
};
/* Builtin types. */
enum brig_builtin_type
{
#define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
#define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6) NAME,
#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7) NAME,
#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7, ARG8) NAME,
#define DEF_FUNCTION_TYPE_9(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7, ARG8, ARG9) NAME,
#define DEF_FUNCTION_TYPE_10(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7, ARG8, ARG9, ARG10) NAME,
#define DEF_FUNCTION_TYPE_11(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) NAME,
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \
NAME,
#define DEF_FUNCTION_TYPE_VAR_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6) NAME,
#define DEF_FUNCTION_TYPE_VAR_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7) NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
#undef DEF_FUNCTION_TYPE_0
#undef DEF_FUNCTION_TYPE_1
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
#undef DEF_FUNCTION_TYPE_7
#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_9
#undef DEF_FUNCTION_TYPE_10
#undef DEF_FUNCTION_TYPE_11
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_FUNCTION_TYPE_VAR_4
#undef DEF_FUNCTION_TYPE_VAR_5
#undef DEF_FUNCTION_TYPE_VAR_6
#undef DEF_FUNCTION_TYPE_VAR_7
#undef DEF_POINTER_TYPE
BT_LAST
};
typedef enum brig_builtin_type builtin_type;

66
gcc/brig/brig-c.h Normal file
View file

@ -0,0 +1,66 @@
/* brig-c.h -- Header file for brig input's gcc C interface.
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef BRIG_BRIG_C_H
#define BRIG_BRIG_C_H
#define BRIG_EXTERN_C
#include "machmode.h"
/* Functions defined in the Brig frontend proper called by the GCC
interface. */
extern int brig_enable_dump (const char *);
extern int brig_enable_optimize (const char *);
extern void brig_add_search_path (const char *);
extern void brig_create_brigbrig (int int_type_size, int pointer_size,
const char *pkgpath, const char *prefix,
const char *relative_import_path);
extern void brig_parse_input_files (const char **, unsigned int,
bool only_check_syntax,
bool require_return_statement);
extern void brig_write_globals (void);
extern tree brig_type_for_size (unsigned int bits, int unsignedp);
extern tree brig_type_for_mode (enum machine_mode, int unsignedp);
/* Functions defined in the GCC interface called by the Brig frontend
proper. */
extern void brig_preserve_from_gc (tree);
extern const char *brig_localize_identifier (const char *);
extern unsigned int brig_field_alignment (tree);
extern void brig_trampoline_info (unsigned int *size, unsigned int *alignment);
extern void brig_imported_unsafe (void);
extern void brig_write_export_data (const char *, unsigned int);
extern const char *brig_read_export_data (int, off_t, char **, size_t *, int *);
#endif /* !defined (BRIG_BRIG_C_H) */

807
gcc/brig/brig-lang.c Normal file
View file

@ -0,0 +1,807 @@
/* brig-lang.c -- brig (HSAIL) input gcc interface.
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "ansidecl.h"
#include "coretypes.h"
#include "opts.h"
#include "tree.h"
#include "tree-iterator.h"
#include "print-tree.h"
#include "stringpool.h"
#include "basic-block.h"
#include "gimple-expr.h"
#include "gimplify.h"
#include "dumpfile.h"
#include "stor-layout.h"
#include "toplev.h"
#include "debug.h"
#include "options.h"
#include "flags.h"
#include "convert.h"
#include "diagnostic.h"
#include "langhooks.h"
#include "langhooks-def.h"
#include "target.h"
#include "vec.h"
#include "brigfrontend/brig-to-generic.h"
#include "machmode.h"
#include "fold-const.h"
#include "common/common-target.h"
#include <mpfr.h>
#include "brig-c.h"
#include "brig-builtins.h"
/* This file is based on Go frontent'd go-lang.c and gogo-tree.cc. */
/* If -v set. */
int gccbrig_verbose = 0;
/* Language-dependent contents of a type. */
struct GTY (()) lang_type
{
char dummy;
};
/* Language-dependent contents of a decl. */
struct GTY ((variable_size)) lang_decl
{
char dummy;
};
/* Language-dependent contents of an identifier. This must include a
tree_identifier. */
struct GTY (()) lang_identifier
{
struct tree_identifier common;
};
/* The resulting tree type. */
union GTY ((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), "
"TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN "
"(&%h.generic)) : NULL"))) lang_tree_node
{
union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) generic;
struct lang_identifier GTY ((tag ("1"))) identifier;
};
/* We don't use language_function. */
struct GTY (()) language_function
{
int dummy;
};
/* The option mask. */
static unsigned int
brig_langhook_option_lang_mask (void)
{
return CL_BRIG;
}
/* Initialize the options structure. */
static void
brig_langhook_init_options_struct (struct gcc_options *opts)
{
/* Signed overflow is precisely defined. */
opts->x_flag_wrapv = 1;
/* If we set this to one, the whole program optimizations internalize
all global variables, making them invisible to the dyn loader (and
thus the HSA runtime implementation). */
opts->x_flag_whole_program = 0;
/* The builtin math functions should not set errno. */
opts->x_flag_errno_math = 0;
opts->frontend_set_flag_errno_math = false;
opts->x_flag_exceptions = 0;
opts->x_flag_non_call_exceptions = 0;
opts->x_flag_finite_math_only = 0;
opts->x_flag_signed_zeros = 1;
}
/* Handle Brig specific options. Return 0 if we didn't do anything. */
static bool
brig_langhook_handle_option
(size_t scode, const char *arg ATTRIBUTE_UNUSED,
int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
location_t loc ATTRIBUTE_UNUSED,
const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
{
enum opt_code code = (enum opt_code) scode;
switch (code)
{
case OPT_v:
gccbrig_verbose = 1;
break;
default:
break;
}
return 1;
}
/* Run after parsing options. */
static bool
brig_langhook_post_options (const char **pfilename ATTRIBUTE_UNUSED)
{
if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT)
flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD;
/* gccbrig casts pointers around like crazy, TBAA produces
broken code if not force disabling it. */
flag_strict_aliasing = 0;
/* Returning false means that the backend should be used. */
return false;
}
static size_t
get_file_size (FILE *file)
{
size_t size;
fseek (file, 0, SEEK_END);
size = (size_t) ftell (file);
fseek (file, 0, SEEK_SET);
return size;
}
static void
brig_langhook_parse_file (void)
{
brig_to_generic brig_to_gen;
for (unsigned int i = 0; i < num_in_fnames; ++i)
{
FILE *f;
f = fopen (in_fnames[i], "r");
size_t fsize = get_file_size (f);
char *brig_blob = new char[fsize];
if (fread (brig_blob, 1, fsize, f) != fsize)
{
error ("could not read the BRIG file");
exit (1);
}
brig_to_gen.parse (brig_blob);
fclose (f);
}
brig_to_gen.write_globals ();
}
static tree
brig_langhook_type_for_size (unsigned int bits,
int unsignedp)
{
/* Copied from go-lang.c */
tree type;
if (unsignedp)
{
if (bits == INT_TYPE_SIZE)
type = unsigned_type_node;
else if (bits == CHAR_TYPE_SIZE)
type = unsigned_char_type_node;
else if (bits == SHORT_TYPE_SIZE)
type = short_unsigned_type_node;
else if (bits == LONG_TYPE_SIZE)
type = long_unsigned_type_node;
else if (bits == LONG_LONG_TYPE_SIZE)
type = long_long_unsigned_type_node;
else
type = make_unsigned_type(bits);
}
else
{
if (bits == INT_TYPE_SIZE)
type = integer_type_node;
else if (bits == CHAR_TYPE_SIZE)
type = signed_char_type_node;
else if (bits == SHORT_TYPE_SIZE)
type = short_integer_type_node;
else if (bits == LONG_TYPE_SIZE)
type = long_integer_type_node;
else if (bits == LONG_LONG_TYPE_SIZE)
type = long_long_integer_type_node;
else
type = make_signed_type(bits);
}
return type;
}
static tree
brig_langhook_type_for_mode (enum machine_mode mode, int unsignedp)
{
if (mode == TYPE_MODE (void_type_node))
return void_type_node;
if (VECTOR_MODE_P (mode))
{
tree inner;
inner = brig_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
if (inner != NULL_TREE)
return build_vector_type_for_mode (inner, mode);
gcc_unreachable ();
return NULL_TREE;
}
enum mode_class mc = GET_MODE_CLASS (mode);
if (mc == MODE_FLOAT)
{
switch (GET_MODE_BITSIZE (mode))
{
case 32:
return float_type_node;
case 64:
return double_type_node;
default:
/* We have to check for long double in order to support
i386 excess precision. */
if (mode == TYPE_MODE (long_double_type_node))
return long_double_type_node;
gcc_unreachable ();
return NULL_TREE;
}
}
else if (mc == MODE_INT)
return brig_langhook_type_for_size(GET_MODE_BITSIZE(mode), unsignedp);
else
{
/* E.g., build_common_builtin_nodes () asks for modes/builtins
we do not generate or need. Just ignore them silently for now.
*/
return NULL_TREE;
}
return NULL_TREE;
}
static tree
brig_langhook_builtin_function (tree decl)
{
return decl;
}
static GTY(()) tree registered_builtin_types;
static void
brig_langhook_register_builtin_type (tree type, const char *name)
{
tree decl;
if (!TYPE_NAME (type))
{
decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
get_identifier (name), type);
DECL_ARTIFICIAL (decl) = 1;
TYPE_NAME (type) = decl;
}
registered_builtin_types = tree_cons (0, type, registered_builtin_types);
}
/* Return true if we are in the global binding level. */
static bool
brig_langhook_global_bindings_p (void)
{
return current_function_decl == NULL_TREE;
}
/* Push a declaration into the current binding level. From Go: We can't
usefully implement this since we don't want to convert from tree
back to one of our internal data structures. I think the only way
this is used is to record a decl which is to be returned by
getdecls, and we could implement it for that purpose if
necessary. */
static tree
brig_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
{
gcc_unreachable ();
}
/* This hook is used to get the current list of declarations as trees.
From Go: We don't support that; instead we use the write_globals hook.
This can't simply crash because it is called by -gstabs. */
static tree
brig_langhook_getdecls (void)
{
return NULL;
}
static int
brig_langhook_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
gimple_seq *post_p ATTRIBUTE_UNUSED)
{
/* Strip off the static chain info that appears to function
calls for some strange reason even though we don't add
nested functions. Maybe something wrong with the function
declaration contexts? */
if (TREE_CODE (*expr_p) == CALL_EXPR
&& CALL_EXPR_STATIC_CHAIN (*expr_p) != NULL_TREE)
CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL_TREE;
return GS_UNHANDLED;
}
static tree
brig_langhook_eh_personality (void)
{
gcc_unreachable ();
}
/* Functions called directly by the generic backend.
Adapted from go-lang.c. */
tree
convert (tree type, tree expr)
{
if (type == error_mark_node || expr == error_mark_node
|| TREE_TYPE (expr) == error_mark_node)
return error_mark_node;
if (type == TREE_TYPE (expr))
return expr;
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
return fold_convert (type, expr);
switch (TREE_CODE (type))
{
case VOID_TYPE:
case BOOLEAN_TYPE:
return fold_convert (type, expr);
case INTEGER_TYPE:
return fold (convert_to_integer (type, expr));
case REAL_TYPE:
return fold (convert_to_real (type, expr));
case VECTOR_TYPE:
return fold (convert_to_vector (type, expr));
case POINTER_TYPE:
return build1 (VIEW_CONVERT_EXPR, type, convert (size_type_node, expr));
default:
break;
}
gcc_unreachable ();
}
static GTY (()) tree brig_gc_root;
/* Preserve trees that we create from the garbage collector. */
void
brig_preserve_from_gc (tree t)
{
brig_gc_root = tree_cons (NULL_TREE, t, brig_gc_root);
}
/* Convert an identifier for use in an error message. */
const char *
brig_localize_identifier (const char *ident)
{
return identifier_to_locale (ident);
}
/* Built-in initialization code cribbed from lto-lang.c which cribbed it
from c-common.c. */
static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
static GTY(()) tree builtin_types[(int) BT_LAST + 1];
static GTY(()) tree string_type_node;
static GTY(()) tree const_string_type_node;
static GTY(()) tree wint_type_node;
static GTY(()) tree intmax_type_node;
static GTY(()) tree uintmax_type_node;
static GTY(()) tree signed_size_type_node;
/* Flags needed to process builtins.def. */
int flag_isoc94;
int flag_isoc99;
int flag_isoc11;
static void
def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
{
tree t;
tree *args = XALLOCAVEC (tree, n);
va_list list;
int i;
bool err = false;
va_start (list, n);
for (i = 0; i < n; ++i)
{
builtin_type a = (builtin_type) va_arg (list, int);
t = builtin_types[a];
if (t == error_mark_node)
err = true;
args[i] = t;
}
va_end (list);
t = builtin_types[ret];
if (err)
t = error_mark_node;
if (t == error_mark_node)
;
else if (var)
t = build_varargs_function_type_array (t, n, args);
else
t = build_function_type_array (t, n, args);
builtin_types[def] = t;
}
/* Used to help initialize the builtin-types.def table. When a type of
the correct size doesn't exist, use error_mark_node instead of NULL.
The later results in segfaults even when a decl using the type doesn't
get invoked. */
static tree
builtin_type_for_size (int size, bool unsignedp)
{
tree type = brig_langhook_type_for_size (size, unsignedp);
return type ? type : error_mark_node;
}
/* Support for DEF_BUILTIN. */
static void
def_builtin_1 (enum built_in_function fncode, const char *name,
enum built_in_class fnclass, tree fntype, tree libtype,
bool both_p, bool fallback_p, bool nonansi_p,
tree fnattrs, bool implicit_p)
{
tree decl;
const char *libname;
if (fntype == error_mark_node)
return;
libname = name + strlen ("__builtin_");
decl = add_builtin_function (name, fntype, fncode, fnclass,
(fallback_p ? libname : NULL),
fnattrs);
if (both_p
&& !flag_no_builtin
&& !(nonansi_p && flag_no_nonansi_builtin))
add_builtin_function (libname, libtype, fncode, fnclass,
NULL, fnattrs);
set_builtin_decl (fncode, decl, implicit_p);
}
/* Initialize the attribute table for all the supported builtins. */
static void
brig_init_attributes (void)
{
/* Fill in the built_in_attributes array. */
#define DEF_ATTR_NULL_TREE(ENUM) \
built_in_attributes[(int) ENUM] = NULL_TREE;
#define DEF_ATTR_INT(ENUM, VALUE) \
built_in_attributes[(int) ENUM] = build_int_cst (NULL_TREE, VALUE);
#define DEF_ATTR_STRING(ENUM, VALUE) \
built_in_attributes[(int) ENUM] = build_string (strlen (VALUE), VALUE);
#define DEF_ATTR_IDENT(ENUM, STRING) \
built_in_attributes[(int) ENUM] = get_identifier (STRING);
#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \
built_in_attributes[(int) ENUM] \
= tree_cons (built_in_attributes[(int) PURPOSE], \
built_in_attributes[(int) VALUE], \
built_in_attributes[(int) CHAIN]);
#include "builtin-attrs.def"
#undef DEF_ATTR_NULL_TREE
#undef DEF_ATTR_INT
#undef DEF_ATTR_STRING
#undef DEF_ATTR_IDENT
#undef DEF_ATTR_TREE_LIST
}
/* Create builtin types and functions. VA_LIST_REF_TYPE_NODE and
VA_LIST_ARG_TYPE_NODE are used in builtin-types.def. */
static void
brig_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED,
tree va_list_arg_type_node ATTRIBUTE_UNUSED)
{
#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
builtin_types[ENUM] = VALUE;
#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
def_fn_type (ENUM, RETURN, 0, 0);
#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
def_fn_type (ENUM, RETURN, 0, 1, ARG1);
#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6) \
def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7) \
def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7, ARG8) \
def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
ARG7, ARG8);
#define DEF_FUNCTION_TYPE_9(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7, ARG8, ARG9) \
def_fn_type (ENUM, RETURN, 0, 9, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
ARG7, ARG8, ARG9);
#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7, ARG8, ARG9, ARG10) \
def_fn_type (ENUM, RETURN, 0, 10, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
ARG7, ARG8, ARG9, ARG10);
#define DEF_FUNCTION_TYPE_11(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) \
def_fn_type (ENUM, RETURN, 0, 11, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
ARG7, ARG8, ARG9, ARG10, ARG11);
#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
def_fn_type (ENUM, RETURN, 1, 0);
#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
def_fn_type (ENUM, RETURN, 1, 1, ARG1);
#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
#define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6) \
def_fn_type (ENUM, RETURN, 1, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
#define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7) \
def_fn_type (ENUM, RETURN, 1, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
#define DEF_POINTER_TYPE(ENUM, TYPE) \
builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
#undef DEF_FUNCTION_TYPE_0
#undef DEF_FUNCTION_TYPE_1
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
#undef DEF_FUNCTION_TYPE_7
#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_9
#undef DEF_FUNCTION_TYPE_10
#undef DEF_FUNCTION_TYPE_11
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_FUNCTION_TYPE_VAR_4
#undef DEF_FUNCTION_TYPE_VAR_5
#undef DEF_FUNCTION_TYPE_VAR_6
#undef DEF_FUNCTION_TYPE_VAR_7
#undef DEF_POINTER_TYPE
builtin_types[(int) BT_LAST] = NULL_TREE;
brig_init_attributes ();
#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,\
NONANSI_P, ATTRS, IMPLICIT, COND) \
if (NAME && COND) \
def_builtin_1 (ENUM, NAME, CLASS, builtin_types[(int) TYPE], \
builtin_types[(int) LIBTYPE], BOTH_P, FALLBACK_P, \
NONANSI_P, built_in_attributes[(int) ATTRS], IMPLICIT);
#undef DEF_HSAIL_BUILTIN
#define DEF_HSAIL_BUILTIN(ENUM, HSAIL_OPCODE, HSAIL_TYPE, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
false, true, true, ATTRS, false, true)
/* HSAIL atomic builtins do not have separate identifying opcodes. */
#undef DEF_HSAIL_ATOMIC_BUILTIN
#define DEF_HSAIL_ATOMIC_BUILTIN(ENUM, ATOMIC_OPCODE, HSAIL_TYPE, NAME, \
TYPE, ATTRS) \
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
false, true, true, ATTRS, false, true)
/* HSAIL saturating arithmetics builtins. */
#undef DEF_HSAIL_SAT_BUILTIN
#define DEF_HSAIL_SAT_BUILTIN(ENUM, BRIG_OPCODE, HSAIL_TYPE, NAME, \
TYPE, ATTRS) \
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
false, true, true, ATTRS, false, true)
/* HSAIL builtins used internally by the frontend. */
#undef DEF_HSAIL_INTR_BUILTIN
#define DEF_HSAIL_INTR_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
false, true, true, ATTRS, false, true)
/* HSAIL saturated conversions. */
#undef DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN
#define DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN(ENUM, HSAIL_DEST_TYPE, HSAIL_SRC_TYPE, \
NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
false, true, true, ATTRS, false, true)
#include "builtins.def"
}
/* Build nodes that would have be created by the C front-end; necessary
for including builtin-types.def and ultimately builtins.def. Borrowed
from lto-lang.c. */
static void
brig_build_c_type_nodes (void)
{
gcc_assert (void_type_node);
void_list_node = build_tree_list (NULL_TREE, void_type_node);
string_type_node = build_pointer_type (char_type_node);
const_string_type_node
= build_pointer_type (build_qualified_type (char_type_node,
TYPE_QUAL_CONST));
if (strcmp (SIZE_TYPE, "unsigned int") == 0)
{
intmax_type_node = integer_type_node;
uintmax_type_node = unsigned_type_node;
signed_size_type_node = integer_type_node;
}
else if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
{
intmax_type_node = long_integer_type_node;
uintmax_type_node = long_unsigned_type_node;
signed_size_type_node = long_integer_type_node;
}
else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
{
intmax_type_node = long_long_integer_type_node;
uintmax_type_node = long_long_unsigned_type_node;
signed_size_type_node = long_long_integer_type_node;
}
else
{
int i;
signed_size_type_node = NULL_TREE;
for (i = 0; i < NUM_INT_N_ENTS; i++)
if (int_n_enabled_p[i])
{
char name[50];
sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
if (strcmp (name, SIZE_TYPE) == 0)
{
intmax_type_node = int_n_trees[i].signed_type;
uintmax_type_node = int_n_trees[i].unsigned_type;
signed_size_type_node = int_n_trees[i].signed_type;
}
}
if (signed_size_type_node == NULL_TREE)
gcc_unreachable ();
}
wint_type_node = unsigned_type_node;
pid_type_node = integer_type_node;
}
static bool
brig_langhook_init (void)
{
build_common_tree_nodes (false);
/* Builtin initialization related code borrowed from lto-lang.c. */
void_list_node = build_tree_list (NULL_TREE, void_type_node);
brig_build_c_type_nodes ();
if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
{
tree x = build_pointer_type (TREE_TYPE (va_list_type_node));
brig_define_builtins (x, x);
}
else
{
brig_define_builtins (build_reference_type (va_list_type_node),
va_list_type_node);
}
targetm.init_builtins ();
build_common_builtin_nodes ();
return true;
}
#undef LANG_HOOKS_NAME
#undef LANG_HOOKS_INIT
#undef LANG_HOOKS_OPTION_LANG_MASK
#undef LANG_HOOKS_INIT_OPTIONS_STRUCT
#undef LANG_HOOKS_HANDLE_OPTION
#undef LANG_HOOKS_POST_OPTIONS
#undef LANG_HOOKS_PARSE_FILE
#undef LANG_HOOKS_TYPE_FOR_MODE
#undef LANG_HOOKS_TYPE_FOR_SIZE
#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
#undef LANG_HOOKS_BUILTIN_FUNCTION
#undef LANG_HOOKS_GLOBAL_BINDINGS_P
#undef LANG_HOOKS_PUSHDECL
#undef LANG_HOOKS_GETDECLS
#undef LANG_HOOKS_WRITE_GLOBALS
#undef LANG_HOOKS_GIMPLIFY_EXPR
#undef LANG_HOOKS_EH_PERSONALITY
#define LANG_HOOKS_NAME "GNU Brig"
#define LANG_HOOKS_INIT brig_langhook_init
#define LANG_HOOKS_OPTION_LANG_MASK brig_langhook_option_lang_mask
#define LANG_HOOKS_INIT_OPTIONS_STRUCT brig_langhook_init_options_struct
#define LANG_HOOKS_HANDLE_OPTION brig_langhook_handle_option
#define LANG_HOOKS_POST_OPTIONS brig_langhook_post_options
#define LANG_HOOKS_PARSE_FILE brig_langhook_parse_file
#define LANG_HOOKS_TYPE_FOR_MODE brig_langhook_type_for_mode
#define LANG_HOOKS_TYPE_FOR_SIZE brig_langhook_type_for_size
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE brig_langhook_register_builtin_type
#define LANG_HOOKS_BUILTIN_FUNCTION brig_langhook_builtin_function
#define LANG_HOOKS_GLOBAL_BINDINGS_P brig_langhook_global_bindings_p
#define LANG_HOOKS_PUSHDECL brig_langhook_pushdecl
#define LANG_HOOKS_GETDECLS brig_langhook_getdecls
#define LANG_HOOKS_GIMPLIFY_EXPR brig_langhook_gimplify_expr
#define LANG_HOOKS_EH_PERSONALITY brig_langhook_eh_personality
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
#include "gt-brig-brig-lang.h"
#include "gtype-brig.h"

View file

@ -0,0 +1,66 @@
/* brig-arg-block-handler.cc -- brig arg block start/end directive handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "tree-iterator.h"
#include "system.h"
#include "errors.h"
#include "tree-pretty-print.h"
#include "print-tree.h"
size_t
brig_directive_arg_block_handler::operator () (const BrigBase *base)
{
if (base->kind == BRIG_KIND_DIRECTIVE_ARG_BLOCK_START)
{
/* Initiate a new code block for the call site. */
tree stmt_list = alloc_stmt_list ();
tree bind_expr
= build3 (BIND_EXPR, void_type_node, NULL, stmt_list, NULL);
tree block = make_node (BLOCK);
BIND_EXPR_BLOCK (bind_expr) = block;
static int block_id = 0;
BLOCK_NUMBER (block) = block_id++;
TREE_USED (block) = 1;
tree m_parentblock = DECL_INITIAL (m_parent.m_cf->m_func_decl);
BLOCK_SUPERCONTEXT (block) = m_parentblock;
chainon (BLOCK_SUBBLOCKS (m_parentblock), block);
m_parent.m_cf->m_current_bind_expr = bind_expr;
m_parent.m_cf->m_generating_arg_block = true;
}
else if (base->kind == BRIG_KIND_DIRECTIVE_ARG_BLOCK_END)
{
/* Restore the used bind expression back to the function
scope. */
tree new_bind_expr = m_parent.m_cf->m_current_bind_expr;
m_parent.m_cf->m_current_bind_expr
= DECL_SAVED_TREE (m_parent.m_cf->m_func_decl);
m_parent.m_cf->append_statement (new_bind_expr);
m_parent.m_cf->m_generating_arg_block = false;
}
else
gcc_unreachable ();
return base->byteCount;
}

View file

@ -0,0 +1,265 @@
/* brig-atomic-inst-handler.cc -- brig atomic instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include "brig-code-entry-handler.h"
#include "brig-util.h"
#include "fold-const.h"
#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "print-tree.h"
#include "convert.h"
#include "langhooks.h"
#include "gimple-expr.h"
#include "stringpool.h"
#include "brig-builtins.h"
brig_atomic_inst_handler::brig_atomic_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t
brig_atomic_inst_handler::generate_tree (const BrigInstBase &inst,
BrigAtomicOperation8_t atomic_opcode)
{
tree_stl_vec operands = build_operands (inst);
const int first_input
= gccbrig_hsa_opcode_op_output_p (inst.opcode, 0) ? 1 : 0;
tree instr_type = gccbrig_tree_type_for_hsa_type (inst.type);
/* Utilize the atomic data types (from C++11 support) for implementing
atomic operations. */
tree atomic_type = build_qualified_type (instr_type, TYPE_QUAL_ATOMIC);
gcc_assert (atomic_type != NULL_TREE);
tree signal_handle = operands[first_input];
tree atomic_ptype = build_pointer_type (atomic_type);
tree casted_to_ptr = convert_to_pointer (atomic_ptype, signal_handle);
tree src0 = NULL_TREE;
if (atomic_opcode != BRIG_ATOMIC_LD)
src0 = operands[first_input + 1];
tree instr_expr = NULL_TREE;
tree ptype = build_pointer_type (instr_type);
tree ptr = convert_to_pointer (ptype, operands[first_input]);
if (atomic_opcode == BRIG_ATOMIC_ST)
{
tree mem_ref = build2 (MEM_REF, atomic_type, casted_to_ptr,
build_int_cst (atomic_ptype, 0));
instr_expr = build2 (MODIFY_EXPR, atomic_type, mem_ref, src0);
}
else if (atomic_opcode == BRIG_ATOMIC_LD
|| (atomic_opcode >= BRIG_ATOMIC_WAIT_EQ
&& atomic_opcode <= BRIG_ATOMIC_WAITTIMEOUT_GTE))
{
tree mem_ref = build2 (MEM_REF, atomic_type, casted_to_ptr,
build_int_cst (atomic_ptype, 0));
/* signal_wait* instructions can return spuriously before the
condition becomes true. Therefore it's legal to return
right away. TODO: builtin calls which can be
implemented with a power efficient sleep-wait. */
instr_expr = mem_ref;
}
else if (atomic_opcode == BRIG_ATOMIC_CAS)
{
/* Special case for CAS due to the two args. */
tree built_in = NULL_TREE;
switch (gccbrig_hsa_type_bit_size (inst.type))
{
case 32:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4);
break;
case 64:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8);
break;
default:
gcc_unreachable ();
}
tree src1 = operands[first_input + 2];
tree src0_type
= TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (built_in))));
tree src1_type = TREE_VALUE
(TREE_CHAIN (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (built_in)))));
instr_expr = call_builtin (built_in, 3, instr_type, ptype, ptr,
src0_type, src0, src1_type, src1);
}
else
{
tree built_in = NULL_TREE;
/* The rest of the builtins have the same number of parameters.
Generate a big if..else that finds the correct builtin
automagically from the def file. */
#undef DEF_HSAIL_SAT_BUILTIN
#undef DEF_HSAIL_BUILTIN
#undef DEF_HSAIL_ATOMIC_BUILTIN
#undef DEF_HSAIL_INTR_BUILTIN
#undef DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN
#define DEF_HSAIL_ATOMIC_BUILTIN(ENUM, ATOMIC_OPCODE, HSAIL_TYPE, \
NAME, TYPE, ATTRS) \
if (atomic_opcode == ATOMIC_OPCODE && inst.type == HSAIL_TYPE) \
built_in = builtin_decl_explicit (ENUM); \
else
#include "brig-builtins.def"
switch (atomic_opcode)
{
case BRIG_ATOMIC_ADD:
switch (gccbrig_hsa_type_bit_size (inst.type))
{
case 32:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_ADD_4);
break;
case 64:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_ADD_8);
break;
default:
gcc_unreachable ();
}
break;
case BRIG_ATOMIC_SUB:
switch (gccbrig_hsa_type_bit_size (inst.type))
{
case 32:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_SUB_4);
break;
case 64:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_SUB_8);
break;
default:
gcc_unreachable ();
}
break;
case BRIG_ATOMIC_AND:
switch (gccbrig_hsa_type_bit_size (inst.type))
{
case 32:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_AND_4);
break;
case 64:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_AND_8);
break;
default:
gcc_unreachable ();
}
break;
case BRIG_ATOMIC_XOR:
switch (gccbrig_hsa_type_bit_size (inst.type))
{
case 32:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_XOR_4);
break;
case 64:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_XOR_8);
break;
default:
gcc_unreachable ();
}
break;
case BRIG_ATOMIC_OR:
switch (gccbrig_hsa_type_bit_size (inst.type))
{
case 32:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_OR_4);
break;
case 64:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_FETCH_AND_OR_8);
break;
default:
gcc_unreachable ();
}
break;
case BRIG_ATOMIC_EXCH:
switch (gccbrig_hsa_type_bit_size (inst.type))
{
case 32:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_LOCK_TEST_AND_SET_4);
break;
case 64:
built_in
= builtin_decl_explicit (BUILT_IN_SYNC_LOCK_TEST_AND_SET_8);
break;
default:
gcc_unreachable ();
}
break;
default:
gcc_unreachable ();
};
gcc_assert (built_in != NULL_TREE);
tree arg0_type
= TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (built_in))));
instr_expr = call_builtin (built_in, 2, instr_type, ptr_type_node,
ptr, arg0_type, src0);
/* We need a temp variable for the result, because otherwise
the gimplifier drops a necessary (unsigned to signed) cast in
the output assignment and fails a check later. */
tree tmp_var = create_tmp_var (arg0_type, "builtin_out");
tree tmp_assign
= build2 (MODIFY_EXPR, TREE_TYPE (tmp_var), tmp_var, instr_expr);
m_parent.m_cf->append_statement (tmp_assign);
instr_expr = tmp_var;
}
if (first_input > 0)
build_output_assignment (inst, operands[0], instr_expr);
else
m_parent.m_cf->append_statement (instr_expr);
return inst.base.byteCount;
}
size_t
brig_atomic_inst_handler::operator () (const BrigBase *base)
{
const BrigInstAtomic *inst = (const BrigInstAtomic *) base;
BrigAtomicOperation8_t atomic_opcode;
atomic_opcode = inst->atomicOperation;
return generate_tree (inst->base, atomic_opcode);
}

View file

@ -0,0 +1,865 @@
/* brig-basic-inst-handler.cc -- brig basic instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include "brig-code-entry-handler.h"
#include "brig-util.h"
#include "errors.h"
#include "gimple-expr.h"
#include "convert.h"
#include "print-tree.h"
#include "tree-pretty-print.h"
#include "langhooks.h"
#include "stor-layout.h"
#include "diagnostic-core.h"
#include "brig-builtins.h"
brig_basic_inst_handler::brig_basic_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
class scalarized_sat_arithmetics : public tree_element_binary_visitor
{
public:
scalarized_sat_arithmetics (const BrigInstBase &brig_inst)
: m_brig_inst (brig_inst)
{
BrigType16_t element_type = brig_inst.type & BRIG_TYPE_BASE_MASK;
#undef DEF_HSAIL_SAT_BUILTIN
#undef DEF_HSAIL_BUILTIN
#undef DEF_HSAIL_ATOMIC_BUILTIN
#undef DEF_HSAIL_INTR_BUILTIN
#undef DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN
#define DEF_HSAIL_SAT_BUILTIN(ENUM, BRIG_OPCODE, HSAIL_TYPE, \
NAME, TYPE, ATTRS) \
if (brig_inst.opcode == BRIG_OPCODE && element_type == HSAIL_TYPE) \
m_builtin = builtin_decl_explicit (ENUM); \
else
#include "brig-builtins.def"
gcc_unreachable ();
}
virtual tree
visit_element (brig_code_entry_handler &, tree operand0, tree operand1)
{
/* Implement saturating arithmetics with scalar built-ins for now.
TODO: emit GENERIC nodes for the simplest cases or at least
emit vector built-ins. */
return call_builtin (m_builtin, 2, TREE_TYPE (operand0),
TREE_TYPE (operand0), operand0,
TREE_TYPE (operand1), operand1);
}
const BrigInstBase &m_brig_inst;
tree m_builtin;
};
/* Implements a vector shuffle. ARITH_TYPE is the type of the vector,
OPERANDS[0] is the first vector, OPERAND[1] the second vector and
OPERANDS[2] the shuffle mask in HSAIL format. The output is a VEC_PERM_EXPR
that implements the shuffle as a GENERIC expression. */
tree
brig_basic_inst_handler::build_shuffle (tree arith_type,
tree_stl_vec &operands)
{
tree element_type
= get_unsigned_int_type (TREE_TYPE (TREE_TYPE (operands[0])));
/* Offsets to add to the mask values to convert from the
HSAIL mask to VEC_PERM_EXPR masks. VEC_PERM_EXPR mask
assumes an index spanning from 0 to 2 times the vec
width while HSAIL refers separately to two different
input vectors, thus is not a "full shuffle" where all
output elements can originate from any input element. */
vec<constructor_elt, va_gc> *mask_offset_vals = NULL;
vec<constructor_elt, va_gc> *input_mask_vals = NULL;
size_t input_mask_element_size
= exact_log2 (TYPE_VECTOR_SUBPARTS (arith_type));
/* Unpack the tightly packed mask elements to BIT_FIELD_REFs
from which to construct the mask vector as understood by
VEC_PERM_EXPR. */
tree mask_operand = add_temp_var ("shuffle_mask", operands[2]);
tree mask_element_type
= build_nonstandard_integer_type (input_mask_element_size, true);
for (size_t i = 0; i < TYPE_VECTOR_SUBPARTS (arith_type); ++i)
{
tree mask_element
= build3 (BIT_FIELD_REF, mask_element_type, mask_operand,
build_int_cst (unsigned_char_type_node,
input_mask_element_size),
build_int_cst (unsigned_char_type_node,
i * input_mask_element_size));
mask_element = convert (element_type, mask_element);
tree offset;
if (i < TYPE_VECTOR_SUBPARTS (arith_type) / 2)
offset = build_int_cst (element_type, 0);
else
offset
= build_int_cst (element_type, TYPE_VECTOR_SUBPARTS (arith_type));
CONSTRUCTOR_APPEND_ELT (mask_offset_vals, NULL_TREE, offset);
CONSTRUCTOR_APPEND_ELT (input_mask_vals, NULL_TREE, mask_element);
}
tree mask_vec_type
= build_vector_type (element_type, TYPE_VECTOR_SUBPARTS (arith_type));
tree mask_vec = build_constructor (mask_vec_type, input_mask_vals);
tree offset_vec = build_constructor (mask_vec_type, mask_offset_vals);
tree mask = build2 (PLUS_EXPR, mask_vec_type, mask_vec, offset_vec);
tree perm = build3 (VEC_PERM_EXPR, TREE_TYPE (operands[0]), operands[0],
operands[1], mask);
return perm;
}
/* Unpacks (extracts) a scalar element with an index in OPERANDS[1]
from the vector expression in OPERANDS[0]. */
tree
brig_basic_inst_handler::build_unpack (tree_stl_vec &operands)
{
/* Implement the unpack with a shuffle that stores the unpacked
element to the lowest bit positions in the dest. After that
a bitwise AND is used to clear the uppermost bits. */
tree src_element_type = TREE_TYPE (TREE_TYPE (operands[0]));
/* Perform the operations with a raw (unsigned int type) type. */
tree element_type = get_unsigned_int_type (src_element_type);
vec<constructor_elt, va_gc> *input_mask_vals = NULL;
vec<constructor_elt, va_gc> *and_mask_vals = NULL;
size_t element_count = TYPE_VECTOR_SUBPARTS (TREE_TYPE (operands[0]));
tree vec_type = build_vector_type (element_type, element_count);
for (size_t i = 0; i < element_count; ++i)
{
tree mask_element;
if (i == 0)
mask_element = convert (element_type, operands[1]);
else
mask_element = build_int_cst (element_type, 0);
CONSTRUCTOR_APPEND_ELT (input_mask_vals, NULL_TREE, mask_element);
tree and_mask_element;
if (i == 0)
and_mask_element = build_int_cst (element_type, -1);
else
and_mask_element = build_int_cst (element_type, 0);
CONSTRUCTOR_APPEND_ELT (and_mask_vals, NULL_TREE, and_mask_element);
}
tree mask_vec = build_constructor (vec_type, input_mask_vals);
tree and_mask_vec = build_constructor (vec_type, and_mask_vals);
tree perm = build3 (VEC_PERM_EXPR, vec_type,
build_reinterpret_cast (vec_type, operands[0]),
build_reinterpret_cast (vec_type, operands[0]), mask_vec);
tree cleared = build2 (BIT_AND_EXPR, vec_type, perm, and_mask_vec);
size_t s = int_size_in_bytes (TREE_TYPE (cleared)) * BITS_PER_UNIT;
tree raw_type = build_nonstandard_integer_type (s, true);
tree as_int = build_reinterpret_cast (raw_type, cleared);
if (int_size_in_bytes (src_element_type) < 4)
{
if (INTEGRAL_TYPE_P (src_element_type))
return extend_int (as_int, uint32_type_node, src_element_type);
}
return as_int;
}
/* Packs (inserts) a scalar element in OPERANDS[1]
to the vector in OPERANDS[0] at element position defined by
OPERANDS[2]. */
tree
brig_basic_inst_handler::build_pack (tree_stl_vec &operands)
{
/* Implement using a bit level insertion.
TODO: Reuse this for implementing 'bitinsert'
without a builtin call. */
size_t ecount = TYPE_VECTOR_SUBPARTS (TREE_TYPE (operands[0]));
size_t vecsize = int_size_in_bytes (TREE_TYPE (operands[0])) * BITS_PER_UNIT;
tree wide_type = build_nonstandard_integer_type (vecsize, 1);
tree src_vect = build_reinterpret_cast (wide_type, operands[0]);
src_vect = add_temp_var ("src_vect", src_vect);
tree scalar = operands[1];
scalar = add_temp_var ("scalar", convert_to_integer (wide_type, scalar));
tree pos = operands[2];
/* The upper bits of the position can contain garbage.
Zero them for well-defined semantics. */
tree t = build2 (BIT_AND_EXPR, TREE_TYPE (pos), operands[2],
build_int_cstu (TREE_TYPE (pos), ecount - 1));
pos = add_temp_var ("pos", convert (wide_type, t));
tree element_type = TREE_TYPE (TREE_TYPE (operands[0]));
size_t element_width = int_size_in_bytes (element_type) * BITS_PER_UNIT;
tree ewidth = build_int_cstu (wide_type, element_width);
tree bitoffset = build2 (MULT_EXPR, wide_type, ewidth, pos);
bitoffset = add_temp_var ("offset", bitoffset);
uint64_t mask_int
= element_width == 64 ? (uint64_t) -1 : ((uint64_t) 1 << element_width) - 1;
tree mask = build_int_cstu (wide_type, mask_int);
mask = add_temp_var ("mask", convert_to_integer (wide_type, mask));
tree clearing_mask
= build1 (BIT_NOT_EXPR, wide_type,
build2 (LSHIFT_EXPR, wide_type, mask, bitoffset));
tree zeroed_element
= build2 (BIT_AND_EXPR, wide_type, src_vect, clearing_mask);
/* TODO: Is the AND necessary: does HSA define what
happens if the upper bits in the inserted element are not
zero? */
tree element_in_position
= build2 (LSHIFT_EXPR, wide_type,
build2 (BIT_AND_EXPR, wide_type, scalar, mask), bitoffset);
tree inserted
= build2 (BIT_IOR_EXPR, wide_type, zeroed_element, element_in_position);
return inserted;
}
/* Implement the unpack{lo,hi}. BRIG_OPCODE should tell which one and
ARITH_TYPE describe the type of the vector arithmetics.
OPERANDS[0] and OPERANDS[1] are the input vectors. */
tree
brig_basic_inst_handler::build_unpack_lo_or_hi (BrigOpcode16_t brig_opcode,
tree arith_type,
tree_stl_vec &operands)
{
tree element_type = get_unsigned_int_type (TREE_TYPE (arith_type));
tree mask_vec_type
= build_vector_type (element_type, TYPE_VECTOR_SUBPARTS (arith_type));
size_t element_count = TYPE_VECTOR_SUBPARTS (arith_type);
vec<constructor_elt, va_gc> *input_mask_vals = NULL;
size_t offset = (brig_opcode == BRIG_OPCODE_UNPACKLO) ? 0 : element_count / 2;
for (size_t i = 0; i < element_count / 2; ++i)
{
CONSTRUCTOR_APPEND_ELT (input_mask_vals, NULL_TREE,
build_int_cst (element_type, offset + i));
CONSTRUCTOR_APPEND_ELT (input_mask_vals, NULL_TREE,
build_int_cst (element_type,
offset + i + element_count));
}
tree mask_vec = build_constructor (mask_vec_type, input_mask_vals);
tree perm = build3 (VEC_PERM_EXPR, TREE_TYPE (operands[0]), operands[0],
operands[1], mask_vec);
return perm;
}
/* Builds a basic instruction expression from a BRIG instruction. BRIG_OPCODE
is the opcode, BRIG_TYPE the brig type of the instruction, ARITH_TYPE the
desired tree type for the instruction, and OPERANDS the instruction's
input operands already converted to tree nodes. */
tree
brig_basic_inst_handler::build_inst_expr (BrigOpcode16_t brig_opcode,
BrigType16_t brig_type,
tree arith_type,
tree_stl_vec &operands)
{
tree_code opcode = get_tree_code_for_hsa_opcode (brig_opcode, brig_type);
BrigType16_t inner_type = brig_type & BRIG_TYPE_BASE_MASK;
tree instr_inner_type
= VECTOR_TYPE_P (arith_type) ? TREE_TYPE (arith_type) : arith_type;
if (opcode == RSHIFT_EXPR || opcode == LSHIFT_EXPR)
{
/* HSA defines modulo/clipping behavior for shift amounts larger
than the bit width, while tree.def leaves it undefined.
We need to mask the upper bits to ensure the defined behavior. */
tree scalar_mask
= build_int_cst (instr_inner_type,
gccbrig_hsa_type_bit_size (inner_type) - 1);
tree mask = VECTOR_TYPE_P (arith_type)
? build_vector_from_val (arith_type, scalar_mask)
: scalar_mask;
/* The shift amount is a scalar, broadcast it to produce
a vector shift. */
if (VECTOR_TYPE_P (arith_type))
operands[1] = build_vector_from_val (arith_type, operands[1]);
operands[1] = build2 (BIT_AND_EXPR, arith_type, operands[1], mask);
}
size_t input_count = operands.size ();
size_t output_count = gccbrig_hsa_opcode_op_output_p (brig_opcode, 0) ?
1 : 0;
if (opcode == TREE_LIST)
{
/* There was no direct GENERIC opcode for the instruction;
try to emulate it with a chain of GENERIC nodes. */
if (brig_opcode == BRIG_OPCODE_MAD || brig_opcode == BRIG_OPCODE_MAD24)
{
/* There doesn't seem to be a "standard" MAD built-in in gcc so let's
use a chain of multiply + add for now (double rounding method).
It should be easier for optimizers than a custom built-in call
WIDEN_MULT_EXPR is close, but requires a double size result
type. */
tree mult_res
= build2 (MULT_EXPR, arith_type, operands[0], operands[1]);
return build2 (PLUS_EXPR, arith_type, mult_res, operands[2]);
}
else if (brig_opcode == BRIG_OPCODE_MAD24HI)
{
tree mult_res
= build2 (MULT_HIGHPART_EXPR, arith_type, operands[0], operands[1]);
return build2 (PLUS_EXPR, arith_type, mult_res, operands[2]);
}
else if (brig_opcode == BRIG_OPCODE_SHUFFLE)
{
return build_shuffle (arith_type, operands);
}
else if (brig_opcode == BRIG_OPCODE_UNPACKLO
|| brig_opcode == BRIG_OPCODE_UNPACKHI)
{
return build_unpack_lo_or_hi (brig_opcode, arith_type, operands);
}
else if (brig_opcode == BRIG_OPCODE_UNPACK)
{
return build_unpack (operands);
}
else if (brig_opcode == BRIG_OPCODE_PACK)
{
return build_pack (operands);
}
else if (brig_opcode == BRIG_OPCODE_NRSQRT)
{
/* Implement as 1.0/sqrt (x) and assume gcc instruction selects to
native ISA other than a division, if available.
TODO: this will happen only with unsafe math optimizations
on which cannot be used in general to remain HSAIL compliant.
Perhaps a builtin call would be better option here. */
return build2 (RDIV_EXPR, arith_type, build_one_cst (arith_type),
expand_or_call_builtin (BRIG_OPCODE_SQRT, brig_type,
arith_type, operands));
}
else if (brig_opcode == BRIG_OPCODE_NRCP)
{
/* Implement as 1.0/x and assume gcc instruction selects to
native ISA other than a division, if available. */
return build2 (RDIV_EXPR, arith_type, build_one_cst (arith_type),
operands[0]);
}
else if (brig_opcode == BRIG_OPCODE_LANEID
|| brig_opcode == BRIG_OPCODE_MAXWAVEID
|| brig_opcode == BRIG_OPCODE_WAVEID)
{
/* Assuming WAVESIZE 1 (for now), therefore LANEID, WAVEID and
MAXWAVEID always return 0. */
return build_zero_cst (arith_type);
}
else
gcc_unreachable ();
}
else if (opcode == CALL_EXPR)
return expand_or_call_builtin (brig_opcode, brig_type, arith_type,
operands);
else if (output_count == 1)
{
if (input_count == 1)
{
if (opcode == MODIFY_EXPR)
return operands[0];
else
return build1 (opcode, arith_type, operands[0]);
}
else if (input_count == 2)
return build2 (opcode, arith_type, operands[0], operands[1]);
else if (input_count == 3)
return build3 (opcode, arith_type, operands[0], operands[1],
operands[2]);
else
gcc_unreachable ();
}
else
gcc_unreachable ();
return NULL_TREE;
}
/* Handles the basic instructions, including packed instructions. Deals
with the different packing modes by unpacking/packing the wanted
elements. Delegates most of the instruction cases to build_inst_expr(). */
size_t
brig_basic_inst_handler::operator () (const BrigBase *base)
{
const BrigInstBase *brig_inst = (const BrigInstBase *) base;
tree_stl_vec operands = build_operands (*brig_inst);
size_t output_count
= gccbrig_hsa_opcode_op_output_p (brig_inst->opcode, 0) ? 1 : 0;
size_t input_count
= operands.size () == 0 ? 0 : (operands.size () - output_count);
gcc_assert (output_count == 0 || output_count == 1);
tree_stl_vec::iterator first_input_i = operands.begin ();
if (output_count > 0 && operands.size () > 0)
++first_input_i;
tree_stl_vec in_operands;
in_operands.assign (first_input_i, operands.end ());
BrigType16_t brig_inst_type = brig_inst->type;
if (brig_inst->opcode == BRIG_OPCODE_NOP)
return base->byteCount;
else if (brig_inst->opcode == BRIG_OPCODE_FIRSTBIT
|| brig_inst->opcode == BRIG_OPCODE_LASTBIT
|| brig_inst->opcode == BRIG_OPCODE_SAD)
/* These instructions are reported to be always 32b in HSAIL, but we want
to treat them according to their input argument's type to select the
correct instruction/builtin. */
brig_inst_type
= gccbrig_tree_type_to_hsa_type (TREE_TYPE (in_operands[0]));
tree instr_type = gccbrig_tree_type_for_hsa_type (brig_inst_type);
if (!instr_type)
{
gcc_unreachable ();
return base->byteCount;
}
bool is_vec_instr = hsa_type_packed_p (brig_inst_type);
size_t element_size_bits;
size_t element_count;
if (is_vec_instr)
{
BrigType16_t brig_element_type = brig_inst_type & BRIG_TYPE_BASE_MASK;
element_size_bits = gccbrig_hsa_type_bit_size (brig_element_type);
element_count = gccbrig_hsa_type_bit_size (brig_inst_type)
/ gccbrig_hsa_type_bit_size (brig_element_type);
}
else
{
element_size_bits = gccbrig_hsa_type_bit_size (brig_inst_type);
element_count = 1;
}
/* The actual arithmetics type that should be performed with the
operation. This is not always the same as the original BRIG
opcode's type due to implicit conversions of storage-only f16. */
tree arith_type = gccbrig_is_bit_operation (brig_inst->opcode)
? gccbrig_tree_type_for_hsa_type (brig_inst_type)
: get_tree_expr_type_for_hsa_type (brig_inst_type);
tree instr_expr = NULL_TREE;
BrigPack8_t p = BRIG_PACK_NONE;
if (brig_inst->base.kind == BRIG_KIND_INST_MOD)
p = ((const BrigInstMod *) brig_inst)->pack;
else if (brig_inst->base.kind == BRIG_KIND_INST_CMP)
p = ((const BrigInstCmp *) brig_inst)->pack;
if (p == BRIG_PACK_PS || p == BRIG_PACK_PSSAT)
in_operands[1] = build_lower_element_broadcast (in_operands[1]);
else if (p == BRIG_PACK_SP || p == BRIG_PACK_SPSAT)
in_operands[0] = build_lower_element_broadcast (in_operands[0]);
tree_code opcode
= get_tree_code_for_hsa_opcode (brig_inst->opcode, brig_inst_type);
if (p >= BRIG_PACK_PPSAT && p <= BRIG_PACK_PSAT)
{
scalarized_sat_arithmetics sat_arith (*brig_inst);
gcc_assert (input_count == 2);
instr_expr = sat_arith (*this, in_operands[0], in_operands[1]);
}
else if (opcode == RETURN_EXPR)
{
if (m_parent.m_cf->m_is_kernel)
{
tree goto_stmt
= build1 (GOTO_EXPR, void_type_node, m_parent.m_cf->m_exit_label);
m_parent.m_cf->append_statement (goto_stmt);
return base->byteCount;
}
else
{
m_parent.m_cf->append_return_stmt ();
return base->byteCount;
}
}
else if (opcode == MULT_HIGHPART_EXPR &&
is_vec_instr && element_size_bits < 64)
{
/* MULT_HIGHPART_EXPR works only on target dependent vector sizes and
even the scalars do not seem to work at least for char elements.
Let's fall back to scalarization and promotion of the vector elements
to larger types with the MULHI computed as a regular MUL.
MULHI for 2x64b seems to work with the Intel CPUs I've tested so
that is passed on for vector processing so there is no need for
128b scalar arithmetics.
This is not modular as these type of things do not belong to the
frontend, there should be a legalization phase before the backend
that figures out the best way to compute the MULHI for any
integer vector datatype.
TODO: promote to larger vector types instead. For example
MULT_HIGHPART_EXPR with s8x8 doesn't work, but s16x8 seems to at least
with my x86-64.
*/
tree_stl_vec operand0_elements;
if (input_count > 0)
unpack (in_operands[0], operand0_elements);
tree_stl_vec operand1_elements;
if (input_count > 1)
unpack (in_operands[1], operand1_elements);
tree_stl_vec result_elements;
tree scalar_type = TREE_TYPE (arith_type);
BrigType16_t element_type = brig_inst_type & BRIG_TYPE_BASE_MASK;
tree promoted_type = short_integer_type_node;
switch (element_type)
{
case BRIG_TYPE_S8:
promoted_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_S16);
break;
case BRIG_TYPE_U8:
promoted_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U16);
break;
case BRIG_TYPE_S16:
promoted_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_S32);
break;
case BRIG_TYPE_U16:
promoted_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U32);
break;
case BRIG_TYPE_S32:
promoted_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_S64);
break;
case BRIG_TYPE_U32:
promoted_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U64);
break;
default:
gcc_unreachable ();
}
size_t promoted_type_size = int_size_in_bytes (promoted_type) * 8;
for (size_t i = 0; i < TYPE_VECTOR_SUBPARTS (arith_type); ++i)
{
tree operand0 = convert (promoted_type, operand0_elements.at (i));
tree operand1 = convert (promoted_type, operand1_elements.at (i));
tree scalar_expr
= build2 (MULT_EXPR, promoted_type, operand0, operand1);
scalar_expr
= build2 (RSHIFT_EXPR, promoted_type, scalar_expr,
build_int_cstu (promoted_type, promoted_type_size / 2));
result_elements.push_back (convert (scalar_type, scalar_expr));
}
instr_expr = pack (result_elements);
}
else
{
/* 'class' is always of b1 type, let's consider it by its
float type when building the instruction to find the
correct builtin. */
if (brig_inst->opcode == BRIG_OPCODE_CLASS)
brig_inst_type = ((const BrigInstSourceType *) base)->sourceType;
instr_expr = build_inst_expr (brig_inst->opcode, brig_inst_type,
arith_type, in_operands);
}
if (instr_expr == NULL_TREE)
{
gcc_unreachable ();
return base->byteCount;
}
if (p == BRIG_PACK_SS || p == BRIG_PACK_S || p == BRIG_PACK_SSSAT
|| p == BRIG_PACK_SSAT)
{
/* In case of _s_ or _ss_, select only the lowest element
from the new input to the output. We could extract
the element and use a scalar operation, but try
to keep data in vector registers as much as possible
to avoid copies between scalar and vector datapaths. */
tree old_value;
tree half_storage_type = gccbrig_tree_type_for_hsa_type (brig_inst_type);
bool is_fp16_operation
= (brig_inst_type & BRIG_TYPE_BASE_MASK) == BRIG_TYPE_F16
&& !gccbrig_is_bit_operation (brig_inst->opcode);
if (is_fp16_operation)
old_value = build_h2f_conversion
(build_reinterpret_cast (half_storage_type, operands[0]));
else
old_value
= build_reinterpret_cast (TREE_TYPE (instr_expr), operands[0]);
size_t esize = is_fp16_operation ? 32 : element_size_bits;
/* Construct a permutation mask where other elements than the lowest one
is picked from the old_value. */
tree mask_inner_type = build_nonstandard_integer_type (esize, 1);
vec<constructor_elt, va_gc> *constructor_vals = NULL;
for (size_t i = 0; i < element_count; ++i)
{
tree cst;
if (i == 0)
cst = build_int_cstu (mask_inner_type, element_count);
else
cst = build_int_cstu (mask_inner_type, i);
CONSTRUCTOR_APPEND_ELT (constructor_vals, NULL_TREE, cst);
}
tree mask_vec_type = build_vector_type (mask_inner_type, element_count);
tree mask = build_vector_from_ctor (mask_vec_type, constructor_vals);
tree new_value = create_tmp_var (TREE_TYPE (instr_expr), "new_output");
tree assign
= build2 (MODIFY_EXPR, TREE_TYPE (instr_expr), new_value, instr_expr);
m_parent.m_cf->append_statement (assign);
instr_expr
= build3 (VEC_PERM_EXPR, arith_type, old_value, new_value, mask);
tree lower_output = create_tmp_var (TREE_TYPE (instr_expr), "s_output");
tree assign_lower = build2 (MODIFY_EXPR, TREE_TYPE (instr_expr),
lower_output, instr_expr);
m_parent.m_cf->append_statement (assign_lower);
instr_expr = lower_output;
}
if (output_count == 1)
build_output_assignment (*brig_inst, operands[0], instr_expr);
else
m_parent.m_cf->append_statement (instr_expr);
return base->byteCount;
}
/* Create an expression that broadcasts the lowest element of the
vector in VEC_OPERAND to all elements of the returned vector. */
tree
brig_basic_inst_handler::build_lower_element_broadcast (tree vec_operand)
{
/* Build the broadcast using shuffle because there's no
direct broadcast in GENERIC and this way there's no need for
a separate extract of the lowest element. */
tree element_type = TREE_TYPE (TREE_TYPE (vec_operand));
size_t esize = 8 * int_size_in_bytes (element_type);
size_t element_count = TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec_operand));
tree mask_inner_type = build_nonstandard_integer_type (esize, 1);
vec<constructor_elt, va_gc> *constructor_vals = NULL;
/* Construct the mask. */
for (size_t i = 0; i < element_count; ++i)
{
tree cst = build_int_cstu (mask_inner_type, element_count);
CONSTRUCTOR_APPEND_ELT (constructor_vals, NULL_TREE, cst);
}
tree mask_vec_type = build_vector_type (mask_inner_type, element_count);
tree mask = build_vector_from_ctor (mask_vec_type, constructor_vals);
return build3 (VEC_PERM_EXPR, TREE_TYPE (vec_operand), vec_operand,
vec_operand, mask);
}
/* Returns the tree code that should be used to implement the given
HSA instruction opcode (BRIG_OPCODE) for the given type of instruction
(BRIG_TYPE). In case the opcode cannot be mapped to a TREE node directly,
returns TREE_LIST (if it can be emulated with a simple chain of tree
nodes) or CALL_EXPR if the opcode should be implemented using a builtin
call. */
tree_code
brig_basic_inst_handler::get_tree_code_for_hsa_opcode
(BrigOpcode16_t brig_opcode, BrigType16_t brig_type) const
{
BrigType16_t brig_inner_type = brig_type & BRIG_TYPE_BASE_MASK;
switch (brig_opcode)
{
case BRIG_OPCODE_NOP:
return NOP_EXPR;
case BRIG_OPCODE_ADD:
return PLUS_EXPR;
case BRIG_OPCODE_CMOV:
if (brig_inner_type == brig_type)
return COND_EXPR;
else
return VEC_COND_EXPR;
case BRIG_OPCODE_SUB:
return MINUS_EXPR;
case BRIG_OPCODE_MUL:
case BRIG_OPCODE_MUL24:
return MULT_EXPR;
case BRIG_OPCODE_MULHI:
case BRIG_OPCODE_MUL24HI:
return MULT_HIGHPART_EXPR;
case BRIG_OPCODE_DIV:
if (gccbrig_is_float_type (brig_inner_type))
return RDIV_EXPR;
else
return TRUNC_DIV_EXPR;
case BRIG_OPCODE_NEG:
return NEGATE_EXPR;
case BRIG_OPCODE_MIN:
if (gccbrig_is_float_type (brig_inner_type))
return CALL_EXPR;
else
return MIN_EXPR;
case BRIG_OPCODE_MAX:
if (gccbrig_is_float_type (brig_inner_type))
return CALL_EXPR;
else
return MAX_EXPR;
case BRIG_OPCODE_FMA:
return FMA_EXPR;
case BRIG_OPCODE_ABS:
return ABS_EXPR;
case BRIG_OPCODE_SHL:
return LSHIFT_EXPR;
case BRIG_OPCODE_SHR:
return RSHIFT_EXPR;
case BRIG_OPCODE_OR:
return BIT_IOR_EXPR;
case BRIG_OPCODE_XOR:
return BIT_XOR_EXPR;
case BRIG_OPCODE_AND:
return BIT_AND_EXPR;
case BRIG_OPCODE_NOT:
return BIT_NOT_EXPR;
case BRIG_OPCODE_RET:
return RETURN_EXPR;
case BRIG_OPCODE_MOV:
case BRIG_OPCODE_LDF:
return MODIFY_EXPR;
case BRIG_OPCODE_LD:
case BRIG_OPCODE_ST:
return MEM_REF;
case BRIG_OPCODE_BR:
return GOTO_EXPR;
case BRIG_OPCODE_REM:
if (brig_type == BRIG_TYPE_U64 || brig_type == BRIG_TYPE_U32)
return TRUNC_MOD_EXPR;
else
return CALL_EXPR;
case BRIG_OPCODE_NRCP:
case BRIG_OPCODE_NRSQRT:
/* Implement as 1/f (x). gcc should pattern detect that and
use a native instruction, if available, for it. */
return TREE_LIST;
case BRIG_OPCODE_FLOOR:
case BRIG_OPCODE_CEIL:
case BRIG_OPCODE_SQRT:
case BRIG_OPCODE_NSQRT:
case BRIG_OPCODE_RINT:
case BRIG_OPCODE_TRUNC:
case BRIG_OPCODE_POPCOUNT:
case BRIG_OPCODE_COPYSIGN:
case BRIG_OPCODE_NCOS:
case BRIG_OPCODE_NSIN:
case BRIG_OPCODE_NLOG2:
case BRIG_OPCODE_NEXP2:
case BRIG_OPCODE_NFMA:
/* Class has type B1 regardless of the float type, thus
the below builtin map search cannot find it. */
case BRIG_OPCODE_CLASS:
case BRIG_OPCODE_WORKITEMABSID:
return CALL_EXPR;
default:
/* Some BRIG opcodes can use the same builtins for unsigned and
signed types. Force these cases to unsigned types.
*/
if (brig_opcode == BRIG_OPCODE_BORROW
|| brig_opcode == BRIG_OPCODE_CARRY
|| brig_opcode == BRIG_OPCODE_LASTBIT
|| brig_opcode == BRIG_OPCODE_BITINSERT)
{
if (brig_type == BRIG_TYPE_S32)
brig_type = BRIG_TYPE_U32;
else if (brig_type == BRIG_TYPE_S64)
brig_type = BRIG_TYPE_U64;
}
builtin_map::const_iterator i
= s_custom_builtins.find (std::make_pair (brig_opcode, brig_type));
if (i != s_custom_builtins.end ())
return CALL_EXPR;
else if (s_custom_builtins.find
(std::make_pair (brig_opcode, brig_inner_type))
!= s_custom_builtins.end ())
return CALL_EXPR;
if (brig_inner_type == BRIG_TYPE_F16
&& s_custom_builtins.find
(std::make_pair (brig_opcode, BRIG_TYPE_F32))
!= s_custom_builtins.end ())
return CALL_EXPR;
break;
}
return TREE_LIST; /* Emulate using a chain of nodes. */
}

View file

@ -0,0 +1,221 @@
/* brig-branch-inst-handler.cc -- brig branch instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "errors.h"
#include "brig-util.h"
#include "tree-pretty-print.h"
#include "print-tree.h"
#include "vec.h"
#include "fold-const.h"
size_t
brig_branch_inst_handler::operator () (const BrigBase *base)
{
const BrigInstBase *brig_inst
= (const BrigInstBase *) &((const BrigInstBasic *) base)->base;
if (brig_inst->opcode == BRIG_OPCODE_CALL)
{
const BrigData *operand_entries
= m_parent.get_brig_data_entry (brig_inst->operands);
tree func_ref = NULL_TREE;
vec<tree, va_gc> *out_args;
vec_alloc (out_args, 1);
vec<tree, va_gc> *in_args;
vec_alloc (in_args, 4);
size_t operand_count = operand_entries->byteCount / 4;
gcc_assert (operand_count < 4);
for (size_t i = 0; i < operand_count; ++i)
{
uint32_t operand_offset
= ((const uint32_t *) &operand_entries->bytes)[i];
const BrigBase *operand_data
= m_parent.get_brig_operand_entry (operand_offset);
if (i == 1)
{
gcc_assert (operand_data->kind == BRIG_KIND_OPERAND_CODE_REF);
func_ref = build_tree_operand (*brig_inst, *operand_data);
continue;
}
gcc_assert (operand_data->kind == BRIG_KIND_OPERAND_CODE_LIST);
const BrigOperandCodeList *codelist
= (const BrigOperandCodeList *) operand_data;
const BrigData *data
= m_parent.get_brig_data_entry (codelist->elements);
size_t bytes = data->byteCount;
const BrigOperandOffset32_t *operand_ptr
= (const BrigOperandOffset32_t *) data->bytes;
vec<tree, va_gc> *args = i == 0 ? out_args : in_args;
while (bytes > 0)
{
BrigOperandOffset32_t offset = *operand_ptr;
const BrigBase *code_element
= m_parent.get_brig_code_entry (offset);
gcc_assert (code_element->kind == BRIG_KIND_DIRECTIVE_VARIABLE);
const BrigDirectiveVariable *brig_var
= (const BrigDirectiveVariable *) code_element;
tree var = m_parent.m_cf->arg_variable (brig_var);
if (brig_var->type & BRIG_TYPE_ARRAY)
{
/* Array return values are passed as the first argument. */
args = in_args;
/* Pass pointer to the element zero and use its element zero
as the base address. */
tree etype = TREE_TYPE (TREE_TYPE (var));
tree ptype = build_pointer_type (etype);
tree element_zero
= build4 (ARRAY_REF, etype, var, integer_zero_node,
NULL_TREE, NULL_TREE);
var = build1 (ADDR_EXPR, ptype, element_zero);
}
gcc_assert (var != NULL_TREE);
vec_safe_push (args, var);
++operand_ptr;
bytes -= 4;
}
}
gcc_assert (func_ref != NULL_TREE);
gcc_assert (out_args->length () == 0 || out_args->length () == 1);
tree ret_val_type = void_type_node;
tree ret_val = NULL_TREE;
if (out_args->length () == 1)
{
ret_val = (*out_args)[0];
ret_val_type = TREE_TYPE (ret_val);
}
/* Pass the hidden kernel arguments along to the called functions as
they might call builtins that need them or access group/private
memory. */
vec_safe_push (in_args, m_parent.m_cf->m_context_arg);
vec_safe_push (in_args, m_parent.m_cf->m_group_base_arg);
vec_safe_push (in_args, m_parent.m_cf->m_private_base_arg);
tree call = build_call_vec (ret_val_type, build_fold_addr_expr (func_ref),
in_args);
TREE_NOTHROW (func_ref) = 1;
TREE_NOTHROW (call) = 1;
if (ret_val != NULL_TREE)
{
TREE_ADDRESSABLE (ret_val) = 1;
tree result_assign
= build2 (MODIFY_EXPR, TREE_TYPE (ret_val), ret_val, call);
m_parent.m_cf->append_statement (result_assign);
}
else
{
m_parent.m_cf->append_statement (call);
}
m_parent.m_cf->m_has_unexpanded_dp_builtins = false;
m_parent.m_cf->m_called_functions.push_back (func_ref);
return base->byteCount;
}
tree instr_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
tree_stl_vec operands = build_operands (*brig_inst);
if (brig_inst->opcode == BRIG_OPCODE_BR)
{
tree goto_stmt = build1 (GOTO_EXPR, instr_type, operands[0]);
m_parent.m_cf->append_statement (goto_stmt);
}
else if (brig_inst->opcode == BRIG_OPCODE_SBR)
{
tree select = operands[0];
tree cases = operands[1];
tree switch_expr = build3 (SWITCH_EXPR, TREE_TYPE (select), select,
NULL_TREE, NULL_TREE);
tree default_case
= build_case_label (NULL_TREE, NULL_TREE,
create_artificial_label (UNKNOWN_LOCATION));
append_to_statement_list (default_case, &SWITCH_BODY (switch_expr));
tree default_jump
= build1 (GOTO_EXPR, void_type_node, TREE_VEC_ELT (cases, 0));
append_to_statement_list (default_jump, &SWITCH_BODY (switch_expr));
for (int c = 0; c < TREE_VEC_LENGTH (cases); ++c)
{
tree case_label
= build_case_label (build_int_cst (integer_type_node, c), NULL_TREE,
create_artificial_label (UNKNOWN_LOCATION));
append_to_statement_list (case_label, &SWITCH_BODY (switch_expr));
tree jump
= build1 (GOTO_EXPR, void_type_node, TREE_VEC_ELT (cases, c));
append_to_statement_list (jump, &SWITCH_BODY (switch_expr));
}
m_parent.m_cf->append_statement (switch_expr);
}
else if (brig_inst->opcode == BRIG_OPCODE_CBR)
{
tree condition = operands[0];
tree target_goto = build1 (GOTO_EXPR, void_type_node, operands[1]);
/* Represents the if..else as (condition)?(goto foo):(goto bar). */
tree if_stmt
= build3 (COND_EXPR, void_type_node, condition, target_goto, NULL_TREE);
m_parent.m_cf->append_statement (if_stmt);
}
else if (brig_inst->opcode == BRIG_OPCODE_WAVEBARRIER)
{
/* WAVEBARRIER is a NOP when WAVESIZE = 1. */
}
else if (brig_inst->opcode == BRIG_OPCODE_BARRIER)
{
m_parent.m_cf->m_has_barriers = true;
tree_stl_vec call_operands;
/* FIXME. We should add attributes (are there suitable ones in gcc?) that
ensure the barrier won't be duplicated or moved out of loops etc.
Like the 'noduplicate' of LLVM. Same goes for fbarriers. */
m_parent.m_cf->append_statement
(expand_or_call_builtin (brig_inst->opcode, BRIG_TYPE_NONE, NULL_TREE,
call_operands));
}
else if (brig_inst->opcode >= BRIG_OPCODE_ARRIVEFBAR
&& brig_inst->opcode <= BRIG_OPCODE_WAITFBAR)
{
m_parent.m_cf->m_has_barriers = true;
m_parent.m_cf->append_statement
(expand_or_call_builtin (brig_inst->opcode, BRIG_TYPE_NONE,
uint32_type_node, operands));
}
else
gcc_unreachable ();
return base->byteCount;
}

View file

@ -0,0 +1,198 @@
/* brig-cmp-inst-handler.cc -- brig cmp instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "print-tree.h"
#include "brig-util.h"
#include "convert.h"
size_t
brig_cmp_inst_handler::operator () (const BrigBase *base)
{
const BrigInstBase *inst_base = (const BrigInstBase *) base;
const BrigInstCmp *inst = (const BrigInstCmp *) base;
tree cmp_type = get_tree_expr_type_for_hsa_type (inst->sourceType);
/* The destination type to convert the comparison result to. */
tree dest_type = gccbrig_tree_type_for_hsa_type (inst_base->type);
const bool is_fp16_dest
= (inst_base->type & BRIG_TYPE_BASE_MASK) == BRIG_TYPE_F16;
const bool is_boolean_dest
= (inst_base->type & BRIG_TYPE_BASE_MASK) == BRIG_TYPE_B1;
bool is_int_cmp = VECTOR_TYPE_P (cmp_type)
? INTEGRAL_TYPE_P (TREE_TYPE (cmp_type))
: INTEGRAL_TYPE_P (cmp_type);
/* The type for the GENERIC comparison. It should match the
input operand width for vector comparisons, a boolean
otherwise. */
tree result_type = get_comparison_result_type (cmp_type);
/* Save the result as a boolean and extend/convert it to the
wanted destination type. */
tree expr = NULL_TREE;
std::vector<tree> operands = build_operands (*inst_base);
switch (inst->compare)
{
case BRIG_COMPARE_SEQ:
case BRIG_COMPARE_EQ:
expr = build2 (EQ_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SNE:
case BRIG_COMPARE_NE:
expr = build2 (NE_EXPR, result_type, operands[1], operands[2]);
if (!is_int_cmp)
expr = build2 (BIT_AND_EXPR, TREE_TYPE (expr),
expr,
build2 (ORDERED_EXPR, result_type, operands[1],
operands[2]));
break;
case BRIG_COMPARE_SLT:
case BRIG_COMPARE_LT:
expr = build2 (LT_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SLE:
case BRIG_COMPARE_LE:
expr = build2 (LE_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SGT:
case BRIG_COMPARE_GT:
expr = build2 (GT_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SGE:
case BRIG_COMPARE_GE:
expr = build2 (GE_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SEQU:
case BRIG_COMPARE_EQU:
expr = build2 (UNEQ_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SNEU:
case BRIG_COMPARE_NEU:
expr = build2 (NE_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SLTU:
case BRIG_COMPARE_LTU:
expr = build2 (UNLT_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SLEU:
case BRIG_COMPARE_LEU:
expr = build2 (UNLE_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SGTU:
case BRIG_COMPARE_GTU:
expr = build2 (UNGT_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SGEU:
case BRIG_COMPARE_GEU:
expr = build2 (UNGE_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SNUM:
case BRIG_COMPARE_NUM:
expr = build2 (ORDERED_EXPR, result_type, operands[1], operands[2]);
break;
case BRIG_COMPARE_SNAN:
case BRIG_COMPARE_NAN:
expr = build2 (UNORDERED_EXPR, result_type, operands[1], operands[2]);
break;
default:
break;
}
if (expr == NULL_TREE)
gcc_unreachable ();
if (is_fp16_dest)
{
expr = convert_to_real (brig_to_generic::s_fp32_type, expr);
}
else if (VECTOR_TYPE_P (dest_type) && ANY_INTEGRAL_TYPE_P (dest_type)
&& !is_boolean_dest
&& (inst->sourceType & BRIG_TYPE_BASE_MASK) != BRIG_TYPE_F16)
{
/* In later gcc versions, the output of comparison is not
all ones for vectors like still in 4.9.1. We need to use
an additional VEC_COND_EXPR to produce the all ones 'true' value
required by HSA.
VEC_COND_EXPR <a == b, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>; */
tree all_ones
= build_vector_from_val (dest_type,
build_minus_one_cst (TREE_TYPE (dest_type)));
tree all_zeroes
= build_vector_from_val (dest_type,
build_zero_cst (TREE_TYPE (dest_type)));
expr = build3 (VEC_COND_EXPR, dest_type, expr, all_ones, all_zeroes);
}
else if (INTEGRAL_TYPE_P (dest_type) && !is_boolean_dest)
{
/* We need to produce the all-ones pattern for the width of the whole
resulting integer type. Use back and forth shifts for propagating
the lower 1. */
tree signed_type = signed_type_for (dest_type);
tree signed_result = convert_to_integer (signed_type, expr);
size_t result_width = int_size_in_bytes (dest_type) * BITS_PER_UNIT;
tree shift_amount_cst
= build_int_cstu (signed_type, result_width - 1);
tree shift_left_result
= build2 (LSHIFT_EXPR, signed_type, signed_result, shift_amount_cst);
expr = build2 (RSHIFT_EXPR, signed_type, shift_left_result,
shift_amount_cst);
}
else if (SCALAR_FLOAT_TYPE_P (dest_type))
{
expr = convert_to_real (dest_type, expr);
}
else if (VECTOR_TYPE_P (dest_type)
&& (inst->sourceType & BRIG_TYPE_BASE_MASK) == BRIG_TYPE_F16)
{
/* Because F16 comparison is emulated as an F32 comparison with S32
results, we must now truncate the result vector to S16s so it
fits to the destination register. We can build the target vector
type from the f16 storage type (unsigned ints). */
expr = add_temp_var ("wide_cmp_result", expr);
tree_stl_vec wide_elements;
tree_stl_vec shrunk_elements;
unpack (expr, wide_elements);
for (size_t i = 0; i < wide_elements.size (); ++i)
{
tree wide = wide_elements.at (i);
shrunk_elements.push_back
(convert_to_integer (short_integer_type_node, wide));
}
expr = pack (shrunk_elements);
}
build_output_assignment (*inst_base, operands[0], expr);
return base->byteCount;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,425 @@
/* brig-code-entry-handler.h -- a gccbrig base class
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_BRIG_CODE_ENTRY_HANDLER_H
#define GCC_BRIG_CODE_ENTRY_HANDLER_H
#include "brig-to-generic.h"
#include <map>
#include <vector>
class tree_element_unary_visitor;
/* An interface to organize the different types of element handlers
for the code section. */
class brig_code_entry_handler : public brig_entry_handler
{
public:
typedef std::map<std::pair<BrigOpcode16_t, BrigType16_t>, tree> builtin_map;
brig_code_entry_handler (brig_to_generic &parent);
/* Handles the brig_code data at the given pointer and adds it to the
currently built tree. Returns the number of consumed bytes. */
virtual size_t operator () (const BrigBase *base) = 0;
void append_statement (tree stmt);
protected:
tree get_tree_expr_type_for_hsa_type (BrigType16_t brig_type) const;
tree get_tree_cst_for_hsa_operand (const BrigOperandConstantBytes *brigConst,
tree type) const;
tree get_builtin_for_hsa_opcode (tree type, BrigOpcode16_t brig_opcode,
BrigType16_t brig_type) const;
tree get_comparison_result_type (tree source_type);
tree build_code_ref (const BrigBase &ref);
tree build_tree_operand (const BrigInstBase &brig_inst,
const BrigBase &operand,
tree operand_type = NULL_TREE,
bool is_input = false);
tree build_address_operand (const BrigInstBase &brig_inst,
const BrigOperandAddress &addr_operand);
tree build_tree_operand_from_brig (const BrigInstBase *brig_inst,
tree operand_type, size_t operand_index);
tree build_tree_cst_element (BrigType16_t element_type,
const unsigned char *next_data) const;
bool needs_workitem_context_data (BrigOpcode16_t brig_opcode) const;
void unpack (tree value, tree_stl_vec &elements);
tree pack (tree_stl_vec &elements);
bool can_expand_builtin (BrigOpcode16_t brig_opcode) const;
tree expand_builtin (BrigOpcode16_t brig_opcode, tree_stl_vec &operands);
tree expand_or_call_builtin (BrigOpcode16_t brig_opcode,
BrigType16_t brig_type, tree arith_type,
tree_stl_vec &operands);
tree add_temp_var (std::string name, tree expr);
tree build_f2h_conversion (tree source);
tree build_h2f_conversion (tree source);
tree_stl_vec build_operands (const BrigInstBase &brig_inst);
tree build_output_assignment (const BrigInstBase &brig_inst, tree output,
tree inst_expr);
tree apply_to_all_elements (tree_element_unary_visitor &visitor,
tree operand);
HOST_WIDE_INT int_constant_value (tree node);
tree extend_int (tree input, tree dest_type, tree src_type);
/* HSAIL-specific builtin functions not yet integrated to gcc. */
static builtin_map s_custom_builtins;
};
/* Implement the Visitor software pattern for performing various actions on
elements of vector operands. This enables separating the vector element
traversal/extraction/packing code from whatever different actions are
performed to each element. */
class tree_element_unary_visitor
{
public:
tree operator () (brig_code_entry_handler &handler, tree operand);
/* Performs an action to a single element, which can have originally
been a vector element or a scalar. */
virtual tree visit_element (brig_code_entry_handler &handler, tree operand)
= 0;
};
class tree_element_binary_visitor
{
public:
tree operator () (brig_code_entry_handler &handler, tree operand0,
tree operand1);
/* Performs an action to a pair of elements, which can have originally
been a vector element or a scalar. */
virtual tree visit_element (brig_code_entry_handler &handler, tree operand0,
tree operand1)
= 0;
};
/* Visitor for flushing float elements to zero. */
class flush_to_zero : public tree_element_unary_visitor
{
public:
flush_to_zero (bool fp16) : m_fp16 (fp16)
{
}
virtual tree visit_element (brig_code_entry_handler &caller, tree operand);
private:
/* True if the value should be flushed according to fp16 limits. */
bool m_fp16;
};
/* Visitor for converting F16 elements to F32. */
class half_to_float : public tree_element_unary_visitor
{
public:
virtual tree visit_element (brig_code_entry_handler &caller, tree operand);
};
/* Visitor for converting F32 elements to F16. */
class float_to_half : public tree_element_unary_visitor
{
public:
virtual tree visit_element (brig_code_entry_handler &caller, tree operand);
};
/* A base class for instruction types that support floating point
modifiers.
operator () delegates to subclasses (template method pattern) in
type specific parts. */
class brig_inst_mod_handler : public brig_code_entry_handler
{
public:
brig_inst_mod_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
virtual size_t generate (const BrigBase *base);
virtual const BrigAluModifier8_t *modifier (const BrigBase *base) const;
virtual const BrigRound8_t *round (const BrigBase *base) const;
size_t operator () (const BrigBase *base);
};
class brig_directive_function_handler : public brig_code_entry_handler
{
public:
brig_directive_function_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_directive_control_handler : public brig_code_entry_handler
{
public:
brig_directive_control_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_directive_variable_handler : public brig_code_entry_handler
{
public:
brig_directive_variable_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
tree build_variable (const BrigDirectiveVariable *brigVar,
tree_code var_decltype = VAR_DECL);
size_t get_brig_var_alignment (const BrigDirectiveVariable *brigVar);
};
class brig_directive_fbarrier_handler : public brig_code_entry_handler
{
public:
brig_directive_fbarrier_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_directive_label_handler : public brig_code_entry_handler
{
public:
brig_directive_label_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_directive_comment_handler : public brig_code_entry_handler
{
public:
brig_directive_comment_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_directive_arg_block_handler : public brig_code_entry_handler
{
public:
brig_directive_arg_block_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_basic_inst_handler : public brig_code_entry_handler
{
public:
brig_basic_inst_handler (brig_to_generic &parent);
size_t operator () (const BrigBase *base);
private:
tree build_lower_element_broadcast (tree vec_operand);
bool must_be_scalarized (const BrigInstBase *brig_inst,
tree instr_type) const;
tree build_inst_expr (BrigOpcode16_t brig_opcode, BrigType16_t brig_type,
tree arith_type, tree_stl_vec &operands);
tree build_shuffle (tree arith_type, tree_stl_vec &operands);
tree build_unpack (tree_stl_vec &operands);
tree build_pack (tree_stl_vec &operands);
tree build_unpack_lo_or_hi (BrigOpcode16_t brig_opcode, tree arith_type,
tree_stl_vec &operands);
tree_code get_tree_code_for_hsa_opcode (BrigOpcode16_t brig_opcode,
BrigType16_t brig_type) const;
};
class brig_cvt_inst_handler : public brig_inst_mod_handler
{
public:
brig_cvt_inst_handler (brig_to_generic &parent)
: brig_inst_mod_handler (parent)
{
}
virtual size_t generate (const BrigBase *base);
virtual const BrigAluModifier8_t *modifier (const BrigBase *base) const;
virtual const BrigRound8_t *round (const BrigBase *base) const;
};
class brig_branch_inst_handler : public brig_code_entry_handler
{
public:
brig_branch_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_mem_inst_handler : public brig_code_entry_handler
{
public:
brig_mem_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
private:
tree build_mem_access (const BrigInstBase *brig_inst, tree addr, tree data);
};
class brig_copy_move_inst_handler : public brig_code_entry_handler
{
public:
brig_copy_move_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
private:
size_t handle_lda (const BrigInstBase *base);
};
class brig_atomic_inst_handler : public brig_code_entry_handler
{
private:
typedef std::map<std::string, tree> atomic_builtins_map;
public:
brig_atomic_inst_handler (brig_to_generic &parent);
size_t operator () (const BrigBase *base);
protected:
size_t generate_tree (const BrigInstBase &inst,
BrigAtomicOperation8_t atomic_opcode);
};
class brig_signal_inst_handler : public brig_atomic_inst_handler
{
public:
brig_signal_inst_handler (brig_to_generic &parent)
: brig_atomic_inst_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_cmp_inst_handler : public brig_code_entry_handler
{
public:
brig_cmp_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
class brig_seg_inst_handler : public brig_code_entry_handler
{
public:
brig_seg_inst_handler (brig_to_generic &parent);
size_t operator () (const BrigBase *base);
};
class brig_lane_inst_handler : public brig_code_entry_handler
{
public:
brig_lane_inst_handler (brig_to_generic &parent);
size_t operator () (const BrigBase *base);
};
class brig_queue_inst_handler : public brig_code_entry_handler
{
public:
brig_queue_inst_handler (brig_to_generic &parent);
size_t operator () (const BrigBase *base);
};
class brig_directive_module_handler : public brig_code_entry_handler
{
public:
brig_directive_module_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t operator () (const BrigBase *base);
};
#endif

View file

@ -0,0 +1,38 @@
/* brig-comment-handler.cc -- brig comment directive handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
extern int gccbrig_verbose;
size_t
brig_directive_comment_handler::operator () (const BrigBase *base)
{
const BrigDirectiveComment *brig_comment
= (const BrigDirectiveComment *) base;
if (gccbrig_verbose)
{
std::string cmnt = m_parent.get_string (brig_comment->name);
fprintf (stderr, "brig: Comment: '%s'\n", cmnt.c_str());
}
return base->byteCount;
}

View file

@ -0,0 +1,108 @@
/* brig-control-handler.cc -- brig control directive handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "diagnostic.h"
#include "print-tree.h"
size_t
brig_directive_control_handler::operator () (const BrigBase *base)
{
const BrigDirectiveControl *inst = (const BrigDirectiveControl *) base;
const BrigData *operand_entries
= m_parent.get_brig_data_entry (inst->operands);
/* Parse the constant integer operands. */
std::vector<tree> operands;
for (size_t i = 0; i < operand_entries->byteCount / 4; ++i)
{
uint32_t operand_offset
= ((const uint32_t *) &operand_entries->bytes)[i];
const BrigBase *operand_data
= m_parent.get_brig_operand_entry (operand_offset);
tree operand_type
= (inst->control == BRIG_CONTROL_REQUIREDGRIDSIZE
|| inst->control == BRIG_CONTROL_MAXFLATGRIDSIZE) ?
uint64_type_node : uint32_type_node;
operands.push_back
(build_tree_operand (*(const BrigInstBase*)inst, *operand_data,
operand_type));
}
switch (inst->control)
{
case BRIG_CONTROL_MAXDYNAMICGROUPSIZE:
{
m_parent.m_cf->m_descriptor.max_dynamic_group_size
= int_constant_value (operands.at (0));
break;
}
case BRIG_CONTROL_MAXFLATGRIDSIZE:
{
m_parent.m_cf->m_descriptor.max_flat_grid_size
= int_constant_value (operands.at (0));
break;
}
case BRIG_CONTROL_MAXFLATWORKGROUPSIZE:
{
m_parent.m_cf->m_descriptor.max_flat_workgroup_size
= int_constant_value (operands.at (0));
break;
}
case BRIG_CONTROL_REQUIREDDIM:
{
m_parent.m_cf->m_descriptor.required_dim
= int_constant_value (operands.at (0));
break;
}
case BRIG_CONTROL_REQUIREDGRIDSIZE:
{
m_parent.m_cf->m_descriptor.required_grid_size[0]
= int_constant_value (operands.at (0));
m_parent.m_cf->m_descriptor.required_grid_size[1]
= int_constant_value (operands.at (1));
m_parent.m_cf->m_descriptor.required_grid_size[2]
= int_constant_value (operands.at (2));
break;
}
case BRIG_CONTROL_REQUIREDWORKGROUPSIZE:
{
m_parent.m_cf->m_descriptor.required_workgroup_size[0]
= int_constant_value (operands.at (0));
m_parent.m_cf->m_descriptor.required_workgroup_size[1]
= int_constant_value (operands.at (1));
m_parent.m_cf->m_descriptor.required_workgroup_size[2]
= int_constant_value (operands.at (2));
break;
}
case BRIG_CONTROL_REQUIRENOPARTIALWORKGROUPS:
/* Performance hint only, ignored for now. */
break;
case BRIG_CONTROL_ENABLEBREAKEXCEPTIONS:
case BRIG_CONTROL_ENABLEDETECTEXCEPTIONS:
/* Unimplemented. */
break;
default:
sorry ("Unsupported control directive %x.\n", inst->control);
}
return base->byteCount;
}

View file

@ -0,0 +1,73 @@
/* brig-copy-move-inst-handler.cc -- brig copy/move instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "tree-pretty-print.h"
#include "print-tree.h"
#include "errors.h"
#include "brig-util.h"
size_t
brig_copy_move_inst_handler::handle_lda (const BrigInstBase *brig_inst)
{
tree dest_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
tree input = build_tree_operand_from_brig (brig_inst, NULL, 1);
tree output = build_tree_operand_from_brig (brig_inst, dest_type, 0);
build_output_assignment (*brig_inst, output, input);
return brig_inst->base.byteCount;
}
size_t
brig_copy_move_inst_handler::operator () (const BrigBase *base)
{
const BrigInstBase *brig_inst
= (const BrigInstBase *) &((const BrigInstBasic *) base)->base;
if (brig_inst->opcode == BRIG_OPCODE_LDA)
return handle_lda (brig_inst);
const BrigInstSourceType *inst_src_type = (const BrigInstSourceType *) base;
tree source_type = gccbrig_tree_type_for_hsa_type (inst_src_type->sourceType);
tree dest_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
tree input = build_tree_operand_from_brig (brig_inst, source_type, 1);
tree output = build_tree_operand_from_brig (brig_inst, dest_type, 0);
if (brig_inst->opcode == BRIG_OPCODE_COMBINE)
{
/* For combine, a simple reinterpret cast from the array constructor
works. */
tree casted = build_reinterpret_cast (dest_type, input);
tree assign = build2 (MODIFY_EXPR, TREE_TYPE (output), output, casted);
m_parent.m_cf->append_statement (assign);
}
else if (brig_inst->opcode == BRIG_OPCODE_EXPAND)
build_output_assignment (*brig_inst, output, input);
else
{
brig_basic_inst_handler basic (m_parent);
return basic (base);
}
return base->byteCount;
}

View file

@ -0,0 +1,260 @@
/* brig-cvt-inst-handler.cc -- brig cvt (convert) instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include "brig-code-entry-handler.h"
#include "gimple-expr.h"
#include "errors.h"
#include "convert.h"
#include "tree-pretty-print.h"
#include "print-tree.h"
#include "diagnostic-core.h"
#include "brig-util.h"
const BrigAluModifier8_t *
brig_cvt_inst_handler::modifier (const BrigBase *base) const
{
const BrigInstCvt *inst = (const BrigInstCvt *) base;
return &inst->modifier;
}
const BrigRound8_t *
brig_cvt_inst_handler::round (const BrigBase *base) const
{
const BrigInstCvt *inst = (const BrigInstCvt *) base;
return &inst->round;
}
size_t
brig_cvt_inst_handler::generate (const BrigBase *base)
{
/* In cvt instructions there can be at least four data types involved:
- the input register type
- the output register type
- the conversion source type
- the conversion destination type
*/
const BrigInstBase *brig_inst
= (const BrigInstBase *) &((const BrigInstBasic *) base)->base;
const BrigInstCvt *cvt_inst = (const BrigInstCvt *) base;
const BrigAluModifier8_t *inst_modifier = modifier (base);
const bool FTZ = inst_modifier != NULL && (*inst_modifier) & BRIG_ALU_FTZ;
/* The conversion source type. */
tree src_type = get_tree_expr_type_for_hsa_type (cvt_inst->sourceType);
bool src_is_fp16 = cvt_inst->sourceType == BRIG_TYPE_F16;
/* The conversion destination type. */
tree dest_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
bool dest_is_fp16 = brig_inst->type == BRIG_TYPE_F16;
if (!dest_type || !src_type)
{
gcc_unreachable ();
return base->byteCount;
}
tree_stl_vec operands = build_operands (*brig_inst);
tree &input = operands.at (1);
tree &output = operands.at (0);
size_t conv_src_size = int_size_in_bytes (src_type);
size_t conv_dst_size = int_size_in_bytes (dest_type);
size_t src_reg_size = int_size_in_bytes (TREE_TYPE (input));
/* The input register can be of different type&size than the
conversion input size. First cast the input to the conversion
input type. These casts are always bitcasts which can be
expressed as casts between different unsigned integers. */
if (src_reg_size != conv_src_size)
{
tree unsigned_int_type = NULL_TREE;
if (INTEGRAL_TYPE_P (src_type))
unsigned_int_type = unsigned_type_for (src_type);
else /* Find a matching size int type for the REAL type. */
{
if (conv_src_size == 2)
unsigned_int_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U16);
else if (conv_src_size == 4)
unsigned_int_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U32);
else if (conv_src_size == 8)
unsigned_int_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U64);
else
gcc_unreachable ();
}
input = convert_to_integer (unsigned_int_type, input);
}
if (src_is_fp16)
input = build_h2f_conversion (input);
/* Flush the float operand to zero if indicated with 'ftz'. */
if (FTZ && SCALAR_FLOAT_TYPE_P (src_type))
{
tree casted_input = build_reinterpret_cast (src_type, input);
input = flush_to_zero (src_is_fp16) (*this, casted_input);
}
tree conversion_result = NULL_TREE;
if (brig_inst->type == BRIG_TYPE_B1)
{
/* When the destination is b1, cvt does a 'ztest' operation which is
defined as a != 0 for integers and similarly (!= 0.0f) for floats. */
if (INTEGRAL_TYPE_P (src_type))
{
/* Generate an integer not equal operation. */
conversion_result = build2 (NE_EXPR, TREE_TYPE (input), input,
build_int_cst (TREE_TYPE (input), 0));
}
else
{
/* For REAL source types, ztest returns 1 if the value is not +- 0.0f.
We can perform this check with an integer comparison after
masking away the sign bit from a correct position. This is safer
than using absf because of exceptions in case of a NaN
input (NaN exceptions are not generated with cvt). */
tree unsigned_int_type = NULL_TREE;
/* Bit battern with all but the upper bit 1. */
tree and_mask = NULL_TREE;
if (conv_src_size == 2)
{
unsigned_int_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U16);
and_mask = build_int_cst (unsigned_int_type, 0x7FFF);
}
else if (conv_src_size == 4)
{
unsigned_int_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U32);
and_mask = build_int_cst (unsigned_int_type, 0x7FFFFFFF);
}
else if (conv_src_size == 8)
{
unsigned_int_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U64);
and_mask = build_int_cst (unsigned_int_type, 0x7FFFFFFFFFFFFFFF);
}
else
gcc_unreachable ();
tree casted_input = build_reinterpret_cast (unsigned_int_type, input);
tree masked_input
= build2 (BIT_AND_EXPR, unsigned_int_type, casted_input, and_mask);
conversion_result
= build2 (NE_EXPR, TREE_TYPE (masked_input), masked_input,
build_int_cst (unsigned_int_type, 0));
}
/* The result from the comparison is a boolean, convert it to such. */
conversion_result
= convert_to_integer (gccbrig_tree_type_for_hsa_type (BRIG_TYPE_B1),
conversion_result);
}
else if (dest_is_fp16)
{
tree casted_input = build_reinterpret_cast (src_type, input);
conversion_result
= convert_to_real (brig_to_generic::s_fp32_type, casted_input);
if (FTZ)
conversion_result = flush_to_zero (true) (*this, conversion_result);
conversion_result = build_f2h_conversion (conversion_result);
}
else if (SCALAR_FLOAT_TYPE_P (dest_type))
{
tree casted_input = build_reinterpret_cast (src_type, input);
conversion_result = convert_to_real (dest_type, casted_input);
}
else if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
{
conversion_result = extend_int (input, dest_type, src_type);
}
else if (INTEGRAL_TYPE_P (dest_type) && SCALAR_FLOAT_TYPE_P (src_type))
{
if (cvt_inst->round == BRIG_ROUND_INTEGER_ZERO_SAT)
{
/* Use builtins for the saturating conversions. */
#undef DEF_HSAIL_SAT_BUILTIN
#undef DEF_HSAIL_BUILTIN
#undef DEF_HSAIL_ATOMIC_BUILTIN
#undef DEF_HSAIL_INTR_BUILTIN
#undef DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN
tree builtin = NULL_TREE;
BrigType16_t src_arith_type
= src_is_fp16
? (BrigType16_t) BRIG_TYPE_F32 : cvt_inst->sourceType;
#define DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN(ENUM, HSAIL_DST_TYPE, HSAIL_SRC_TYPE, \
NAME, TYPE, ATTRS) \
if (brig_inst->type == HSAIL_DST_TYPE \
&& src_arith_type == HSAIL_SRC_TYPE) \
builtin = builtin_decl_explicit (ENUM); \
else
#include "brig-builtins.def"
gcc_unreachable ();
tree casted_input = build_reinterpret_cast (src_type, input);
conversion_result
= call_builtin (builtin, 1, dest_type, src_type, casted_input);
}
else
{
tree casted_input = build_reinterpret_cast (src_type, input);
/* Perform the int to float conversion. */
conversion_result = convert_to_integer (dest_type, casted_input);
}
/* The converted result is finally extended to the target register
width, using the same sign as the destination. */
conversion_result
= convert_to_integer (TREE_TYPE (output), conversion_result);
}
else
{
/* Just use CONVERT_EXPR and hope for the best. */
tree casted_input = build_reinterpret_cast (dest_type, input);
conversion_result = build1 (CONVERT_EXPR, dest_type, casted_input);
}
size_t dst_reg_size = int_size_in_bytes (TREE_TYPE (output));
tree assign = NULL_TREE;
/* The output register can be of different type&size than the
conversion output size. Cast it to the register variable type. */
if (dst_reg_size > conv_dst_size)
{
tree casted_output
= build1 (CONVERT_EXPR, TREE_TYPE (output), conversion_result);
assign = build2 (MODIFY_EXPR, TREE_TYPE (output), output, casted_output);
}
else
{
tree casted_output
= build_reinterpret_cast (TREE_TYPE (output), conversion_result);
assign = build2 (MODIFY_EXPR, TREE_TYPE (output), output, casted_output);
}
m_parent.m_cf->append_statement (assign);
return base->byteCount;
}

View file

@ -0,0 +1,44 @@
/* brig-fbarrier-handler.cc -- brig fbarrier directive handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "stringpool.h"
#include "errors.h"
/* Allocate this many bytes from the group segment for each fbarrier. */
#define FBARRIER_STRUCT_SIZE 32
size_t
brig_directive_fbarrier_handler::operator () (const BrigBase *base)
{
/* Model fbarriers as group segment variables with fixed size
large enough to store whatever data the actual target needs
to store to maintain the barrier info. The handle is the
offset to the beginning of the object. */
const BrigDirectiveFbarrier* fbar = (const BrigDirectiveFbarrier*)base;
if (m_parent.m_cf != NULL)
m_parent.m_cf->m_function_scope_vars.insert (base);
std::string var_name = m_parent.get_mangled_name (fbar);
m_parent.append_group_variable (var_name, FBARRIER_STRUCT_SIZE, 1);
return base->byteCount;
}

View file

@ -0,0 +1,374 @@
/* brig-code-entry-handler.cc -- brig function directive handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include <iomanip>
#include "brig-code-entry-handler.h"
#include "brig-machine.h"
#include "stringpool.h"
#include "tree-iterator.h"
#include "gimple-expr.h"
#include "function.h"
#include "phsa.h"
#include "tree-pretty-print.h"
#include "print-tree.h"
extern int gccbrig_verbose;
size_t
brig_directive_function_handler::operator () (const BrigBase *base)
{
m_parent.finish_function ();
size_t bytes_consumed = base->byteCount;
const BrigDirectiveExecutable *exec = (const BrigDirectiveExecutable *) base;
if (gccbrig_verbose)
{
printf ("brig: function name %s\n",
m_parent.get_string (exec->name).c_str());
printf ("brig: inargs %d outargs %d name offset %d\n", exec->inArgCount,
exec->outArgCount, exec->name);
}
const bool is_definition
= exec->modifier & BRIG_EXECUTABLE_DEFINITION;
const bool is_kernel = base->kind == BRIG_KIND_DIRECTIVE_KERNEL;
/* There doesn't seem to be actual use cases for kernel declarations
as they cannot be called by the program. Ignore them until there's
a reason not to. */
if (is_kernel && !is_definition)
return bytes_consumed;
m_parent.m_cf = new brig_function (exec, &m_parent);
std::string func_name = m_parent.get_mangled_name (exec);
tree fndecl;
tree ret_value = NULL_TREE;
tree stmt_list = alloc_stmt_list ();
/* Add a function scope BIND_EXPR using which we can push local variables that
represent HSAIL registers. */
tree bind_expr = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, NULL);
if (is_kernel)
{
/* The generated kernel function is not the one that should be
called by the host. */
func_name = std::string ("_") + func_name;
tree name_identifier
= get_identifier_with_length (func_name.c_str (), func_name.size ());
/* The generated kernel functions take the following arguments:
1) a char* which is a starting address of the argument segment where
the call's arguments are stored by the launcher.
2) a void* parameter that points to a phsail-finalizer context object
which passes the hsa kernel packet etc.
3) a void* parameter that contains the first flat address of the group
region allocated to the current work-group. */
tree char_ptr_type_node = build_pointer_type (char_type_node);
fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, name_identifier,
build_function_type_list (void_type_node,
char_ptr_type_node,
ptr_type_node,
ptr_type_node, NULL_TREE));
SET_DECL_ASSEMBLER_NAME (fndecl, name_identifier);
tree resdecl
= build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, void_type_node);
tree typelist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
tree argtype = TREE_VALUE (typelist);
TYPE_ADDR_SPACE (argtype)
= gccbrig_get_target_addr_space_id (BRIG_SEGMENT_KERNARG);
tree arg_arg = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("__args"), char_ptr_type_node);
DECL_ARGUMENTS (fndecl) = arg_arg;
DECL_ARG_TYPE (arg_arg) = char_ptr_type_node;
DECL_CONTEXT (arg_arg) = fndecl;
DECL_ARTIFICIAL (arg_arg) = 1;
TREE_READONLY (arg_arg) = 1;
TREE_USED (arg_arg) = 1;
DECL_RESULT (fndecl) = resdecl;
DECL_CONTEXT (resdecl) = fndecl;
DECL_EXTERNAL (fndecl) = 0;
}
else
{
/* Build a regular function fingerprint to enable targets to optimize
the calling convention as they see fit. */
tree name_identifier
= get_identifier_with_length (func_name.c_str (), func_name.size ());
m_parent.m_cf->m_arg_variables.clear ();
brig_directive_variable_handler arg_handler (m_parent);
vec<tree, va_gc> *args;
vec_alloc (args, 4);
tree arg_decls = NULL_TREE;
tree ret_type = void_type_node;
if (exec->outArgCount == 1)
{
/* The return value variable should be the first entry after the
function directive. */
const BrigBase *retval
= (const BrigBase *) ((const char *) base + base->byteCount);
gcc_assert (retval->kind == BRIG_KIND_DIRECTIVE_VARIABLE);
const BrigDirectiveVariable *brigVar
= (const BrigDirectiveVariable *) retval;
brig_directive_variable_handler varhandler (m_parent);
if (brigVar->type & BRIG_TYPE_ARRAY)
{
/* Push array output arguments to the beginning of the
function argument list instead of regular function
return values. */
tree arg_var = varhandler.build_variable (brigVar, PARM_DECL);
vec_safe_push (args, TREE_TYPE (arg_var));
m_parent.m_cf->add_arg_variable (brigVar, arg_var);
if (arg_decls == NULL_TREE)
arg_decls = arg_var;
else
chainon (arg_decls, arg_var);
m_parent.m_cf->add_arg_variable (brigVar, arg_var);
ret_value = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
void_type_node);
}
else
{
ret_value = varhandler.build_variable (brigVar, RESULT_DECL);
m_parent.m_cf->m_ret_value = ret_value;
ret_type = TREE_TYPE (ret_value);
m_parent.m_cf->m_ret_value_brig_var = brigVar;
}
bytes_consumed += retval->byteCount;
}
else
ret_value = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
void_type_node);
TREE_ADDRESSABLE (ret_value) = 1;
if (exec->inArgCount > 0)
{
uint32_t arg_offset = exec->firstInArg;
for (size_t arg = 0; arg < exec->inArgCount; ++arg)
{
const BrigDirectiveVariable *brigVar
= (const BrigDirectiveVariable *) m_parent.get_brig_code_entry
(arg_offset);
gcc_assert (brigVar->base.kind == BRIG_KIND_DIRECTIVE_VARIABLE);
/* Delegate to the brig_directive_variable_handler. */
brig_directive_variable_handler varhandler (m_parent);
tree arg_var = varhandler.build_variable (brigVar, PARM_DECL);
arg_offset += brigVar->base.byteCount;
vec_safe_push (args, TREE_TYPE (arg_var));
m_parent.m_cf->add_arg_variable (brigVar, arg_var);
if (arg_decls == NULL_TREE)
arg_decls = arg_var;
else
chainon (arg_decls, arg_var);
}
}
vec_safe_push (args, ptr_type_node);
vec_safe_push (args, ptr_type_node);
fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, name_identifier,
build_function_type_vec (ret_type, args));
DECL_RESULT (fndecl) = ret_value;
DECL_CONTEXT (ret_value) = fndecl;
DECL_EXTERNAL (fndecl) = 0;
DECL_ARGUMENTS (fndecl) = arg_decls;
}
/* All functions need the hidden __context argument passed on
because they might call WI-specific functions which need
the context info. */
tree context_arg = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("__context"), ptr_type_node);
if (DECL_ARGUMENTS (fndecl) == NULL_TREE)
DECL_ARGUMENTS (fndecl) = context_arg;
else
chainon (DECL_ARGUMENTS (fndecl), context_arg);
DECL_CONTEXT (context_arg) = fndecl;
DECL_ARG_TYPE (context_arg) = ptr_type_node;
DECL_ARTIFICIAL (context_arg) = 1;
TREE_READONLY (context_arg) = 1;
TREE_USED (context_arg) = 1;
/* They can also access group memory, so we need to pass the
group pointer along too. */
tree group_base_arg
= build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("__group_base_addr"), ptr_type_node);
chainon (DECL_ARGUMENTS (fndecl), group_base_arg);
DECL_ARG_TYPE (group_base_arg) = ptr_type_node;
DECL_CONTEXT (group_base_arg) = fndecl;
DECL_ARTIFICIAL (group_base_arg) = 1;
TREE_READONLY (group_base_arg) = 1;
TREE_USED (group_base_arg) = 1;
/* Same for private. */
tree private_base_arg
= build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("__private_base_addr"), ptr_type_node);
chainon (DECL_ARGUMENTS (fndecl), private_base_arg);
DECL_ARG_TYPE (private_base_arg) = ptr_type_node;
DECL_CONTEXT (private_base_arg) = fndecl;
DECL_ARTIFICIAL (private_base_arg) = 1;
TREE_READONLY (private_base_arg) = 1;
TREE_USED (private_base_arg) = 1;
DECL_SAVED_TREE (fndecl) = bind_expr;
/* Try to preserve the functions across IPA. */
DECL_PRESERVE_P (fndecl) = 1;
TREE_SIDE_EFFECTS (fndecl) = 1;
TREE_ADDRESSABLE (fndecl) = 1;
if (base->kind == BRIG_KIND_DIRECTIVE_FUNCTION)
{
TREE_STATIC (fndecl) = 1;
TREE_PUBLIC (fndecl) = 1;
}
else if (base->kind == BRIG_KIND_DIRECTIVE_KERNEL)
{
TREE_STATIC (fndecl) = 1;
TREE_PUBLIC (fndecl) = 1;
}
else if (base->kind == BRIG_KIND_DIRECTIVE_SIGNATURE)
{
TREE_STATIC (fndecl) = 0;
TREE_PUBLIC (fndecl) = 1;
DECL_EXTERNAL (fndecl) = 1;
}
else if (base->kind == BRIG_KIND_DIRECTIVE_INDIRECT_FUNCTION)
{
TREE_STATIC (fndecl) = 0;
TREE_PUBLIC (fndecl) = 1;
}
else
gcc_unreachable ();
TREE_USED (fndecl) = 1;
DECL_ARTIFICIAL (fndecl) = 0;
tree initial_block = make_node (BLOCK);
DECL_INITIAL (fndecl) = initial_block;
TREE_USED (DECL_INITIAL (fndecl)) = 1;
if (ret_value != NULL_TREE && TREE_TYPE (ret_value) != void_type_node)
{
DECL_CONTEXT (ret_value) = fndecl;
DECL_CHAIN (ret_value) = BIND_EXPR_VARS (bind_expr);
BIND_EXPR_VARS (bind_expr) = ret_value;
}
tree arg;
for (arg = DECL_ARGUMENTS (fndecl); arg != NULL_TREE; arg = TREE_CHAIN (arg))
{
DECL_CONTEXT (arg) = fndecl;
DECL_ARG_TYPE (arg) = TREE_TYPE (arg);
}
m_parent.add_function_decl (func_name, fndecl);
m_parent.append_global (fndecl);
if (!is_definition)
return bytes_consumed;
m_parent.start_function (fndecl);
m_parent.m_cf->m_name = func_name;
m_parent.m_cf->m_func_decl = fndecl;
m_parent.m_cf->m_current_bind_expr = bind_expr;
m_parent.m_cf->m_is_kernel = is_kernel;
m_parent.m_cf->m_context_arg = context_arg;
m_parent.m_cf->m_group_base_arg = group_base_arg;
m_parent.m_cf->m_private_base_arg = private_base_arg;
if (ret_value != NULL_TREE && TREE_TYPE (ret_value) != void_type_node)
{
/* We cannot assign to <<retval>> directly in gcc trunk. We need to
create a local temporary variable which can be stored to and when
returning from the function, we'll copy it to the actual <<retval>>
in return statement's argument. */
tree temp_var = m_parent.m_cf->m_ret_temp
= m_parent.m_cf->add_local_variable ("_retvalue_temp",
TREE_TYPE (ret_value));
TREE_ADDRESSABLE (temp_var) = 1;
}
if (is_kernel)
{
m_parent.m_cf->add_id_variables ();
/* Create a single entry point in the function. */
m_parent.m_cf->m_entry_label_stmt
= build_stmt (LABEL_EXPR, m_parent.m_cf->label ("__kernel_entry"));
m_parent.m_cf->append_statement (m_parent.m_cf->m_entry_label_stmt);
tree bind_expr = m_parent.m_cf->m_current_bind_expr;
tree stmts = BIND_EXPR_BODY (bind_expr);
m_parent.m_cf->m_kernel_entry = tsi_last (stmts);
/* Let's not append the exit label yet, but only after the
function has been built. We need to build it so it can
be referred to because returns are converted to gotos to this
label. */
m_parent.m_cf->m_exit_label = m_parent.m_cf->label ("__kernel_exit");
}
return bytes_consumed;
}

View file

@ -0,0 +1,723 @@
/* brig-function.cc -- declaration of brig_function class.
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include <iomanip>
#include "brig-function.h"
#include "stringpool.h"
#include "tree-iterator.h"
#include "toplev.h"
#include "gimplify.h"
#include "gimple-expr.h"
#include "print-tree.h"
#include "hsa-brig-format.h"
#include "stor-layout.h"
#include "diagnostic-core.h"
#include "brig-code-entry-handler.h"
#include "brig-machine.h"
#include "brig-util.h"
#include "phsa.h"
#include "tree-pretty-print.h"
#include "dumpfile.h"
#include "tree-cfg.h"
#include "errors.h"
#include "function.h"
#include "brig-to-generic.h"
#include "brig-builtins.h"
brig_function::brig_function (const BrigDirectiveExecutable *exec,
brig_to_generic *parent)
: m_brig_def (exec), m_is_kernel (false), m_is_finished (false), m_name (""),
m_current_bind_expr (NULL_TREE), m_func_decl (NULL_TREE),
m_context_arg (NULL_TREE), m_group_base_arg (NULL_TREE),
m_private_base_arg (NULL_TREE), m_ret_value (NULL_TREE),
m_next_kernarg_offset (0), m_kernarg_max_align (0),
m_ret_value_brig_var (NULL), m_has_barriers (false),
m_has_allocas (false), m_has_function_calls_with_barriers (false),
m_calls_analyzed (false), m_is_wg_function (false),
m_has_unexpanded_dp_builtins (false), m_generating_arg_block (false),
m_parent (parent)
{
memset (m_regs, 0,
BRIG_2_TREE_HSAIL_TOTAL_REG_COUNT * sizeof (BrigOperandRegister *));
memset (&m_descriptor, 0, sizeof (phsa_descriptor));
}
brig_function::~brig_function ()
{
for (size_t i = 0; i < BRIG_2_TREE_HSAIL_TOTAL_REG_COUNT; ++i)
{
if (m_regs[i] != NULL)
{
delete m_regs[i];
m_regs[i] = NULL;
}
}
}
/* Returns a GENERIC label with the given name in the given function.
Creates it, if not yet found. */
tree
brig_function::label (const std::string &name)
{
label_index::const_iterator i = m_label_index.find (name);
if (i == m_label_index.end ())
{
tree name_identifier
= get_identifier_with_length (name.c_str (), name.size ());
tree label_decl = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
name_identifier, void_type_node);
DECL_CONTEXT (label_decl) = m_func_decl;
DECL_ARTIFICIAL (label_decl) = 0;
m_label_index[name] = label_decl;
return label_decl;
}
else
return (*i).second;
}
/* Record an argument variable for later use. This includes both local
variables inside arg blocks and incoming function arguments. */
void
brig_function::add_arg_variable (const BrigDirectiveVariable *brigVar,
tree treeDecl)
{
m_arg_variables[brigVar] = treeDecl;
}
tree
brig_function::arg_variable (const BrigDirectiveVariable *var) const
{
variable_index::const_iterator i = m_arg_variables.find (var);
if (i == m_arg_variables.end ())
return NULL_TREE;
else
return (*i).second;
}
/* Appends a new kernel argument descriptor for the current kernel's
arg space. */
void
brig_function::append_kernel_arg (const BrigDirectiveVariable *var, size_t size,
size_t alignment)
{
gcc_assert (m_func_decl != NULL_TREE);
gcc_assert (m_is_kernel);
size_t align_padding = m_next_kernarg_offset % alignment == 0 ?
0 : (alignment - m_next_kernarg_offset % alignment);
m_next_kernarg_offset += align_padding;
m_kernarg_offsets[var] = m_next_kernarg_offset;
m_next_kernarg_offset += size;
m_kernarg_max_align
= m_kernarg_max_align < alignment ? alignment : m_kernarg_max_align;
}
size_t
brig_function::kernel_arg_offset (const BrigDirectiveVariable *var) const
{
var_offset_table::const_iterator i = m_kernarg_offsets.find (var);
gcc_assert (i != m_kernarg_offsets.end ());
return (*i).second;
}
/* Add work-item ID variables to the beginning of the kernel function
which can be used for address computation as kernel dispatch packet
instructions can be expanded to GENERIC nodes referring to them. */
void
brig_function::add_id_variables ()
{
tree bind_expr = m_current_bind_expr;
tree stmts = BIND_EXPR_BODY (bind_expr);
/* Initialize the WG limits and local ids. */
tree_stmt_iterator entry = tsi_start (stmts);
for (int i = 0; i < 3; ++i)
{
char dim_char = (char) ((int) 'x' + i);
/* The local sizes are limited to 16b values, but let's still use 32b
to avoid unnecessary casts (the ID functions are 32b). */
m_local_id_vars[i]
= add_local_variable (std::string ("__local_") + dim_char,
uint32_type_node);
tree workitemid_call
= call_builtin (builtin_decl_explicit (BUILT_IN_HSAIL_WORKITEMID), 2,
uint32_type_node, uint32_type_node,
build_int_cst (uint32_type_node, i), ptr_type_node,
m_context_arg);
tree id_init = build2 (MODIFY_EXPR, TREE_TYPE (m_local_id_vars[i]),
m_local_id_vars[i], workitemid_call);
tsi_link_after (&entry, id_init, TSI_NEW_STMT);
m_cur_wg_size_vars[i]
= add_local_variable (std::string ("__cur_wg_size_") + dim_char,
uint32_type_node);
tree cwgz_call
= call_builtin
(builtin_decl_explicit (BUILT_IN_HSAIL_CURRENTWORKGROUPSIZE),
2, uint32_type_node, uint32_type_node,
build_int_cst (uint32_type_node, i), ptr_type_node, m_context_arg);
tree limit_init = build2 (MODIFY_EXPR, TREE_TYPE (m_cur_wg_size_vars[i]),
m_cur_wg_size_vars[i], cwgz_call);
tsi_link_after (&entry, limit_init, TSI_NEW_STMT);
m_wg_id_vars[i]
= add_local_variable (std::string ("__workgroupid_") + dim_char,
uint32_type_node);
tree wgid_call
= call_builtin (builtin_decl_explicit (BUILT_IN_HSAIL_WORKGROUPID),
2, uint32_type_node, uint32_type_node,
build_int_cst (uint32_type_node, i), ptr_type_node,
m_context_arg);
tree wgid_init = build2 (MODIFY_EXPR, TREE_TYPE (m_wg_id_vars[i]),
m_wg_id_vars[i], wgid_call);
tsi_link_after (&entry, wgid_init, TSI_NEW_STMT);
m_wg_size_vars[i]
= add_local_variable (std::string ("__workgroupsize_") + dim_char,
uint32_type_node);
tree wgsize_call
= call_builtin (builtin_decl_explicit (BUILT_IN_HSAIL_WORKGROUPSIZE),
2, uint32_type_node, uint32_type_node,
build_int_cst (uint32_type_node, i), ptr_type_node,
m_context_arg);
tree wgsize_init = build2 (MODIFY_EXPR, TREE_TYPE (m_wg_size_vars[i]),
m_wg_size_vars[i], wgsize_call);
tsi_link_after (&entry, wgsize_init, TSI_NEW_STMT);
m_grid_size_vars[i]
= add_local_variable (std::string ("__gridsize_") + dim_char,
uint32_type_node);
tree gridsize_call
= call_builtin (builtin_decl_explicit (BUILT_IN_HSAIL_GRIDSIZE), 2,
uint32_type_node, uint32_type_node,
build_int_cst (uint32_type_node, i), ptr_type_node,
m_context_arg);
tree gridsize_init = build2 (MODIFY_EXPR, TREE_TYPE (m_grid_size_vars[i]),
m_grid_size_vars[i], gridsize_call);
tsi_link_after (&entry, gridsize_init, TSI_NEW_STMT);
}
m_kernel_entry = entry;
}
/* Creates a new local variable with the given NAME and given GENERIC
TYPE. */
tree
brig_function::add_local_variable (std::string name, tree type)
{
tree name_identifier
= get_identifier_with_length (name.c_str (), name.size ());
tree variable
= build_decl (UNKNOWN_LOCATION, VAR_DECL, name_identifier, type);
DECL_NONLOCAL (variable) = 0;
TREE_ADDRESSABLE (variable) = 0;
TREE_STATIC (variable) = 0;
TREE_USED (variable) = 1;
DECL_ARTIFICIAL (variable) = 0;
tree bind_expr = DECL_SAVED_TREE (m_func_decl);
DECL_CONTEXT (variable) = m_func_decl;
DECL_CHAIN (variable) = BIND_EXPR_VARS (bind_expr);
BIND_EXPR_VARS (bind_expr) = variable;
return variable;
}
/* Returns a DECL_VAR for the given HSAIL operand register.
If it has not been created yet for the function being generated,
creates it as an unsigned int variable. */
tree
brig_function::get_m_var_declfor_reg (const BrigOperandRegister *reg)
{
size_t offset = reg->regNum;
switch (reg->regKind)
{
case BRIG_REGISTER_KIND_QUAD:
offset
+= BRIG_2_TREE_HSAIL_D_REG_COUNT + BRIG_2_TREE_HSAIL_S_REG_COUNT +
BRIG_2_TREE_HSAIL_C_REG_COUNT;
break;
case BRIG_REGISTER_KIND_DOUBLE:
offset += BRIG_2_TREE_HSAIL_S_REG_COUNT + BRIG_2_TREE_HSAIL_C_REG_COUNT;
break;
case BRIG_REGISTER_KIND_SINGLE:
offset += BRIG_2_TREE_HSAIL_C_REG_COUNT;
case BRIG_REGISTER_KIND_CONTROL:
break;
default:
gcc_unreachable ();
break;
}
reg_decl_index_entry *regEntry = m_regs[offset];
if (regEntry == NULL)
{
size_t reg_size = gccbrig_reg_size (reg);
tree type;
if (reg_size > 1)
type = build_nonstandard_integer_type (reg_size, true);
else
type = boolean_type_node;
/* Drop the const qualifier so we do not end up with a read only
register variable which cannot be written to later. */
tree nonconst_type = build_type_variant (type, false, false);
regEntry = new reg_decl_index_entry;
regEntry->m_var_decl
= add_local_variable (gccbrig_reg_name (reg), nonconst_type);
m_regs[offset] = regEntry;
}
return regEntry->m_var_decl;
}
/* Builds a work-item do..while loop for a single DIM. HEADER_ENTRY is
a statement after which the iteration variables should be initialized and
the loop body starts. BRANCH_AFTER is the statement after which the loop
predicate check and the back edge goto will be appended. */
void
brig_function::add_wi_loop (int dim, tree_stmt_iterator *header_entry,
tree_stmt_iterator *branch_after)
{
tree ivar = m_local_id_vars[dim];
tree ivar_max = m_cur_wg_size_vars[dim];
tree_stmt_iterator entry = *header_entry;
/* TODO: this is not a parallel loop as we share the "register variables"
across work-items. Should create a copy of them per WI instance. That
is, declare temporaries for new definitions inside the loop body, not at
function scope. */
tree ivar_init = build2 (MODIFY_EXPR, TREE_TYPE (ivar), ivar,
build_zero_cst (TREE_TYPE (ivar)));
tsi_link_after (&entry, ivar_init, TSI_NEW_STMT);
tree loop_body_label
= label (std::string ("__wi_loop_") + (char) ((int) 'x' + dim));
tree loop_body_label_stmt = build_stmt (LABEL_EXPR, loop_body_label);
tsi_link_after (&entry, loop_body_label_stmt, TSI_NEW_STMT);
if (m_has_unexpanded_dp_builtins)
{
tree id_set_builtin
= builtin_decl_explicit (BUILT_IN_HSAIL_SETWORKITEMID);
/* Set the local ID to the current wi-loop iteration variable value to
ensure the builtins see the correct values. */
tree id_set_call
= call_builtin (id_set_builtin, 3,
void_type_node, uint32_type_node,
build_int_cst (uint32_type_node, dim), uint32_type_node,
ivar, ptr_type_node, m_context_arg);
tsi_link_after (&entry, id_set_call, TSI_NEW_STMT);
}
/* Increment the WI iteration variable. */
tree incr = build2 (PREINCREMENT_EXPR, TREE_TYPE (ivar), ivar,
build_one_cst (TREE_TYPE (ivar)));
tsi_link_after (branch_after, incr, TSI_NEW_STMT);
/* Append the predicate check with the back edge goto. */
tree condition = build2 (LT_EXPR, TREE_TYPE (ivar), ivar, ivar_max);
tree target_goto = build1 (GOTO_EXPR, void_type_node, loop_body_label);
tree if_stmt
= build3 (COND_EXPR, void_type_node, condition, target_goto, NULL_TREE);
tsi_link_after (branch_after, if_stmt, TSI_NEW_STMT);
}
/* Recursively analyzes the function and its callees for barrier usage. */
void
brig_function::analyze_calls ()
{
if (m_calls_analyzed)
return;
/* Set this early to not get stuck in case of recursive call graphs.
This is safe because if the function calls itself, either the function
has barrier calls which implies a call to a function with barrier calls,
or it doesn't in which case the result depends on the later called
functions. */
m_calls_analyzed = true;
for (size_t i = 0; i < m_called_functions.size (); ++i)
{
tree f = m_called_functions[i];
brig_function *called_f = m_parent->get_finished_function (f);
if (called_f == NULL)
{
/* Unfinished function (only declaration within the set of BRIGs)
found. Cannot finish the CG analysis. Have to assume it does have
a barrier for safety. */
m_has_function_calls_with_barriers = true;
m_has_unexpanded_dp_builtins = true;
break;
}
called_f->analyze_calls ();
/* We can assume m_has_barriers has been correctly set during the
construction of the function decl. No need to reanalyze it. */
m_has_function_calls_with_barriers |= called_f->m_has_barriers;
/* If the function or any of its called functions has dispatch
packet builtin calls that require the local id, we need to
set the local id to the context in the work item loop before
the functions are called. If we analyze the opposite, these
function calls can be omitted. */
m_has_unexpanded_dp_builtins |= called_f->m_has_unexpanded_dp_builtins;
}
}
/* Tries to convert the current kernel to a work-group function that executes
all work-items using loops. Returns true in case the conversion was
successful. */
bool
brig_function::convert_to_wg_function ()
{
if (!m_calls_analyzed)
analyze_calls ();
if (m_has_barriers || m_has_function_calls_with_barriers)
return false;
/* The most trivial case: No barriers at all in the kernel.
We can create one big work-item loop around the whole kernel. */
tree bind_expr = m_current_bind_expr;
tree stmts = BIND_EXPR_BODY (bind_expr);
for (int i = 0; i < 3; ++i)
{
/* The previous loop has added a new label to the end of the function,
the next level loop should wrap around it also. */
tree_stmt_iterator function_exit = tsi_last (stmts);
add_wi_loop (i, &m_kernel_entry, &function_exit);
}
m_is_wg_function = true;
return false;
}
/* Emits a kernel description to a special ELF section so it can be
utilized by an HSA runtime implementation. The assembly block
must be emitted to a statement list of an function, which is given
as an argument. Returns the assembly block used to emit the section. */
tree
brig_function::emit_metadata (tree stmt_list)
{
/* Emit an ELF section via an assembly directive that generates a special
ELF section for each kernel that contains raw bytes of a descriptor
object. This is pretty disgusting, but life is never perfect ;) */
/* Use the original kernel name without the '_' prefix in the section name. */
std::string kern_name = m_is_kernel ? m_name.substr (1) : m_name;
std::ostringstream strstr;
strstr << std::endl
<< ".pushsection " << PHSA_DESC_SECTION_PREFIX << kern_name
<< std::endl
<< "\t.p2align 1, 1, 1" << std::endl
<< "\t.byte ";
for (size_t i = 0; i < sizeof (phsa_descriptor); ++i)
{
strstr << "0x" << std::setw (2) << std::setfill ('0') << std::hex
<< (unsigned) *((unsigned char *) &m_descriptor + i);
if (i + 1 < sizeof (phsa_descriptor))
strstr << ", ";
}
strstr << std::endl << ".popsection" << std::endl << std::endl;
tree metadata_asm
= build_stmt (ASM_EXPR,
build_string (strstr.str ().size (), strstr.str ().c_str ()),
NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
append_to_statement_list_force (metadata_asm, &stmt_list);
return metadata_asm;
}
/* Emits the kernel launcher function. Also emits the metadata section
creation statements in it.
The launcher function calls the device-side runtime
that runs the kernel for all work-items. In C:
void KernelName (void* context, void* group_base_addr)
{
__hsail_launch_kernel (_KernelName, context, group_base_addr);
}
or, in case of a successful conversion to a work-group function:
void KernelName (void* context, void* group_base_addr)
{
__hsail_launch_wg_function (_KernelName, context, group_base_addr);
}
The user/host sees this function as the kernel to call from the
outside. The actual kernel generated from HSAIL was named _KernelName.
*/
tree
brig_function::emit_launcher_and_metadata ()
{
/* The original kernel name without the '_' prefix. */
std::string kern_name = m_name.substr (1);
tree name_identifier
= get_identifier_with_length (kern_name.c_str (), kern_name.size ());
tree launcher
= build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, name_identifier,
build_function_type_list (void_type_node, ptr_type_node,
ptr_type_node, NULL_TREE));
TREE_USED (launcher) = 1;
DECL_ARTIFICIAL (launcher) = 1;
tree context_arg = build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("__context"), ptr_type_node);
DECL_ARGUMENTS (launcher) = context_arg;
DECL_ARG_TYPE (context_arg) = ptr_type_node;
DECL_CONTEXT (context_arg) = launcher;
TREE_USED (context_arg) = 1;
DECL_ARTIFICIAL (context_arg) = 1;
tree group_base_addr_arg
= build_decl (UNKNOWN_LOCATION, PARM_DECL,
get_identifier ("__group_base_addr"), ptr_type_node);
chainon (DECL_ARGUMENTS (launcher), group_base_addr_arg);
DECL_ARG_TYPE (group_base_addr_arg) = ptr_type_node;
DECL_CONTEXT (group_base_addr_arg) = launcher;
TREE_USED (group_base_addr_arg) = 1;
DECL_ARTIFICIAL (group_base_addr_arg) = 1;
tree resdecl
= build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, void_type_node);
DECL_RESULT (launcher) = resdecl;
DECL_CONTEXT (resdecl) = launcher;
DECL_INITIAL (launcher) = make_node (BLOCK);
TREE_USED (DECL_INITIAL (launcher)) = 1;
tree stmt_list = alloc_stmt_list ();
tree bind_expr = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, NULL);
TREE_STATIC (launcher) = 0;
TREE_PUBLIC (launcher) = 1;
DECL_SAVED_TREE (launcher) = bind_expr;
if (DECL_STRUCT_FUNCTION (launcher) == NULL)
push_struct_function (launcher);
else
push_cfun (DECL_STRUCT_FUNCTION (launcher));
tree kernel_func_ptr = build1 (ADDR_EXPR, ptr_type_node, m_func_decl);
tree phsail_launch_kernel_call;
/* Emit a launcher depending whether we converted the kernel function to
a work group function or not. */
if (m_is_wg_function)
phsail_launch_kernel_call
= call_builtin (builtin_decl_explicit (BUILT_IN_HSAIL_LAUNCH_WG_FUNC),
3, void_type_node,
ptr_type_node, kernel_func_ptr, ptr_type_node,
context_arg, ptr_type_node, group_base_addr_arg);
else
phsail_launch_kernel_call
= call_builtin (builtin_decl_explicit (BUILT_IN_HSAIL_LAUNCH_KERNEL),
3, void_type_node,
ptr_type_node, kernel_func_ptr, ptr_type_node,
context_arg, ptr_type_node, group_base_addr_arg);
append_to_statement_list_force (phsail_launch_kernel_call, &stmt_list);
emit_metadata (stmt_list);
return launcher;
}
tree
brig_function::append_statement (tree stmt)
{
gcc_assert (m_func_decl != NULL);
tree bind_expr = m_current_bind_expr;
tree stmts = BIND_EXPR_BODY (bind_expr);
append_to_statement_list_force (stmt, &stmts);
return stmt;
}
/* Creates a new "alloca frame" for the current function by
injecting an alloca frame push in the beginning of the function
and an alloca frame pop before all function exit points. */
void
brig_function::create_alloca_frame ()
{
tree_stmt_iterator entry;
/* Adds the alloca push only after the ids have been initialized
in case of a kernel function. */
if (m_is_kernel)
entry = m_kernel_entry;
else
{
tree bind_expr = m_current_bind_expr;
tree stmts = BIND_EXPR_BODY (bind_expr);
entry = tsi_start (stmts);
}
tree push_frame_builtin = builtin_decl_explicit (BUILT_IN_HSAIL_PUSH_FRAME);
tree push_frame_call
= call_builtin (push_frame_builtin, 1, void_type_node, ptr_type_node,
m_context_arg);
tsi_link_before (&entry, push_frame_call, TSI_NEW_STMT);
tree pop_frame_builtin = builtin_decl_explicit (BUILT_IN_HSAIL_POP_FRAME);
do
{
tree stmt = tsi_stmt (entry);
if (TREE_CODE (stmt) == RETURN_EXPR)
{
tree pop_frame_call
= call_builtin (pop_frame_builtin, 1, void_type_node,
ptr_type_node, m_context_arg);
tsi_link_before (&entry, pop_frame_call, TSI_SAME_STMT);
}
tsi_next (&entry);
}
while (!tsi_end_p (entry));
}
/* Finishes the currently built function. After calling this, no new
statements should be appeneded to the function. */
void
brig_function::finish ()
{
append_return_stmt ();
/* Currently assume single alloca frame per WG. */
if (m_has_allocas)
create_alloca_frame ();
}
void
brig_function::finish_kernel ()
{
/* Kernel functions should have a single exit point.
Let's create one. The return instructions should have
been converted to branches to this label. */
append_statement (build_stmt (LABEL_EXPR, m_exit_label));
/* Attempt to convert the kernel to a work-group function that
executes all work-items of the WG using a loop. */
convert_to_wg_function ();
append_return_stmt ();
/* Currently assume single alloca frame per WG. */
if (m_has_allocas)
create_alloca_frame ();
}
void
brig_function::append_return_stmt ()
{
gcc_assert (m_current_bind_expr != NULL_TREE);
tree stmts = BIND_EXPR_BODY (m_current_bind_expr);
if (STATEMENT_LIST_TAIL (stmts) == NULL)
return; /* Empty function. */
tree last_stmt = tsi_stmt (tsi_last (stmts));
if (TREE_CODE (last_stmt) == RETURN_EXPR)
return;
if (m_ret_value != NULL_TREE)
{
tree result_assign
= build2 (MODIFY_EXPR, TREE_TYPE (m_ret_value), m_ret_value,
m_ret_temp);
tree return_expr
= build1 (RETURN_EXPR, TREE_TYPE (result_assign), result_assign);
append_to_statement_list_force (return_expr, &stmts);
}
else
{
tree return_stmt = build_stmt (RETURN_EXPR, NULL);
append_to_statement_list_force (return_stmt, &stmts);
}
}
bool
brig_function::has_function_scope_var (const BrigBase* var) const
{
return m_function_scope_vars.find (var) != m_function_scope_vars.end ();
}

View file

@ -0,0 +1,213 @@
/* brig-function.h -- declaration of brig_function class.
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef BRIG_FUNCTION_H
#define BRIG_FUNCTION_H
#include "config.h"
#include "system.h"
#include "ansidecl.h"
#include "coretypes.h"
#include "opts.h"
#include "tree.h"
#include "tree-iterator.h"
#include "hsa-brig-format.h"
class brig_to_generic;
#include <map>
#include <string>
#include <vector>
#include <set>
#include "phsa.h"
typedef std::map<std::string, tree> label_index;
typedef std::map<const BrigDirectiveVariable *, tree> variable_index;
typedef std::vector<tree> tree_stl_vec;
/* There are 128 c regs and 2048 s/d/q regs each in the HSAIL. */
#define BRIG_2_TREE_HSAIL_C_REG_COUNT (128)
#define BRIG_2_TREE_HSAIL_S_REG_COUNT (2048)
#define BRIG_2_TREE_HSAIL_D_REG_COUNT (2048)
#define BRIG_2_TREE_HSAIL_Q_REG_COUNT (2048)
#define BRIG_2_TREE_HSAIL_TOTAL_REG_COUNT \
(BRIG_2_TREE_HSAIL_C_REG_COUNT + BRIG_2_TREE_HSAIL_S_REG_COUNT \
+ BRIG_2_TREE_HSAIL_D_REG_COUNT + BRIG_2_TREE_HSAIL_Q_REG_COUNT)
/* Holds data for the currently built GENERIC function. */
class brig_function
{
public:
typedef std::map<const BrigDirectiveVariable *, size_t> var_offset_table;
private:
struct reg_decl_index_entry
{
tree m_var_decl;
};
public:
brig_function (const BrigDirectiveExecutable *exec, brig_to_generic *parent);
~brig_function ();
tree arg_variable (const BrigDirectiveVariable *var) const;
void add_arg_variable (const BrigDirectiveVariable *brigVar, tree treeDecl);
void append_kernel_arg (const BrigDirectiveVariable *var, size_t size,
size_t alignment);
size_t kernel_arg_offset (const BrigDirectiveVariable *var) const;
void add_id_variables ();
tree label (const std::string &name);
tree add_local_variable (std::string name, tree type);
tree get_m_var_declfor_reg (const BrigOperandRegister *reg);
bool convert_to_wg_function ();
void add_wi_loop (int dim, tree_stmt_iterator *header_entry,
tree_stmt_iterator *branch_after);
tree emit_metadata (tree stmt_list);
tree emit_launcher_and_metadata ();
tree append_statement (tree stmt);
void create_alloca_frame ();
void finish ();
void finish_kernel ();
void append_return_stmt ();
bool has_function_scope_var (const BrigBase* var) const;
void analyze_calls ();
const BrigDirectiveExecutable *m_brig_def;
bool m_is_kernel;
bool m_is_finished;
std::string m_name;
tree m_current_bind_expr;
tree m_func_decl;
tree m_entry_label_stmt;
tree m_exit_label;
/* The __context function argument. */
tree m_context_arg;
/* The __group_base_ptr argument in the current function.
Points to the start of the group segment for the kernel
instance. */
tree m_group_base_arg;
/* The __private_base_ptr argument in the current function.
Points to the start of the private segment. */
tree m_private_base_arg;
/* The return value variable for the current function. */
tree m_ret_value;
/* The offsets of the kernel arguments in the __arg blob
pointing to the kernel argument space. */
size_t m_next_kernarg_offset;
/* The largest kernel argument variable alignment. */
size_t m_kernarg_max_align;
var_offset_table m_kernarg_offsets;
/* Argument variables in the currently handled binding expression
(argument segment). */
variable_index m_arg_variables;
/* The brig variable for the function return value. */
const BrigDirectiveVariable *m_ret_value_brig_var;
/* The function local temporary variable for the return value. */
tree m_ret_temp;
/* Labels in the current function are collected here so we can refer
to them from jumps before they have been placed to the function. */
label_index m_label_index;
/* If the kernel contains at least one barrier, this is set to true. */
bool m_has_barriers;
/* True if the function has at least one alloca instruction. */
bool m_has_allocas;
/* If the kernel containts at least one function call that _may_
contain a barrier call, this is set to true. */
bool m_has_function_calls_with_barriers;
/* Set to true after this function has been analyzed for barrier and
dispatch packet instruction usage in the final call graph analysis. */
bool m_calls_analyzed;
/* True in case the function was successfully converted to a WG function. */
bool m_is_wg_function;
/* Work-item ID related variables are cached in the entry of the kernel
function in order to use them directly in address computations, leading
to more efficient optimizations. The references to the local variables
are stored here. */
tree m_local_id_vars[3];
tree m_cur_wg_size_vars[3];
tree m_wg_id_vars[3];
tree m_wg_size_vars[3];
tree m_grid_size_vars[3];
/* Set to true in case the kernel contains at least one dispatch packet
(work-item ID-related) builtin call that could not be expanded to
tree nodes. */
bool m_has_unexpanded_dp_builtins;
/* Points to the instruction after which the real kernel code starts.
Usually points to the last WI ID variable initialization statement. */
tree_stmt_iterator m_kernel_entry;
/* True if we are currently generating the contents of an arg block. */
bool m_generating_arg_block;
/* A collection of function scope variables seen so far for resolving
variable references vs. module scope declarations. */
std::set<const BrigBase*> m_function_scope_vars;
/* The functions called by this function. */
std::vector<tree> m_called_functions;
brig_to_generic *m_parent;
/* The metadata of the function that should be stored with the binary and
passed to the HSA runtime: */
phsa_descriptor m_descriptor;
private:
/* Bookkeeping for the different HSA registers and their tree declarations
for the currently generated function. */
reg_decl_index_entry *m_regs[BRIG_2_TREE_HSAIL_TOTAL_REG_COUNT];
};
#endif

View file

@ -0,0 +1,58 @@
/* brig-inst-mod-handler.cc -- brig rounding moded instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "gimple-expr.h"
#include "errors.h"
size_t
brig_inst_mod_handler::generate (const BrigBase *base)
{
brig_basic_inst_handler basic_handler (m_parent);
return basic_handler (base);
}
const BrigAluModifier8_t *
brig_inst_mod_handler::modifier (const BrigBase *base) const
{
const BrigInstMod *inst = (const BrigInstMod *) base;
return &inst->modifier;
}
const BrigRound8_t *
brig_inst_mod_handler::round (const BrigBase *base) const
{
const BrigInstMod *inst = (const BrigInstMod *) base;
return &inst->round;
}
/* This used to inject fesetround () calls to control the rounding mode of the
actual executed floating point operation. It turned out that supporting
conversions using fesetround calls won't work in gcc due to it not being
able to restrict code motions across calls at the moment. This
functionality is therefore disabled for now until a better solution is
found or if fesetround () is fixed in gcc. */
size_t
brig_inst_mod_handler::operator () (const BrigBase *base)
{
return generate (base);
}

View file

@ -0,0 +1,37 @@
/* brig-label-handler.cc -- brig label directive handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
size_t
brig_directive_label_handler::operator () (const BrigBase *base)
{
const BrigDirectiveLabel *brig_label = (const BrigDirectiveLabel *) base;
const BrigData *label_name = m_parent.get_brig_data_entry (brig_label->name);
std::string label_str ((const char *) (label_name->bytes),
label_name->byteCount);
tree stmt = build_stmt (LABEL_EXPR, m_parent.m_cf->label (label_str));
m_parent.m_cf->append_statement (stmt);
return base->byteCount;
}

View file

@ -0,0 +1,84 @@
/* brig-lane-inst-handler.cc -- brig lane instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "errors.h"
#include "diagnostic-core.h"
#include "brig-util.h"
brig_lane_inst_handler::brig_lane_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t
brig_lane_inst_handler::operator () (const BrigBase *base)
{
const BrigInstLane &inst = *(const BrigInstLane *) base;
tree_stl_vec operands = build_operands (inst.base);
tree expr = NULL_TREE;
if (inst.base.opcode == BRIG_OPCODE_ACTIVELANECOUNT)
{
/* Because we are fixed to single WI per wave, it's enough to
just check the src value of the single work item itself. */
expr = build2 (NE_EXPR, uint32_type_node,
build_zero_cst (uint32_type_node), operands[1]);
}
else if (inst.base.opcode == BRIG_OPCODE_ACTIVELANEID)
{
expr = build_zero_cst (uint32_type_node);
}
else if (inst.base.opcode == BRIG_OPCODE_ACTIVELANEMASK)
{
tree u64_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U64);
tree zero_cst = build_zero_cst (u64_type);
expr = build2 (NE_EXPR, u64_type, zero_cst, operands[1]);
tree_stl_vec elements;
elements.push_back (expr);
elements.push_back (zero_cst);
elements.push_back (zero_cst);
elements.push_back (zero_cst);
expr = pack (elements);
}
else if (inst.base.opcode == BRIG_OPCODE_ACTIVELANEPERMUTE)
{
tree src = operands[1];
tree identity = operands[3];
tree use_identity = operands[4];
/* When WAVESIZE is 1, we either select the src of the work-item
itself or 'identity' in case use_identity is 1. */
tree cmp = build2 (EQ_EXPR, uint32_type_node,
build_int_cstu (uint32_type_node, 1), use_identity);
expr = build3 (COND_EXPR, TREE_TYPE (src), cmp, identity, src);
}
else
gcc_unreachable ();
build_output_assignment (inst.base, operands[0], expr);
return base->byteCount;
}

View file

@ -0,0 +1,44 @@
/* brig-machine.c -- gccbrig machine queries
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "brig-machine.h"
/* Return the numerical address space id for the segment in the current
target. Currently a dummy function that always returns 0, serves as
a placeholder for multi-AS machines. */
unsigned
gccbrig_get_target_addr_space_id (BrigSegment8_t)
{
return 0;
}
/* Return the WAVESIZE for the current target. For now a dummy placeholder
returning always 1. */
unsigned
gccbrig_get_target_wavesize ()
{
return 1;
}

View file

@ -0,0 +1,33 @@
/* brig-machine.h -- gccbrig machine queries
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_BRIG_MACHINE_H
#define GCC_BRIG_MACHINE_H
#include "hsa-brig-format.h"
/* These functions should be eventually converted to machine info queries and
redefined at backends. At that point make these functions delegate to
those. */
unsigned gccbrig_get_target_addr_space_id (BrigSegment8_t segment);
unsigned gccbrig_get_target_wavesize ();
#endif

View file

@ -0,0 +1,180 @@
/* brig-mem-inst-handler.cc -- brig memory inst handler
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "errors.h"
#include "brig-util.h"
#include "gimple-expr.h"
#include "print-tree.h"
#include "tree-pretty-print.h"
#include "convert.h"
#include "diagnostic-core.h"
tree
brig_mem_inst_handler::build_mem_access (const BrigInstBase *brig_inst,
tree addr, tree data)
{
bool is_load = brig_inst->opcode == BRIG_OPCODE_LD;
bool is_store = brig_inst->opcode == BRIG_OPCODE_ST;
if (!is_load && !is_store)
gcc_unreachable ();
tree instr_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
if (VECTOR_TYPE_P (TREE_TYPE (data)))
instr_type = TREE_TYPE (data);
tree ptype = build_pointer_type (instr_type);
/* The HSAIL mem instructions are unaligned by default.
TODO: exploit the align modifier, it should lead to faster code.
*/
tree unaligned_type = build_aligned_type (instr_type, 8);
/* Create a mem ref from the previous result, without offset. */
tree mem_ref
= build2 (MEM_REF, unaligned_type, addr, build_int_cst (ptype, 0));
if (is_load)
{
/* Add a temporary variable so there won't be multiple
reads in case of vector unpack. */
mem_ref = add_temp_var ("mem_read", mem_ref);
return build_output_assignment (*brig_inst, data, mem_ref);
}
else
{
tree stmt = build2 (MODIFY_EXPR, TREE_TYPE (mem_ref), mem_ref, data);
return m_parent.m_cf->append_statement (stmt);
}
return mem_ref;
}
size_t
brig_mem_inst_handler::operator () (const BrigBase *base)
{
const BrigInstBase *brig_inst
= (const BrigInstBase *) &((const BrigInstBasic *) base)->base;
if (brig_inst->opcode == BRIG_OPCODE_ALLOCA)
{
tree_stl_vec operands = build_operands (*brig_inst);
size_t alignment = 1;
const BrigInstMem *mem_inst = (const BrigInstMem *) brig_inst;
if (mem_inst->align != BRIG_ALIGNMENT_NONE)
{
alignment = 1 << (mem_inst->align - 1);
}
tree align_opr = build_int_cstu (size_type_node, alignment);
tree_stl_vec inputs;
inputs.push_back (operands[1]);
inputs.push_back (align_opr);
tree builtin_call
= expand_or_call_builtin (BRIG_OPCODE_ALLOCA, BRIG_TYPE_U32,
uint32_type_node, inputs);
build_output_assignment (*brig_inst, operands[0], builtin_call);
m_parent.m_cf->m_has_allocas = true;
return base->byteCount;
}
tree instr_type = gccbrig_tree_type_for_hsa_type (brig_inst->type);
const BrigData *operand_entries
= m_parent.get_brig_data_entry (brig_inst->operands);
uint32_t data_operand_offset;
memcpy (&data_operand_offset, &operand_entries->bytes, 4);
const BrigBase *operand
= m_parent.get_brig_operand_entry (data_operand_offset);
const BrigData *operandData = NULL;
bool is_store = brig_inst->opcode == BRIG_OPCODE_ST;
bool is_three_element_vector_access
= operand->kind == BRIG_KIND_OPERAND_OPERAND_LIST
&& (operandData = m_parent.get_brig_data_entry
(((const BrigOperandOperandList *) operand)->elements))
&& operandData->byteCount / 4 == 3;
if (is_three_element_vector_access)
{
/* We need to scalarize the 3-element vector accesses here
because gcc assumes the GENERIC vector datatypes are of two exponent
size internally. */
size_t bytes = operandData->byteCount;
const BrigOperandOffset32_t *operand_ptr
= (const BrigOperandOffset32_t *) operandData->bytes;
uint32_t addr_operand_offset;
memcpy (&addr_operand_offset, &operand_entries->bytes + 4, 4);
const BrigOperandAddress *addr_operand
= (const BrigOperandAddress *) m_parent.get_brig_operand_entry
(addr_operand_offset);
tree address_base = build_address_operand (*brig_inst, *addr_operand);
uint32_t address_offset = 0;
while (bytes > 0)
{
BrigOperandOffset32_t offset = *operand_ptr;
const BrigBase *operand_element
= m_parent.get_brig_operand_entry (offset);
tree data
= build_tree_operand (*brig_inst, *operand_element, instr_type);
tree ptr_offset = build_int_cst (size_type_node, address_offset);
tree address = build2 (POINTER_PLUS_EXPR, TREE_TYPE (address_base),
address_base, ptr_offset);
if (is_store && TREE_TYPE (data) != instr_type)
{
if (int_size_in_bytes (TREE_TYPE (data))
== int_size_in_bytes (instr_type)
&& !INTEGRAL_TYPE_P (instr_type))
data = build1 (VIEW_CONVERT_EXPR, instr_type, data);
else
data = convert (instr_type, data);
}
build_mem_access (brig_inst, address, data);
address_offset += int_size_in_bytes (instr_type);
++operand_ptr;
bytes -= 4;
}
}
else
{
tree_stl_vec operands = build_operands (*brig_inst);
tree &data = operands.at (0);
tree &addr = operands.at (1);
build_mem_access (brig_inst, addr, data);
}
return base->byteCount;
}

View file

@ -0,0 +1,41 @@
/* brig-module-handler.cc -- brig module directive handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "diagnostic-core.h"
size_t
brig_directive_module_handler::operator () (const BrigBase *base)
{
const BrigDirectiveModule* mod = (const BrigDirectiveModule*)base;
m_parent.m_module_name = m_parent.get_string (mod->name).substr (1);
if (mod->hsailMajor != 1 || mod->hsailMinor != 0)
fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE " "
"HSAIL version not supported. HSAIL 1.0 required.");
if (mod->machineModel != BRIG_MACHINE_LARGE)
fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE " "
"Only HSA 'large' machine model supported.");
/* Do not check for the profile as the runtime conformance suite tests
with 'full' profile BRIGs even though they don't use any full profile
features. This allows us to run the conformance suite with the
BRIG FE. */
return base->byteCount;
}

View file

@ -0,0 +1,93 @@
/* brig-queue-inst-handler.cc -- brig user mode queue related instruction
handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include "brig-code-entry-handler.h"
#include "brig-util.h"
#include "convert.h"
#include "tree-pretty-print.h"
#include "errors.h"
#include "diagnostic-core.h"
#include "brig-builtins.h"
brig_queue_inst_handler::brig_queue_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t
brig_queue_inst_handler::operator () (const BrigBase *base)
{
const BrigInstBase &inst_base = *(const BrigInstBase *) base;
tree_stl_vec operands = build_operands (inst_base);
if (inst_base.opcode == BRIG_OPCODE_LDQUEUEWRITEINDEX
|| inst_base.opcode == BRIG_OPCODE_LDQUEUEREADINDEX)
{
tree builtin
= inst_base.opcode == BRIG_OPCODE_LDQUEUEWRITEINDEX
? builtin_decl_explicit (BUILT_IN_HSAIL_LDQUEUEWRITEINDEX)
: builtin_decl_explicit (BUILT_IN_HSAIL_LDQUEUEREADINDEX);
tree expr
= call_builtin (builtin, 1, uint64_type_node,
uint64_type_node, operands[1]);
build_output_assignment (inst_base, operands[0], expr);
}
else if (inst_base.opcode == BRIG_OPCODE_STQUEUEWRITEINDEX
|| inst_base.opcode == BRIG_OPCODE_STQUEUEREADINDEX)
{
tree builtin
= inst_base.opcode == BRIG_OPCODE_STQUEUEWRITEINDEX
? builtin_decl_explicit (BUILT_IN_HSAIL_STQUEUEWRITEINDEX)
: builtin_decl_explicit (BUILT_IN_HSAIL_STQUEUEREADINDEX);
call_builtin (builtin, 2, void_type_node,
uint64_type_node, operands[0], uint64_type_node,
operands[1]);
}
else if (inst_base.opcode == BRIG_OPCODE_ADDQUEUEWRITEINDEX)
{
tree builtin = builtin_decl_explicit (BUILT_IN_HSAIL_ADDQUEUEWRITEINDEX);
tree expr = call_builtin (builtin, 2,
uint64_type_node, uint64_type_node, operands[1],
uint64_type_node, operands[2]);
build_output_assignment (inst_base, operands[0], expr);
}
else if (inst_base.opcode == BRIG_OPCODE_CASQUEUEWRITEINDEX)
{
tree builtin = builtin_decl_explicit (BUILT_IN_HSAIL_CASQUEUEWRITEINDEX);
tree expr
= call_builtin (builtin, 3, uint64_type_node,
uint64_type_node, operands[1], uint64_type_node,
operands[2], uint64_type_node, operands[3]);
build_output_assignment (inst_base, operands[0], expr);
}
else
gcc_unreachable ();
return base->byteCount;
}

View file

@ -0,0 +1,146 @@
/* brig-seg-inst-handler.cc -- brig segment related instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include "brig-code-entry-handler.h"
#include "brig-util.h"
#include "convert.h"
#include "tree-pretty-print.h"
#include "errors.h"
#include "diagnostic-core.h"
brig_seg_inst_handler::brig_seg_inst_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t
brig_seg_inst_handler::operator () (const BrigBase *base)
{
const BrigInstBase &inst_base = *(const BrigInstBase *) base;
std::vector<tree> operands = build_operands (inst_base);
tree expr = NULL_TREE;
if (inst_base.opcode == BRIG_OPCODE_STOF)
{
const BrigInstSegCvt &inst = *(const BrigInstSegCvt *) base;
if (inst.segment == BRIG_SEGMENT_GROUP)
expr = build2 (PLUS_EXPR, size_type_node,
convert_to_integer (size_type_node,
m_parent.m_cf->m_group_base_arg),
convert_to_integer (size_type_node, operands[1]));
else if (inst.segment == BRIG_SEGMENT_PRIVATE
|| inst.segment == BRIG_SEGMENT_SPILL)
expr = build2 (PLUS_EXPR, size_type_node,
convert_to_integer (size_type_node,
m_parent.m_cf->m_private_base_arg),
convert_to_integer (size_type_node, operands[1]));
else
gcc_unreachable ();
if (!(inst.modifier & BRIG_SEG_CVT_NONULL))
{
/* Need to convert the null value. -1 is used for 32b segments,
and 0 for flat/global. */
tree cmp
= build2 (EQ_EXPR, uint32_type_node,
build_int_cstu (uint32_type_node, -1), operands[1]);
tree null_check = build3 (COND_EXPR, size_type_node, cmp,
build_int_cstu (size_type_node, 0), expr);
expr = null_check;
}
}
else if (inst_base.opcode == BRIG_OPCODE_FTOS)
{
const BrigInstSegCvt &inst = *(const BrigInstSegCvt *) base;
if (inst.segment == BRIG_SEGMENT_GROUP)
expr = build2 (MINUS_EXPR, size_type_node,
convert_to_integer (size_type_node,
m_parent.m_cf->m_group_base_arg),
convert_to_integer (size_type_node, operands[1]));
else if (inst.segment == BRIG_SEGMENT_PRIVATE)
expr = build2 (MINUS_EXPR, size_type_node,
convert_to_integer (size_type_node,
m_parent.m_cf->m_private_base_arg),
convert_to_integer (size_type_node, operands[1]));
else
gcc_unreachable ();
if (!(inst.modifier & BRIG_SEG_CVT_NONULL))
{
/* Need to convert the null value. -1 is used for 32b segments,
and 0 for flat/global. */
tree cmp = build2 (EQ_EXPR, size_type_node,
build_int_cstu (size_type_node, 0), operands[1]);
tree null_check
= build3 (COND_EXPR, size_type_node, cmp,
build_int_cstu (uint32_type_node, -1), expr);
expr = null_check;
}
}
else if (inst_base.opcode == BRIG_OPCODE_NULLPTR)
{
const BrigInstSeg &inst = *(const BrigInstSeg *) base;
if (inst.segment == BRIG_SEGMENT_GLOBAL
|| inst.segment == BRIG_SEGMENT_FLAT
|| inst.segment == BRIG_SEGMENT_READONLY)
expr = build_int_cstu (uint64_type_node, 0);
else
expr = build_int_cstu (uint32_type_node, -1);
}
else if (inst_base.opcode == BRIG_OPCODE_SEGMENTP)
{
const BrigInstSegCvt &inst = *(const BrigInstSegCvt *) base;
tree builtin = NULL_TREE;
switch (inst.segment)
{
case BRIG_SEGMENT_GLOBAL:
builtin = builtin_decl_explicit (BUILT_IN_HSAIL_SEGMENTP_GLOBAL);
break;
case BRIG_SEGMENT_GROUP:
builtin = builtin_decl_explicit (BUILT_IN_HSAIL_SEGMENTP_GROUP);
break;
case BRIG_SEGMENT_PRIVATE:
builtin = builtin_decl_explicit (BUILT_IN_HSAIL_SEGMENTP_PRIVATE);
break;
default:
gcc_unreachable ();
}
expr = call_builtin (builtin, 2,
uint32_type_node, uint64_type_node, operands[1],
ptr_type_node, m_parent.m_cf->m_context_arg);
}
else
gcc_unreachable ();
build_output_assignment (inst_base, operands[0], expr);
return base->byteCount;
}

View file

@ -0,0 +1,42 @@
/* brig-signal-inst-handler.cc -- brig signal instruction handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include "brig-code-entry-handler.h"
#include "brig-util.h"
#include "fold-const.h"
#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "print-tree.h"
#include "convert.h"
#include "langhooks.h"
#include "gimple-expr.h"
size_t
brig_signal_inst_handler::operator () (const BrigBase *base)
{
const BrigInstSignal *inst = (const BrigInstSignal *) base;
BrigAtomicOperation8_t atomic_opcode;
atomic_opcode = inst->signalOperation;
return generate_tree (inst->base, atomic_opcode);
}

View file

@ -0,0 +1,796 @@
/* brig2tree.cc -- brig to gcc generic/gimple tree conversion
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <cassert>
#include <iostream>
#include <iomanip>
#include <sstream>
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "target.h"
#include "function.h"
#include "brig-to-generic.h"
#include "stringpool.h"
#include "tree-iterator.h"
#include "toplev.h"
#include "gimplify.h"
#include "gimple-expr.h"
#include "print-tree.h"
#include "hsa-brig-format.h"
#include "stor-layout.h"
#include "diagnostic-core.h"
#include "brig-code-entry-handler.h"
#include "brig-machine.h"
#include "brig-util.h"
#include "phsa.h"
#include "tree-pretty-print.h"
#include "dumpfile.h"
#include "tree-cfg.h"
#include "errors.h"
#include "fold-const.h"
#include "cgraph.h"
#include "dumpfile.h"
#include "tree-pretty-print.h"
extern int gccbrig_verbose;
tree brig_to_generic::s_fp16_type;
tree brig_to_generic::s_fp32_type;
tree brig_to_generic::s_fp64_type;
brig_to_generic::brig_to_generic ()
: m_cf (NULL), m_brig (NULL), m_next_group_offset (0),
m_next_private_offset (0)
{
m_globals = NULL_TREE;
/* Initialize the basic REAL types.
This doesn't work straight away because most of the targets
do not support fp16 natively. Let's by default convert
to fp32 and back before and after each instruction (handle it as
a storage format only), and later add an optimization pass
that removes the extra converts (in case of multiple fp16 ops
in a row). */
s_fp16_type = make_node (REAL_TYPE);
TYPE_PRECISION (s_fp16_type) = 16;
TYPE_SIZE (s_fp16_type) = bitsize_int (16);
TYPE_SIZE_UNIT (s_fp16_type) = size_int (2);
SET_TYPE_ALIGN (s_fp16_type, 16);
layout_type (s_fp16_type);
s_fp32_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_F32);
s_fp64_type = gccbrig_tree_type_for_hsa_type (BRIG_TYPE_F64);
/* TODO: (machine)query the preferred rounding mode that is set by
the machine by default. This can be redefined by each BRIG module
header. */
m_default_float_rounding_mode = BRIG_ROUND_FLOAT_ZERO;
m_dump_file = dump_begin (TDI_original, &m_dump_flags);
}
class unimplemented_entry_handler : public brig_code_entry_handler
{
public:
unimplemented_entry_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t
operator () (const BrigBase *base)
{
gcc_unreachable ();
return base->byteCount;
}
};
/* Handler for entries that can be (and are) safely skipped for the purposes
of GENERIC generation. */
class skipped_entry_handler : public brig_code_entry_handler
{
public:
skipped_entry_handler (brig_to_generic &parent)
: brig_code_entry_handler (parent)
{
}
size_t
operator () (const BrigBase *base)
{
return base->byteCount;
}
};
/* Parses the given BRIG blob. */
void
brig_to_generic::parse (const char *brig_blob)
{
m_brig = brig_blob;
m_brig_blobs.push_back (brig_blob);
const BrigModuleHeader *mheader = (const BrigModuleHeader *) brig_blob;
if (strncmp (mheader->identification, "HSA BRIG", 8) != 0)
fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE
"Unrecognized file format.");
if (mheader->brigMajor != 1 || mheader->brigMinor != 0)
fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE
"BRIG version not supported. BRIG 1.0 required.");
m_data = m_code = m_operand = NULL;
/* Find the positions of the different sections. */
for (uint32_t sec = 0; sec < mheader->sectionCount; ++sec)
{
uint64_t offset
= ((const uint64_t *) (brig_blob + mheader->sectionIndex))[sec];
const BrigSectionHeader *section_header
= (const BrigSectionHeader *) (brig_blob + offset);
std::string name ((const char *) (&section_header->name),
section_header->nameLength);
if (sec == BRIG_SECTION_INDEX_DATA && name == "hsa_data")
{
m_data = (const char *) section_header;
m_data_size = section_header->byteCount;
}
else if (sec == BRIG_SECTION_INDEX_CODE && name == "hsa_code")
{
m_code = (const char *) section_header;
m_code_size = section_header->byteCount;
}
else if (sec == BRIG_SECTION_INDEX_OPERAND && name == "hsa_operand")
{
m_operand = (const char *) section_header;
m_operand_size = section_header->byteCount;
}
else
{
gcc_unreachable ();
}
}
if (m_code == NULL)
gcc_unreachable ();
if (m_data == NULL)
gcc_unreachable ();
if (m_operand == NULL)
gcc_unreachable ();
brig_basic_inst_handler inst_handler (*this);
brig_branch_inst_handler branch_inst_handler (*this);
brig_cvt_inst_handler cvt_inst_handler (*this);
brig_seg_inst_handler seg_inst_handler (*this);
brig_copy_move_inst_handler copy_move_inst_handler (*this);
brig_signal_inst_handler signal_inst_handler (*this);
brig_atomic_inst_handler atomic_inst_handler (*this);
brig_cmp_inst_handler cmp_inst_handler (*this);
brig_mem_inst_handler mem_inst_handler (*this);
brig_inst_mod_handler inst_mod_handler (*this);
brig_directive_label_handler label_handler (*this);
brig_directive_variable_handler var_handler (*this);
brig_directive_fbarrier_handler fbar_handler (*this);
brig_directive_comment_handler comment_handler (*this);
brig_directive_function_handler func_handler (*this);
brig_directive_control_handler control_handler (*this);
brig_directive_arg_block_handler arg_block_handler (*this);
brig_directive_module_handler module_handler (*this);
brig_lane_inst_handler lane_inst_handler (*this);
brig_queue_inst_handler queue_inst_handler (*this);
skipped_entry_handler skipped_handler (*this);
unimplemented_entry_handler unimplemented_handler (*this);
struct code_entry_handler_info
{
BrigKind kind;
brig_code_entry_handler *handler;
};
/* TODO: Convert to a hash table / map. For now, put the more common
entries to the top to keep the scan fast on average. */
code_entry_handler_info handlers[]
= {{BRIG_KIND_INST_BASIC, &inst_handler},
{BRIG_KIND_INST_CMP, &cmp_inst_handler},
{BRIG_KIND_INST_MEM, &mem_inst_handler},
{BRIG_KIND_INST_MOD, &inst_mod_handler},
{BRIG_KIND_INST_CVT, &cvt_inst_handler},
{BRIG_KIND_INST_SEG_CVT, &seg_inst_handler},
{BRIG_KIND_INST_SEG, &seg_inst_handler},
{BRIG_KIND_INST_ADDR, &copy_move_inst_handler},
{BRIG_KIND_INST_SOURCE_TYPE, &copy_move_inst_handler},
{BRIG_KIND_INST_ATOMIC, &atomic_inst_handler},
{BRIG_KIND_INST_SIGNAL, &signal_inst_handler},
{BRIG_KIND_INST_BR, &branch_inst_handler},
{BRIG_KIND_INST_LANE, &lane_inst_handler},
{BRIG_KIND_INST_QUEUE, &queue_inst_handler},
/* Assuming fences are not needed. FIXME: call builtins
when porting to a platform where they are. */
{BRIG_KIND_INST_MEM_FENCE, &skipped_handler},
{BRIG_KIND_DIRECTIVE_LABEL, &label_handler},
{BRIG_KIND_DIRECTIVE_VARIABLE, &var_handler},
{BRIG_KIND_DIRECTIVE_ARG_BLOCK_START, &arg_block_handler},
{BRIG_KIND_DIRECTIVE_ARG_BLOCK_END, &arg_block_handler},
{BRIG_KIND_DIRECTIVE_FBARRIER, &fbar_handler},
{BRIG_KIND_DIRECTIVE_COMMENT, &comment_handler},
{BRIG_KIND_DIRECTIVE_KERNEL, &func_handler},
{BRIG_KIND_DIRECTIVE_SIGNATURE, &func_handler},
{BRIG_KIND_DIRECTIVE_FUNCTION, &func_handler},
{BRIG_KIND_DIRECTIVE_INDIRECT_FUNCTION, &func_handler},
{BRIG_KIND_DIRECTIVE_MODULE, &module_handler},
/* Skipping debug locations for now as not needed for conformance. */
{BRIG_KIND_DIRECTIVE_LOC, &skipped_handler},
/* There are no supported pragmas at this moment. */
{BRIG_KIND_DIRECTIVE_PRAGMA, &skipped_handler},
{BRIG_KIND_DIRECTIVE_CONTROL, &control_handler},
{BRIG_KIND_DIRECTIVE_EXTENSION, &skipped_handler}};
const BrigSectionHeader *csection_header = (const BrigSectionHeader *) m_code;
for (size_t b = csection_header->headerByteCount; b < m_code_size;)
{
const BrigBase *entry = (const BrigBase *) (m_code + b);
brig_code_entry_handler *handler = &unimplemented_handler;
if (m_cf != NULL && b >= m_cf->m_brig_def->nextModuleEntry)
finish_function (); /* The function definition ended. */
/* Find a handler. */
for (size_t i = 0;
i < sizeof (handlers) / sizeof (code_entry_handler_info); ++i)
{
if (handlers[i].kind == entry->kind)
handler = handlers[i].handler;
}
b += (*handler) (entry);
continue;
}
finish_function ();
}
const BrigData *
brig_to_generic::get_brig_data_entry (size_t entry_offset) const
{
return (const BrigData *) (m_data + entry_offset);
}
const BrigBase *
brig_to_generic::get_brig_operand_entry (size_t entry_offset) const
{
return (const BrigBase *) (m_operand + entry_offset);
}
const BrigBase *
brig_to_generic::get_brig_code_entry (size_t entry_offset) const
{
return (const BrigBase *) (m_code + entry_offset);
}
void
brig_to_generic::append_global (tree g)
{
if (m_globals == NULL_TREE)
{
m_globals = g;
return;
}
else
{
tree last = tree_last (m_globals);
TREE_CHAIN (last) = g;
}
}
tree
brig_to_generic::global_variable (const std::string &name) const
{
label_index::const_iterator i = m_global_variables.find (name);
if (i == m_global_variables.end ())
return NULL_TREE;
else
return (*i).second;
}
/* Returns a function declaration with the given name. Assumes it has been
created previously via a DirectiveFunction or similar. */
tree
brig_to_generic::function_decl (const std::string &name)
{
label_index::const_iterator i = m_function_index.find (name);
if (i == m_function_index.end ())
return NULL_TREE;
return (*i).second;
}
void
brig_to_generic::add_function_decl (const std::string &name, tree func_decl)
{
m_function_index[name] = func_decl;
}
/* Adds a GENERIC global variable VAR_DECL with the given NAME to the
current module. If we have generated a host def var ptr (a place holder
for variables that are defined by the HSA host code) for this global
variable definition (because there was a declaration earlier which looked
like it might have been a host defined variable), we now have
to assign its address and make it private to allow the references to
point to the defined variable instead. */
void
brig_to_generic::add_global_variable (const std::string &name, tree var_decl)
{
append_global (var_decl);
m_global_variables[name] = var_decl;
std::string host_def_var_name
= std::string (PHSA_HOST_DEF_PTR_PREFIX) + name;
tree host_def_var = global_variable (host_def_var_name.c_str ());
if (host_def_var == NULL_TREE)
return;
tree ptype = build_pointer_type (TREE_TYPE (var_decl));
tree var_addr = build1 (ADDR_EXPR, ptype, var_decl);
DECL_INITIAL (host_def_var) = var_addr;
TREE_PUBLIC (host_def_var) = 0;
}
/* Adds an indirection pointer for a potential host-defined program scope
variable declaration. */
void
brig_to_generic::add_host_def_var_ptr (const std::string &name, tree var_decl)
{
std::string var_name = std::string (PHSA_HOST_DEF_PTR_PREFIX) + name;
tree name_identifier = get_identifier (var_name.c_str ());
tree ptr_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, name_identifier,
build_pointer_type (TREE_TYPE (var_decl)));
DECL_EXTERNAL (ptr_var) = 0;
DECL_ARTIFICIAL (ptr_var) = 0;
TREE_PUBLIC (ptr_var) = 1;
TREE_USED (ptr_var) = 1;
TREE_ADDRESSABLE (ptr_var) = 1;
TREE_STATIC (ptr_var) = 1;
append_global (ptr_var);
m_global_variables[var_name] = ptr_var;
}
/* Produce a "mangled name" for the given brig function or kernel.
The mangling is used to make unique global symbol name in case of
module scope functions. Program scope functions are not mangled
(except for dropping the leading &), which makes the functions
directly visible for linking using the original function name. */
std::string
brig_to_generic::get_mangled_name
(const BrigDirectiveExecutable *func) const
{
/* Strip the leading &. */
std::string func_name = get_string (func->name).substr (1);
if (func->linkage == BRIG_LINKAGE_MODULE)
{
/* Mangle the module scope function names with the module name and
make them public so they can be queried by the HSA runtime from
the produced binary. Assume it's the currently processed function
we are always referring to. */
func_name = "gccbrig." + m_module_name + "." + func_name;
}
return func_name;
}
std::string
brig_to_generic::get_string (size_t entry_offset) const
{
const BrigData *data_item = get_brig_data_entry (entry_offset);
return std::string ((const char *) &data_item->bytes, data_item->byteCount);
}
/* Adapted from c-semantics.c. */
tree
build_stmt (enum tree_code code, ...)
{
tree ret;
int length, i;
va_list p;
bool side_effects;
/* This function cannot be used to construct variably-sized nodes. */
gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
va_start (p, code);
ret = make_node (code);
TREE_TYPE (ret) = void_type_node;
length = TREE_CODE_LENGTH (code);
/* TREE_SIDE_EFFECTS will already be set for statements with
implicit side effects. Here we make sure it is set for other
expressions by checking whether the parameters have side
effects. */
side_effects = false;
for (i = 0; i < length; i++)
{
tree t = va_arg (p, tree);
if (t && !TYPE_P (t))
side_effects |= TREE_SIDE_EFFECTS (t);
TREE_OPERAND (ret, i) = t;
}
TREE_SIDE_EFFECTS (ret) |= side_effects;
va_end (p);
return ret;
}
/* BRIG regs are untyped, but GENERIC is not. We need to add implicit casts
in case treating the operand with an instruction with a type different
than the created reg var type in order to select correct instruction type
later on. This function creates the necessary reinterpret type cast from
a source variable to the destination type. In case no cast is needed to
the same type, SOURCE is returned directly. */
tree
build_reinterpret_cast (tree destination_type, tree source)
{
gcc_assert (source && destination_type && TREE_TYPE (source) != NULL_TREE
&& destination_type != NULL_TREE);
tree source_type = TREE_TYPE (source);
if (TREE_CODE (source) == CALL_EXPR)
{
tree func_decl = TREE_OPERAND (TREE_OPERAND (source, 1), 0);
source_type = TREE_TYPE (TREE_TYPE (func_decl));
}
if (destination_type == source_type)
return source;
size_t src_size = int_size_in_bytes (source_type);
size_t dst_size = int_size_in_bytes (destination_type);
if (src_size == dst_size)
return build1 (VIEW_CONVERT_EXPR, destination_type, source);
else if (src_size < dst_size)
{
/* The src_size can be smaller at least with f16 scalars which are
stored to 32b register variables. First convert to an equivalent
size unsigned type, then extend to an unsigned type of the
target width, after which VIEW_CONVERT_EXPR can be used to
force to the target type. */
tree unsigned_temp = build1 (VIEW_CONVERT_EXPR,
get_unsigned_int_type (source_type),
source);
return build1 (VIEW_CONVERT_EXPR, destination_type,
convert (get_unsigned_int_type (destination_type),
unsigned_temp));
}
else
gcc_unreachable ();
return NULL_TREE;
}
/* Returns the finished brig_function for the given generic FUNC_DECL,
or NULL, if not found. */
brig_function *
brig_to_generic::get_finished_function (tree func_decl)
{
std::string func_name
= identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (func_decl)));
std::map<std::string, brig_function *>::iterator i
= m_finished_functions.find (func_name);
if (i != m_finished_functions.end ())
return (*i).second;
else
return NULL;
}
/* Finalizes the currently handled function. Should be called before
setting a new function. */
void
brig_to_generic::finish_function ()
{
if (m_cf == NULL || m_cf->m_func_decl == NULL_TREE)
{
/* It can be a finished func declaration fingerprint, in that case we
don't have m_func_decl. */
m_cf = NULL;
return;
}
if (!m_cf->m_is_kernel)
{
tree bind_expr = m_cf->m_current_bind_expr;
tree stmts = BIND_EXPR_BODY (bind_expr);
m_cf->finish ();
m_cf->emit_metadata (stmts);
dump_function (m_dump_file, m_cf);
gimplify_function_tree (m_cf->m_func_decl);
cgraph_node::finalize_function (m_cf->m_func_decl, true);
}
else
/* Emit the kernel only at the very end so we can analyze the total
group and private memory usage. */
m_kernels.push_back (m_cf);
pop_cfun ();
m_finished_functions[m_cf->m_name] = m_cf;
m_cf = NULL;
}
/* Initializes a new currently handled function. */
void
brig_to_generic::start_function (tree f)
{
if (DECL_STRUCT_FUNCTION (f) == NULL)
push_struct_function (f);
else
push_cfun (DECL_STRUCT_FUNCTION (f));
m_cf->m_func_decl = f;
}
/* Appends a new group variable (or an fbarrier) to the current kernel's
group segment. */
void
brig_to_generic::append_group_variable (const std::string &name, size_t size,
size_t alignment)
{
size_t align_padding = m_next_group_offset % alignment == 0 ?
0 : (alignment - m_next_group_offset % alignment);
m_next_group_offset += align_padding;
m_group_offsets[name] = m_next_group_offset;
m_next_group_offset += size;
}
size_t
brig_to_generic::group_variable_segment_offset (const std::string &name) const
{
var_offset_table::const_iterator i = m_group_offsets.find (name);
gcc_assert (i != m_group_offsets.end ());
return (*i).second;
}
/* The size of the group and private segments required by the currently
processed kernel. Private segment size must be multiplied by the
number of work-items in the launch, in case of a work-group function. */
size_t
brig_to_generic::group_segment_size () const
{
return m_next_group_offset;
}
/* Appends a new group variable to the current kernel's private segment. */
void
brig_to_generic::append_private_variable (const std::string &name,
size_t size, size_t alignment)
{
size_t align_padding = m_next_private_offset % alignment == 0 ?
0 : (alignment - m_next_private_offset % alignment);
m_next_private_offset += align_padding;
m_private_offsets[name] = m_next_private_offset;
m_next_private_offset += size;
m_private_data_sizes[name] = size + align_padding;
}
size_t
brig_to_generic::private_variable_segment_offset
(const std::string &name) const
{
var_offset_table::const_iterator i = m_private_offsets.find (name);
gcc_assert (i != m_private_offsets.end ());
return (*i).second;
}
bool
brig_to_generic::has_private_variable (const std::string &name) const
{
std::map<std::string, size_t>::const_iterator i
= m_private_data_sizes.find (name);
return i != m_private_data_sizes.end ();
}
bool
brig_to_generic::has_group_variable (const std::string &name) const
{
var_offset_table::const_iterator i = m_group_offsets.find (name);
return i != m_group_offsets.end ();
}
size_t
brig_to_generic::private_variable_size (const std::string &name) const
{
std::map<std::string, size_t>::const_iterator i
= m_private_data_sizes.find (name);
gcc_assert (i != m_private_data_sizes.end ());
return (*i).second;
}
size_t
brig_to_generic::private_segment_size () const
{
return m_next_private_offset;
}
/* Cached builtins indexed by name. */
typedef std::map<std::string, tree> builtin_index;
builtin_index builtin_cache_;
/* Build a call to a builtin function. PDECL is the builtin function to
call. NARGS is the number of input arguments, RETTYPE the built-in
functions return value type, and ... is the list of arguments passed to
the call with type first, then the value. */
tree
call_builtin (tree pdecl, int nargs, tree rettype, ...)
{
if (rettype == error_mark_node)
return error_mark_node;
tree *types = new tree[nargs];
tree *args = new tree[nargs];
va_list ap;
va_start (ap, rettype);
for (int i = 0; i < nargs; ++i)
{
types[i] = va_arg (ap, tree);
tree arg = va_arg (ap, tree);
args[i] = build_reinterpret_cast (types[i], arg);
if (types[i] == error_mark_node || args[i] == error_mark_node)
{
delete[] types;
delete[] args;
return error_mark_node;
}
}
va_end (ap);
tree fnptr = build_fold_addr_expr (pdecl);
tree ret = build_call_array (rettype, fnptr, nargs, args);
delete[] types;
delete[] args;
return ret;
}
/* Generate all global declarations. Should be called after the last
BRIG has been fed in. */
void
brig_to_generic::write_globals ()
{
/* Now that the whole BRIG module has been processed, build a launcher
and a metadata section for each built kernel. */
for (size_t i = 0; i < m_kernels.size (); ++i)
{
brig_function *f = m_kernels[i];
/* Finish kernels now that we know the call graphs and their barrier
usage. */
f->finish_kernel ();
dump_function (m_dump_file, f);
gimplify_function_tree (f->m_func_decl);
cgraph_node::finalize_function (f->m_func_decl, true);
f->m_descriptor.is_kernel = 1;
/* TODO: analyze the kernel's actual group and private segment usage
using a call graph. Now the private and group mem sizes are overly
pessimistic in case of multiple kernels in the same module. */
f->m_descriptor.group_segment_size = group_segment_size ();
f->m_descriptor.private_segment_size = private_segment_size ();
/* The kernarg size is rounded up to a multiple of 16 according to
the PRM specs. */
f->m_descriptor.kernarg_segment_size = f->m_next_kernarg_offset;
if (f->m_descriptor.kernarg_segment_size % 16 > 0)
f->m_descriptor.kernarg_segment_size
+= 16 - f->m_next_kernarg_offset % 16;
f->m_descriptor.kernarg_max_align = f->m_kernarg_max_align;
tree launcher = f->emit_launcher_and_metadata ();
append_global (launcher);
gimplify_function_tree (launcher);
cgraph_node::finalize_function (launcher, true);
pop_cfun ();
}
int no_globals = list_length (m_globals);
tree *vec = new tree[no_globals];
int i = 0;
tree global = m_globals;
while (global)
{
vec[i] = global;
++i;
global = TREE_CHAIN (global);
}
wrapup_global_declarations (vec, no_globals);
delete[] vec;
for (size_t i = 0; i < m_brig_blobs.size (); ++i)
delete m_brig_blobs[i];
}
/* Returns an type with unsigned int elements corresponding to the
size and element count of ORIGINAL_TYPE. */
tree
get_unsigned_int_type (tree original_type)
{
if (VECTOR_TYPE_P (original_type))
{
size_t esize
= int_size_in_bytes (TREE_TYPE (original_type)) * BITS_PER_UNIT;
size_t ecount = TYPE_VECTOR_SUBPARTS (original_type);
return build_vector_type (build_nonstandard_integer_type (esize, true),
ecount);
}
else
return build_nonstandard_integer_type (int_size_in_bytes (original_type)
* BITS_PER_UNIT,
true);
}
void
dump_function (FILE *dump_file, brig_function *f)
{
/* Dump the BRIG-specific tree IR. */
if (dump_file)
{
fprintf (dump_file, "\n;; Function %s", f->m_name.c_str ());
fprintf (dump_file, "\n;; enabled by -%s\n\n",
dump_flag_name (TDI_original));
print_generic_decl (dump_file, f->m_func_decl, 0);
print_generic_expr (dump_file, f->m_current_bind_expr, 0);
fprintf (dump_file, "\n");
}
}

View file

@ -0,0 +1,225 @@
/* brig-to-generic.h -- brig to gcc generic conversion
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef BRIG_TO_GENERIC_H
#define BRIG_TO_GENERIC_H
#include <string>
#include <map>
#include <vector>
#include "config.h"
#include "system.h"
#include "ansidecl.h"
#include "coretypes.h"
#include "opts.h"
#include "tree.h"
#include "tree-iterator.h"
#include "hsa-brig-format.h"
#include "brig-function.h"
struct reg_decl_index_entry;
/* Converts an HSAIL BRIG input to GENERIC. This class holds global state
for the translation process. Handling of the smaller pieces of BRIG data
is delegated to various handler classes declared in
brig-code-entry-handlers.h. */
class brig_to_generic
{
public:
typedef std::map<const BrigDirectiveVariable *, tree> variable_index;
private:
typedef std::map<std::string, size_t> var_offset_table;
typedef std::map<const BrigBase *, std::string> name_index;
public:
brig_to_generic ();
void parse (const char *brig_blob);
void write_globals ();
std::string get_string (size_t entry_offset) const;
const BrigData *get_brig_data_entry (size_t entry_offset) const;
const BrigBase *get_brig_operand_entry (size_t entry_offset) const;
const BrigBase *get_brig_code_entry (size_t entry_offset) const;
void append_global (tree g);
tree function_decl (const std::string &name);
void add_function_decl (const std::string &name, tree func_decl);
tree global_variable (const std::string &name) const;
void add_global_variable (const std::string &name, tree var_decl);
void add_host_def_var_ptr (const std::string &name, tree var_decl);
void start_function (tree f);
void finish_function ();
void append_group_variable (const std::string &name, size_t size,
size_t alignment);
void append_private_variable (const std::string &name, size_t size,
size_t alignment);
size_t group_variable_segment_offset (const std::string &name) const;
bool
has_group_variable (const std::string &name) const;
size_t
private_variable_segment_offset (const std::string &name) const;
bool
has_private_variable (const std::string &name) const;
size_t private_variable_size (const std::string &name) const;
template <typename T>
std::string
get_mangled_name_tmpl (const T *brigVar) const;
std::string get_mangled_name (const BrigDirectiveFbarrier *fbar) const
{ return get_mangled_name_tmpl (fbar); }
std::string get_mangled_name (const BrigDirectiveVariable *var) const
{ return get_mangled_name_tmpl (var); }
std::string get_mangled_name (const BrigDirectiveExecutable *func) const;
size_t group_segment_size () const;
size_t private_segment_size () const;
brig_function *get_finished_function (tree func_decl);
static tree s_fp16_type;
static tree s_fp32_type;
static tree s_fp64_type;
/* The default rounding mode that should be used for float instructions.
This can be set in each BRIG module header. */
BrigRound8_t m_default_float_rounding_mode;
/* The currently built function. */
brig_function *m_cf;
/* The name of the currently handled BRIG module. */
std::string m_module_name;
private:
/* The BRIG blob and its different sections of the file currently being
parsed. */
const char *m_brig;
const char *m_data;
size_t m_data_size;
const char *m_operand;
size_t m_operand_size;
const char *m_code;
size_t m_code_size;
tree m_globals;
label_index m_global_variables;
/* The size of each private variable, including the alignment padding. */
std::map<std::string, size_t> m_private_data_sizes;
/* The same for group variables. */
size_t m_next_group_offset;
var_offset_table m_group_offsets;
/* And private. */
size_t m_next_private_offset;
var_offset_table m_private_offsets;
/* Name index for declared functions. */
label_index m_function_index;
/* Stores all processed kernels in order. */
std::vector<brig_function *> m_kernels;
/* Stores all already processed functions from the translation unit
for some interprocedural analysis. */
std::map<std::string, brig_function *> m_finished_functions;
/* The parsed BRIG blobs. Owned and will be deleted after use. */
std::vector<const char *> m_brig_blobs;
/* The original dump file. */
FILE *m_dump_file;
/* The original dump file flags. */
int m_dump_flags;
};
/* Produce a "mangled name" for the given brig variable. The mangling is used
to make unique global symbol names for module and function scope variables.
The templated version is suitable for most of the variable types. Functions
and kernels (BrigDirectiveExecutable) are handled with a specialized
get_mangled_name() version. */
template <typename T>
std::string
brig_to_generic::get_mangled_name_tmpl (const T *brigVar) const
{
std::string var_name = get_string (brigVar->name).substr (1);
/* Mangle the variable name using the function name and the module name
in case of a function scope variable. */
if (m_cf != NULL
&& m_cf->has_function_scope_var (&brigVar->base))
var_name = m_cf->m_name + "." + var_name;
if (brigVar->linkage == BRIG_LINKAGE_MODULE)
var_name = "gccbrig." + m_module_name + "." + var_name;
return var_name;
}
/* An interface to organize the different types of BRIG element handlers. */
class brig_entry_handler
{
public:
brig_entry_handler (brig_to_generic &parent) : m_parent (parent)
{
}
/* Handles the brig_code data at the given pointer and adds it to the
currently built tree. Returns the number of consumed bytes; */
virtual size_t operator () (const BrigBase *base) = 0;
protected:
brig_to_generic &m_parent;
};
tree call_builtin (tree pdecl, int nargs, tree rettype, ...);
tree build_reinterpret_cast (tree destination_type, tree source);
tree build_stmt (enum tree_code code, ...);
tree get_unsigned_int_type (tree type);
void dump_function (FILE *dump_file, brig_function *f);
#endif

View file

@ -0,0 +1,447 @@
/* brig-util.cc -- gccbrig utility functions
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <sstream>
#include "stdint.h"
#include "hsa-brig-format.h"
#include "brig-util.h"
#include "errors.h"
#include "diagnostic-core.h"
/* Return true if operand number OPNUM of instruction with OPCODE is an output.
False if it is an input. Some code reused from Martin Jambor's gcc-hsa
tree. */
bool
gccbrig_hsa_opcode_op_output_p (BrigOpcode16_t opcode, int opnum)
{
switch (opcode)
{
case BRIG_OPCODE_BR:
case BRIG_OPCODE_SBR:
case BRIG_OPCODE_CBR:
case BRIG_OPCODE_ST:
case BRIG_OPCODE_ATOMICNORET:
case BRIG_OPCODE_SIGNALNORET:
case BRIG_OPCODE_INITFBAR:
case BRIG_OPCODE_JOINFBAR:
case BRIG_OPCODE_WAITFBAR:
case BRIG_OPCODE_ARRIVEFBAR:
case BRIG_OPCODE_LEAVEFBAR:
case BRIG_OPCODE_RELEASEFBAR:
case BRIG_OPCODE_DEBUGTRAP:
return false;
default:
return opnum == 0;
}
}
unsigned
gccbrig_hsa_type_bit_size (BrigType16_t t)
{
unsigned pack_type = t & ~BRIG_TYPE_BASE_MASK;
if (pack_type == BRIG_TYPE_PACK_32)
return 32;
else if (pack_type == BRIG_TYPE_PACK_64)
return 64;
else if (pack_type == BRIG_TYPE_PACK_128)
return 128;
switch (t)
{
case BRIG_TYPE_NONE:
return 0;
case BRIG_TYPE_B1:
return 1;
case BRIG_TYPE_U8:
case BRIG_TYPE_S8:
case BRIG_TYPE_B8:
return 8;
case BRIG_TYPE_U16:
case BRIG_TYPE_S16:
case BRIG_TYPE_B16:
case BRIG_TYPE_F16:
return 16;
case BRIG_TYPE_U32:
case BRIG_TYPE_S32:
case BRIG_TYPE_B32:
case BRIG_TYPE_F32:
case BRIG_TYPE_U8X4:
case BRIG_TYPE_U16X2:
case BRIG_TYPE_S8X4:
case BRIG_TYPE_S16X2:
case BRIG_TYPE_F16X2:
case BRIG_TYPE_SIG32:
return 32;
case BRIG_TYPE_U64:
case BRIG_TYPE_S64:
case BRIG_TYPE_F64:
case BRIG_TYPE_B64:
case BRIG_TYPE_U8X8:
case BRIG_TYPE_U16X4:
case BRIG_TYPE_U32X2:
case BRIG_TYPE_S8X8:
case BRIG_TYPE_S16X4:
case BRIG_TYPE_S32X2:
case BRIG_TYPE_F16X4:
case BRIG_TYPE_F32X2:
case BRIG_TYPE_SIG64:
return 64;
case BRIG_TYPE_B128:
case BRIG_TYPE_U8X16:
case BRIG_TYPE_U16X8:
case BRIG_TYPE_U32X4:
case BRIG_TYPE_U64X2:
case BRIG_TYPE_S8X16:
case BRIG_TYPE_S16X8:
case BRIG_TYPE_S32X4:
case BRIG_TYPE_S64X2:
case BRIG_TYPE_F16X8:
case BRIG_TYPE_F32X4:
case BRIG_TYPE_F64X2:
return 128;
default:
printf ("HMM %d %x\n", t, t);
gcc_unreachable ();
}
}
/* gcc-hsa borrowed code ENDS. */
uint64_t
gccbrig_to_uint64_t (const BrigUInt64 &brig_type)
{
return (uint64_t (brig_type.hi) << 32) | uint64_t (brig_type.lo);
}
int
gccbrig_reg_size (const BrigOperandRegister *brig_reg)
{
switch (brig_reg->regKind)
{
case BRIG_REGISTER_KIND_CONTROL:
return 1;
case BRIG_REGISTER_KIND_SINGLE:
return 32;
case BRIG_REGISTER_KIND_DOUBLE:
return 64;
case BRIG_REGISTER_KIND_QUAD:
return 128;
default:
gcc_unreachable ();
break;
}
}
std::string
gccbrig_reg_name (const BrigOperandRegister *reg)
{
std::ostringstream strstr;
switch (reg->regKind)
{
case BRIG_REGISTER_KIND_CONTROL:
strstr << 'c';
break;
case BRIG_REGISTER_KIND_SINGLE:
strstr << 's';
break;
case BRIG_REGISTER_KIND_DOUBLE:
strstr << 'd';
break;
case BRIG_REGISTER_KIND_QUAD:
strstr << 'q';
break;
default:
gcc_unreachable ();
return "";
}
strstr << reg->regNum;
return strstr.str ();
}
std::string
gccbrig_type_name (BrigType16_t type)
{
switch (type)
{
case BRIG_TYPE_U8:
return "u8";
case BRIG_TYPE_U16:
return "u16";
case BRIG_TYPE_U32:
return "u32";
case BRIG_TYPE_U64:
return "u64";
case BRIG_TYPE_S8:
return "s8";
case BRIG_TYPE_S16:
return "s16";
case BRIG_TYPE_S32:
return "s32";
case BRIG_TYPE_S64:
return "s64";
default:
gcc_unreachable ();
break;
}
}
std::string
gccbrig_segment_name (BrigSegment8_t segment)
{
if (segment == BRIG_SEGMENT_GLOBAL)
return "global";
else if (segment == BRIG_SEGMENT_GROUP)
return "group";
else if (segment == BRIG_SEGMENT_PRIVATE)
return "private";
else
gcc_unreachable ();
}
bool
gccbrig_is_float_type (BrigType16_t type)
{
return (type == BRIG_TYPE_F32 || type == BRIG_TYPE_F64
|| type == BRIG_TYPE_F16);
}
BrigType16_t
gccbrig_tree_type_to_hsa_type (tree tree_type)
{
if (INTEGRAL_TYPE_P (tree_type))
{
if (TYPE_UNSIGNED (tree_type))
{
switch (int_size_in_bytes (tree_type))
{
case 1:
return BRIG_TYPE_U8;
case 2:
return BRIG_TYPE_U16;
case 4:
return BRIG_TYPE_U32;
case 8:
return BRIG_TYPE_U64;
default:
break;
}
}
else
{
switch (int_size_in_bytes (tree_type))
{
case 1:
return BRIG_TYPE_S8;
case 2:
return BRIG_TYPE_S16;
case 4:
return BRIG_TYPE_S32;
case 8:
return BRIG_TYPE_S64;
default:
break;
}
}
}
else if (VECTOR_TYPE_P (tree_type))
{
tree element_type = TREE_TYPE (tree_type);
size_t element_size = int_size_in_bytes (element_type) * 8;
BrigType16_t brig_element_type;
switch (element_size)
{
case 8:
brig_element_type
= TYPE_UNSIGNED (element_type) ? BRIG_TYPE_U8 : BRIG_TYPE_S8;
break;
case 16:
brig_element_type
= TYPE_UNSIGNED (element_type) ? BRIG_TYPE_U16 : BRIG_TYPE_S16;
break;
case 32:
brig_element_type
= TYPE_UNSIGNED (element_type) ? BRIG_TYPE_U32 : BRIG_TYPE_S32;
break;
case 64:
brig_element_type
= TYPE_UNSIGNED (element_type) ? BRIG_TYPE_U64 : BRIG_TYPE_S64;
break;
default:
gcc_unreachable ();
}
BrigType16_t pack_type;
switch (int_size_in_bytes (tree_type) * 8)
{
case 32:
pack_type = BRIG_TYPE_PACK_32;
break;
case 64:
pack_type = BRIG_TYPE_PACK_64;
break;
case 128:
pack_type = BRIG_TYPE_PACK_128;
break;
default:
gcc_unreachable ();
}
return brig_element_type | pack_type;
}
gcc_unreachable ();
}
/* Returns true in case the operation is a "bit level" operation,
that is, not having operand type depending semantical differences. */
bool
gccbrig_is_bit_operation (BrigOpcode16_t opcode)
{
return opcode == BRIG_OPCODE_CMOV || opcode == BRIG_OPCODE_SHUFFLE
|| opcode == BRIG_OPCODE_UNPACK || opcode == BRIG_OPCODE_UNPACKLO
|| opcode == BRIG_OPCODE_UNPACKHI || opcode == BRIG_OPCODE_ST
|| opcode == BRIG_OPCODE_PACK;
}
/* The program scope definition can be left external within the
kernel binary which means it must be defined by the host via
HSA runtime. For these we have special treatment:
Create additional pointer indirection when accessing the variable
value from kernel code through a generated pointer
__gccbrig_ptr_variable_name. The pointer value then can be set either
within the kernel binary (in case of a later linked in definition)
or from the host. */
bool
gccbrig_might_be_host_defined_var_p (const BrigDirectiveVariable *brigVar)
{
bool is_definition = brigVar->modifier & BRIG_VARIABLE_DEFINITION;
return (brigVar->segment == BRIG_SEGMENT_GLOBAL
|| brigVar->segment == BRIG_SEGMENT_READONLY) && !is_definition
&& brigVar->linkage == BRIG_LINKAGE_PROGRAM
&& (brigVar->allocation == BRIG_ALLOCATION_PROGRAM
|| brigVar->allocation == BRIG_ALLOCATION_AGENT);
}
/* Produce a GENERIC type for the given HSA/BRIG type. Returns the element
type in case of vector instructions. */
tree
gccbrig_tree_type_for_hsa_type (BrigType16_t brig_type)
{
tree tree_type = NULL_TREE;
if (hsa_type_packed_p (brig_type))
{
/* The element type is encoded in the bottom 5 bits. */
BrigType16_t inner_brig_type = brig_type & BRIG_TYPE_BASE_MASK;
unsigned full_size = gccbrig_hsa_type_bit_size (brig_type);
if (inner_brig_type == BRIG_TYPE_F16)
return build_vector_type (gccbrig_tree_type_for_hsa_type (BRIG_TYPE_U16),
full_size / 16);
tree inner_type = gccbrig_tree_type_for_hsa_type (inner_brig_type);
unsigned inner_size = gccbrig_hsa_type_bit_size (inner_brig_type);
unsigned nunits = full_size / inner_size;
tree_type = build_vector_type (inner_type, nunits);
}
else
{
switch (brig_type)
{
case BRIG_TYPE_NONE:
tree_type = void_type_node;
break;
case BRIG_TYPE_B1:
tree_type = boolean_type_node;
break;
case BRIG_TYPE_S8:
case BRIG_TYPE_S16:
case BRIG_TYPE_S32:
case BRIG_TYPE_S64:
/* Ensure a fixed width integer. */
tree_type
= build_nonstandard_integer_type
(gccbrig_hsa_type_bit_size (brig_type), false);
break;
case BRIG_TYPE_U8:
return unsigned_char_type_node;
case BRIG_TYPE_U16:
case BRIG_TYPE_U32:
case BRIG_TYPE_U64:
case BRIG_TYPE_B8: /* Handle bit vectors as unsigned ints. */
case BRIG_TYPE_B16:
case BRIG_TYPE_B32:
case BRIG_TYPE_B64:
case BRIG_TYPE_B128:
case BRIG_TYPE_SIG32: /* Handle signals as integers for now. */
case BRIG_TYPE_SIG64:
tree_type = build_nonstandard_integer_type
(gccbrig_hsa_type_bit_size (brig_type), true);
break;
case BRIG_TYPE_F16:
tree_type = uint16_type_node;
break;
case BRIG_TYPE_F32:
/* TODO: make sure that the alignment of the float are at least as
strict than mandated by HSA, and conform to IEEE (like mandated
by HSA). */
tree_type = float_type_node;
break;
case BRIG_TYPE_F64:
tree_type = double_type_node;
break;
case BRIG_TYPE_SAMP:
case BRIG_TYPE_ROIMG:
case BRIG_TYPE_WOIMG:
case BRIG_TYPE_RWIMG:
{
/* Handle images and samplers as target-specific blobs of data
that should be allocated earlier on from the runtime side.
Create a void* that should be initialized to point to the blobs
by the kernel launcher. Images and samplers are accessed
via builtins that take void* as the reference. TODO: who and
how these arrays should be initialized? */
tree void_ptr = build_pointer_type (void_type_node);
return void_ptr;
}
default:
gcc_unreachable ();
break;
}
}
/* Drop const qualifiers. */
return tree_type;
}

View file

@ -0,0 +1,53 @@
/* brig-util.h -- gccbrig utility functions
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_BRIG_UTIL_H
#define GCC_BRIG_UTIL_H
#include "brig-to-generic.h"
bool gccbrig_hsa_opcode_op_output_p (BrigOpcode16_t opcode, int opnum);
unsigned gccbrig_hsa_type_bit_size (BrigType16_t t);
uint64_t gccbrig_to_uint64_t (const BrigUInt64 &brig_type);
int gccbrig_reg_size (const BrigOperandRegister *brig_reg);
std::string gccbrig_reg_name (const BrigOperandRegister *reg);
std::string gccbrig_type_name (BrigType16_t type);
std::string gccbrig_segment_name (BrigSegment8_t segment);
bool gccbrig_is_float_type (BrigType16_t type);
bool gccbrig_is_bit_operation (BrigOpcode16_t opcode);
BrigType16_t gccbrig_tree_type_to_hsa_type (tree tree_type);
tree gccbrig_tree_type_for_hsa_type (BrigType16_t brig_type);
bool gccbrig_might_be_host_defined_var_p (const BrigDirectiveVariable *brigVar);
/* From hsa.h. */
bool hsa_type_packed_p (BrigType16_t type);
#endif

View file

@ -0,0 +1,264 @@
/* brig-variable-handler.cc -- brig variable directive handling
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "brig-code-entry-handler.h"
#include "stringpool.h"
#include "errors.h"
#include "brig-machine.h"
#include "brig-util.h"
#include "print-tree.h"
#include "diagnostic-core.h"
tree
brig_directive_variable_handler::build_variable
(const BrigDirectiveVariable *brigVar, tree_code var_decltype)
{
std::string var_name = m_parent.get_mangled_name (brigVar);
bool is_definition = brigVar->modifier & BRIG_VARIABLE_DEFINITION;
tree name_identifier = get_identifier (var_name.c_str ());
tree var_decl;
tree t;
if (brigVar->type & BRIG_TYPE_ARRAY)
{
tree element_type
= gccbrig_tree_type_for_hsa_type (brigVar->type & ~BRIG_TYPE_ARRAY);
uint64_t element_count = gccbrig_to_uint64_t (brigVar->dim);
if (is_definition && element_count == 0)
fatal_error (UNKNOWN_LOCATION, "Array definition with zero elements.");
if (var_decltype == PARM_DECL)
t = build_pointer_type (element_type);
else
t = build_array_type_nelts (element_type, element_count);
}
else
{
t = gccbrig_tree_type_for_hsa_type (brigVar->type);
}
size_t alignment = get_brig_var_alignment (brigVar);
if (brigVar->segment == BRIG_SEGMENT_READONLY
|| brigVar->segment == BRIG_SEGMENT_KERNARG
|| (brigVar->modifier & BRIG_VARIABLE_CONST))
TYPE_READONLY (t) = 1;
TYPE_ADDR_SPACE (t) = gccbrig_get_target_addr_space_id (brigVar->segment);
var_decl = build_decl (UNKNOWN_LOCATION, var_decltype, name_identifier, t);
SET_DECL_ALIGN (var_decl, alignment * BITS_PER_UNIT);
/* Force the HSA alignments. */
DECL_USER_ALIGN (var_decl) = 1;
TREE_USED (var_decl) = 1;
TREE_PUBLIC (var_decl) = 1;
if (is_definition)
DECL_EXTERNAL (var_decl) = 0;
else
DECL_EXTERNAL (var_decl) = 1; /* The definition is elsewhere. */
if (brigVar->init != 0)
{
gcc_assert (brigVar->segment == BRIG_SEGMENT_READONLY
|| brigVar->segment == BRIG_SEGMENT_GLOBAL);
const BrigBase *cst_operand_data
= m_parent.get_brig_operand_entry (brigVar->init);
tree initializer = NULL_TREE;
if (cst_operand_data->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES)
initializer = get_tree_cst_for_hsa_operand
((const BrigOperandConstantBytes *) cst_operand_data, t);
else
error ("variable initializers of type %x not implemented",
cst_operand_data->kind);
gcc_assert (initializer != NULL_TREE);
DECL_INITIAL (var_decl) = initializer;
}
if (var_decltype == PARM_DECL)
{
DECL_ARG_TYPE (var_decl) = TREE_TYPE (var_decl);
DECL_EXTERNAL (var_decl) = 0;
TREE_PUBLIC (var_decl) = 0;
}
TREE_ADDRESSABLE (var_decl) = 1;
TREE_USED (var_decl) = 1;
DECL_NONLOCAL (var_decl) = 1;
DECL_ARTIFICIAL (var_decl) = 0;
return var_decl;
}
size_t
brig_directive_variable_handler::operator () (const BrigBase *base)
{
const BrigDirectiveVariable *brigVar = (const BrigDirectiveVariable *) base;
bool is_definition = brigVar->modifier & BRIG_VARIABLE_DEFINITION;
size_t var_size;
tree var_type;
if (brigVar->type & BRIG_TYPE_ARRAY)
{
tree element_type
= gccbrig_tree_type_for_hsa_type (brigVar->type & ~BRIG_TYPE_ARRAY);
uint64_t element_count = gccbrig_to_uint64_t (brigVar->dim);
if (is_definition && element_count == 0)
fatal_error (UNKNOWN_LOCATION, "Array definition with zero elements.");
var_type = build_array_type_nelts (element_type, element_count);
size_t element_size = tree_to_uhwi (TYPE_SIZE (element_type));
var_size = element_size * element_count / 8;
}
else
{
var_type = gccbrig_tree_type_for_hsa_type (brigVar->type);
var_size = tree_to_uhwi (TYPE_SIZE (var_type)) / 8;
}
size_t alignment = get_brig_var_alignment (brigVar);
if (m_parent.m_cf != NULL)
m_parent.m_cf->m_function_scope_vars.insert (base);
std::string var_name = m_parent.get_mangled_name (brigVar);
if (brigVar->segment == BRIG_SEGMENT_KERNARG)
{
/* Do not create a real variable, but only a table of
offsets to the kernarg segment buffer passed as the
single argument by the kernel launcher for later
reference. Ignore kernel declarations. */
if (m_parent.m_cf != NULL && m_parent.m_cf->m_func_decl != NULL_TREE)
m_parent.m_cf->append_kernel_arg (brigVar, var_size, alignment);
return base->byteCount;
}
else if (brigVar->segment == BRIG_SEGMENT_GROUP)
{
/* Handle group region variables similarly as kernargs:
assign offsets to the group region on the fly when
a new module scope or function scope group variable is
introduced. These offsets will be then added to the
group_base hidden pointer passed to the kernel in order to
get the flat address. */
if (!m_parent.has_group_variable (var_name))
m_parent.append_group_variable (var_name, var_size, alignment);
return base->byteCount;
}
else if (brigVar->segment == BRIG_SEGMENT_PRIVATE
|| brigVar->segment == BRIG_SEGMENT_SPILL)
{
/* Private variables are handled like group variables,
except that their offsets are multiplied by the work-item
flat id, when accessed. */
if (!m_parent.has_private_variable (var_name))
m_parent.append_private_variable (var_name, var_size, alignment);
return base->byteCount;
}
else if (brigVar->segment == BRIG_SEGMENT_GLOBAL
|| brigVar->segment == BRIG_SEGMENT_READONLY)
{
tree def = is_definition ? NULL_TREE :
m_parent.global_variable (var_name);
if (!is_definition && def != NULL_TREE)
{
/* We have a definition already for this declaration.
Use the definition instead of the declaration. */
}
else if (gccbrig_might_be_host_defined_var_p (brigVar))
{
tree var_decl = build_variable (brigVar);
m_parent.add_host_def_var_ptr (var_name, var_decl);
}
else
{
tree var_decl = build_variable (brigVar);
/* Make all global variables program scope for now
so we can get their address from the Runtime API. */
DECL_CONTEXT (var_decl) = NULL_TREE;
TREE_STATIC (var_decl) = 1;
m_parent.add_global_variable (var_name, var_decl);
}
}
else if (brigVar->segment == BRIG_SEGMENT_ARG)
{
if (m_parent.m_cf->m_generating_arg_block)
{
tree var_decl = build_variable (brigVar);
tree bind_expr = m_parent.m_cf->m_current_bind_expr;
DECL_CONTEXT (var_decl) = m_parent.m_cf->m_func_decl;
DECL_CHAIN (var_decl) = BIND_EXPR_VARS (bind_expr);
BIND_EXPR_VARS (bind_expr) = var_decl;
TREE_PUBLIC (var_decl) = 0;
m_parent.m_cf->add_arg_variable (brigVar, var_decl);
}
else
{
/* Must be an incoming function argument which has
been parsed in brig-function-handler.cc. No
need to generate anything here. */
}
}
else
gcc_unreachable ();
return base->byteCount;
}
/* Returns the alignment for the given BRIG variable. In case the variable
explicitly defines alignment and its larger than the natural alignment,
returns it instead of the natural one. */
size_t
brig_directive_variable_handler::get_brig_var_alignment
(const BrigDirectiveVariable *brigVar)
{
size_t defined_alignment
= brigVar->align == BRIG_ALIGNMENT_NONE ? 0 : 1 << (brigVar->align - 1);
size_t natural_alignment;
if (brigVar->type & BRIG_TYPE_ARRAY)
{
tree element_type
= gccbrig_tree_type_for_hsa_type (brigVar->type & ~BRIG_TYPE_ARRAY);
size_t element_size = tree_to_uhwi (TYPE_SIZE (element_type));
natural_alignment = element_size / BITS_PER_UNIT;
}
else
{
tree t = gccbrig_tree_type_for_hsa_type (brigVar->type);
natural_alignment = tree_to_uhwi (TYPE_SIZE (t)) / BITS_PER_UNIT;
}
return natural_alignment > defined_alignment
? natural_alignment : defined_alignment;
}

View file

@ -0,0 +1,69 @@
/* phsa.h -- interfacing between the gcc BRIG FE and the phsa runtime
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef PHSA_H
#define PHSA_H
#include <stdint.h>
/* This struct is used to pass information from the BRIG FE to the
runtime of the finalizer kernel, its control directives etc.
The data is passed raw in a special ELF section named
phsa.kerneldesc.kernel_function_name. */
typedef struct __attribute__((__packed__))
{
/* Set to 1 in case the function is a kernel. */
uint8_t is_kernel;
/* The size of the group segment used by the kernel. */
uint32_t group_segment_size;
/* Size of the private segment used by a single work-item. */
uint32_t private_segment_size;
/* Total size of the kernel arguments. */
uint32_t kernarg_segment_size;
/* Maximum alignment of a kernel argument variable. */
uint16_t kernarg_max_align;
/* Maximum size (in bytes) of dynamic group memory. */
uint32_t max_dynamic_group_size;
/* Max number of work-items used to launch the kernel. */
uint64_t max_flat_grid_size;
/* Max number of work-items in a work-group used to launch the kernel. */
uint32_t max_flat_workgroup_size;
/* The grid size required by the kernel. */
uint64_t required_grid_size[3];
/* The work group size required by the kernel. */
uint32_t required_workgroup_size[3];
/* The number of dimensions required by the kernel. */
uint8_t required_dim;
} phsa_descriptor;
/* The prefix to use in the ELF section containing descriptor for
a function. */
#define PHSA_DESC_SECTION_PREFIX "phsa.desc."
#define PHSA_HOST_DEF_PTR_PREFIX "__phsa.host_def."
/* The frontend error messages are parsed by the host runtime, known
prefix strings are used to separate the different runtime error
codes. */
#define PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE "Incompatible module:"
#endif

135
gcc/brig/brigspec.c Normal file
View file

@ -0,0 +1,135 @@
/* brigspec.c -- Specific flags and argument handling of the gcc BRIG front end.
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "gcc.h"
#include "opts.h"
/* This bit is set if we saw a `-xfoo' language specification. */
#define LANGSPEC (1 << 1)
/* This bit is set if they did `-lm' or `-lmath'. */
#define MATHLIB (1 << 2)
/* This bit is set if they did `-lpthread'. */
#define THREADLIB (1 << 3)
/* This bit is set if they did `-lc'. */
#define WITHLIBC (1 << 4)
/* Skip this option. */
#define SKIPOPT (1 << 5)
#ifndef MATH_LIBRARY
#define MATH_LIBRARY "m"
#endif
#ifndef MATH_LIBRARY_PROFILE
#define MATH_LIBRARY_PROFILE MATH_LIBRARY
#endif
#define LIBHSAIL "hsail-rt"
void
lang_specific_driver (struct cl_decoded_option **in_decoded_options,
unsigned int *in_decoded_options_count,
int *in_added_libraries)
{
unsigned int i, j;
/* The new argument list will be contained in this. */
struct cl_decoded_option *new_decoded_options;
/* An array used to flag each argument that needs a bit set for
LANGSPEC, MATHLIB, or WITHLIBC. */
int *args;
/* By default, we throw on the math library if we have one. */
int need_math = (MATH_LIBRARY[0] != '\0');
/* True if we should add -shared-libgcc to the command-line. */
int shared_libgcc = 1;
/* The total number of arguments with the new stuff. */
unsigned int argc;
/* The argument list. */
struct cl_decoded_option *decoded_options;
/* The number of libraries added in. */
int added_libraries;
/* The total number of arguments with the new stuff. */
int num_args = 1;
argc = *in_decoded_options_count;
decoded_options = *in_decoded_options;
added_libraries = *in_added_libraries;
args = XCNEWVEC (int, argc);
for (i = 1; i < argc; i++)
{
switch (decoded_options[i].opt_index)
{
case OPT_o:
break;
case OPT_SPECIAL_input_file:
break;
}
}
/* Make sure to have room for the trailing NULL argument. */
num_args = argc + need_math + shared_libgcc + 10;
new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
i = 0;
j = 0;
/* Copy the 0th argument, i.e., the name of the program itself. */
new_decoded_options[j++] = decoded_options[i++];
/* NOTE: We start at 1 now, not 0. */
while (i < argc)
{
new_decoded_options[j] = decoded_options[i];
if ((args[i] & SKIPOPT) != 0)
--j;
i++;
j++;
}
generate_option (OPT_l, LIBHSAIL, 1, CL_DRIVER, &new_decoded_options[j]);
j++;
*in_decoded_options_count = j;
*in_decoded_options = new_decoded_options;
*in_added_libraries = added_libraries;
}
/* Called before linking. Returns 0 on success and -1 on failure. */
int lang_specific_pre_link (void) /* Not used for Brig. */ { return 0; }
/* Number of extra output files that lang_specific_pre_link may generate. */
int lang_specific_extra_outfiles = 0; /* Not used for Brig. */

41
gcc/brig/config-lang.in Normal file
View file

@ -0,0 +1,41 @@
# config-lang.in -- Top level configure fragment for gcc BRIG (HSAIL) frontend.
# Copyright (C) 2015 Free Software Foundation, Inc.
# This file is part of GCC.
# GCC is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# GCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# Configure looks for the existence of this file to auto-config each language.
# We define several parameters used by configure:
#
# language - name of language as it would appear in $(LANGUAGES)
# compilers - value to add to $(COMPILERS)
language="brig"
compilers="brig1\$(exeext)"
target_libs="target-libbrig target-libhsail-rt"
# The BRIG frontend is written in C++, so we need to build the C++
# compiler during stage 1. Note: when cross-compiling / not bootstrapping,
# this can be safely removed. gcc 4.9.1 force enables c++/libstdc++ to the
# target compiler due to this.
lang_requires_boot_languages=c++
gtfiles="\$(srcdir)/brig/brig-lang.c \$(srcdir)/brig/brig-c.h"
build_by_default="no"

28
gcc/brig/lang-specs.h Normal file
View file

@ -0,0 +1,28 @@
/* lang-specs.h -- gcc driver specs for BRIG (HSAIL) frontend.
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* This is the contribution to the `default_compilers' array in gcc.c
for the BRIG (HSAIL) input. */
{".brig", "@brig", 0, 1, 0},
{"@brig",
"brig1 %i %(cc1_options) %{I*} %{L*} %D %{!fsyntax-only:%(invoke_as)}", 0, 1,
0},

41
gcc/brig/lang.opt Normal file
View file

@ -0,0 +1,41 @@
; lang.opt -- Options for the gcc BRIG (HSAIL) front end.
; Copyright (C) 2015 Free Software Foundation, Inc.
;
; This file is part of GCC.
;
; GCC is free software; you can redistribute it and/or modify it under
; the terms of the GNU General Public License as published by the Free
; Software Foundation; either version 3, or (at your option) any later
; version.
;
; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
; WARRANTY; without even the implied warranty of MERCHANTABILITY or
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
; for more details.
;
; You should have received a copy of the GNU General Public License
; along with GCC; see the file COPYING3. If not see
; <http://www.gnu.org/licenses/>.
; See the GCC internals manual for a description of this file's format.
; Please try to keep this file in ASCII collating order.
Language
BRIG
-dump
BRIG Separate Alias(d)
-dump=
BRIG Joined Alias(d)
L
BRIG Joined Separate
; Not documented
-output=
BRIG Driver Joined Alias(o) MissingArgError(missing filename after %qs)
; This comment is to ensure we retain the blank line above.

View file

@ -67,7 +67,10 @@ DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
DEF_PRIMITIVE_TYPE (BT_INT8, signed_char_type_node)
DEF_PRIMITIVE_TYPE (BT_INT16, short_integer_type_node)
DEF_PRIMITIVE_TYPE (BT_UINT8, char_type_node)
DEF_PRIMITIVE_TYPE (BT_UINT16, short_unsigned_type_node)
DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
@ -167,6 +170,7 @@ DEF_FUNCTION_TYPE_0 (BT_FN_CONST_STRING, BT_CONST_STRING)
DEF_FUNCTION_TYPE_0 (BT_FN_PID, BT_PID)
DEF_FUNCTION_TYPE_0 (BT_FN_INT, BT_INT)
DEF_FUNCTION_TYPE_0 (BT_FN_UINT, BT_UINT)
DEF_FUNCTION_TYPE_0 (BT_FN_ULONG, BT_ULONG)
DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT, BT_FLOAT)
DEF_FUNCTION_TYPE_0 (BT_FN_DOUBLE, BT_DOUBLE)
/* For "long double" we use LONGDOUBLE (not LONG_DOUBLE) to
@ -271,16 +275,29 @@ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_CONST_PTR, BT_VOID, BT_CONST_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_INT, BT_UINT, BT_INT)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_ULONG, BT_UINT, BT_ULONG)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_LONG, BT_UINT, BT_LONG)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_PTR, BT_UINT, BT_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_PTR, BT_ULONG, BT_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG)
DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
DEF_FUNCTION_TYPE_1 (BT_FN_INT8_FLOAT, BT_INT8, BT_FLOAT)
DEF_FUNCTION_TYPE_1 (BT_FN_INT16_FLOAT, BT_INT16, BT_FLOAT)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_FLOAT, BT_UINT32, BT_FLOAT)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_FLOAT, BT_UINT16, BT_FLOAT)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT8_FLOAT, BT_UINT8, BT_FLOAT)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT16, BT_UINT16, BT_UINT16)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_FLOAT, BT_UINT64, BT_FLOAT)
DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_INT, BT_BOOL, BT_INT)
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_CONST_PTR_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_BND_CONST_PTR, BT_BND, BT_CONST_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_CONST_PTR_BND, BT_CONST_PTR, BT_BND)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT32, BT_UINT16, BT_UINT32)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT16, BT_UINT32, BT_UINT16)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
@ -301,18 +318,52 @@ DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_FILEPTR,
BT_INT, BT_CONST_STRING, BT_FILEPTR)
DEF_FUNCTION_TYPE_2 (BT_FN_INT_INT_FILEPTR,
BT_INT, BT_INT, BT_FILEPTR)
DEF_FUNCTION_TYPE_2 (BT_FN_UINT16_UINT16_UINT16,
BT_UINT16, BT_UINT16, BT_UINT16)
DEF_FUNCTION_TYPE_2 (BT_FN_INT_PTR_INT,
BT_INT, BT_PTR, BT_INT)
DEF_FUNCTION_TYPE_2 (BT_FN_UINT_PTR_UINT,
BT_UINT, BT_PTR, BT_UINT)
DEF_FUNCTION_TYPE_2 (BT_FN_LONG_PTR_LONG,
BT_LONG, BT_PTR, BT_LONG)
DEF_FUNCTION_TYPE_2 (BT_FN_ULONG_PTR_ULONG,
BT_ULONG, BT_PTR, BT_ULONG)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRMODE_PTR,
BT_VOID, BT_PTRMODE, BT_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTRMODE,
BT_VOID, BT_PTR, BT_PTRMODE)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT64_UINT64,
BT_VOID, BT_UINT64, BT_UINT64)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VALIST_REF_VALIST_ARG,
BT_VOID, BT_VALIST_REF, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_2 (BT_FN_LONG_LONG_LONG,
BT_LONG, BT_LONG, BT_LONG)
DEF_FUNCTION_TYPE_2 (BT_FN_UINT8_UINT8_UINT8,
BT_UINT8, BT_UINT8, BT_UINT8)
DEF_FUNCTION_TYPE_2 (BT_FN_INT8_INT8_INT8,
BT_INT8, BT_INT8, BT_INT8)
DEF_FUNCTION_TYPE_2 (BT_FN_INT16_INT16_INT16,
BT_INT16, BT_INT16, BT_INT16)
DEF_FUNCTION_TYPE_2 (BT_FN_INT_INT_INT,
BT_INT, BT_INT, BT_INT)
DEF_FUNCTION_TYPE_2 (BT_FN_UINT_FLOAT_UINT,
BT_UINT, BT_FLOAT, BT_UINT)
DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_UINT_UINT,
BT_FLOAT, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_2 (BT_FN_ULONG_UINT_UINT,
BT_ULONG, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_2 (BT_FN_ULONG_UINT_PTR,
BT_ULONG, BT_UINT, BT_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_ULONG_ULONG_ULONG,
BT_ULONG, BT_ULONG, BT_ULONG)
DEF_FUNCTION_TYPE_2 (BT_FN_UINT_UINT_UINT,
BT_UINT, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_2 (BT_FN_INT_PTR_CONST_STRING,
BT_INT, BT_PTR, BT_CONST_STRING)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_SIZE,
BT_VOID, BT_PTR, BT_SIZE)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_PTR,
BT_VOID, BT_UINT, BT_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_FLOAT,
BT_FLOAT, BT_FLOAT, BT_FLOAT)
DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_DOUBLE,
@ -408,6 +459,7 @@ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE,
BT_CONST_VOLATILE_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_INT_BOOL, BT_BOOL, BT_INT, BT_BOOL)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_2 (BT_FN_UINT_UINT_PTR, BT_UINT, BT_UINT, BT_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_SIZE)
DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR, BT_CONST_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRPTR_CONST_PTR, BT_VOID, BT_PTR_PTR, BT_CONST_PTR)
@ -415,6 +467,8 @@ DEF_FUNCTION_TYPE_2 (BT_FN_VOID_CONST_PTR_SIZE, BT_VOID, BT_CONST_PTR, BT_SIZE)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_BND, BT_VOID, BT_PTR, BT_BND)
DEF_FUNCTION_TYPE_2 (BT_FN_CONST_PTR_CONST_PTR_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_BND_CONST_PTR_SIZE, BT_BND, BT_CONST_PTR, BT_SIZE)
DEF_FUNCTION_TYPE_2 (BT_FN_UINT32_UINT64_PTR,
BT_UINT32, BT_UINT64, BT_PTR)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
@ -444,6 +498,20 @@ DEF_FUNCTION_TYPE_3 (BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG,
BT_INT, BT_FILEPTR, BT_CONST_STRING, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_3 (BT_FN_INT_PTR_PTR_PTR,
BT_INT, BT_PTR, BT_PTR, BT_PTR)
DEF_FUNCTION_TYPE_3 (BT_FN_INT_INT_UINT_UINT,
BT_INT, BT_INT, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_UINT_UINT,
BT_UINT, BT_UINT, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_UINT_PTR,
BT_UINT, BT_UINT, BT_UINT, BT_PTR)
DEF_FUNCTION_TYPE_3 (BT_FN_UINT_ULONG_ULONG_UINT,
BT_UINT, BT_ULONG, BT_ULONG, BT_UINT)
DEF_FUNCTION_TYPE_3 (BT_FN_ULONG_ULONG_ULONG_ULONG,
BT_ULONG, BT_ULONG, BT_ULONG, BT_ULONG)
DEF_FUNCTION_TYPE_3 (BT_FN_LONG_LONG_UINT_UINT,
BT_LONG, BT_LONG, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_3 (BT_FN_ULONG_ULONG_UINT_UINT,
BT_ULONG, BT_ULONG, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_3 (BT_FN_STRING_CONST_STRING_CONST_STRING_INT,
BT_STRING, BT_CONST_STRING, BT_CONST_STRING, BT_INT)
DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT_FLOAT_FLOAT_FLOAT,
@ -512,6 +580,10 @@ DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_ULONG_ULONG_ULONGPTR, BT_BOOL, BT_ULONG,
BT_ULONG, BT_PTR_ULONG)
DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, BT_BOOL,
BT_ULONGLONG, BT_ULONGLONG, BT_PTR_ULONGLONG)
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_UINT32_UINT64_PTR,
BT_VOID, BT_UINT32, BT_UINT64, BT_PTR)
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_UINT32_UINT32_PTR,
BT_VOID, BT_UINT32, BT_UINT32, BT_PTR)
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
@ -523,6 +595,12 @@ DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE,
BT_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE, BT_SIZE)
DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_INT_SIZE_SIZE,
BT_PTR, BT_PTR, BT_INT, BT_SIZE, BT_SIZE)
DEF_FUNCTION_TYPE_4 (BT_FN_UINT_UINT_UINT_UINT_UINT,
BT_UINT, BT_UINT, BT_UINT, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_4 (BT_FN_UINT_FLOAT_FLOAT_FLOAT_FLOAT,
BT_UINT, BT_FLOAT, BT_FLOAT, BT_FLOAT, BT_FLOAT)
DEF_FUNCTION_TYPE_4 (BT_FN_ULONG_ULONG_ULONG_UINT_UINT,
BT_ULONG, BT_ULONG, BT_ULONG, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_4 (BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE,
BT_STRING, BT_STRING, BT_CONST_STRING, BT_SIZE, BT_SIZE)
DEF_FUNCTION_TYPE_4 (BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG,

View file

@ -1000,5 +1000,48 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST)
/* Pointer Bounds Checker builtins. */
#include "chkp-builtins.def"
/* Do not expose the BRIG builtins by default gcc-wide, but only privately in
the BRIG FE as long as there are no references for them in the middle end
or any of the upstream backends. */
#ifndef DEF_HSAIL_BUILTIN
#define DEF_HSAIL_BUILTIN(ENUM, HSAIL_OPCODE, HSAIL_TYPE, NAME, TYPE, ATTRS) \
DEF_BUILTIN_STUB (ENUM, "__builtin_" NAME)
#endif
/* HSAIL atomic builtins do not have separate identifying opcodes. */
#ifndef DEF_HSAIL_ATOMIC_BUILTIN
#define DEF_HSAIL_ATOMIC_BUILTIN(ENUM, ATOMIC_OPCODE, HSAIL_TYPE, NAME, \
TYPE, ATTRS) \
DEF_BUILTIN_STUB (ENUM, "__builtin_" NAME)
#endif
/* HSAIL saturating arithmetics builtins. */
#ifndef DEF_HSAIL_SAT_BUILTIN
#define DEF_HSAIL_SAT_BUILTIN(ENUM, BRIG_OPCODE, HSAIL_TYPE, NAME, \
TYPE, ATTRS) \
DEF_BUILTIN_STUB (ENUM, "__builtin_" NAME)
#endif
/* HSAIL builtins used internally by the frontend. */
#ifndef DEF_HSAIL_INTR_BUILTIN
#define DEF_HSAIL_INTR_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN_STUB (ENUM, "__builtin_" NAME)
#endif
/* HSAIL saturated conversions. */
#ifndef DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN
#define DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN(ENUM, HSAIL_DEST_TYPE, HSAIL_SRC_TYPE, \
NAME, TYPE, ATTRS) \
DEF_BUILTIN_STUB (ENUM, "__builtin_" NAME)
#endif
/* HSAIL/BRIG frontend builtins. */
#include "brig-builtins.def"
#undef DEF_BUILTIN_CHKP
#undef DEF_BUILTIN

View file

@ -16,7 +16,7 @@
GCC stands for ``GNU Compiler Collection''. GCC is an integrated
distribution of compilers for several major programming languages. These
languages currently include C, C++, Objective-C, Objective-C++,
Fortran, Ada, and Go.
Fortran, Ada, Go, and BRIG (HSAIL).
The abbreviation @dfn{GCC} has multiple meanings in common use. The
current official meaning is ``GNU Compiler Collection'', which refers

View file

@ -2665,7 +2665,10 @@ separately.
Second, you must have the testing tools installed. This includes
@uref{http://www.gnu.org/software/dejagnu/,,DejaGnu}, Tcl, and Expect;
the DejaGnu site has links to these.
the DejaGnu site has links to these. For running the BRIG frontend
tests, a tool to assemble the binary BRIGs from HSAIL text,
@uref{https://github.com/HSAFoundation/HSAIL-Tools/,,HSAILasm} must
be installed.
If the directories where @command{runtest} and @command{expect} were
installed are not in the @env{PATH}, you may need to set the following

View file

@ -1338,6 +1338,9 @@ traditional preprocessor).
@item @var{file}.go
Go source code.
@item @var{file}.brig
BRIG files (binary representation of HSAIL).
@item @var{file}.ads
Ada source code file that contains a library unit declaration (a
declaration of a package, subprogram, or generic, or a generic
@ -1386,6 +1389,7 @@ assembler assembler-with-cpp
ada
f77 f77-cpp-input f95 f95-cpp-input
go
brig
@end smallexample
@item -x none

View file

@ -301,6 +301,14 @@ available online, see @uref{http://gcc.gnu.org/readings.html}
As of the GCC 4.7.1 release, GCC supports the Go 1 language standard,
described at @uref{http://golang.org/doc/go1.html}.
@section HSA Intermediate Language (HSAIL)
GCC can compile the binary representation (BRIG) of the HSAIL text format as
described in HSA Programmer's Reference Manual version 1.0.1. This
capability is typically utilized to implement the HSA runtime API's HSAIL
finalization extension for a gcc supported processor. HSA standards are
freely available at @uref{http://www.hsafoundation.com/standards/}.
@section References for Other Languages
@xref{Top, GNAT Reference Manual, About This Guide, gnat_rm,

View file

@ -1,3 +1,23 @@
2017-01-24 Pekka Jääskeläinen <pekka@parmance.com>
Martin Jambor <mjambor@suse.cz>
* lib/brig-dg.exp: New file.
* lib/brig.exp: Likewise.
* brig.dg/README: Likewise.
* brig.dg/dg.exp: Likewise.
* brig.dg/test/gimple/alloca.hsail: Likewise.
* brig.dg/test/gimple/atomics.hsail: Likewise.
* brig.dg/test/gimple/branches.hsail: Likewise.
* brig.dg/test/gimple/fbarrier.hsail: Likewise.
* brig.dg/test/gimple/function_calls.hsail: Likewise.
* brig.dg/test/gimple/kernarg.hsail: Likewise.
* brig.dg/test/gimple/mem.hsail: Likewise.
* brig.dg/test/gimple/mulhi.hsail: Likewise.
* brig.dg/test/gimple/packed.hsail: Likewise.
* brig.dg/test/gimple/smoke_test.hsail: Likewise.
* brig.dg/test/gimple/variables.hsail: Likewise.
* brig.dg/test/gimple/vector.hsail: Likewise.
2017-01-24 Jakub Jelinek <jakub@redhat.com>
* g++.dg/asan/asan_test.C: Enable on all *-*-linux* targets that

View file

@ -0,0 +1,12 @@
BRIG (HSAIL) frontend test cases
--------------------------------
The suite consists of "smoke tests" that test several features of
the compilation and regression tests, but is not an exhaustive test
suite for all HSAIL instructions. The HSA PRM conformance suite
is supposed to be used for that.
HSAILasm is required for converting the text HSAIL files to BRIGs
which the compiler consumes. It can be built from
https://github.com/HSAFoundation/HSAIL-Tools

View file

@ -0,0 +1,31 @@
# Copyright (C) 2009-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# GCC testsuite that uses the `dg.exp' driver.
load_lib brig-dg.exp
# Initialize `dg'.
dg-init
if [expr [llength [auto_execok HSAILasm]] > 0] {
dg-runtest [find $srcdir/$subdir *.hsail] "" ""
} else {
unsupported "All BRIG FE tests require HSAILasm in PATH."
}
# All done.
dg-finish

View file

@ -0,0 +1,37 @@
module &module:1:0:$full:$large:$default;
/* Tests for alloca. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
prog function &subfunction(arg_u32 %return_value)() {
alloca_align(1)_u32 $s2, 256;
st_arg_u32 $s2, [%return_value];
ret;
};
prog kernel &kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_u32 $s0, [$d0];
alloca_align(256)_u32 $s1, 16;
{
arg_u32 %return_value;
call &subfunction(%return_value)();
ld_arg_u32 $s1, [%return_value];
}
ld_kernarg_u64 $d1, [%output_ptr];
st_global_u32 $s1, [$d0];
};
/* { dg-final { scan-tree-dump "s2 = __builtin___hsail_alloca \\\(256, 1, __context\\\);" "gimple" } } */
/* { dg-final { scan-tree-dump "s1 = __builtin___hsail_alloca \\\(16, 256, __context\\\);" "gimple" } } */
/* Both functions should have an alloca frame push and pop. */
/* { dg-final { scan-tree-dump-times "__builtin___hsail_alloca_push_frame \\\(__context\\\);" 2 "gimple" } } */
/* { dg-final { scan-tree-dump-times "__builtin___hsail_alloca_pop_frame \\\(__context\\\);" 2 "gimple" } } */

View file

@ -0,0 +1,33 @@
module &module:1:0:$full:$large:$default;
/* Test for atomic instructions. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-original" } */
prog kernel &Kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
atomic_ld_global_rlx_system_b32 $s0, [$d0];
atomic_add_global_rlx_system_u32 $s1, [$d0 + 4], $s0;
ld_kernarg_u64 $d0, [%output_ptr];
atomicnoret_st_global_rlx_system_b32 [$d0], $s2;
atomicnoret_min_global_rlx_system_u32 [$d0 + 4], $s1;
ret;
};
/* The atomic loads are implemented by casting to an atomic pointer. */
/* { dg-final { scan-tree-dump "s0 = VIEW_CONVERT_EXPR<unsigned int>\\\(\\\*\\\(atomic unsigned int \\\*\\\)" "original"} } */
/* The atomic add should call a gcc builtin. */
/* { dg-final { scan-tree-dump "= __sync_fetch_and_add_4 \\\(" "original"} } */
/* The atomic stores are implemented by casting to an atomic pointer. */
/* { dg-final { scan-tree-dump "\\\*\\\(atomic unsigned int \\\*\\\) d0 = s2;" "original"} } */
/* The atomic min is implemented by a custom builtin. */
/* { dg-final { scan-tree-dump "builtin_out.\[0-9\]+ = __builtin___hsail_atomic_min_u32 \\\(" "original"} } */

View file

@ -0,0 +1,58 @@
module &module:1:0:$full:$large:$default;
/* Test different style of branches. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
prog kernel &Kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_u64 $d1, [$d0];
ld_global_u64 $d2, [$d0 + 8];
ld_global_u32 $s0, [$d0 + 16];
ld_global_u32 $s1, [$d0 + 20];
sbr_width(all)_u32 $s1 [@case0, @case1, @case2];
@case0:
st_global_u64 0, [$d0];
br @out;
@case1:
st_global_u64 1, [$d0];
br @out;
@case2:
st_global_u64 2, [$d0];
@out:
cmp_eq_u32_u32 $s2, $s1, $s0;
cvt_b1_u32 $c0, $s2;
cbr_width(all)_b1 $c0, @true_branch;
@false_branch:
st_global_u64 $d1, [$d0];
@true_branch:
ld_kernarg_u64 $d0, [%output_ptr];
st_global_u32 $s2, [$d0 + 8];
br @skip;
st_global_u32 $s3, [$d0 + 12];
@skip:
ret;
};
/* sbr is converted to a switch */
/* { dg-final { scan-tree-dump "switch \\\(s1\\\) <default: <D.\[0-9\]+>, case 0: <D.\[0-9\]+>, case 1: <D.\[0-9\]+>, case 2: <D.\[0-9\]+>>" "gimple"} } */
/* br @out converted to gotos */
/* { dg-final { scan-tree-dump-times "goto @out" 2 "gimple"} } */
/* the comparison instruction */
/* { dg-final { scan-tree-dump "c0 = s2 != 0;" "gimple" } } */
/* cbr to an if clause */
/* { dg-final { scan-tree-dump "if \\\(c0 != 0\\\) goto @true_branch; else goto <D.\[0-9\]+>;" "gimple" } } */
/* br @skip converted to a goto */
/* { dg-final { scan-tree-dump "goto @skip" "gimple"} } */

View file

@ -0,0 +1,74 @@
module &module:1:0:$full:$large:$default;
/* Tests for fbarrier. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
fbarrier &fb_module_scope;
prog function &subfunction(arg_u32 %return_value)() {
workitemflatabsid_u32 $s3;
cvt_b1_u32 $c1, $s3;
cbr_width(all)_b1 $c1, @skip_fbar;
waitfbar &fb_module_scope;
@skip_fbar:
st_arg_u32 $s3, [%return_value];
ret;
};
prog kernel &kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
fbarrier %fb_func_scope;
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_u32 $s0, [$d0];
workitemflatabsid_u32 $s1;
cvt_b1_u32 $c1, $s1;
cbr_width(all)_b1 $c1, @skip_init;
initfbar &fb_module_scope;
initfbar %fb_func_scope;
joinfbar &fb_module_scope;
@skip_init:
barrier_width(all);
joinfbar %fb_func_scope;
{
arg_u32 %return_value;
call &subfunction(%return_value)();
ld_arg_u32 $s1, [%return_value];
}
arrivefbar %fb_func_scope;
ld_kernarg_u64 $d1, [%output_ptr];
st_global_u32 $s1, [$d0];
workitemflatabsid_u32 $s1;
cvt_b1_u32 $c0, $s1;
cbr_width(all)_b1 $c0, @skip_fini;
releasefbar &fb_module_scope;
releasefbar %fb_func_scope;
@skip_fini:
};
/* fbarriers are allocated from the group memory in the order of
appearance. The current implementation allocates 32B per fbarrier. */
/* { dg-final { scan-tree-dump "__hsail_waitfbar \\\(0, __context\\\);" "gimple"} } */
/* { dg-final { scan-tree-dump "__hsail_initfbar \\\(0, __context\\\);" "gimple"} } */
/* { dg-final { scan-tree-dump "__hsail_initfbar \\\(32, __context\\\);" "gimple"} } */
/* { dg-final { scan-tree-dump "__hsail_joinfbar \\\(0, __context\\\);" "gimple"} } */
/* { dg-final { scan-tree-dump "@skip_init:\[\n ]+__builtin___hsail_barrier \\\(__context\\\);\[\n ]+__builtin___hsail_joinfbar \\\(32, __context\\\);" "gimple"} } */
/* { dg-final { scan-tree-dump "__hsail_arrivefbar \\\(32, __context\\\);" "gimple"} } */
/* { dg-final { scan-tree-dump "__hsail_releasefbar \\\(0, __context\\\);\[\n ]+__builtin___hsail_releasefbar \\\(32, __context\\\);" "gimple"} } */

View file

@ -0,0 +1,59 @@
module &module:1:0:$full:$large:$default;
/* Function calls and argument passing. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
prog function &subfunction(arg_u32 %return_value)(arg_f32 %float_arg, arg_f64 %double_arg, arg_f16 %half_arg) {
ld_arg_f32 $s0, [%float_arg];
cvt_u32_f32 $s0, $s0;
ld_arg_f64 $d0, [%double_arg];
cvt_u32_f64 $s1, $d0;
ld_arg_f16 $s2, [%half_arg];
cvt_u32_f16 $s2, $s2;
add_u32 $s3, $s0, $s1;
add_u32 $s3, $s3, $s2;
st_arg_u32 $s3, [%return_value];
ret;
};
prog kernel &kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_u32 $s0, [$d0];
{
arg_f32 %float_arg;
arg_f64 %double_arg;
arg_f16 %half_arg;
arg_u32 %return_value;
st_arg_f32 12.0f, [%float_arg];
st_arg_f64 640.0d, [%double_arg];
st_arg_f16 12.0h, [%half_arg];
call &subfunction(%return_value)(%float_arg, %double_arg, %half_arg);
ld_arg_u32 $s1, [%return_value];
}
ld_kernarg_u64 $d1, [%output_ptr];
st_global_u32 $s1, [$d0];
};
/* The generated function call should have the incoming arguments and three hidden arguments. */
/* { dg-final { scan-tree-dump "_\[0-9\]+ = subfunction \\\(_kernel.float_arg.\[_0-9\]+, _kernel.double_arg.\[_0-9\]+, _kernel.half_arg.\[_0-9\]+, __context, __group_base_addr, __private_base_addr\\\);" "gimple"} } */
/* The callee should refer directly to the scalar arguments when it reads them. */
/* { dg-final { scan-tree-dump "= float_arg;" "gimple"} } */
/* { dg-final { scan-tree-dump "= double_arg;" "gimple"} } */
/* { dg-final { scan-tree-dump "= half_arg;" "gimple"} } */
/* The return value is stored to a temporary before returned. */
/* { dg-final { scan-tree-dump "_retvalue_temp = s3;" "gimple"} } */
/* { dg-final { scan-tree-dump "D.\[0-9\]+ = _retvalue_temp;" "gimple"} } */
/* { dg-final { scan-tree-dump "return D.\[0-9\]+;" "gimple"} } */

View file

@ -0,0 +1,25 @@
module &module:1:0:$full:$large:$default;
/* Tests for kernarg addressing modes. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-original" } */
prog kernel &Kernel(kernarg_u64 %input[4], kernarg_u64 %output_ptr, kernarg_u64 %i)
{
ld_kernarg_u64 $d0, [%i];
ld_kernarg_u64 $d0, [%input][$d0 + 1];
ld_kernarg_u64 $d1, [%output_ptr];
st_global_u64 $d0, [$d1];
ret;
};
/* [%i] */
/* { dg-final { scan-tree-dump " = \\\*\\\(unsigned long \\\*\\\) \\\(__args \\\+ 40\\\);" "original"} } */
/* [%input][$d0 + 1] */
/* { dg-final { scan-tree-dump "\\\*\\\(unsigned long \\\*\\\) \\\(\\\(VIEW_CONVERT_EXPR<void \\\*>\\\(\\\(unsigned long\\\) __args\\\) \\\+ \\\(unsigned long\\\) d0\\\) \\\+ 1\\\);" "original"} } */

View file

@ -0,0 +1,39 @@
module &module:1:0:$full:$large:$default;
/* Tests for load/store addressing modes. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-original" } */
prog kernel &Kernel(kernarg_u64 %input_ptr, kernarg_u64 %input_ptr2, kernarg_u64 %output_ptr)
{
global_u32 %global_array[4];
ld_kernarg_u64 $d0, [%input_ptr];
ld_kernarg_u64 $d2, [%input_ptr2];
ld_global_u32 $s0, [$d0];
ld_global_u64 $d1, [$d2 + 4];
ld_global_u32 $s2, [%global_array][$d1 + 4];
ld_kernarg_u64 $d0, [%output_ptr];
st_global_u32 $s0, [$d0];
st_global_u32 $s1, [$d0 + 4];
st_global_u32 $s2, [$d0 + 8];
ret;
};
/* %input_ptr, %input_ptr2 and %output_ptr accesses should generate offsets to the __args array */
/* { dg-final { scan-tree-dump "__args;\[\n \]+d0 =" "original"} } */
/* { dg-final { scan-tree-dump "\\\(__args \\\+ 8\\\);\[\n \]+d2 =" "original"} } */
/* { dg-final { scan-tree-dump "\\\(__args \\\+ 16\\\);\[\n \]+d0 =" "original"} } */
/* ld_global_u32 $s0, [$d0] */
/* { dg-final { scan-tree-dump "\\\*\\\(unsigned int \\\*\\\) d0;\[\n \]+s0 =" "original"} } */
/* ld_global_u64 $d1, [$d2 + 4] pointer arithmetics*/
/* { dg-final { scan-tree-dump "d2 \\\+ 4\\\);\[\n \]+d1 = " "original"} } */
/* ld_global_u32 $s2, [%global_array][$d1 + 4]; is the most complex form */
/* { dg-final { scan-tree-dump "\\\(unsigned long\\\) &_Kernel.global_array\\\) \\\+ \\\(unsigned long\\\) d1\\\) \\\+ 4" "original" } } */

View file

@ -0,0 +1,33 @@
module &module:1:0:$full:$large:$default;
/* Test high part multiplies. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
prog kernel &Kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_u64 $d1, [$d0];
ld_global_u64 $d2, [$d0 + 8];
ld_global_u32 $s0, [$d0 + 16];
ld_global_u32 $s1, [$d0 + 20];
mulhi_s32 $s2, $s0, $s1;
mulhi_s64 $d2, $d1, $d2;
mad24hi_s32 $s3, $s0, $s1, $s2;
mul24hi_s32 $s3, $s3, $s1;
ld_kernarg_u64 $d0, [%output_ptr];
st_global_u64 $d1, [$d0];
st_global_u32 $s2, [$d0 + 8];
st_global_u32 $s3, [$d0 + 12];
ret;
};
/* All of the hipart mults areImplemented using MULT_HIGHPART_EXPR (h*). */
/* { dg-final { scan-tree-dump-times " h\\\* " 4 "gimple"} } */

View file

@ -0,0 +1,78 @@
module &module:1:0:$full:$large:$default;
/* Test for different cases of packed instruction controls. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple -fdump-tree-original" } */
prog kernel &Kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_b128 $q0, [$d0];
add_pp_u8x16 $q1, $q0, u8x16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
/* Broadcast the 15 as it's the lowest element (pos 0) in the resulting vector. */
add_ps_u8x16 $q2, $q1, u8x16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
/* Broadcast the lowest element of q1. */
add_sp_u8x16 $q3, $q1, $q2;
/* Perform a scalar computation with the lowest element of both inputs and store it to the lowest element of dest. */
add_ss_u8x16 $q4, $q2, $q3;
/* Saturating arithmetics variations. */
add_pp_sat_u8x16 $q5, $q4, u8x16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
/* Broadcast the 15 as it's the lowest element (pos 0) in the resulting vector. */
add_ps_sat_u8x16 $q6, $q5, u8x16(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
/* Broadcast the lowest element of q1. */
add_sp_sat_u8x16 $q7, $q6, $q5;
/* Perform a scalar computation with the lowest element of both inputs and store it to the lowest element of dest. */
add_ss_sat_u8x16 $q8, $q7, $q6;
/* Single operand vector computation. */
neg_p_s16x8 $q9, $q8;
ld_kernarg_u64 $d0, [%output_ptr];
st_global_b128 $q8, [$d0];
ret;
};
/* The b128 load is done using uint128_t*.
/* { dg-final { scan-tree-dump "q0 = VIEW_CONVERT_EXPR<uint128_t>\\\(mem_read.\[0-9\]+\\\);" "original"} } */
/* Before arithmetics, the uint128_t is casted to a vector datatype. */
/* { dg-final { scan-tree-dump "<vector\\\(16\\\) unsigned char>\\\(q0\\\) \\\+ \\\{" "original"} } */
/* The u8x16 constant is generated to an array with elements in reverse order */
/* in comparison to the HSAIL syntax. */
/* { dg-final { scan-tree-dump "\\\+ { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }" "original"} } */
/* After arithmetics, the vector DT is casted back to a uint128_t. */
/* { dg-final { scan-tree-dump "q1 = VIEW_CONVERT_EXPR<uint128_t>" "original"} } */
/* Broadcasted the constant vector's lowest element and summed it up in the next line. */
/* { dg-final { scan-tree-dump "= { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };\[\n \]+_\[0-9\]+ = _\[0-9\]+ \\\+ _\[0-9\]+;" "gimple"} } */
/* Broadcasted the registers lowest element via a VEC_PERM_EXPR that has an all-zeros mask. */
/* { dg-final { scan-tree-dump "VEC_PERM_EXPR <_\[0-9\]+, _\[0-9\]+, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }>;" "gimple" } } */
/* For the add_ss we assume performing the computation over the whole vector is cheaper than */
/* extracting the scalar and performing a scalar operation. This aims to stay in the vector
/* datapath as long as possible. */
/* { dg-final { scan-tree-dump "_\[0-9\]+ = VIEW_CONVERT_EXPR<vector\\\(16\\\) unsigned char>\\\(q2\\\);\[\n \]+_\[0-9\]+ = VIEW_CONVERT_EXPR<vector\\\(16\\\) unsigned char>\\\(q3\\\);\[\n \]+_\[0-9\]+ = _\[0-9\]+ \\\+ _\[0-9\]+;" "gimple" } } */
/* Insert the lowest element of the result to the lowest element of the result register. */
/* { dg-final { scan-tree-dump "= VEC_PERM_EXPR <_\[0-9\]+, new_output.\[0-9\]+_\[0-9\]+, { 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }>;" "gimple" } } */
/* { dg-final { scan-tree-dump "q4 = VIEW_CONVERT_EXPR<uint128_t>\\\(s_output.\[0-9\]+_\[0-9\]+\\\);" "gimple" } } */
/* The saturating arithmetics are (curently) implemented using scalar builtin calls. */
/* { dg-final { scan-tree-dump-times "= __builtin___hsail_sat_add_u8" 64 "gimple" } } */
/* A single operand vector instr (neg.) */
/* { dg-final { scan-tree-dump " = VIEW_CONVERT_EXPR<vector\\\(8\\\) signed short>\\\(q8\\\);\[\n \]+_\[0-9\]+ = -_\[0-9\]+;\[\n \]+" "gimple" } } */

View file

@ -0,0 +1,91 @@
module &module:1:0:$full:$large:$default;
/* A basic smoke test. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
prog kernel &Kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_u32 $s0, [$d0];
ld_global_u32 $s1, [$d0 + 4];
add_u32 $s2, $s0, $s1;
add_u32 $s3, $s0, 4294967295;
ld_kernarg_u64 $d0, [%output_ptr];
st_global_u32 $s2, [$d0];
st_global_u32 $s3, [$d0 + 4];
ret;
};
prog kernel &KernelWithBarrier(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_u32 $s0, [$d0];
ld_global_u32 $s1, [$d0 + 4];
add_u32 $s2, $s0, $s1;
barrier_width(all);
add_u32 $s3, $s0, 4294967295;
ld_kernarg_u64 $d0, [%output_ptr];
st_global_u32 $s2, [$d0];
st_global_u32 $s3, [$d0 + 4];
ret;
};
/* The kernel function itself should have a fingerprint as follows */
/* _Kernel (unsigned char * __args, void * __context, void * __group_base_addr, void * __private_base_addr) */
/* { dg-final { scan-tree-dump "_Kernel \\\(unsigned char \\\* __args, void \\\* __context, void \\\* __group_base_addr, void \\\* __private_base_addr\\\)" "gimple"} } */
/* ld_kernarg: mem_read.0 = MEM[(unsigned long *)__args]; */
/* { dg-final { scan-tree-dump "mem_read.\[0-9\] = MEM\\\[\\\(unsigned long \\\*\\\)__args\\\];" "gimple"} } */
/* The latter ld_global_u32 should be visible as a pointer dereference (after pointer arithmetics on a temporary var): */
/* mem_read.2 = *D.1691; */
/* { dg-final { scan-tree-dump "mem_read.\[0-9\] = \\\*\[_0-9\]+;" "gimple"} } */
/* add_u32s should generate +operators */
/* { dg-final { scan-tree-dump "s2 = s0 \\\+ s1;" "gimple"} } */
/* { dg-final { scan-tree-dump "s3 = s0 \\\+ 4294967295;" "gimple"} } */
/* The latter st_global_u32 should be visible as a pointer dereference (after pointer arithmetics on a temporary var): */
/* *D.1694 = s3; */
/* { dg-final { scan-tree-dump "\\\*\[_0-9\]+ = s3;" "gimple"} } */
/* The return inside the kernel should be generated to a goto to the end of the kernel. */
/* goto __kernel_exit; */
/* __kernel_exit: */
/* { dg-final { scan-tree-dump "goto __kernel_exit;" "gimple"} } */
/* { dg-final { scan-tree-dump "__kernel_exit:" "gimple"} } */
/* Expecting a work item loop because there are no barrier calls. */
/* { dg-final { scan-tree-dump "if \\\(__local_x < __cur_wg_size_x\\\) goto __wi_loop_x; else goto" "gimple"} } */
/* { dg-final { scan-tree-dump "if \\\(__local_y < __cur_wg_size_y\\\) goto __wi_loop_y; else goto" "gimple"} } */
/* { dg-final { scan-tree-dump "if \\\(__local_z < __cur_wg_size_z\\\) goto __wi_loop_z; else goto" "gimple"} } */
/* The launcher should call __hsail_launch_wg_function in this case: */
/* Kernel (void * __context, void * __group_base_addr) */
/* { dg-final { scan-tree-dump "Kernel \\\(void \\\* __context, void \\\* __group_base_addr\\\)" "gimple"} } */
/* { dg-final { scan-tree-dump "__hsail_launch_wg_function \\\(_Kernel, __context, __group_base_addr\\\);" "gimple"} }*/
/* The kernel should have the magic metadata section injected to the ELF. */
/* TODO: this should be disabled in case not outputting to an ELF. */
/* Currently ELF is assumed by the brig frontend. Do not check for the context */
/* as it is likely to change. */
/* { dg-final { scan-tree-dump "\\\.pushsection phsa\\\.desc\\\.Kernel" "gimple"} }*/
/* The kernel with the barrier call should have the barrier builtin call in between the two summations. */
/* { dg-final { scan-tree-dump "s2 = s0 \\\+ s1;\[\n \]+__builtin___hsail_barrier \\\(__context\\\);\[\n \]+s3 = s0 \\\+ 4294967295;" "gimple"} } */
/* The kernel with the barrier call's launcher function should call the thread-spawning function. */
/* { dg-final { scan-tree-dump "__hsail_launch_kernel \\\(_KernelWithBarrier, __context, __group_base_addr\\\);" "gimple" } } */

View file

@ -0,0 +1,124 @@
module &module:1:0:$full:$large:$default;
/* Tests for different variable scopes and address spaces. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
prog align(256) private_u32 &prog_private;
private_u32 &mod_private;
prog group_u32 &prog_group;
group_u32 &mod_group;
prog global_u32 &prog_global;
global_u32 &mod_global;
decl prog global_u32 &prog_global_host_def;
prog readonly_u32 &prog_readonly;
readonly_u32 &mod_readonly;
prog function &subfunction(arg_u32 %return_value)(arg_u32 %arg) {
private_u32 %func_private;
group_u32 %func_group;
align(256) global_u32 %func_global;
readonly_u32 %func_readonly;
ld_private_u32 $s200, [%func_private];
st_private_u32 $s200, [&prog_private];
ld_group_u32 $s203, [%func_group];
st_group_u32 $s203, [&prog_group];
ld_global_u32 $s204, [%func_global];
st_global_u32 $s204, [&prog_global];
ld_readonly_u32 $s205, [%func_readonly];
st_global_u32 $s205, [%func_global];
st_arg_u32 $s2, [%return_value];
ret;
};
prog kernel &kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
private_u32 %kern_private;
group_u32 %kern_group;
global_u32 %kern_global;
readonly_u32 %kern_readonly;
ld_kernarg_u64 $d0, [%input_ptr];
ld_global_u32 $s0, [$d0];
ld_private_u32 $s2, [&prog_private];
st_private_u32 $s2, [%kern_private];
ld_private_u32 $s3, [&mod_private];
st_private_u32 $s3, [&prog_private];
ld_group_u32 $s4, [&prog_group];
st_group_u32 $s4, [%kern_group];
ld_group_u32 $s5, [&mod_group];
st_group_u32 $s5, [&prog_group];
ld_global_u32 $s6, [&prog_global];
st_global_u32 $s6, [%kern_global];
ld_global_u32 $s7, [&mod_global];
st_global_u32 $s7, [&prog_global];
ld_readonly_u32 $s8, [&prog_readonly];
st_global_u32 $s8, [%kern_global];
ld_readonly_u32 $s9, [&mod_readonly];
st_global_u32 $s9, [&prog_global];
ld_readonly_u32 $s10, [%kern_readonly];
st_global_u32 $s10, [%kern_global];
ld_readonly_u32 $s11, [%kern_readonly];
st_global_u32 $s11, [&prog_global_host_def];
{
arg_u32 %arg;
arg_u32 %return_value;
st_arg_u32 $s1, [%arg];
call &subfunction(%return_value)(%arg);
ld_arg_u32 $s1, [%return_value];
}
ld_kernarg_u64 $d1, [%output_ptr];
st_global_u32 $s1, [$d0];
};
/* Private variable offsets assigned in the order of their appearance */
/*
prog_private @0 (align 256) -> until 254 to ensure all WIs
mod_private @256 have their chunks aligned
func_private @260
kern_private @264
*/
/* Group variable offsets assigned in the order of their appearance */
/*
prog_group @0 (2)
mod_group @4 (4)
func_group @8 (1)
kern_group @12 (3)
*/
/* { dg-final { scan-tree-dump "\\\+ 8;.*\\\+ 12;.*\\\+ 4;" "gimple" } } */
/* The "mangling" of the global and readonly vars. */
/* { dg-final { scan-tree-dump "\[ \]*prog_global = s204;" "gimple" } } */
/* { dg-final { scan-tree-dump "\.module.mod_global;" "gimple" } } */
/* Host defined variables need indirect access as the address is
known only at run time. */
/* { dg-final { scan-tree-dump "\\\*\\\__phsa.host_def.prog_global_host_def.\[0-9\]+_\[0-9\]+ = s11;" "gimple" } } */
/* { dg-final { scan-tree-dump "\.subfunction.func_global;" "gimple" } } */
/* { dg-final { scan-tree-dump "\.subfunction.func_readonly;" "gimple" } } */
/* { dg-final { scan-tree-dump "kernel.kern_global" "gimple" } } */
/* { dg-final { scan-tree-dump "kernel.kern_readonly" "gimple" } } */

View file

@ -0,0 +1,57 @@
module &module:1:0:$full:$large:$default;
/* A test for vector operands. */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-original" } */
prog kernel &Kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
{
ld_kernarg_u64 $d0, [%input_ptr];
ld_v2_global_f32 ($s0, $s1), [$d0];
ld_v3_global_f32 ($s2, $s3, $s4), [$d0 + 8];
ld_v4_global_f32 ($s5, $s6, $s7, $s8), [$d0 + 20];
add_f32 $s9, $s0, $s1;
combine_v2_b64_b32 $d2, ($s1, $s0);
combine_v2_b64_b32 $d3, ($s2, $s3);
add_pp_f32x2 $d4, $d2, $d3;
expand_v2_b32_b64 ($s0, $s3), $d4;
ld_kernarg_u64 $d1, [%output_ptr];
st_v2_global_f32 ($s0, $s1), [$d1];
st_v3_global_f32 ($s2, $s3, $s4), [$d1 + 8];
st_v4_global_f32 ($s5, $s6, $s7, $s8), [$d1 + 20];
ret;
};
/* The v2 load is done via casting to a vector datatype ptr. */
/* { dg-final { scan-tree-dump " = MEM\\\[\\\(vector\\\(2\\\) <float:32> \\\*\\\)" "original"} } */
/* The v3 load is scalarized (at the moment) due to gcc requiring 2's exponent wide vectors. */
/* { dg-final { scan-tree-dump "s0 = VIEW_CONVERT_EXPR<unsigned int>\\\(BIT_FIELD_REF <mem_read.\[0-9\]+, 32, 0>\\\);\[\n ]+s1 = VIEW_CONVERT_EXPR<unsigned int>\\\(BIT_FIELD_REF <mem_read.\[0-9\]+, 32, 32>\\\);" "original"} } */
/* The v4 load is done via casting to a vector datatype ptr. */
/* { dg-final { scan-tree-dump " = MEM\\\[\\\(vector\\\(4\\\) <float:32> \\\*\\\)" "original"} } */
/* The combines are generated to vector constructors. */
/* { dg-final { scan-tree-dump "{s1, s0}" "original"} } */
/* { dg-final { scan-tree-dump "{s2, s3}" "original"} } */
/* Expands to BIT_FIELD_REFs. */
/* { dg-final { scan-tree-dump "s0 = BIT_FIELD_REF <d4, 32, 0>;" "original"} } */
/* { dg-final { scan-tree-dump "s3 = BIT_FIELD_REF <d4, 32, 32>;" "original"} } */
/* The v1 store is done via casting to a vector datatype ptr and constructing a vector from the inputs. */
/* { dg-final { scan-tree-dump "MEM\\\[\\\(vector\\\(2\\\) <float:32> \\\*\\\)\\\(<float:32> \\\*\\\) d1\\\] = " "original"} } */
/* The v3 store is scalarized (at the moment) due to gcc requiring 2's exponent wide vectors. */
/* { dg-final { scan-tree-dump "\\\*\\\(<float:32> \\\*\\\) \\\(\\\(sizetype\\\) d1 \\\+ 8\\\) \\\+ 0 = VIEW_CONVERT_EXPR<<float:32>>\\\(s2\\\);" "original"} } */
/* { dg-final { scan-tree-dump "\\\*\\\(<float:32> \\\*\\\) \\\(\\\(sizetype\\\) d1 \\\+ 8\\\) \\\+ 4 = VIEW_CONVERT_EXPR<<float:32>>\\\(s3\\\);" "original"} } */
/* { dg-final { scan-tree-dump "\\\*\\\(<float:32> \\\*\\\) \\\(\\\(sizetype\\\) d1 \\\+ 8\\\) \\\+ 8 = VIEW_CONVERT_EXPR<<float:32>>\\\(s4\\\);" "original"} } */
/* The v4 store is done via casting to a vector datatype and constructing a vector from the inputs. */
/* { dg-final { scan-tree-dump "MEM\\\[\\\(vector\\\(4\\\) <float:32> \\\*\\\)\\\(<float:32> \\\*\\\) \\\(\\\(sizetype\\\) d1 \\\+ 20\\\)\\\] = {VIEW_CONVERT_EXPR<<float:32>>\\\(s5\\\), VIEW_CONVERT_EXPR<<float:32>>\\\(s6\\\), VIEW_CONVERT_EXPR<<float:32>>\\\(s7\\\), VIEW_CONVERT_EXPR<<float:32>>\\\(s8\\\)};" "original"} } */

View file

@ -0,0 +1,29 @@
# Copyright (C) 2009-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
load_lib gcc-dg.exp
# Define brig callbacks for dg.exp.
proc brig-dg-test { prog do_what extra_tool_flags } {
set result \
[gcc-dg-test-1 brig_target_compile $prog $do_what $extra_tool_flags]
set comp_output [lindex $result 0]
set output_file [lindex $result 1]
return [list $comp_output $output_file]
}

View file

@ -0,0 +1,40 @@
# Copyright (C) 2009-2016 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
load_lib prune.exp
load_lib gcc-defs.exp
load_lib timeout.exp
load_lib target-libpath.exp
#
# brig_target_compile -- compile a HSAIL input to BRIG using HSAILasm and then
# compile the BRIG to target ISA using gcc
proc brig_target_compile { source dest type options } {
global tmpdir
global testname_with_flags
if { [file extension $source] == ".hsail" } {
# We cannot assume all inputs are .hsail as the dg machinery
# calls this for a some c files to check linker plugin support or
# similar.
set brig_source ${tmpdir}/[file tail ${source}].brig
exec HSAILasm $source -o ${brig_source}
set source ${brig_source}
# Change the testname the .brig.
set testname_with_flags [file tail $source]
}
return [target_compile $source $dest $type $options]
}

View file

@ -1,3 +1,8 @@
2017-01-24 Pekka Jääskeläinen <pekka@parmance.com>
Martin Jambor <mjambor@suse.cz>
* hsa.h: Moved here from libgomp/plugin/hsa.h.
2017-01-04 Richard Earnshaw <rearnsha@arm.com>
Jiong Wang <jiong.wang@arm.com>

View file

@ -1,3 +1,9 @@
2017-01-24 Pekka Jääskeläinen <pekka@parmance.com>
Martin Jambor <mjambor@suse.cz>
* plugin/hsa.h: Moved to top level include.
* plugin/plugin-hsa.c: Chanfgd include of hsa.h accordingly.
2017-01-21 Jakub Jelinek <jakub@redhat.com>
PR other/79046

View file

@ -34,7 +34,7 @@
#include <pthread.h>
#include <inttypes.h>
#include <stdbool.h>
#include <plugin/hsa.h>
#include <hsa.h>
#include <plugin/hsa_ext_finalize.h>
#include <dlfcn.h>
#include "libgomp-plugin.h"

27
libhsail-rt/ChangeLog Normal file
View file

@ -0,0 +1,27 @@
2017-01-24 Pekka Jääskeläinen <pekka@parmance.com>
Martin Jambor <mjambor@suse.cz>
* Makefile.am: New file.
* target-config.h.in: Likewise.
* configure.ac: Likewise.
* configure: Likewise.
* config.h.in: Likewise.
* aclocal.m4: Likewise.
* README: Likewise.
* Makefile.in: Likewise.
* include/internal/fibers.h: Likewise.
* include/internal/phsa-queue-interface.h: Likewise.
* include/internal/phsa-rt.h: Likewise.
* include/internal/workitems.h: Likewise.
* rt/arithmetic.c: Likewise.
* rt/atomics.c: Likewise.
* rt/bitstring.c: Likewise.
* rt/fbarrier.c: Likewise.
* rt/fibers.c: Likewise.
* rt/fp16.c: Likewise.
* rt/misc.c: Likewise.
* rt/multimedia.c: Likewise.
* rt/queue.c: Likewise.
* rt/sat_arithmetic.c: Likewise.
* rt/segment.c: Likewise.
* rt/workitems.c: Likewise.

124
libhsail-rt/Makefile.am Normal file
View file

@ -0,0 +1,124 @@
# Makefile.am -- libhsail-rt library Makefile.
# Starting point copied from libcilkrts:
# @copyright
# Copyright (C) 2011, 2013, Intel Corporation
# All rights reserved.
#
# @copyright
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# @copyright
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# libhsail-rt modifications:
# Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
# for General Processor Tech.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Process this file with autoreconf to produce Makefile.in.
AUTOMAKE_OPTIONS = foreign subdir-objects
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
MAINT_CHARSET = latin1
mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs
ACLOCAL_AMFLAGS = -I m4
WARN_CFLAGS = $(WARN_FLAGS) $(WERROR)
# -I/-D flags to pass when compiling.
AM_CPPFLAGS = -I$(srcdir)/rt -I$(srcdir)/include/internal
AM_CFLAGS = \
-I $(srcdir)/../include \
-I $(srcdir)/../libgcc \
-I $(MULTIBUILDTOP)../../gcc/include $(PTH_CFLAGS)
toolexeclib_LTLIBRARIES = libhsail-rt.la
runtime_files = \
rt/arithmetic.c \
rt/atomics.c \
rt/bitstring.c \
rt/fbarrier.c \
rt/fp16.c \
rt/misc.c \
rt/multimedia.c \
rt/queue.c \
rt/sat_arithmetic.c \
rt/segment.c \
rt/workitems.c \
rt/fibers.c
libhsail_rt_la_SOURCES = $(runtime_files)
libhsail_rt_la_LDFLAGS = -rpath '$(libdir)'
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
# friends when we are called from the top level Makefile.
AM_MAKEFLAGS = \
"AR_FLAGS=$(AR_FLAGS)" \
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
"CFLAGS=$(CFLAGS)" \
"CXXFLAGS=$(CXXFLAGS)" \
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
"INSTALL=$(INSTALL)" \
"INSTALL_DATA=$(INSTALL_DATA)" \
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
"JC1FLAGS=$(JC1FLAGS)" \
"LDFLAGS=$(LDFLAGS)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
"MAKE=$(MAKE)" \
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
"PICFLAG=$(PICFLAG)" \
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
"SHELL=$(SHELL)" \
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
"exec_prefix=$(exec_prefix)" \
"infodir=$(infodir)" \
"libdir=$(libdir)" \
"prefix=$(prefix)" \
"includedir=$(includedir)" \
"AR=$(AR)" \
"AS=$(AS)" \
"LD=$(LD)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"NM=$(NM)" \
"PICFLAG=$(PICFLAG)" \
"RANLIB=$(RANLIB)" \
"DESTDIR=$(DESTDIR)"
MAKEOVERRIDES=

740
libhsail-rt/Makefile.in Normal file
View file

@ -0,0 +1,740 @@
# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Makefile.am -- libhsail-rt library Makefile.
# Starting point copied from libcilkrts:
# @copyright
# Copyright (C) 2011, 2013, Intel Corporation
# All rights reserved.
#
# @copyright
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# @copyright
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# libhsail-rt modifications:
# Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
# for General Processor Tech.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Process this file with autoreconf to produce Makefile.in.
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
*) \
for am__flg in $$MAKEFLAGS; do \
case $$am__flg in \
*=*|--*) ;; \
*n*) am__dry=yes; break;; \
esac; \
done;; \
esac; \
test $$am__dry = yes; \
}
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = .
DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
$(srcdir)/target-config.h.in $(srcdir)/../mkinstalldirs \
$(srcdir)/../depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/lead-dot.m4 \
$(top_srcdir)/../config/multi.m4 $(top_srcdir)/../libtool.m4 \
$(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
CONFIG_HEADER = target-config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(toolexeclibdir)"
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
libhsail_rt_la_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp
am__objects_1 = rt/arithmetic.lo rt/atomics.lo rt/bitstring.lo \
rt/fbarrier.lo rt/fp16.lo rt/misc.lo rt/multimedia.lo \
rt/queue.lo rt/sat_arithmetic.lo rt/segment.lo rt/workitems.lo \
rt/fibers.lo
am_libhsail_rt_la_OBJECTS = $(am__objects_1)
libhsail_rt_la_OBJECTS = $(am_libhsail_rt_la_OBJECTS)
libhsail_rt_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libhsail_rt_la_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/../depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libhsail_rt_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
ETAGS = etags
CTAGS = ctags
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
config_dir = @config_dir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
toolexecdir = @toolexecdir@
toolexeclibdir = @toolexeclibdir@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign subdir-objects
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
MAINT_CHARSET = latin1
mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs
ACLOCAL_AMFLAGS = -I m4
WARN_CFLAGS = $(WARN_FLAGS) $(WERROR)
# -I/-D flags to pass when compiling.
AM_CPPFLAGS = -I$(srcdir)/rt -I$(srcdir)/include/internal
AM_CFLAGS = \
-I $(srcdir)/../include \
-I $(srcdir)/../libgcc \
-I $(MULTIBUILDTOP)../../gcc/include $(PTH_CFLAGS)
toolexeclib_LTLIBRARIES = libhsail-rt.la
runtime_files = \
rt/arithmetic.c \
rt/atomics.c \
rt/bitstring.c \
rt/fbarrier.c \
rt/fp16.c \
rt/misc.c \
rt/multimedia.c \
rt/queue.c \
rt/sat_arithmetic.c \
rt/segment.c \
rt/workitems.c \
rt/fibers.c
libhsail_rt_la_SOURCES = $(runtime_files)
libhsail_rt_la_LDFLAGS = -rpath '$(libdir)'
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
# friends when we are called from the top level Makefile.
AM_MAKEFLAGS = \
"AR_FLAGS=$(AR_FLAGS)" \
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
"CFLAGS=$(CFLAGS)" \
"CXXFLAGS=$(CXXFLAGS)" \
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
"INSTALL=$(INSTALL)" \
"INSTALL_DATA=$(INSTALL_DATA)" \
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
"JC1FLAGS=$(JC1FLAGS)" \
"LDFLAGS=$(LDFLAGS)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
"MAKE=$(MAKE)" \
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
"PICFLAG=$(PICFLAG)" \
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
"SHELL=$(SHELL)" \
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
"exec_prefix=$(exec_prefix)" \
"infodir=$(infodir)" \
"libdir=$(libdir)" \
"prefix=$(prefix)" \
"includedir=$(includedir)" \
"AR=$(AR)" \
"AS=$(AS)" \
"LD=$(LD)" \
"LIBCFLAGS=$(LIBCFLAGS)" \
"NM=$(NM)" \
"PICFLAG=$(PICFLAG)" \
"RANLIB=$(RANLIB)" \
"DESTDIR=$(DESTDIR)"
MAKEOVERRIDES =
all: target-config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
am--refresh: Makefile
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
target-config.h: stamp-h1
@if test ! -f $@; then rm -f stamp-h1; else :; fi
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
stamp-h1: $(srcdir)/target-config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status target-config.h
$(srcdir)/target-config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
distclean-hdr:
-rm -f target-config.h stamp-h1
install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
list2="$$list2 $$p"; \
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(MKDIR_P) '$(DESTDIR)$(toolexeclibdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \
}
uninstall-toolexeclibLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
for p in $$list; do \
$(am__strip_dir) \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \
done
clean-toolexeclibLTLIBRARIES:
-test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES)
@list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
rt/$(am__dirstamp):
@$(MKDIR_P) rt
@: > rt/$(am__dirstamp)
rt/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) rt/$(DEPDIR)
@: > rt/$(DEPDIR)/$(am__dirstamp)
rt/arithmetic.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/atomics.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/bitstring.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/fbarrier.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/fp16.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/misc.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/multimedia.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/queue.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/sat_arithmetic.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/segment.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/workitems.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
rt/fibers.lo: rt/$(am__dirstamp) rt/$(DEPDIR)/$(am__dirstamp)
libhsail-rt.la: $(libhsail_rt_la_OBJECTS) $(libhsail_rt_la_DEPENDENCIES) $(EXTRA_libhsail_rt_la_DEPENDENCIES)
$(libhsail_rt_la_LINK) -rpath $(toolexeclibdir) $(libhsail_rt_la_OBJECTS) $(libhsail_rt_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f rt/arithmetic.$(OBJEXT)
-rm -f rt/arithmetic.lo
-rm -f rt/atomics.$(OBJEXT)
-rm -f rt/atomics.lo
-rm -f rt/bitstring.$(OBJEXT)
-rm -f rt/bitstring.lo
-rm -f rt/fbarrier.$(OBJEXT)
-rm -f rt/fbarrier.lo
-rm -f rt/fibers.$(OBJEXT)
-rm -f rt/fibers.lo
-rm -f rt/fp16.$(OBJEXT)
-rm -f rt/fp16.lo
-rm -f rt/misc.$(OBJEXT)
-rm -f rt/misc.lo
-rm -f rt/multimedia.$(OBJEXT)
-rm -f rt/multimedia.lo
-rm -f rt/queue.$(OBJEXT)
-rm -f rt/queue.lo
-rm -f rt/sat_arithmetic.$(OBJEXT)
-rm -f rt/sat_arithmetic.lo
-rm -f rt/segment.$(OBJEXT)
-rm -f rt/segment.lo
-rm -f rt/workitems.$(OBJEXT)
-rm -f rt/workitems.lo
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/arithmetic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/atomics.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/bitstring.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/fbarrier.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/fibers.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/fp16.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/misc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/multimedia.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/queue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/sat_arithmetic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/segment.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@rt/$(DEPDIR)/workitems.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-rm -rf rt/.libs rt/_libs
distclean-libtool:
-rm -f libtool config.lt
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) target-config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) target-config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) target-config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) target-config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) target-config.h
installdirs:
for dir in "$(DESTDIR)$(toolexeclibdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f rt/$(DEPDIR)/$(am__dirstamp)
-rm -f rt/$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-toolexeclibLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf rt/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-toolexeclibLTLIBRARIES
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -rf rt/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-toolexeclibLTLIBRARIES
.MAKE: all install-am install-strip
.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
clean-generic clean-libtool clean-toolexeclibLTLIBRARIES ctags \
distclean distclean-compile distclean-generic distclean-hdr \
distclean-libtool distclean-tags dvi dvi-am html html-am info \
info-am install install-am install-data install-data-am \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-info install-info-am \
install-man install-pdf install-pdf-am install-ps \
install-ps-am install-strip install-toolexeclibLTLIBRARIES \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-toolexeclibLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

4
libhsail-rt/README Normal file
View file

@ -0,0 +1,4 @@
Run autoconf2.64 && automake-1.11 to regenerate the buildfiles.
You might need to manually tweak the minor automake version number
in configure.ac and aclocal.m4 (search for 1.11.6) in case your
local 1.11 minor version doesn't match.

978
libhsail-rt/aclocal.m4 vendored Normal file
View file

@ -0,0 +1,978 @@
# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
[m4_warning([this file was generated for autoconf 2.64.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.])])
# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.11'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.11.6], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# _AM_AUTOCONF_VERSION(VERSION)
# -----------------------------
# aclocal traces this macro to find the Autoconf version.
# This is a private macro too. Using m4_define simplifies
# the logic in aclocal, which can simply ignore this definition.
m4_define([_AM_AUTOCONF_VERSION], [])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.11.6])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
# therefore $ac_aux_dir as well) can be either absolute or relative,
# depending on how configure is run. This is pretty annoying, since
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
# source directory, any form will work fine, but in subdirectories a
# relative path needs to be adjusted first.
#
# $ac_aux_dir/missing
# fails when called from a subdirectory if $ac_aux_dir is relative
# $top_srcdir/$ac_aux_dir/missing
# fails if $ac_aux_dir is absolute,
# fails when called from a subdirectory in a VPATH build with
# a relative $ac_aux_dir
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
# harmless because $srcdir is `.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
# and then we would define $MISSING as
# MISSING="\${SHELL} $am_aux_dir/missing"
# This will work as long as MISSING is not called from configure, because
# unfortunately $(top_srcdir) has no meaning in configure.
# However there are other variables, like CC, which are often used in
# configure, and could therefore not use this "fixed" $ac_aux_dir.
#
# Another solution, used here, is to always expand $ac_aux_dir to an
# absolute PATH. The drawback is that using absolute paths prevent a
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
[dnl Rely on autoconf to set up CDPATH properly.
AC_PREREQ([2.50])dnl
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 9
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[AC_PREREQ(2.52)dnl
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
m4_define([_AM_COND_VALUE_$1], [$2])dnl
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi
AC_CONFIG_COMMANDS_PRE(
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
AC_MSG_ERROR([[conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 10
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
# written in clear, in which case automake, when reading aclocal.m4,
# will think it sees a *use*, and therefore will trigger all it's
# C support machinery. Also note that it means that autoscan, seeing
# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
# _AM_DEPENDENCIES(NAME)
# ----------------------
# See how the compiler implements dependency checking.
# NAME is "CC", "CXX", "GCJ", or "OBJC".
# We try a few techniques and use that to set a single cache variable.
#
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
# dependency, and given that the user is not expected to run this macro,
# just rely on AC_PROG_CC.
AC_DEFUN([_AM_DEPENDENCIES],
[AC_REQUIRE([AM_SET_DEPDIR])dnl
AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
AC_REQUIRE([AM_DEP_TRACK])dnl
ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
[$1], CXX, [depcc="$CXX" am_compiler_list=],
[$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
[$1], UPC, [depcc="$UPC" am_compiler_list=],
[$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
[depcc="$$1" am_compiler_list=])
AC_CACHE_CHECK([dependency style of $depcc],
[am_cv_$1_dependencies_compiler_type],
[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
cp "$am_depcomp" conftest.dir
cd conftest.dir
# We will build objects and dependencies in a subdirectory because
# it helps to detect inapplicable dependency modes. For instance
# both Tru64's cc and ICC support -MD to output dependencies as a
# side effect of compilation, but ICC will put the dependencies in
# the current directory while Tru64 will put them in the object
# directory.
mkdir sub
am_cv_$1_dependencies_compiler_type=none
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
fi
am__universal=false
m4_case([$1], [CC],
[case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac],
[CXX],
[case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac])
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
# we should not choose a depcomp mode which is confused by this.
#
# We need to recreate these files for each test, as the compiler may
# overwrite some of them when testing with obscure command lines.
# This happens at least with the AIX C compiler.
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
# Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
# Solaris 8's {/usr,}/bin/sh.
touch sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
# We check with `-c' and `-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
# handle `-M -o', and we need to detect this. Also, some Intel
# versions had trouble with output in subdirs
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
gcc)
# This depmode causes a compiler race in universal mode.
test "$am__universal" = false || continue
;;
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
if test "x$enable_dependency_tracking" = xyes; then
continue
else
break
fi
;;
msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
am__minus_obj=
;;
none) break ;;
esac
if depmode=$depmode \
source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thusly:
# icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported
if (grep 'ignoring option' conftest.err ||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
am_cv_$1_dependencies_compiler_type=$depmode
break
fi
fi
done
cd ..
rm -rf conftest.dir
else
am_cv_$1_dependencies_compiler_type=none
fi
])
AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
AM_CONDITIONAL([am__fastdep$1], [
test "x$enable_dependency_tracking" != xno \
&& test "$am_cv_$1_dependencies_compiler_type" = gcc3])
])
# AM_SET_DEPDIR
# -------------
# Choose a directory name for dependency files.
# This macro is AC_REQUIREd in _AM_DEPENDENCIES
AC_DEFUN([AM_SET_DEPDIR],
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
])
# AM_DEP_TRACK
# ------------
AC_DEFUN([AM_DEP_TRACK],
[AC_ARG_ENABLE(dependency-tracking,
[ --disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors])
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
fi
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
AC_SUBST([AMDEPBACKSLASH])dnl
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
])
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#serial 5
# _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
[{
# Autoconf 2.62 quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
*\'*) eval set x "$CONFIG_FILES" ;;
*) set x $CONFIG_FILES ;;
esac
shift
for mf
do
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named `Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# Grep'ing the whole file is not good either: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
dirpart=`AS_DIRNAME("$mf")`
else
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running `make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# When using ansi2knr, U may be empty or an underscore; expand it
U=`sed -n 's/^U = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`AS_DIRNAME(["$file"])`
AS_MKDIR_P([$dirpart/$fdir])
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
done
}
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
# AM_OUTPUT_DEPENDENCY_COMMANDS
# -----------------------------
# This macro should only be invoked once -- use via AC_REQUIRE.
#
# This code is only required when automatic dependency tracking
# is enabled. FIXME. This creates each `.P' file that we will
# need in order to bootstrap the dependency handling code.
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AC_CONFIG_COMMANDS([depfiles],
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 16
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
# AM_INIT_AUTOMAKE([OPTIONS])
# -----------------------------------------------
# The call with PACKAGE and VERSION arguments is the old style
# call (pre autoconf-2.50), which is being phased out. PACKAGE
# and VERSION should now be passed to AC_INIT and removed from
# the call to AM_INIT_AUTOMAKE.
# We support both call styles for the transition. After
# the next Automake release, Autoconf can make the AC_INIT
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.62])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
AC_REQUIRE([AC_PROG_INSTALL])dnl
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
fi
# test whether we have cygpath
if test -z "$CYGPATH_W"; then
if (cygpath --version) >/dev/null 2>/dev/null; then
CYGPATH_W='cygpath -w'
else
CYGPATH_W=echo
fi
fi
AC_SUBST([CYGPATH_W])
# Define the identity of the package.
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
_AM_IF_OPTION([no-define],,
[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
# Some tools Automake needs.
AC_REQUIRE([AM_SANITY_CHECK])dnl
AC_REQUIRE([AC_ARG_PROGRAM])dnl
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
AM_MISSING_PROG(AUTOCONF, autoconf)
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
AM_MISSING_PROG(AUTOHEADER, autoheader)
AM_MISSING_PROG(MAKEINFO, makeinfo)
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
[_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
[_AM_DEPENDENCIES(CC)],
[define([AC_PROG_CC],
defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES(CXX)],
[define([AC_PROG_CXX],
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES(OBJC)],
[define([AC_PROG_OBJC],
defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
])
_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
])
dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
dnl mangled by Autoconf and run in a shell conditional statement.
m4_define([_AC_COMPILER_EXEEXT],
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp files are numbered to have different names.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[# Compute $1's index in $config_headers.
_am_arg=$1
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
if test x"${install_sh}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
*)
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
AC_SUBST(install_sh)])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 5
# AM_MAINTAINER_MODE([DEFAULT-MODE])
# ----------------------------------
# Control maintainer-specific portions of Makefiles.
# Default is to disable them, unless `enable' is passed literally.
# For symmetry, `disable' may be passed as well. Anyway, the user
# can override the default with the --enable/--disable switch.
AC_DEFUN([AM_MAINTAINER_MODE],
[m4_case(m4_default([$1], [disable]),
[enable], [m4_define([am_maintainer_other], [disable])],
[disable], [m4_define([am_maintainer_other], [enable])],
[m4_define([am_maintainer_other], [enable])
m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
dnl maintainer-mode's default is 'disable' unless 'enable' is passed
AC_ARG_ENABLE([maintainer-mode],
[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful
(and sometimes confusing) to the casual installer],
[USE_MAINTAINER_MODE=$enableval],
[USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
AC_MSG_RESULT([$USE_MAINTAINER_MODE])
AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
MAINT=$MAINTAINER_MODE_TRUE
AC_SUBST([MAINT])dnl
]
)
AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 4
# AM_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
@echo this is the am__doit target
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
AC_MSG_CHECKING([for style of include used by $am_make])
am__include="#"
am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# Ignore all kinds of additional output from `make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
;;
esac
fi
AC_SUBST([am__include])
AC_SUBST([am__quote])
AC_MSG_RESULT([$_am_result])
rm -f confinc confmf
])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 6
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
[AC_REQUIRE([AM_MISSING_HAS_RUN])
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
# AM_MISSING_HAS_RUN
# ------------------
# Define MISSING if not defined so far and test if it supports --run.
# If it does, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
else
am_missing_run=
AC_MSG_WARN([`missing' script is too old or missing])
fi
])
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_MKDIR_P
# ---------------
# Check for `mkdir -p'.
AC_DEFUN([AM_PROG_MKDIR_P],
[AC_PREREQ([2.60])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
dnl while keeping a definition of mkdir_p for backward compatibility.
dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
dnl Makefile.ins that do not define MKDIR_P, so we do our own
dnl adjustment using top_builddir (which is defined more often than
dnl MKDIR_P).
AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
case $mkdir_p in
[[\\/$]]* | ?:[[\\/]]*) ;;
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
esac
])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 4
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
# ------------------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
# _AM_SET_OPTIONS(OPTIONS)
# ----------------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
# -------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 5
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftest.file
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
'
case `pwd` in
*[[\\\"\#\$\&\'\`$am_lf]]*)
AC_MSG_ERROR([unsafe absolute working directory name]);;
esac
case $srcdir in
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
esac
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$[*]" = "X"; then
# -L didn't work.
set X `ls -t "$srcdir/configure" conftest.file`
fi
rm -f conftest.file
if test "$[*]" != "X $srcdir/configure conftest.file" \
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "$[2]" = conftest.file
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
AC_MSG_RESULT(yes)])
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_STRIP
# ---------------------
# One issue with vendor `install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
# is unlikely to handle the host's binaries.
# Fortunately install-sh will honor a STRIPPROG variable, so we
# always use install-sh in `make install-strip', and initialize
# STRIPPROG with the value of the STRIP variable (set by the user).
AC_DEFUN([AM_PROG_INSTALL_STRIP],
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
# Installed binaries are usually stripped using `strip' when the user
# run `make install-strip'. However `strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the `STRIP' environment variable to overrule this program.
dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
if test "$cross_compiling" != no; then
AC_CHECK_TOOL([STRIP], [strip], :)
fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
# FORMAT should be one of `v7', `ustar', or `pax'.
#
# Substitute a variable $(am__tar) that is a command
# writing to stdout a FORMAT-tarball containing the directory
# $tardir.
# tardir=directory && $(am__tar) > result.tar
#
# Substitute a variable $(am__untar) that extract such
# a tarball read from stdin.
# $(am__untar) < result.tar
AC_DEFUN([_AM_PROG_TAR],
[# Always define AMTAR for backward compatibility.
AM_MISSING_PROG([AMTAR], [tar])
m4_if([$1], [v7],
[am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
[m4_case([$1], [ustar],, [pax],,
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
# Do not fold the above two line into one, because Tru64 sh and
# Solaris sh will not grok spaces in the rhs of `-'.
for _am_tool in $_am_tools
do
case $_am_tool in
gnutar)
for _am_tar in tar gnutar gtar;
do
AM_RUN_LOG([$_am_tar --version]) && break
done
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
am__untar="$_am_tar -xf -"
;;
plaintar)
# Must skip GNU tar: if it does not support --format= it doesn't create
# ustar tarball either.
(tar --version) >/dev/null 2>&1 && continue
am__tar='tar chf - "$$tardir"'
am__tar_='tar chf - "$tardir"'
am__untar='tar xf -'
;;
pax)
am__tar='pax -L -x $1 -w "$$tardir"'
am__tar_='pax -L -x $1 -w "$tardir"'
am__untar='pax -r'
;;
cpio)
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
am__untar='cpio -i -H $1 -d'
;;
none)
am__tar=false
am__tar_=false
am__untar=false
;;
esac
# If the value was cached, stop now. We just wanted to have am__tar
# and am__untar set.
test -n "${am_cv_prog_tar_$1}" && break
# tar/untar a dummy directory, and stop if the command works
rm -rf conftest.dir
mkdir conftest.dir
echo GrepMe > conftest.dir/file
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
rm -rf conftest.dir
if test -s conftest.tar; then
AM_RUN_LOG([$am__untar <conftest.tar])
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
fi
done
rm -rf conftest.dir
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([../config/depstand.m4])
m4_include([../config/lead-dot.m4])
m4_include([../config/multi.m4])
m4_include([../libtool.m4])
m4_include([../ltoptions.m4])
m4_include([../ltsugar.m4])
m4_include([../ltversion.m4])
m4_include([../lt~obsolete.m4])

217
libhsail-rt/config.h.in Normal file
View file

@ -0,0 +1,217 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to 1 if you have the `acosl' function. */
#undef HAVE_ACOSL
/* Define to 1 if you have the `asinl' function. */
#undef HAVE_ASINL
/* Define to 1 if you have the `atan2l' function. */
#undef HAVE_ATAN2L
/* Define to 1 if you have the `atanl' function. */
#undef HAVE_ATANL
/* Define to 1 if you have the `cosl' function. */
#undef HAVE_COSL
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `expl' function. */
#undef HAVE_EXPL
/* Define to 1 if you have the `expm1l' function. */
#undef HAVE_EXPM1L
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `ldexpl' function. */
#undef HAVE_LDEXPL
/* Define to 1 if you have the <linux/ether.h> header file. */
#undef HAVE_LINUX_ETHER_H
/* Define to 1 if you have the <linux/fs.h> header file. */
#undef HAVE_LINUX_FS_H
/* Define to 1 if you have the <linux/reboot.h> header file. */
#undef HAVE_LINUX_REBOOT_H
/* Define to 1 if you have the `log10l' function. */
#undef HAVE_LOG10L
/* Define to 1 if you have the `log1pl' function. */
#undef HAVE_LOG1PL
/* Define to 1 if you have the `logl' function. */
#undef HAVE_LOGL
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <netinet/icmp6.h> header file. */
#undef HAVE_NETINET_ICMP6_H
/* Define to 1 if you have the <netinet/if_ether.h> header file. */
#undef HAVE_NETINET_IF_ETHER_H
/* Define to 1 if you have the <netinet/in_syst.h> header file. */
#undef HAVE_NETINET_IN_SYST_H
/* Define to 1 if you have the <netinet/ip.h> header file. */
#undef HAVE_NETINET_IP_H
/* Define to 1 if you have the <netinet/ip_mroute.h> header file. */
#undef HAVE_NETINET_IP_MROUTE_H
/* Define to 1 if you have the <netpacket/packet.h> header file. */
#undef HAVE_NETPACKET_PACKET_H
/* Define to 1 if you have the <net/if_arp.h> header file. */
#undef HAVE_NET_IF_ARP_H
/* Define to 1 if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H
/* Define to 1 if you have the <net/route.h> header file. */
#undef HAVE_NET_ROUTE_H
/* Define to 1 if you have the <sched.h> header file. */
#undef HAVE_SCHED_H
/* Define to 1 if you have the `sinl' function. */
#undef HAVE_SINL
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if the compiler provides the __sync_bool_compare_and_swap
function for uint32 */
#undef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
/* Define to 1 if the compiler provides the __sync_bool_compare_and_swap
function for uint64 */
#undef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_8
/* Define to 1 if you have the <syscall.h> header file. */
#undef HAVE_SYSCALL_H
/* Define to 1 if you have the <sys/epoll.h> header file. */
#undef HAVE_SYS_EPOLL_H
/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
/* Define to 1 if you have the <sys/inotify.h> header file. */
#undef HAVE_SYS_INOTIFY_H
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/mount.h> header file. */
#undef HAVE_SYS_MOUNT_H
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
/* Define to 1 if you have the <sys/ptrace.h> header file. */
#undef HAVE_SYS_PTRACE_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/statfs.h> header file. */
#undef HAVE_SYS_STATFS_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/syscall.h> header file. */
#undef HAVE_SYS_SYSCALL_H
/* Define to 1 if you have the <sys/sysinfo.h> header file. */
#undef HAVE_SYS_SYSINFO_H
/* Define to 1 if you have the <sys/timex.h> header file. */
#undef HAVE_SYS_TIMEX_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/user.h> header file. */
#undef HAVE_SYS_USER_H
/* Define to 1 if you have the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_H
/* Define to 1 if you have the <sys/vfs.h> header file. */
#undef HAVE_SYS_VFS_H
/* Define to 1 if you have the `tanl' function. */
#undef HAVE_TANL
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif

17016
libhsail-rt/configure vendored Normal file

File diff suppressed because it is too large Load diff

151
libhsail-rt/configure.ac Normal file
View file

@ -0,0 +1,151 @@
# Starting point copied from libcilkrts:
#
# @copyright
# Copyright (C) 2011-2013, Intel Corporation
# All rights reserved.
#
# @copyright
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# @copyright
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
AC_INIT([phsa HSAIL runtime library], [1.0], [pekka.jaaskelainen@parmance.com])
AC_CONFIG_MACRO_DIR([m4])
AC_PREREQ([2.64])
# Needed to define ${target}. Needs to be very early to avoid annoying
# warning about calling AC_ARG_PROGRAM before AC_CANONICAL_SYSTEM
AC_CANONICAL_SYSTEM
target_alias=${target_alias-$host_alias}
AC_SUBST(target_alias)
AM_INIT_AUTOMAKE([1.11.6 foreign no-dist])
AM_MAINTAINER_MODE
AC_PROG_CC
AC_PROG_CXX
# AC_PROG_LIBTOOL
AC_CONFIG_FILES([Makefile])
if test "${multilib}" = "yes"; then
multilib_arg="--enable-multilib"
else
multilib_arg=
fi
AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
AC_ARG_ENABLE([version-specific-runtime-libs],
AC_HELP_STRING([--enable-version-specific-runtime-libs],
[Specify that runtime libraries should be installed in a compi
ler-specific directory]),
[case "$enableval" in
yes) enable_version_specific_runtime_libs=yes ;;
no) enable_version_specific_runtime_libs=no ;;
*) AC_MSG_ERROR([Unknown argument to enable/disable version-specific libs
]);;
esac],
[enable_version_specific_runtime_libs=no])
AC_MSG_RESULT($enable_version_specific_runtime_libs)
# Calculate toolexeclibdir
# Also toolexecdir, though it's only used in toolexeclibdir
case ${enable_version_specific_runtime_libs} in
yes)
# Need the gcc compiler version to know where to install libraries
# and header files if --enable-version-specific-runtime-libs option
# is selected.
toolexecdir='$(libdir)/gcc/$(target_alias)'
toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)'
;;
no)
if test -n "$with_cross_host" &&
test x"$with_cross_host" != x"no"; then
# Install a library built with a cross compiler in tooldir, not libdir.
toolexecdir='$(exec_prefix)/$(target_alias)'
toolexeclibdir='$(toolexecdir)/lib'
else
toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
toolexeclibdir='$(libdir)'
fi
multi_os_directory=`$CC -print-multi-os-directory`
case $multi_os_directory in
.) ;; # Avoid trailing /.
*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
esac
;;
esac
# Set config_dir based on the target. config_dir specifies where to get
# target-specific files. The generic implementation is incomplete, but
# contains information on what's needed
case "${target}" in
x86_64-*-*)
config_dir="x86"
;;
i?86-*-*)
config_dir="x86"
;;
*)
config_dir="generic"
;;
esac
AC_SUBST(config_dir)
# We have linker scripts for appropriate operating systems
linux_linker_script=no
case "${host}" in
*-*-linux*)
linux_linker_script=yes
;;
esac
AM_CONDITIONAL(LINUX_LINKER_SCRIPT, test "$linux_linker_script" = "yes")
mac_linker_script=no
case "${host}" in
*-*-apple*)
mac_linker_script=yes
;;
esac
AM_CONDITIONAL(MAC_LINKER_SCRIPT, test "$mac_linker_script" = "yes")
AC_LIBTOOL_DLOPEN
AM_PROG_LIBTOOL
AC_SUBST(toolexecdir)
AC_SUBST(toolexeclibdir)
AC_CONFIG_HEADER(target-config.h)
AC_CHECK_SIZEOF([int])
AC_CHECK_SIZEOF([void*])
# Must be last
AC_OUTPUT

View file

@ -0,0 +1,99 @@
/* fibers.h -- an extremely simple lightweight thread (fiber) implementation
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PHSA_RT_FIBERS_H
#define PHSA_RT_FIBERS_H
#include <ucontext.h>
typedef enum
{
/* Ready to run. */
FIBER_STATUS_READY,
/* Exited by calling fiber_thread_exit. */
FIBER_STATUS_EXITED,
/* Joined by the main thread. */
FIBER_STATUS_JOINED
} fiber_status_t;
/* A light weight thread (fiber). */
struct fiber_s
{
ucontext_t context;
volatile fiber_status_t status;
struct fiber_s *next;
struct fiber_s *prev;
};
typedef struct fiber_s fiber_t;
typedef void (*fiber_function_t)(int, int);
/* Initializes the fiber with the start function given as the first
argument, and the argument to pass to the start function,
as the second. The allocated stack size is given as the last argument. */
void
fiber_init (fiber_t *fiber, fiber_function_t start_function, void *arg,
size_t stack_size, size_t stack_align);
/* Terminates the fiber execution from within the fiber itself. */
void
fiber_exit ();
/* Blocks until the given fiber returns. Frees the resources allocated
for the fiber. After join returns, the fiber itself can be deleted. */
void
fiber_join (fiber_t *fiber);
/* Co-operatively transfer execution turn to other fibers. */
void
fiber_yield ();
/* A multi-entry barrier. After the last fiber has reached the
barrier, it is automatically re-initialized to the threshold. */
typedef struct
{
/* The barrier participant count. */
volatile size_t threshold;
/* Number of fibers that have reached the barrier. */
volatile size_t reached;
/* Number of fibers that are waiting at the barrier. */
volatile size_t waiting_count;
} fiber_barrier_t;
/* Reach the given barrier. Blocks (co-operatively switches the execution
fibers) until all other parties have reached it. Returns 0 only in case
the calling fiber was the first one to return from the barrier. */
size_t
fiber_barrier_reach (fiber_barrier_t *barrier);
/* Initializes the given barrier. */
void
fiber_barrier_init (fiber_barrier_t *barrier, size_t threshold);
void *
fiber_int_args_to_ptr (int arg0, int arg1);
#endif

View file

@ -0,0 +1,60 @@
/* phsa_queue_interface.h -- Definition for a minimalistic generic in-memory
representation of a user mode queue to be used with the phsa/gccbrig
implementation.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PHSA_QUEUE_INTERFACE_H
#define PHSA_QUEUE_INTERFACE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "hsa.h"
typedef __attribute__ ((aligned (64))) struct phsa_queue_s
{
/* An HSA Architectured Queue object. Must be in the beginning
of the struct to enable direct pointer casting between hsa_queue_
and phsa_queue_t. */
hsa_queue_t hsa_queue;
volatile uint64_t write_index;
volatile uint64_t read_index;
/* True if global mem addresses are 64b. */
uint64_t is_ptr64 : 1;
} phsa_queue_t;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,94 @@
/* phsa-rt.h -- Data structures and functions of the PHSA device side runtime
scheduler, and HSAIL built-ins.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PHSA_RT_H
#define PHSA_RT_H
#include <stdbool.h>
#include <stdint.h>
#include "hsa.h"
#define PHSA_MAX_WG_SIZE 1024 * 10
/* Pointer type for the public facing kernel launcher function generated
by gccbrig. This launches the actual kernel for all work groups and
work items in the grid. */
typedef void (*gccbrigKernelLauncherFunc) (void *context, void *);
/* Pointer type for kernel functions produced by gccbrig from the HSAIL.
This is private from outside the device binary and only called by
the launcher. */
typedef void (*gccbrigKernelFunc) (unsigned char *, void *, void *, void *);
/* Context data that is passed to the kernel function, initialized
by the runtime to the current launch information. The data is
used by different id functions etc.
The struct is used by both the launcher and the targeted device,
thus the fields must have the same alignment/padding in both sides.
*/
typedef struct
{
/* Data set by the HSA Runtime's kernel launcher. */
hsa_kernel_dispatch_packet_t *dp;
size_t packet_id;
/* Data set by the device-side launcher. */
gccbrigKernelFunc kernel;
/* The range of a work groups this dispatch should execute. */
size_t wg_min_x;
size_t wg_min_y;
size_t wg_min_z;
size_t wg_max_x;
size_t wg_max_y;
size_t wg_max_z;
/* The barrier used to synch the work-items before executing a new WG. */
void *wg_start_barrier;
/* The barrier to wait at after executing a work-group. */
void *wg_completion_barrier;
/* The barrier used to synchronize WIs in case of the 'barrier' HSAIL
instruction. */
void *wg_sync_barrier;
/* This should be set to the flat address of the beginning of the group
segment. */
size_t group_segment_start_addr;
/* This must be set to the correct aligned flat address space location from
where the kernel can actually read its arguments. Might point to the
original global kernarg space. */
void *kernarg_addr;
} PHSAKernelLaunchData;
#endif

View file

@ -0,0 +1,107 @@
/* workitems.h -- Types for context data passed as hidden parameters to special
built-ins.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PHSA_RT_WORKITEMS_H
#define PHSA_RT_WORKITEMS_H
/* As the simple fibers implementation relies only on ucontext, we can
assume is found by default as it is part of glibc. However, for partial
HSAIL support on platforms without having it available, the following define
can be undefined. */
#define HAVE_FIBERS
#ifdef HAVE_FIBERS
#include "fibers.h"
#endif
#include <stdint.h>
#include "phsa-rt.h"
/* Data identifying a single work-group instance. */
typedef struct
{
/* The group id of the currently executed WG. */
size_t x;
size_t y;
size_t z;
/* This is 1 in case there are more work groups to execute.
If 0, the work-item threads should finish themselves. */
int more_wgs;
/* If the local size does not evenly divide the grid size, will have
leftover WIs in the last execution. */
int leftover_wg;
int last_wg;
/* (Flat) pointer to the beginning of the group segment allocated
to the work-group. */
void *group_base_ptr;
/* Similarly to the private segment that gets space allocated for all
WIs in the work-group. */
void *private_base_ptr;
uint32_t private_segment_total_size;
/* The first flat address of the group segment allocated for
the given work group. */
uint64_t group_segment_base_addr;
/* Offset from the beginning of the private segment to the start of
the previously allocated chunk of dynamic work-item memory (alloca)
by any WI in the WG.
Initially set to private_segment_total_size to denote no dynamic
allocations have been made. The dynamic allocations are done downwards
from the private segment end. */
uint32_t alloca_stack_p;
/* The position of the first word in the current function's alloca
stack frame. Initialized to point outside the private segment. */
uint32_t alloca_frame_p;
} PHSAWorkGroup;
/* Data identifying a single work-item, passed to the work-item thread in case
of a fiber based work-group execution. */
typedef struct
{
PHSAKernelLaunchData *launch_data;
/* Identifies and keeps book of the currently executed WG of the WI swarm. */
volatile PHSAWorkGroup *wg;
/* The local id of the current WI. */
size_t x;
size_t y;
size_t z;
#ifdef HAVE_FIBERS
fiber_t fiber;
#endif
} PHSAWorkItem;
#endif

475
libhsail-rt/rt/arithmetic.c Normal file
View file

@ -0,0 +1,475 @@
/* arithmetic.c -- Builtins for HSAIL arithmetic instructions for which
there is no feasible direct gcc GENERIC expression.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <math.h>
#include <float.h>
/* HSAIL defines INT_MIN % -1 to be 0 while with C it's undefined,
and causes an overflow exception at least with gcc and C on IA-32. */
int32_t
__hsail_rem_s32 (int32_t dividend, int32_t divisor)
{
if (dividend == INT_MIN && divisor == -1)
return 0;
else
return dividend % divisor;
}
int64_t
__hsail_rem_s64 (int64_t dividend, int64_t divisor)
{
if (dividend == INT64_MIN && divisor == -1)
return 0;
else
return dividend % divisor;
}
/* HSAIL has defined behavior for min and max when one of the operands is
NaN: in that case the other operand is returned. In C and with gcc's
MIN_EXPR/MAX_EXPR, the returned operand is undefined. */
float
__hsail_min_f32 (float a, float b)
{
if (isnan (a))
return b;
else if (isnan (b))
return a;
else if (a == 0.0f && b == 0.0f)
return signbit (a) ? a : b;
else if (a > b)
return b;
else
return a;
}
double
__hsail_min_f64 (double a, double b)
{
if (isnan (a))
return b;
else if (isnan (b))
return a;
else if (a > b)
return b;
else
return a;
}
float
__hsail_max_f32 (float a, float b)
{
if (isnan (a))
return b;
else if (isnan (b))
return a;
else if (a == 0.0f && b == 0.0f && signbit (a))
return b;
else if (a < b)
return b;
else
return a;
}
double
__hsail_max_f64 (double a, double b)
{
if (isnan (a))
return b;
else if (isnan (b))
return a;
else if (a == 0.0 && b == 0.0 && signbit (a))
return b;
else if (a < b)
return b;
else
return a;
}
uint8_t
__hsail_cvt_zeroi_sat_u8_f32 (float a)
{
if (isnan (a))
return 0;
if (a >= (float) UINT8_MAX)
return UINT8_MAX;
else if (a <= 0.0f)
return 0;
return (uint8_t) a;
}
int8_t
__hsail_cvt_zeroi_sat_s8_f32 (float a)
{
if (isnan (a))
return 0;
if (a >= (float) INT8_MAX)
return INT8_MAX;
if (a <= (float) INT8_MIN)
return INT8_MIN;
return (int8_t) a;
}
uint16_t
__hsail_cvt_zeroi_sat_u16_f32 (float a)
{
if (isnan (a))
return 0;
if (a >= (float) UINT16_MAX)
return UINT16_MAX;
else if (a <= 0.0f)
return 0;
return (uint16_t) a;
}
int16_t
__hsail_cvt_zeroi_sat_s16_f32 (float a)
{
if (isnan (a))
return 0;
if (a >= (float) INT16_MAX)
return INT16_MAX;
if (a <= (float) INT16_MIN)
return INT16_MIN;
return (int16_t) a;
}
uint32_t
__hsail_cvt_zeroi_sat_u32_f32 (float a)
{
if (isnan (a))
return 0;
if (a >= (float) UINT32_MAX)
return UINT32_MAX;
else if (a <= 0.0f)
return 0;
return (uint32_t) a;
}
int32_t
__hsail_cvt_zeroi_sat_s32_f32 (float a)
{
if (isnan (a))
return 0;
if (a >= (float) INT32_MAX)
return INT32_MAX;
if (a <= (float) INT32_MIN)
return INT32_MIN;
return (int32_t) a;
}
uint64_t
__hsail_cvt_zeroi_sat_u64_f32 (float a)
{
if (isnan (a))
return 0;
if (a >= (float) UINT64_MAX)
return UINT64_MAX;
else if (a <= 0.0f)
return 0;
return (uint64_t) a;
}
int64_t
__hsail_cvt_zeroi_sat_s64_f32 (float a)
{
if (isnan (a))
return 0;
if (a >= (float) INT64_MAX)
return INT64_MAX;
if (a <= (float) INT64_MIN)
return INT64_MIN;
return (int64_t) a;
}
uint8_t
__hsail_cvt_zeroi_sat_u8_f64 (double a)
{
if (isnan (a))
return 0;
if (a >= (double) UINT8_MAX)
return UINT8_MAX;
else if (a <= 0.0f)
return 0;
return (uint8_t) a;
}
int8_t
__hsail_cvt_zeroi_sat_s8_f64 (double a)
{
if (isnan (a))
return 0;
if (a >= (double) INT8_MAX)
return INT8_MAX;
if (a <= (double) INT8_MIN)
return INT8_MIN;
return (int8_t) a;
}
uint16_t
__hsail_cvt_zeroi_sat_u16_f64 (double a)
{
if (isnan (a))
return 0;
if (a >= (double) UINT16_MAX)
return UINT16_MAX;
else if (a <= 0.0f)
return 0;
return (uint16_t) a;
}
int16_t
__hsail_cvt_zeroi_sat_s16_f64 (double a)
{
if (isnan (a))
return 0;
if (a >= (double) INT16_MAX)
return INT16_MAX;
if (a <= (double) INT16_MIN)
return INT16_MIN;
return (int16_t) a;
}
uint32_t
__hsail_cvt_zeroi_sat_u32_f64 (double a)
{
if (isnan (a))
return 0;
if (a >= (double) UINT32_MAX)
return UINT32_MAX;
else if (a <= 0.0f)
return 0;
return (uint32_t) a;
}
int32_t
__hsail_cvt_zeroi_sat_s32_f64 (double a)
{
if (isnan (a))
return 0;
if (a >= (double) INT32_MAX)
return INT32_MAX;
if (a <= (double) INT32_MIN)
return INT32_MIN;
return (int32_t) a;
}
uint64_t
__hsail_cvt_zeroi_sat_u64_f64 (double a)
{
if (isnan (a))
return 0;
if (a >= (double) UINT64_MAX)
return UINT64_MAX;
else if (a <= 0.0f)
return 0;
return (uint64_t) a;
}
int64_t
__hsail_cvt_zeroi_sat_s64_f64 (double a)
{
if (isnan (a))
return 0;
if (a >= (double) INT64_MAX)
return INT64_MAX;
if (a <= (double) INT64_MIN)
return INT64_MIN;
return (int64_t) a;
}
/* Flush the operand to zero in case it's a denormalized number.
Do not cause any exceptions in case of NaNs. */
float
__hsail_ftz_f32 (float a)
{
if (isnan (a) || isinf (a) || a == 0.0f)
return a;
if (a < 0.0f)
{
if (-a < FLT_MIN)
return -0.0f;
}
else
{
if (a < FLT_MIN)
return 0.0f;
}
return a;
}
#define F16_MIN (6.10e-5)
/* Flush the single precision operand to zero in case it's considered
a denormalized number in case it was a f16. Do not cause any exceptions
in case of NaNs. */
float
__hsail_ftz_f32_f16 (float a)
{
if (isnan (a) || isinf (a) || a == 0.0f)
return a;
if (a < 0.0f)
{
if (-a < F16_MIN)
return -0.0f;
}
else
{
if (a < F16_MIN)
return 0.0f;
}
return a;
}
double
__hsail_ftz_f64 (double a)
{
if (isnan (a) || isinf (a) || a == 0.0d)
return a;
if (a < 0.0d)
{
if (-a < DBL_MIN)
return -0.0d;
}
else
{
if (a < DBL_MIN)
return 0.0d;
}
return a;
}
uint32_t
__hsail_borrow_u32 (uint32_t a, uint32_t b)
{
uint64_t c = (uint64_t) a - (uint64_t) b;
if (c > UINT32_MAX)
return 1;
else
return 0;
}
uint64_t
__hsail_borrow_u64 (uint64_t a, uint64_t b)
{
__uint128_t c = (__uint128_t) a - (__uint128_t) b;
if (c > UINT64_MAX)
return 1;
else
return 0;
}
uint32_t
__hsail_carry_u32 (uint32_t a, uint32_t b)
{
uint64_t c = (uint64_t) a + (uint64_t) b;
if (c > UINT32_MAX)
return 1;
else
return 0;
}
uint64_t
__hsail_carry_u64 (uint64_t a, uint64_t b)
{
__uint128_t c = (__uint128_t) a + (__uint128_t) b;
if (c > UINT64_MAX)
return 1;
else
return 0;
}
float
__hsail_fract_f32 (float a)
{
int exp;
if (isinf (a))
return signbit (a) == 0 ? 0.0f : -0.0f;
if (isnan (a) || a == 0.0f)
return a;
else
return fminf (a - floorf (a), 0x1.fffffep-1f);
}
double
__hsail_fract_f64 (double a)
{
int exp;
if (isinf (a))
return 0.0f * isinf (a);
if (isnan (a) || a == 0.0f)
return a;
else
return fmin (a - floor (a), 0x1.fffffffffffffp-1d);
}
uint32_t
__hsail_class_f32 (float a, uint32_t flags)
{
return (flags & 0x0001 && isnan (a) && !(*(uint32_t *) &a & 0x40000000))
|| (flags & 0x0002 && isnan (a) && (*(uint32_t *) &a & 0x40000000))
|| (flags & 0x0004 && isinf (a) && a < 0.0f)
|| (flags & 0x0008 && isnormal (a) && signbit (a))
|| (flags & 0x0010 && a < 0.0f && a > -FLT_MIN)
|| (flags & 0x0020 && a == 0.0f && signbit (a))
|| (flags & 0x0040 && a == 0.0f && !signbit (a))
|| (flags & 0x0080 && a > 0.0f && a < FLT_MIN)
|| (flags & 0x0100 && isnormal (a) && !signbit (a))
|| (flags & 0x0200 && isinf (a) && a >= 0.0f);
}
/* 'class' for a f32-converted f16 which should otherwise be treated like f32
except for its limits. */
uint32_t
__hsail_class_f32_f16 (float a, uint32_t flags)
{
return (flags & 0x0001 && isnan (a) && !(*(uint32_t *) &a & 0x40000000))
|| (flags & 0x0002 && isnan (a) && (*(uint32_t *) &a & 0x40000000))
|| (flags & 0x0004 && isinf (a) && a < 0.0f)
|| (flags & 0x0008 && a != 0.0f && !isinf (a) && !isnan (a)
&& a <= -F16_MIN)
|| (flags & 0x0010 && a != 0.0f && !isinf (a) && !isnan (a) && a < 0.0f
&& a > -F16_MIN)
|| (flags & 0x0020 && a == 0.0f && signbit (a))
|| (flags & 0x0040 && a == 0.0f && !signbit (a))
|| (flags & 0x0080 && a != 0.0f && !isinf (a) && !isnan (a) && a > 0.0f
&& a < F16_MIN)
|| (flags & 0x0100 && a != 0.0f && !isinf (a) && !isnan (a)
&& a >= F16_MIN)
|| (flags & 0x0200 && isinf (a) && a >= 0.0f);
}

115
libhsail-rt/rt/atomics.c Normal file
View file

@ -0,0 +1,115 @@
/* atomic.c -- Builtins for HSAIL atomic instructions for which
there is no feasible direct gcc GENERIC expression.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdint.h>
#include <stdio.h>
#define DO_ATOMICALLY(T, OPERATION) \
int done = 0; \
T old_value; \
T new_value; \
while (!done) \
{ \
old_value = *ptr; \
new_value = OPERATION; \
done = __sync_bool_compare_and_swap (ptr, old_value, new_value); \
} \
return old_value
int32_t
__hsail_atomic_min_s32 (int32_t *ptr, int32_t a)
{
DO_ATOMICALLY (int32_t, (old_value < a) ? old_value : a);
}
int64_t
__hsail_atomic_min_s64 (int64_t *ptr, int64_t a)
{
DO_ATOMICALLY (int64_t, (old_value < a) ? old_value : a);
}
uint32_t
__hsail_atomic_min_u32 (uint32_t *ptr, uint32_t a)
{
DO_ATOMICALLY (uint32_t, (old_value < a) ? old_value : a);
}
uint64_t
__hsail_atomic_min_u64 (uint64_t *ptr, uint64_t a)
{
DO_ATOMICALLY (uint64_t, (old_value < a) ? old_value : a);
}
uint32_t
__hsail_atomic_max_u32 (uint32_t *ptr, uint32_t a)
{
DO_ATOMICALLY (uint32_t, (old_value > a) ? old_value : a);
}
int32_t
__hsail_atomic_max_s32 (int32_t *ptr, int32_t a)
{
DO_ATOMICALLY (int32_t, (old_value > a) ? old_value : a);
}
uint64_t
__hsail_atomic_max_u64 (uint64_t *ptr, uint64_t a)
{
DO_ATOMICALLY (uint64_t, (old_value > a) ? old_value : a);
}
int64_t
__hsail_atomic_max_s64 (int64_t *ptr, int64_t a)
{
DO_ATOMICALLY (int64_t, (old_value > a) ? old_value : a);
}
uint32_t
__hsail_atomic_wrapinc_u32 (uint32_t *ptr, uint32_t a)
{
DO_ATOMICALLY (uint32_t, (old_value >= a) ? 0 : (old_value + 1));
}
uint64_t
__hsail_atomic_wrapinc_u64 (uint64_t *ptr, uint64_t a)
{
DO_ATOMICALLY (uint64_t, (old_value >= a) ? 0 : (old_value + 1));
}
uint32_t
__hsail_atomic_wrapdec_u32 (uint32_t *ptr, uint32_t a)
{
DO_ATOMICALLY (uint32_t,
((old_value == 0) || (old_value > a)) ? a : (old_value - 1));
}
uint64_t
__hsail_atomic_wrapdec_u64 (uint64_t *ptr, uint64_t a)
{
DO_ATOMICALLY (uint64_t,
((old_value == 0) || (old_value > a)) ? a : (old_value - 1));
}

190
libhsail-rt/rt/bitstring.c Normal file
View file

@ -0,0 +1,190 @@
/* bitstring.c -- Builtins for HSAIL bitstring instructions.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdint.h>
#include <limits.h>
#define BITEXTRACT(DEST_TYPE, SRC0, SRC1, SRC2) \
uint32_t offset = SRC1 & (sizeof (DEST_TYPE) * 8 - 1); \
uint32_t width = SRC2 & (sizeof (DEST_TYPE) * 8 - 1); \
if (width == 0) \
return 0; \
else \
return (SRC0 << (sizeof (DEST_TYPE) * 8 - width - offset)) \
>> (sizeof (DEST_TYPE) * 8 - width)
uint32_t
__hsail_bitextract_u32 (uint32_t src0, uint32_t src1, uint32_t src2)
{
BITEXTRACT (uint32_t, src0, src1, src2);
}
int32_t
__hsail_bitextract_s32 (int32_t src0, uint32_t src1, uint32_t src2)
{
BITEXTRACT (int32_t, src0, src1, src2);
}
uint64_t
__hsail_bitextract_u64 (uint64_t src0, uint32_t src1, uint32_t src2)
{
BITEXTRACT (uint64_t, src0, src1, src2);
}
int64_t
__hsail_bitextract_s64 (int64_t src0, uint32_t src1, uint32_t src2)
{
BITEXTRACT (int64_t, src0, src1, src2);
}
#define BITINSERT(DEST_TYPE, SRC0, SRC1, SRC2, SRC3) \
uint32_t offset = SRC2 & (sizeof (DEST_TYPE) * 8 - 1); \
uint32_t width = SRC3 & (sizeof (DEST_TYPE) * 8 - 1); \
DEST_TYPE mask = ((DEST_TYPE) 1 << width) - 1; \
return (SRC0 & ~(mask << offset)) | ((SRC1 & mask) << offset)
uint32_t
__hsail_bitinsert_u32 (uint32_t src0, uint32_t src1, uint32_t src2,
uint32_t src3)
{
BITINSERT (uint32_t, src0, src1, src2, src3);
}
int64_t
__hsail_bitinsert_u64 (uint64_t src0, uint64_t src1, uint32_t src2,
uint32_t src3)
{
BITINSERT (uint64_t, src0, src1, src2, src3);
}
#define BITMASK(DEST_TYPE, SRC0, SRC1) \
uint32_t offset = SRC0 & (sizeof (DEST_TYPE) * 8 - 1); \
uint32_t width = SRC1 & (sizeof (DEST_TYPE) * 8 - 1); \
DEST_TYPE mask = ((DEST_TYPE) 1 << width) - 1; \
return mask << offset
uint32_t
__hsail_bitmask_u32 (uint32_t src0, uint32_t src1)
{
BITMASK (uint32_t, src0, src1);
}
uint64_t
__hsail_bitmask_u64 (uint32_t src0, uint32_t src1)
{
BITMASK (uint64_t, src0, src1);
}
/* The dummy, but readable version from
http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious
This (also) often maps to a single instruction in DSPs. */
#define BITREV(DEST_TYPE, SRC) \
DEST_TYPE v = SRC; \
DEST_TYPE r = v; \
int s = sizeof (SRC) * CHAR_BIT - 1; \
\
for (v >>= 1; v; v >>= 1) \
{ \
r <<= 1; \
r |= v & 1; \
s--; \
} \
return r << s
uint32_t
__hsail_bitrev_u32 (uint32_t src0)
{
BITREV (uint32_t, src0);
}
uint64_t
__hsail_bitrev_u64 (uint64_t src0)
{
BITREV (uint64_t, src0);
}
uint32_t
__hsail_bitselect_u32 (uint32_t src0, uint32_t src1, uint32_t src2)
{
return (src1 & src0) | (src2 & ~src0);
}
uint64_t
__hsail_bitselect_u64 (uint64_t src0, uint64_t src1, uint64_t src2)
{
return (src1 & src0) | (src2 & ~src0);
}
/* Due to the defined behavior with 0, we cannot use the gcc builtin
__builtin_clz* () directly. __builtin_ffs () has defined behavior, but
returns 0 while HSAIL requires to return -1. */
uint32_t
__hsail_firstbit_u32 (uint32_t src0)
{
if (src0 == 0)
return -1;
return __builtin_clz (src0);
}
uint32_t
__hsail_firstbit_s32 (int32_t src0)
{
uint32_t converted = src0 >= 0 ? src0 : ~src0;
return __hsail_firstbit_u32 (converted);
}
uint32_t
__hsail_firstbit_u64 (uint64_t src0)
{
if (src0 == 0)
return -1;
return __builtin_clzl (src0);
}
uint32_t
__hsail_firstbit_s64 (int64_t src0)
{
uint64_t converted = src0 >= 0 ? src0 : ~src0;
return __hsail_firstbit_u64 (converted);
}
uint32_t
__hsail_lastbit_u32 (uint32_t src0)
{
if (src0 == 0)
return -1;
return __builtin_ctz (src0);
}
uint32_t
__hsail_lastbit_u64 (uint64_t src0)
{
if (src0 == 0)
return -1;
return __builtin_ctzl (src0);
}

87
libhsail-rt/rt/fbarrier.c Normal file
View file

@ -0,0 +1,87 @@
/* fbarrier.c -- HSAIL fbarrier built-ins.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <signal.h>
#include "workitems.h"
#include "phsa-rt.h"
#ifdef HAVE_FIBERS
#include "fibers.h"
typedef fiber_barrier_t fbarrier;
void
__hsail_initfbar (uint32_t addr, PHSAWorkItem *wi)
{
fbarrier *fbar = (fbarrier *) (wi->wg->group_base_ptr + addr);
fbar->threshold = 0;
fbar->reached = 0;
fbar->waiting_count = 0;
}
void
__hsail_releasefbar (uint32_t addr, PHSAWorkItem *wi)
{
fbarrier *fbar = (fbarrier *) (wi->wg->group_base_ptr + addr);
fbar->threshold = 0;
fbar->reached = 0;
fbar->waiting_count = 0;
}
void
__hsail_joinfbar (uint32_t addr, PHSAWorkItem *wi)
{
fbarrier *fbar = (fbarrier *) (wi->wg->group_base_ptr + addr);
++fbar->threshold;
}
void
__hsail_leavefbar (uint32_t addr, PHSAWorkItem *wi)
{
fbarrier *fbar = (fbarrier *) (wi->wg->group_base_ptr + addr);
--fbar->threshold;
}
void
__hsail_waitfbar (uint32_t addr, PHSAWorkItem *wi)
{
fbarrier *fbar = (fbarrier *) (wi->wg->group_base_ptr + addr);
fiber_barrier_reach (fbar);
}
void
__hsail_arrivefbar (uint32_t addr, PHSAWorkItem *wi)
{
fbarrier *fbar = (fbarrier *) (wi->wg->group_base_ptr + addr);
++fbar->reached;
if (fbar->reached == fbar->threshold)
fbar->reached = 0;
}
#endif

220
libhsail-rt/rt/fibers.c Normal file
View file

@ -0,0 +1,220 @@
/* fibers.c -- extremely simple lightweight thread (fiber) implementation
Copyright (C) 2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "target-config.h"
#include "fibers.h"
void
phsa_fatal_error (int code);
ucontext_t main_context;
/* The last fiber in the linked list. */
static fiber_t *tail_fiber = NULL;
/* The first fiber in the linked list. */
static fiber_t *head_fiber = NULL;
/* The fiber currently being executed. */
static fiber_t *current_fiber = NULL;
/* Makecontext accepts only integer arguments. We need to split the
pointer argument in case pointer does not fit into int. This helper
function can be used to restore the pointer from the arguments. */
void *
fiber_int_args_to_ptr (int arg0, int arg1)
{
void *ptr = NULL;
#if SIZEOF_VOIDP == 8 && SIZEOF_INT == 4
ptr = (void*)(((uint64_t) arg0 & (uint64_t) 0xFFFFFFFF)
| ((uint64_t) arg1 << 32));
#elif SIZEOF_VOIDP == 4 && SIZEOF_INT == 4
ptr = (void*)arg0;
#else
# error Unsupported pointer/int size.
#endif
return ptr;
}
void
fiber_init (fiber_t *fiber, fiber_function_t start_function, void *arg,
size_t stack_size, size_t stack_align)
{
int arg0, arg1;
if (getcontext (&fiber->context) != 0)
phsa_fatal_error (3);
if (posix_memalign (&fiber->context.uc_stack.ss_sp, stack_align, stack_size)
!= 0)
phsa_fatal_error (4);
fiber->context.uc_stack.ss_size = stack_size;
fiber->context.uc_link = &main_context;
/* makecontext () accepts only integer arguments. Split the
pointer argument to two args in the case pointer does not fit
into one int. */
#if SIZEOF_VOIDP == 8 && SIZEOF_INT == 4
arg0 = (int32_t) 0xFFFFFFFF & (uint64_t)arg;
arg1 = (int32_t) 0xFFFFFFFF & ((uint64_t)arg >> 32);
#elif SIZEOF_VOIDP == 4 && SIZEOF_INT == 4
arg0 = (int)arg;
arg1 = 0;
#else
# error Unsupported pointer/int size.
#endif
makecontext (&fiber->context, (void*)start_function, 2, arg0, arg1);
fiber->status = FIBER_STATUS_READY;
fiber->next = NULL;
fiber->prev = NULL;
/* Create a linked list of the created fibers. Append the new one at
the end. */
if (tail_fiber == NULL)
tail_fiber = fiber;
else
{
tail_fiber->next = fiber;
fiber->prev = tail_fiber;
tail_fiber = fiber;
}
if (head_fiber == NULL)
head_fiber = fiber;
}
void
fiber_exit ()
{
fiber_status_t old_status = current_fiber->status;
current_fiber->status = FIBER_STATUS_EXITED;
if (old_status == FIBER_STATUS_JOINED)
/* In case this thread has been joined, return back to the joiner. */
swapcontext (&current_fiber->context, &main_context);
else
/* In case the thread exited while being yielded from another thread,
switch back to another fiber. */
fiber_yield ();
}
void
fiber_join (fiber_t *fiber)
{
fiber_t *next_ready_fiber = NULL;
current_fiber = fiber;
if (fiber->status != FIBER_STATUS_EXITED)
{
fiber->status = FIBER_STATUS_JOINED;
while (fiber->status != FIBER_STATUS_EXITED)
swapcontext (&main_context, &fiber->context);
}
/* Remove the successfully joined fiber from the linked list so we won't
access it later (the fiber itself might be freed after the join). */
if (fiber->prev != NULL)
fiber->prev->next = fiber->next;
if (fiber->next != NULL)
fiber->next->prev = fiber->prev;
if (head_fiber == fiber)
head_fiber = fiber->next;
if (tail_fiber == fiber)
tail_fiber = fiber->prev;
free (fiber->context.uc_stack.ss_sp);
}
void
fiber_yield ()
{
fiber_t *next_ready_fiber = current_fiber;
if (current_fiber == head_fiber
&& current_fiber == tail_fiber)
{
/* If the last fiber exits independently, there is no
fiber to switch to. Switch to the main context in that
case. */
if (current_fiber->status == FIBER_STATUS_EXITED)
swapcontext (&current_fiber->context, &main_context);
}
do {
next_ready_fiber = next_ready_fiber->next != NULL
? next_ready_fiber->next : head_fiber;
} while (next_ready_fiber != current_fiber
&& next_ready_fiber->status == FIBER_STATUS_EXITED);
fiber_t *old_current_fiber = current_fiber;
current_fiber = next_ready_fiber;
swapcontext (&old_current_fiber->context, &next_ready_fiber->context);
}
size_t
fiber_barrier_reach (fiber_barrier_t *barrier)
{
/* Yield once to ensure that there are no fibers waiting for
a previous triggering of the barrier in the waiting_count
loop. This should release them before we update the reached
counter again. */
fiber_yield ();
barrier->reached++;
++barrier->waiting_count;
while (barrier->reached < barrier->threshold)
fiber_yield ();
--barrier->waiting_count;
/* Wait until all the fibers have reached this point. */
while (barrier->waiting_count > 0)
fiber_yield ();
/* Now all fibers have been released from the barrier waiting
loop. We can now safely reset the reach count for new triggering. */
if (barrier->reached > 0)
{
barrier->reached = 0;
return 0;
}
return 1;
}
void
fiber_barrier_init (fiber_barrier_t *barrier, size_t threshold)
{
barrier->threshold = threshold;
barrier->waiting_count = 0;
barrier->reached = 0;
}

135
libhsail-rt/rt/fp16.c Normal file
View file

@ -0,0 +1,135 @@
/* Half-float conversion routines. Code mostly borrowed from the ARM's
builtin function.
Copyright (C) 2008-2015 Free Software Foundation, Inc.
Contributed by CodeSourcery.
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
static inline unsigned short
__gnu_f2h_internal (unsigned int a, int ieee)
{
unsigned short sign = (a >> 16) & 0x8000;
int aexp = (a >> 23) & 0xff;
unsigned int mantissa = a & 0x007fffff;
unsigned int mask;
unsigned int increment;
if (aexp == 0xff)
{
if (!ieee)
return sign;
if (mantissa == 0)
return sign | 0x7c00; /* Infinity. */
/* Remaining cases are NaNs. Convert SNaN to QNaN. */
return sign | 0x7e00 | (mantissa >> 13);
}
if (aexp == 0 && mantissa == 0)
return sign;
aexp -= 127;
/* Decimal point between bits 22 and 23. */
mantissa |= 0x00800000;
if (aexp < -14)
{
mask = 0x00ffffff;
if (aexp >= -25)
mask >>= 25 + aexp;
}
else
mask = 0x00001fff;
/* Round. */
if (mantissa & mask)
{
increment = (mask + 1) >> 1;
if ((mantissa & mask) == increment)
increment = mantissa & (increment << 1);
mantissa += increment;
if (mantissa >= 0x01000000)
{
mantissa >>= 1;
aexp++;
}
}
if (ieee)
{
if (aexp > 15)
return sign | 0x7c00;
}
else
{
if (aexp > 16)
return sign | 0x7fff;
}
if (aexp < -24)
return sign;
if (aexp < -14)
{
mantissa >>= -14 - aexp;
aexp = -14;
}
/* We leave the leading 1 in the mantissa, and subtract one
from the exponent bias to compensate. */
return sign | (((aexp + 14) << 10) + (mantissa >> 13));
}
static unsigned int
__gnu_h2f_internal (unsigned short a, int ieee)
{
unsigned int sign = (unsigned int) (a & 0x8000) << 16;
int aexp = (a >> 10) & 0x1f;
unsigned int mantissa = a & 0x3ff;
if (aexp == 0x1f && ieee)
return sign | 0x7f800000 | (mantissa << 13);
if (aexp == 0)
{
int shift;
if (mantissa == 0)
return sign;
shift = __builtin_clz (mantissa) - 21;
mantissa <<= shift;
aexp = -shift;
}
return sign | (((aexp + 0x70) << 23) + (mantissa << 13));
}
unsigned short
__hsail_f32_to_f16 (unsigned int a)
{
return __gnu_f2h_internal (a, 1);
}
unsigned int
__hsail_f16_to_f32 (unsigned short a)
{
return __gnu_h2f_internal (a, 1);
}

89
libhsail-rt/rt/misc.c Normal file
View file

@ -0,0 +1,89 @@
/* misc.c -- Builtins for HSAIL misc instructions.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdint.h>
#include <time.h>
#include "workitems.h"
/* Return the monotonic clock as nanoseconds. */
uint64_t
__hsail_clock ()
{
struct timespec t;
clock_gettime (CLOCK_MONOTONIC, &t);
return (uint64_t) t.tv_sec * 1000000000 + (uint64_t) t.tv_nsec;
}
uint32_t
__hsail_cuid (PHSAWorkItem *wi)
{
/* All WIs are executed with a single compute unit (core/thread)
for now. */
return 0;
}
uint32_t
__hsail_maxcuid (PHSAWorkItem *wi)
{
/* All WIs are executed with a single compute unit (core/thread)
for now. */
return 0;
}
void
__hsail_debugtrap (uint32_t src, PHSAWorkItem *wi)
{
/* Could we produce a SIGTRAP signal here to drop to gdb
console, or similar? In any case, the execution of the
kernel should halt.
*/
return;
}
uint32_t
__hsail_groupbaseptr (PHSAWorkItem *wi)
{
return (uint32_t) (uint64_t) (wi->wg->group_base_ptr
- wi->launch_data->group_segment_start_addr);
}
uint64_t
__hsail_kernargbaseptr_u64 (PHSAWorkItem *wi)
{
/* For now assume only a single kernarg allocation at a time.
Proper kernarg memory management to do. */
return (uint64_t) wi->launch_data->kernarg_addr;
}
uint32_t
__hsail_kernargbaseptr_u32 (PHSAWorkItem *wi)
{
/* For now assume only a single kernarg allocation at a time.
Proper kernarg memory management to do. */
return 0;
}

135
libhsail-rt/rt/multimedia.c Normal file
View file

@ -0,0 +1,135 @@
/* multimedia.c -- Builtins for HSAIL multimedia instructions.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <math.h>
#include <stdint.h>
uint32_t
__hsail_bitalign (uint64_t lower, uint64_t upper, uint32_t shift_amount)
{
shift_amount = shift_amount & 31;
uint64_t packed_value = (upper << 32) | lower;
return (packed_value >> shift_amount) & 0xFFFFFFFF;
}
uint32_t
__hsail_bytealign (uint64_t lower, uint64_t upper, uint32_t shift_amount)
{
shift_amount = (shift_amount & 3) * 8;
uint64_t packed_value = (upper << 32) | lower;
return (packed_value >> shift_amount) & 0xFFFFFFFF;
}
uint32_t
__hsail_lerp (uint32_t a, uint32_t b, uint32_t c)
{
uint32_t e3
= (((((a >> 24) & 0xff) + ((b >> 24) & 0xff) + ((c >> 24) & 0x1)) / 2)
& 0xff)
<< 24;
uint32_t e2
= (((((a >> 16) & 0xff) + ((b >> 16) & 0xff) + ((c >> 16) & 0x1)) / 2)
& 0xff)
<< 16;
uint32_t e1
= (((((a >> 8) & 0xff) + ((b >> 8) & 0xff) + ((c >> 8) & 0x1)) / 2) & 0xff)
<< 8;
uint32_t e0 = (((a & 0xff) + (b & 0xff) + (c & 0x1)) / 2) & 0xff;
return e3 | e2 | e1 | e0;
}
static uint8_t
cvt_neari_sat_u8_f32 (float a)
{
if (isinf (a))
{
if (signbit (a)) return 0;
else return 255;
}
else if (isnan (a)) return 0;
else if (a < 0.0)
return 0;
else if (a > 255.0)
return 255;
else
return (uint8_t) a;
}
uint32_t
__hsail_packcvt (float a, float b, float c, float d)
{
return (uint32_t) cvt_neari_sat_u8_f32 (a)
| (uint32_t) cvt_neari_sat_u8_f32 (b) << 8
| (uint32_t) cvt_neari_sat_u8_f32 (c) << 16
| (uint32_t) cvt_neari_sat_u8_f32 (d) << 24;
}
float
__hsail_unpackcvt (uint32_t val, uint32_t index)
{
return (float) ((val >> (index * 8)) & 0xff);
}
static uint32_t
abs_diff (uint32_t a, uint32_t b)
{
if (a < b)
return b - a;
else
return a - b;
}
uint32_t
__hsail_sad_u8x4 (uint32_t a, uint32_t b, uint32_t add)
{
return abs_diff ((a >> 24) & 0xff, (b >> 24) & 0xff)
+ abs_diff ((a >> 16) & 0xff, (b >> 16) & 0xff)
+ abs_diff ((a >> 8) & 0xff, (b >> 8) & 0xff)
+ abs_diff ((a >> 0) & 0xff, (b >> 0) & 0xff) + add;
}
uint32_t
__hsail_sad_u16x2 (uint32_t a, uint32_t b, uint32_t add)
{
return abs_diff ((a >> 16) & 0xffff, (b >> 16) & 0xffff)
+ abs_diff ((a >> 0) & 0xffff, (b >> 0) & 0xffff) + add;
}
uint32_t
__hsail_sad_u32 (uint32_t a, uint32_t b, uint32_t add)
{
return abs_diff (a, b) + add;
}
uint32_t
__hsail_sadhi_u16x2_u8x4 (uint32_t a, uint32_t b, uint32_t add)
{
return (abs_diff ((a >> 24) & 0xff, (b >> 24) & 0xff) << 16)
+ (abs_diff ((a >> 16) & 0xff, (b >> 16) & 0xff) << 16)
+ (abs_diff ((a >> 8) & 0xff, (b >> 8) & 0xff) << 16)
+ (abs_diff ((a >> 0) & 0xff, (b >> 0) & 0xff) << 16) + add;
}

71
libhsail-rt/rt/queue.c Normal file
View file

@ -0,0 +1,71 @@
/* queue.c -- Builtins for HSAIL queue related instructions.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "phsa-queue-interface.h"
uint64_t
__hsail_ldqueuereadindex (uint64_t queue_addr)
{
phsa_queue_t *queue = (phsa_queue_t *) queue_addr;
return queue->read_index;
}
uint64_t
__hsail_ldqueuewriteindex (uint64_t queue_addr)
{
phsa_queue_t *queue = (phsa_queue_t *) queue_addr;
return queue->write_index;
}
uint64_t
__hsail_addqueuewriteindex (uint64_t queue_addr, uint64_t value)
{
phsa_queue_t *queue = (phsa_queue_t *) queue_addr;
return __sync_fetch_and_add (&queue->write_index, value);
}
uint64_t
__hsail_casqueuewriteindex (uint64_t queue_addr, uint64_t cmp_value,
uint64_t new_value)
{
phsa_queue_t *queue = (phsa_queue_t *) queue_addr;
return __sync_val_compare_and_swap (&queue->write_index, cmp_value,
new_value);
}
void
__hsail_stqueuereadindex (uint64_t queue_addr, uint64_t value)
{
phsa_queue_t *queue = (phsa_queue_t *) queue_addr;
queue->read_index = value;
}
void
__hsail_stqueuewriteindex (uint64_t queue_addr, uint64_t value)
{
phsa_queue_t *queue = (phsa_queue_t *) queue_addr;
queue->write_index = value;
}

View file

@ -0,0 +1,299 @@
/* sat_arithmetic.c -- Builtins for HSAIL saturating arithmetic instructions.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdint.h>
uint8_t
__hsail_sat_add_u8 (uint8_t a, uint8_t b)
{
uint16_t c = (uint16_t) a + (uint16_t) b;
if (c > UINT8_MAX)
return UINT8_MAX;
else
return c;
}
uint16_t
__hsail_sat_add_u16 (uint16_t a, uint16_t b)
{
uint32_t c = (uint32_t) a + (uint32_t) b;
if (c > UINT16_MAX)
return UINT16_MAX;
else
return c;
}
uint32_t
__hsail_sat_add_u32 (uint32_t a, uint32_t b)
{
uint64_t c = (uint64_t) a + (uint64_t) b;
if (c > UINT32_MAX)
return UINT32_MAX;
else
return c;
}
uint64_t
__hsail_sat_add_u64 (uint64_t a, uint64_t b)
{
__uint128_t c = (__uint128_t) a + (__uint128_t) b;
if (c > UINT64_MAX)
return UINT64_MAX;
else
return c;
}
int8_t
__hsail_sat_add_s8 (int8_t a, int8_t b)
{
int16_t c = (int16_t) a + (int16_t) b;
if (c > INT8_MAX)
return INT8_MAX;
else if (c < INT8_MIN)
return INT8_MIN;
else
return c;
}
int16_t
__hsail_sat_add_s16 (int16_t a, int16_t b)
{
int32_t c = (int32_t) a + (int32_t) b;
if (c > INT16_MAX)
return INT16_MAX;
else if (c < INT16_MIN)
return INT16_MIN;
else
return c;
}
int32_t
__hsail_sat_add_s32 (int32_t a, int32_t b)
{
int64_t c = (int64_t) a + (int64_t) b;
if (c > INT32_MAX)
return INT32_MAX;
else if (c < INT32_MIN)
return INT32_MIN;
else
return c;
}
int64_t
__hsail_sat_add_s64 (int64_t a, int64_t b)
{
__int128_t c = (__int128_t) a + (__int128_t) b;
if (c > INT64_MAX)
return INT64_MAX;
else if (c < INT64_MIN)
return INT64_MIN;
else
return c;
}
uint8_t
__hsail_sat_sub_u8 (uint8_t a, uint8_t b)
{
int16_t c = (uint16_t) a - (uint16_t) b;
if (c < 0)
return 0;
else if (c > UINT8_MAX)
return UINT8_MAX;
else
return c;
}
uint16_t
__hsail_sat_sub_u16 (uint16_t a, uint16_t b)
{
int32_t c = (uint32_t) a - (uint32_t) b;
if (c < 0)
return 0;
else if (c > UINT16_MAX)
return UINT16_MAX;
else
return c;
}
uint32_t
__hsail_sat_sub_u32 (uint32_t a, uint32_t b)
{
int64_t c = (uint64_t) a - (uint64_t) b;
if (c < 0)
return 0;
else if (c > UINT32_MAX)
return UINT32_MAX;
else
return c;
}
uint64_t
__hsail_sat_sub_u64 (uint64_t a, uint64_t b)
{
__int128_t c = (__uint128_t) a - (__uint128_t) b;
if (c < 0)
return 0;
else if (c > UINT64_MAX)
return UINT64_MAX;
else
return c;
}
int8_t
__hsail_sat_sub_s8 (int8_t a, int8_t b)
{
int16_t c = (int16_t) a - (int16_t) b;
if (c > INT8_MAX)
return INT8_MAX;
else if (c < INT8_MIN)
return INT8_MIN;
else
return c;
}
int16_t
__hsail_sat_sub_s16 (int16_t a, int16_t b)
{
int32_t c = (int32_t) a - (int32_t) b;
if (c > INT16_MAX)
return INT16_MAX;
else if (c < INT16_MIN)
return INT16_MIN;
else
return c;
}
int32_t
__hsail_sat_sub_s32 (int32_t a, int32_t b)
{
int64_t c = (int64_t) a - (int64_t) b;
if (c > INT32_MAX)
return INT32_MAX;
else if (c < INT32_MIN)
return INT32_MIN;
else
return c;
}
int64_t
__hsail_sat_sub_s64 (int64_t a, int64_t b)
{
__int128_t c = (__int128_t) a - (__int128_t) b;
if (c > INT64_MAX)
return INT64_MAX;
else if (c < INT64_MIN)
return INT64_MIN;
else
return c;
}
uint8_t
__hsail_sat_mul_u8 (uint8_t a, uint8_t b)
{
uint16_t c = (uint16_t) a * (uint16_t) b;
if (c > UINT8_MAX)
return UINT8_MAX;
else
return c;
}
uint16_t
__hsail_sat_mul_u16 (uint16_t a, uint16_t b)
{
uint32_t c = (uint32_t) a * (uint32_t) b;
if (c > UINT16_MAX)
return UINT16_MAX;
else
return c;
}
uint32_t
__hsail_sat_mul_u32 (uint32_t a, uint32_t b)
{
uint64_t c = (uint64_t) a * (uint64_t) b;
if (c > UINT32_MAX)
return UINT32_MAX;
else
return c;
}
uint64_t
__hsail_sat_mul_u64 (uint64_t a, uint64_t b)
{
__uint128_t c = (__uint128_t) a * (__uint128_t) b;
if (c > UINT64_MAX)
return UINT64_MAX;
else
return c;
}
int8_t
__hsail_sat_mul_s8 (int8_t a, int8_t b)
{
int16_t c = (int16_t) a * (int16_t) b;
if (c > INT8_MAX)
return INT8_MAX;
else if (c < INT8_MIN)
return INT8_MIN;
else
return c;
}
int16_t
__hsail_sat_mul_s16 (int16_t a, int16_t b)
{
int32_t c = (int32_t) a * (int32_t) b;
if (c > INT16_MAX)
return INT16_MAX;
else if (c < INT16_MIN)
return INT16_MIN;
else
return c;
}
int32_t
__hsail_sat_mul_s32 (int32_t a, int32_t b)
{
int64_t c = (int64_t) a * (int64_t) b;
if (c > INT32_MAX)
return INT32_MAX;
else if (c < INT32_MIN)
return INT32_MIN;
else
return c;
}
int64_t
__hsail_sat_mul_s64 (int64_t a, int64_t b)
{
__int128_t c = (__int128_t) a * (__int128_t) b;
if (c > INT64_MAX)
return INT64_MAX;
else if (c < INT64_MIN)
return INT64_MIN;
else
return c;
}

57
libhsail-rt/rt/segment.c Normal file
View file

@ -0,0 +1,57 @@
/* segment.c -- Builtins for HSAIL segment related instructions.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "workitems.h"
uint32_t
__hsail_segmentp_private (uint64_t flat_addr, PHSAWorkItem *wi)
{
if (flat_addr == 0)
return 1;
else
return (void *) flat_addr >= wi->wg->private_base_ptr
&& (void *) flat_addr
< wi->wg->private_base_ptr + wi->wg->private_segment_total_size;
}
uint32_t
__hsail_segmentp_group (uint64_t flat_addr, PHSAWorkItem *wi)
{
if (flat_addr == 0)
return 1;
else
return (void *) flat_addr >= wi->wg->group_base_ptr
&& (void *) flat_addr < wi->wg->group_base_ptr
+ wi->launch_data->dp->group_segment_size;
}
uint32_t
__hsail_segmentp_global (uint64_t flat_addr, PHSAWorkItem *wi)
{
return (flat_addr == 0
|| (!__hsail_segmentp_private (flat_addr, wi)
&& !__hsail_segmentp_group (flat_addr, wi)));
}

952
libhsail-rt/rt/workitems.c Normal file
View file

@ -0,0 +1,952 @@
/* workitems.c -- The main runtime entry that performs work-item execution in
various ways and the builtin functions closely related to the
implementation.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
for General Processor Tech.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* The fiber based multiple work-item work-group execution uses ucontext
based user mode threading. However, if gccbrig is able to optimize the
kernel to a much faster work-group function that implements the multiple
WI execution using loops instead of fibers requiring slow context switches,
the fiber-based implementation won't be called.
*/
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include "workitems.h"
#include "phsa-rt.h"
#ifdef HAVE_FIBERS
#include "fibers.h"
#endif
#ifdef BENCHMARK_PHSA_RT
#include <stdio.h>
#include <time.h>
static uint64_t wi_count = 0;
static uint64_t wis_skipped = 0;
static uint64_t wi_total = 0;
static clock_t start_time;
#endif
#ifdef DEBUG_PHSA_RT
#include <stdio.h>
#endif
#define PRIVATE_SEGMENT_ALIGN 256
#define FIBER_STACK_SIZE (64*1024)
#define GROUP_SEGMENT_ALIGN 256
/* HSA requires WGs to be executed in flat work-group id order. Enabling
the following macro can reveal test cases that rely on the ordering,
but is not useful for much else. */
uint32_t __hsail_workitemabsid (uint32_t dim, PHSAWorkItem *context);
uint32_t __hsail_workitemid (uint32_t dim, PHSAWorkItem *context);
uint32_t __hsail_gridgroups (uint32_t dim, PHSAWorkItem *context);
uint32_t __hsail_currentworkgroupsize (uint32_t dim, PHSAWorkItem *wi);
uint32_t __hsail_workgroupsize (uint32_t dim, PHSAWorkItem *wi);
void
phsa_fatal_error (int code)
{
exit (code);
}
#ifdef HAVE_FIBERS
/* ucontext-based work-item thread implementation. Runs all work-items in
separate fibers. */
static void
phsa_work_item_thread (int arg0, int arg1)
{
void *arg = fiber_int_args_to_ptr (arg0, arg1);
PHSAWorkItem *wi = (PHSAWorkItem *) arg;
volatile PHSAWorkGroup *wg = wi->wg;
PHSAKernelLaunchData *l_data = wi->launch_data;
do
{
int retcode
= fiber_barrier_reach ((fiber_barrier_t *) l_data->wg_start_barrier);
/* At this point the threads can assume that either more_wgs is 0 or
the current_work_group_* is set to point to the WG executed next. */
if (!wi->wg->more_wgs)
break;
#ifdef DEBUG_PHSA_RT
printf (
"Running work-item %lu/%lu/%lu for wg %lu/%lu/%lu / %lu/%lu/%lu...\n",
wi->x, wi->y, wi->z, wg->x, wg->y, wg->z, l_data->wg_max_x,
l_data->wg_max_y, l_data->wg_max_z);
#endif
if (wi->x < __hsail_currentworkgroupsize (0, wi)
&& wi->y < __hsail_currentworkgroupsize (1, wi)
&& wi->z < __hsail_currentworkgroupsize (2, wi))
{
l_data->kernel (l_data->kernarg_addr, wi, wg->group_base_ptr,
wg->private_base_ptr);
#ifdef DEBUG_PHSA_RT
printf ("done.\n");
#endif
#ifdef BENCHMARK_PHSA_RT
wi_count++;
#endif
}
else
{
#ifdef DEBUG_PHSA_RT
printf ("skipped (partial WG).\n");
#endif
#ifdef BENCHMARK_PHSA_RT
wis_skipped++;
#endif
}
retcode
= fiber_barrier_reach ((fiber_barrier_t *)
l_data->wg_completion_barrier);
/* The first thread updates the WG to execute next etc. */
if (retcode == 0)
{
#ifdef EXECUTE_WGS_BACKWARDS
if (wg->x == l_data->wg_min_x)
{
wg->x = l_data->wg_max_x - 1;
if (wg->y == l_data->wg_min_y)
{
wg->y = l_data->wg_max_y - 1;
if (wg->z == l_data->wg_min_z)
wg->more_wgs = 0;
else
wg->z--;
}
else
wg->y--;
}
else
wg->x--;
#else
if (wg->x + 1 >= l_data->wg_max_x)
{
wg->x = l_data->wg_min_x;
if (wg->y + 1 >= l_data->wg_max_y)
{
wg->y = l_data->wg_min_y;
if (wg->z + 1 >= l_data->wg_max_z)
wg->more_wgs = 0;
else
wg->z++;
}
else
wg->y++;
}
else
wg->x++;
#endif
/* Reinitialize the work-group barrier according to the new WG's
size, which might not be the same as the previous ones, due
to "partial WGs". */
size_t wg_size = __hsail_currentworkgroupsize (0, wi)
* __hsail_currentworkgroupsize (1, wi)
* __hsail_currentworkgroupsize (2, wi);
#ifdef DEBUG_PHSA_RT
printf ("Reinitializing the WG barrier to %lu.\n", wg_size);
#endif
fiber_barrier_init ((fiber_barrier_t *)
wi->launch_data->wg_sync_barrier,
wg_size);
#ifdef BENCHMARK_PHSA_RT
if (wi_count % 1000 == 0)
{
clock_t spent_time = clock () - start_time;
double spent_time_sec = (double) spent_time / CLOCKS_PER_SEC;
double wis_per_sec = wi_count / spent_time_sec;
uint64_t eta_sec
= (wi_total - wi_count - wis_skipped) / wis_per_sec;
printf ("%lu WIs executed %lu skipped in %lus (%lu WIs/s, ETA in "
"%lu s)\n",
wi_count, wis_skipped, (uint64_t) spent_time_sec,
(uint64_t) wis_per_sec, (uint64_t) eta_sec);
}
#endif
}
}
while (1);
fiber_exit ();
}
#endif
#define MIN(a, b) ((a < b) ? a : b)
#define MAX(a, b) ((a > b) ? a : b)
#ifdef HAVE_FIBERS
/* Spawns a given number of work-items to execute a set of work-groups,
blocks until their completion. */
static void
phsa_execute_wi_gang (PHSAKernelLaunchData *context, void *group_base_ptr,
size_t wg_size_x, size_t wg_size_y, size_t wg_size_z)
{
PHSAWorkItem *wi_threads = NULL;
PHSAWorkGroup wg;
size_t flat_wi_id = 0, x, y, z, max_x, max_y, max_z;
fiber_barrier_t wg_start_barrier;
fiber_barrier_t wg_completion_barrier;
fiber_barrier_t wg_sync_barrier;
max_x = wg_size_x == 0 ? 1 : wg_size_x;
max_y = wg_size_y == 0 ? 1 : wg_size_y;
max_z = wg_size_z == 0 ? 1 : wg_size_z;
size_t wg_size = max_x * max_y * max_z;
if (wg_size > PHSA_MAX_WG_SIZE)
phsa_fatal_error (2);
wg.private_segment_total_size = context->dp->private_segment_size * wg_size;
if (wg.private_segment_total_size > 0
&& posix_memalign (&wg.private_base_ptr, PRIVATE_SEGMENT_ALIGN,
wg.private_segment_total_size)
!= 0)
phsa_fatal_error (3);
wg.alloca_stack_p = wg.private_segment_total_size;
wg.alloca_frame_p = wg.alloca_stack_p;
#ifdef EXECUTE_WGS_BACKWARDS
wg.x = context->wg_max_x - 1;
wg.y = context->wg_max_y - 1;
wg.z = context->wg_max_z - 1;
#else
wg.x = context->wg_min_x;
wg.y = context->wg_min_y;
wg.z = context->wg_min_z;
#endif
fiber_barrier_init (&wg_sync_barrier, wg_size);
fiber_barrier_init (&wg_start_barrier, wg_size);
fiber_barrier_init (&wg_completion_barrier, wg_size);
context->wg_start_barrier = &wg_start_barrier;
context->wg_sync_barrier = &wg_sync_barrier;
context->wg_completion_barrier = &wg_completion_barrier;
wg.more_wgs = 1;
wg.group_base_ptr = group_base_ptr;
#ifdef BENCHMARK_PHSA_RT
wi_count = 0;
wis_skipped = 0;
start_time = clock ();
#endif
wi_threads = malloc (sizeof (PHSAWorkItem) * max_x * max_y * max_z);
for (x = 0; x < max_x; ++x)
for (y = 0; y < max_y; ++y)
for (z = 0; z < max_z; ++z)
{
PHSAWorkItem *wi = &wi_threads[flat_wi_id];
wi->launch_data = context;
wi->wg = &wg;
wi->x = x;
wi->y = y;
wi->z = z;
/* TODO: set the stack size according to the private
segment size. Too big stack consumes huge amount of
memory in case of huge number of WIs and a too small stack
will fail in mysterious and potentially dangerous ways. */
fiber_init (&wi->fiber, phsa_work_item_thread, wi,
FIBER_STACK_SIZE, PRIVATE_SEGMENT_ALIGN);
++flat_wi_id;
}
do
{
--flat_wi_id;
fiber_join (&wi_threads[flat_wi_id].fiber);
}
while (flat_wi_id > 0);
if (wg.private_segment_total_size > 0)
free (wg.private_base_ptr);
free (wi_threads);
}
/* Spawn the work-item threads to execute work-groups and let
them execute all the WGs, including a potential partial WG. */
static void
phsa_spawn_work_items (PHSAKernelLaunchData *context, void *group_base_ptr)
{
hsa_kernel_dispatch_packet_t *dp = context->dp;
size_t x, y, z;
/* TO DO: host-side memory management of group and private segment
memory. Agents in general are less likely to support efficient dynamic mem
allocation. */
if (dp->group_segment_size > 0
&& posix_memalign (&group_base_ptr, PRIVATE_SEGMENT_ALIGN,
dp->group_segment_size) != 0)
phsa_fatal_error (3);
context->group_segment_start_addr = (size_t) group_base_ptr;
/* HSA seems to allow the WG size to be larger than the grid size. We need to
saturate the effective WG size to the grid size to prevent the extra WIs
from executing. */
size_t sat_wg_size_x, sat_wg_size_y, sat_wg_size_z, sat_wg_size;
sat_wg_size_x = MIN (dp->workgroup_size_x, dp->grid_size_x);
sat_wg_size_y = MIN (dp->workgroup_size_y, dp->grid_size_y);
sat_wg_size_z = MIN (dp->workgroup_size_z, dp->grid_size_z);
sat_wg_size = sat_wg_size_x * sat_wg_size_y * sat_wg_size_z;
#ifdef BENCHMARK_PHSA_RT
wi_total = (uint64_t) dp->grid_size_x
* (dp->grid_size_y > 0 ? dp->grid_size_y : 1)
* (dp->grid_size_z > 0 ? dp->grid_size_z : 1);
#endif
/* For now execute all work groups in a single coarse thread (does not utilize
multicore/multithread). */
context->wg_min_x = context->wg_min_y = context->wg_min_z = 0;
int dims = dp->setup & 0x3;
context->wg_max_x = ((uint64_t) dp->grid_size_x + dp->workgroup_size_x - 1)
/ dp->workgroup_size_x;
context->wg_max_y
= dims < 2 ? 1 : ((uint64_t) dp->grid_size_y + dp->workgroup_size_y - 1)
/ dp->workgroup_size_y;
context->wg_max_z
= dims < 3 ? 1 : ((uint64_t) dp->grid_size_z + dp->workgroup_size_z - 1)
/ dp->workgroup_size_z;
#ifdef DEBUG_PHSA_RT
printf ("### launching work-groups %lu/%lu/%lu to %lu/%lu/%lu with "
"wg size %lu/%lu/%lu grid size %u/%u/%u\n",
context->wg_min_x, context->wg_min_y, context->wg_min_z,
context->wg_max_x, context->wg_max_y, context->wg_max_z,
sat_wg_size_x, sat_wg_size_y, sat_wg_size_z, dp->grid_size_x,
dp->grid_size_y, dp->grid_size_z);
#endif
phsa_execute_wi_gang (context, group_base_ptr, sat_wg_size_x, sat_wg_size_y,
sat_wg_size_z);
if (dp->group_segment_size > 0)
free (group_base_ptr);
}
#endif
/* Executes the given work-group function for all work groups in the grid.
A work-group function is a version of the original kernel which executes
the kernel for all work-items in a work-group. It is produced by gccbrig
if it can handle the kernel's barrier usage and is much faster way to
execute massive numbers of work-items in a non-SPMD machine than fibers
(easily 100x faster). */
static void
phsa_execute_work_groups (PHSAKernelLaunchData *context, void *group_base_ptr)
{
hsa_kernel_dispatch_packet_t *dp = context->dp;
size_t x, y, z, wg_x, wg_y, wg_z;
/* TODO: host-side memory management of group and private segment
memory. Agents in general are less likely to support efficient dynamic mem
allocation. */
if (dp->group_segment_size > 0
&& posix_memalign (&group_base_ptr, GROUP_SEGMENT_ALIGN,
dp->group_segment_size) != 0)
phsa_fatal_error (3);
context->group_segment_start_addr = (size_t) group_base_ptr;
/* HSA seems to allow the WG size to be larger than the grid size. We need
to saturate the effective WG size to the grid size to prevent the extra WIs
from executing. */
size_t sat_wg_size_x, sat_wg_size_y, sat_wg_size_z, sat_wg_size;
sat_wg_size_x = MIN (dp->workgroup_size_x, dp->grid_size_x);
sat_wg_size_y = MIN (dp->workgroup_size_y, dp->grid_size_y);
sat_wg_size_z = MIN (dp->workgroup_size_z, dp->grid_size_z);
sat_wg_size = sat_wg_size_x * sat_wg_size_y * sat_wg_size_z;
#ifdef BENCHMARK_PHSA_RT
wi_total = (uint64_t) dp->grid_size_x
* (dp->grid_size_y > 0 ? dp->grid_size_y : 1)
* (dp->grid_size_z > 0 ? dp->grid_size_z : 1);
#endif
context->wg_min_x = context->wg_min_y = context->wg_min_z = 0;
int dims = dp->setup & 0x3;
context->wg_max_x = ((uint64_t) dp->grid_size_x + dp->workgroup_size_x - 1)
/ dp->workgroup_size_x;
context->wg_max_y
= dims < 2 ? 1 : ((uint64_t) dp->grid_size_y + dp->workgroup_size_y - 1)
/ dp->workgroup_size_y;
context->wg_max_z
= dims < 3 ? 1 : ((uint64_t) dp->grid_size_z + dp->workgroup_size_z - 1)
/ dp->workgroup_size_z;
#ifdef DEBUG_PHSA_RT
printf ("### launching work-groups %lu/%lu/%lu to %lu/%lu/%lu with "
"wg size %lu/%lu/%lu grid size %u/%u/%u\n",
context->wg_min_x, context->wg_min_y, context->wg_min_z,
context->wg_max_x, context->wg_max_y, context->wg_max_z,
sat_wg_size_x, sat_wg_size_y, sat_wg_size_z, dp->grid_size_x,
dp->grid_size_y, dp->grid_size_z);
#endif
PHSAWorkItem wi;
PHSAWorkGroup wg;
wi.wg = &wg;
wi.x = wi.y = wi.z = 0;
wi.launch_data = context;
#ifdef BENCHMARK_PHSA_RT
start_time = clock ();
uint64_t wg_count = 0;
#endif
size_t wg_size = __hsail_workgroupsize (0, &wi)
* __hsail_workgroupsize (1, &wi)
* __hsail_workgroupsize (2, &wi);
void *private_base_ptr = NULL;
if (dp->private_segment_size > 0
&& posix_memalign (&private_base_ptr, PRIVATE_SEGMENT_ALIGN,
dp->private_segment_size * wg_size)
!= 0)
phsa_fatal_error (3);
wg.alloca_stack_p = dp->private_segment_size * wg_size;
wg.alloca_frame_p = wg.alloca_stack_p;
wg.private_base_ptr = private_base_ptr;
wg.group_base_ptr = group_base_ptr;
#ifdef DEBUG_PHSA_RT
printf ("priv seg size %u wg_size %lu @ %p\n", dp->private_segment_size,
wg_size, private_base_ptr);
#endif
for (wg_z = context->wg_min_z; wg_z < context->wg_max_z; ++wg_z)
for (wg_y = context->wg_min_y; wg_y < context->wg_max_y; ++wg_y)
for (wg_x = context->wg_min_x; wg_x < context->wg_max_x; ++wg_x)
{
wi.wg->x = wg_x;
wi.wg->y = wg_y;
wi.wg->z = wg_z;
context->kernel (context->kernarg_addr, &wi, group_base_ptr,
private_base_ptr);
#if defined (BENCHMARK_PHSA_RT)
wg_count++;
if (wg_count % 1000000 == 0)
{
clock_t spent_time = clock () - start_time;
uint64_t wi_count = wg_x * sat_wg_size_x + wg_y * sat_wg_size_y
+ wg_z * sat_wg_size_z;
double spent_time_sec = (double) spent_time / CLOCKS_PER_SEC;
double wis_per_sec = wi_count / spent_time_sec;
uint64_t eta_sec = (wi_total - wi_count) / wis_per_sec;
printf ("%lu WIs executed in %lus (%lu WIs/s, ETA in %lu s)\n",
wi_count, (uint64_t) spent_time_sec,
(uint64_t) wis_per_sec, (uint64_t) eta_sec);
}
#endif
}
#ifdef BENCHMARK_PHSA_RT
clock_t spent_time = clock () - start_time;
double spent_time_sec = (double) spent_time / CLOCKS_PER_SEC;
double wis_per_sec = wi_total / spent_time_sec;
printf ("### %lu WIs executed in %lu s (%lu WIs / s)\n", wi_total,
(uint64_t) spent_time_sec, (uint64_t) wis_per_sec);
#endif
if (dp->group_segment_size > 0)
free (group_base_ptr);
free (private_base_ptr);
private_base_ptr = NULL;
}
/* gccbrig generates the following from each HSAIL kernel:
1) The actual kernel function (a single work-item kernel or a work-group
function) generated from HSAIL (BRIG).
static void _Kernel (void* args, void* context, void* group_base_ptr)
{
...
}
2) A public facing kernel function that is called from the PHSA runtime:
a) A single work-item function (that requires fibers for multi-WI):
void Kernel (void* context)
{
__launch_launch_kernel (_Kernel, context);
}
or
b) a when gccbrig could generate a work-group function:
void Kernel (void* context)
{
__hsail_launch_wg_function (_Kernel, context);
}
*/
#ifdef HAVE_FIBERS
void
__hsail_launch_kernel (gccbrigKernelFunc kernel, PHSAKernelLaunchData *context,
void *group_base_ptr)
{
context->kernel = kernel;
phsa_spawn_work_items (context, group_base_ptr);
}
#endif
void
__hsail_launch_wg_function (gccbrigKernelFunc kernel,
PHSAKernelLaunchData *context, void *group_base_ptr)
{
context->kernel = kernel;
phsa_execute_work_groups (context, group_base_ptr);
}
uint32_t
__hsail_workitemabsid (uint32_t dim, PHSAWorkItem *context)
{
hsa_kernel_dispatch_packet_t *dp = context->launch_data->dp;
uint32_t id;
switch (dim)
{
default:
case 0:
/* Overflow semantics in the case of WG dim > grid dim. */
id = ((uint64_t) context->wg->x * dp->workgroup_size_x + context->x)
% dp->grid_size_x;
break;
case 1:
id = ((uint64_t) context->wg->y * dp->workgroup_size_y + context->y)
% dp->grid_size_y;
break;
case 2:
id = ((uint64_t) context->wg->z * dp->workgroup_size_z + context->z)
% dp->grid_size_z;
break;
}
return id;
}
uint64_t
__hsail_workitemabsid_u64 (uint32_t dim, PHSAWorkItem *context)
{
hsa_kernel_dispatch_packet_t *dp = context->launch_data->dp;
uint64_t id;
switch (dim)
{
default:
case 0:
/* Overflow semantics in the case of WG dim > grid dim. */
id = ((uint64_t) context->wg->x * dp->workgroup_size_x + context->x)
% dp->grid_size_x;
break;
case 1:
id = ((uint64_t) context->wg->y * dp->workgroup_size_y + context->y)
% dp->grid_size_y;
break;
case 2:
id = ((uint64_t) context->wg->z * dp->workgroup_size_z + context->z)
% dp->grid_size_z;
break;
}
return id;
}
uint32_t
__hsail_workitemid (uint32_t dim, PHSAWorkItem *context)
{
PHSAWorkItem *c = (PHSAWorkItem *) context;
hsa_kernel_dispatch_packet_t *dp = context->launch_data->dp;
/* The number of dimensions is in the two least significant bits. */
int dims = dp->setup & 0x3;
uint32_t id;
switch (dim)
{
default:
case 0:
id = c->x;
break;
case 1:
id = dims < 2 ? 0 : c->y;
break;
case 2:
id = dims < 3 ? 0 : c->z;
break;
}
return id;
}
uint32_t
__hsail_gridgroups (uint32_t dim, PHSAWorkItem *context)
{
hsa_kernel_dispatch_packet_t *dp = context->launch_data->dp;
int dims = dp->setup & 0x3;
uint32_t id;
switch (dim)
{
default:
case 0:
id = (dp->grid_size_x + dp->workgroup_size_x - 1) / dp->workgroup_size_x;
break;
case 1:
id = dims < 2 ? 1 : (dp->grid_size_y + dp->workgroup_size_y - 1)
/ dp->workgroup_size_y;
break;
case 2:
id = dims < 3 ? 1 : (dp->grid_size_z + dp->workgroup_size_z - 1)
/ dp->workgroup_size_z;
break;
}
return id;
}
uint32_t
__hsail_workitemflatid (PHSAWorkItem *c)
{
hsa_kernel_dispatch_packet_t *dp = c->launch_data->dp;
return c->x + c->y * dp->workgroup_size_x
+ c->z * dp->workgroup_size_x * dp->workgroup_size_y;
}
uint32_t
__hsail_currentworkitemflatid (PHSAWorkItem *c)
{
hsa_kernel_dispatch_packet_t *dp = c->launch_data->dp;
return c->x + c->y * __hsail_currentworkgroupsize (0, c)
+ c->z * __hsail_currentworkgroupsize (0, c)
* __hsail_currentworkgroupsize (1, c);
}
void
__hsail_setworkitemid (uint32_t dim, uint32_t id, PHSAWorkItem *context)
{
switch (dim)
{
default:
case 0:
context->x = id;
break;
case 1:
context->y = id;
break;
case 2:
context->z = id;
break;
}
}
uint64_t
__hsail_workitemflatabsid_u64 (PHSAWorkItem *context)
{
PHSAWorkItem *c = (PHSAWorkItem *) context;
hsa_kernel_dispatch_packet_t *dp = context->launch_data->dp;
/* Work-item flattened absolute ID = ID0 + ID1 * max0 + ID2 * max0 * max1. */
uint64_t id0 = __hsail_workitemabsid (0, context);
uint64_t id1 = __hsail_workitemabsid (1, context);
uint64_t id2 = __hsail_workitemabsid (2, context);
uint64_t max0 = dp->grid_size_x;
uint64_t max1 = dp->grid_size_y;
uint64_t id = id0 + id1 * max0 + id2 * max0 * max1;
return id;
}
uint32_t
__hsail_workitemflatabsid_u32 (PHSAWorkItem *context)
{
PHSAWorkItem *c = (PHSAWorkItem *) context;
hsa_kernel_dispatch_packet_t *dp = context->launch_data->dp;
/* work-item flattened absolute ID = ID0 + ID1 * max0 + ID2 * max0 * max1. */
uint64_t id0 = __hsail_workitemabsid (0, context);
uint64_t id1 = __hsail_workitemabsid (1, context);
uint64_t id2 = __hsail_workitemabsid (2, context);
uint64_t max0 = dp->grid_size_x;
uint64_t max1 = dp->grid_size_y;
uint64_t id = id0 + id1 * max0 + id2 * max0 * max1;
return (uint32_t) id;
}
uint32_t
__hsail_currentworkgroupsize (uint32_t dim, PHSAWorkItem *wi)
{
hsa_kernel_dispatch_packet_t *dp = wi->launch_data->dp;
uint32_t wg_size = 0;
switch (dim)
{
default:
case 0:
if ((uint64_t) wi->wg->x < dp->grid_size_x / dp->workgroup_size_x)
wg_size = dp->workgroup_size_x; /* Full WG. */
else
wg_size = dp->grid_size_x % dp->workgroup_size_x; /* Partial WG. */
break;
case 1:
if ((uint64_t) wi->wg->y < dp->grid_size_y / dp->workgroup_size_y)
wg_size = dp->workgroup_size_y; /* Full WG. */
else
wg_size = dp->grid_size_y % dp->workgroup_size_y; /* Partial WG. */
break;
case 2:
if ((uint64_t) wi->wg->z < dp->grid_size_z / dp->workgroup_size_z)
wg_size = dp->workgroup_size_z; /* Full WG. */
else
wg_size = dp->grid_size_z % dp->workgroup_size_z; /* Partial WG. */
break;
}
return wg_size;
}
uint32_t
__hsail_workgroupsize (uint32_t dim, PHSAWorkItem *wi)
{
hsa_kernel_dispatch_packet_t *dp = wi->launch_data->dp;
switch (dim)
{
default:
case 0:
return dp->workgroup_size_x;
case 1:
return dp->workgroup_size_y;
case 2:
return dp->workgroup_size_z;
}
}
uint32_t
__hsail_gridsize (uint32_t dim, PHSAWorkItem *wi)
{
hsa_kernel_dispatch_packet_t *dp = wi->launch_data->dp;
switch (dim)
{
default:
case 0:
return dp->grid_size_x;
case 1:
return dp->grid_size_y;
case 2:
return dp->grid_size_z;
}
}
uint32_t
__hsail_workgroupid (uint32_t dim, PHSAWorkItem *wi)
{
switch (dim)
{
default:
case 0:
return wi->wg->x;
case 1:
return wi->wg->y;
case 2:
return wi->wg->z;
}
}
uint32_t
__hsail_dim (PHSAWorkItem *wi)
{
hsa_kernel_dispatch_packet_t *dp = wi->launch_data->dp;
return dp->setup & 0x3;
}
uint64_t
__hsail_packetid (PHSAWorkItem *wi)
{
return wi->launch_data->packet_id;
}
uint32_t
__hsail_packetcompletionsig_sig32 (PHSAWorkItem *wi)
{
return (uint32_t) wi->launch_data->dp->completion_signal.handle;
}
uint64_t
__hsail_packetcompletionsig_sig64 (PHSAWorkItem *wi)
{
return (uint64_t) (wi->launch_data->dp->completion_signal.handle);
}
#ifdef HAVE_FIBERS
void
__hsail_barrier (PHSAWorkItem *wi)
{
fiber_barrier_reach ((fiber_barrier_t *) wi->launch_data->wg_sync_barrier);
}
#endif
/* Return a 32b private segment address that points to a dynamically
allocated chunk of 'size' with 'align'.
Allocates the space from the end of the private segment allocated
for the whole work group. In implementations with separate private
memories per WI, we will need to have a stack pointer per WI. But in
the current implementation, the segment is shared, so we possibly
save some space in case all WIs do not call the alloca.
The "alloca frames" are organized as follows:
wg->alloca_stack_p points to the last allocated data (initially
outside the private segment)
wg->alloca_frame_p points to the first address _outside_ the current
function's allocations (initially to the same as alloca_stack_p)
The data is allocated downwards from the end of the private segment.
In the beginning of a new function which has allocas, a new alloca
frame is pushed which adds the current alloca_frame_p (the current
function's frame starting point) to the top of the alloca stack and
alloca_frame_p is set to the current stack position.
At the exit points of a function with allocas, the alloca frame
is popped before returning. This involves popping the alloca_frame_p
to the one of the previous function in the call stack, and alloca_stack_p
similarly, to the position of the last word alloca'd by the previous
function.
*/
uint32_t
__hsail_alloca (uint32_t size, uint32_t align, PHSAWorkItem *wi)
{
volatile PHSAWorkGroup *wg = wi->wg;
uint32_t new_pos = wg->alloca_stack_p - size;
while (new_pos % align != 0)
new_pos--;
wg->alloca_stack_p = new_pos;
#ifdef DEBUG_ALLOCA
printf ("--- alloca (%u, %u) sp @%u fp @%u\n", size, align,
wg->alloca_stack_p, wg->alloca_frame_p);
#endif
return new_pos;
}
/* Initializes a new "alloca frame" in the private segment.
This should be called at all the function entry points in case
the function contains at least one call to alloca. */
void
__hsail_alloca_push_frame (PHSAWorkItem *wi)
{
volatile PHSAWorkGroup *wg = wi->wg;
/* Store the alloca_frame_p without any alignment padding so
we know exactly where the previous frame ended after popping
it. */
#ifdef DEBUG_ALLOCA
printf ("--- push frame ");
#endif
uint32_t last_word_offs = __hsail_alloca (4, 1, wi);
memcpy (wg->private_base_ptr + last_word_offs,
(const void *) &wg->alloca_frame_p, 4);
wg->alloca_frame_p = last_word_offs;
#ifdef DEBUG_ALLOCA
printf ("--- sp @%u fp @%u\n", wg->alloca_stack_p, wg->alloca_frame_p);
#endif
}
/* Frees the current "alloca frame" and restores the frame
pointer.
This should be called at all the function return points in case
the function contains at least one call to alloca. Restores the
alloca stack to the condition it was before pushing the frame
the last time. */
void
__hsail_alloca_pop_frame (PHSAWorkItem *wi)
{
volatile PHSAWorkGroup *wg = wi->wg;
wg->alloca_stack_p = wg->alloca_frame_p;
memcpy (&wg->alloca_frame_p,
(const void *) (wg->private_base_ptr + wg->alloca_frame_p), 4);
/* Now frame_p points to the beginning of the previous function's
frame and stack_p to its end. */
wg->alloca_stack_p += 4;
#ifdef DEBUG_ALLOCA
printf ("--- pop frame sp @%u fp @%u\n", wg->alloca_stack_p,
wg->alloca_frame_p);
#endif
}

View file

@ -0,0 +1,68 @@
/* target-config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `void*', as computed by sizeof. */
#undef SIZEOF_VOIDP
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION