Add wasm tacle-bench targets

This commit is contained in:
2026-06-12 20:06:22 +02:00
parent 30daa8a00c
commit 08c2e9c13d
1122 changed files with 520422 additions and 0 deletions

View File

@ -0,0 +1,25 @@
# ~~~
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
# ~~~
cmake_minimum_required(VERSION 3.20)
project(bitonic)
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/inline/bitonic.c")
else()
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/default/bitonic.c")
endif()
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)

View File

@ -0,0 +1,53 @@
File: bitonic.c
Original provenience: StreamIt benchmark suite,
http://groups.csail.mit.edu/cag/streamit/results/bitonic/code/c/
2015-10-20:
- Removed original header comment, replaced by TACLeBench header.
- Added prefix "bitonic_"/"BITONIC_" to all global symbols
- adjusted names of bitonicSort and bitonicMerge functions to
bitonic_*.
- Replaced initialization code by TACLeBench-compliant initialization code.
- Added new function quicksort_return producing a checksum as return value.
- Added new function quicksort_main according to TACLeBench guidelines.
quicksort_main is annotated as entry-point for timing analysis.
- Applied code formatting according to the following rules
- Lines shall not be wider than 80 characters; whenever possible, appropriate
line breaks shall be inserted to keep lines below 80 characters
- Indentation is done using whitespaces only, no tabs. Code is indented by
two whitespaces
- Two empty lines are put between any two functions
- In non-empty lists or index expressions, opening '(' and '[' are followed by
one whitespace, closing ')' and ']' are preceded by one whitespace
- In comma- or colon-separated argument lists, one whitespace is put after
each comma/colon
- Names of functions and global variables all start with a benchmark-specific
prefix (here: bs_) followed by lowercase letter (e.g., bs_square)
- For pointer types, one whitespace is put before the '*'
- Operators within expressions shall be preceded and followed by one
whitespace
- Code of then- and else-parts of if-then-else statements shall be put in
separate lines, not in the same lines as the if-condition or the keyword
"else"
- Opening braces '{' denoting the beginning of code for some if-else or loop
body shall be put at the end of the same line where the keywords "if",
"else", "for", "while" etc. occur
2016-02-01:
- More formatting:
- In non-empty lists or index expressions, opening '(' and '[' are followed by
one whitespace, closing ')' and ']' are preceded by one whitespace
- Operators within expressions shall be preceded and followed by one
whitespace
2016-04-05:
- Return '0' on success
2016-04-06:
- Fixed generation of return value
2016-06-01:
- Changed all prefixes to lower-case

View File

@ -0,0 +1,157 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: bitonic
Author: Chris Leger
Function: bitonic implements a recursive sorting network algorithm.
Source: MiBench
http://wwweb.eecs.umich.edu/mibench
Changes: no major functional changes
License: MIT
*/
/*
Forward declaration of functions
*/
void bitonic_init( void );
int bitonic_return( void );
void bitonic_compare( int i, int j, int dir );
void bitonic_merge( int lo, int cnt, int dir );
void bitonic_sort( int lo, int cnt, int dir );
int main( void );
/*
Declaration of global variables
*/
int bitonic_numiters = 10;
int bitonic_a[ 32 ]; // the array to be sorted
const int bitonic_ASCENDING = 1;
const int bitonic_DESCENDING = 0;
const int bitonic_CHECKSUM = 55;
/*
Initialization- and return-value-related functions
*/
void bitonic_init( void )
{
/** Initialize array "a" with data **/
int i;
_Pragma( "loopbound min 32 max 32" )
for ( i = 0; i < 32; i++ )
bitonic_a[ i ] = ( 32 - i );
}
int bitonic_return( void )
{
int checksum = 0;
checksum += bitonic_a[ 0 ] + bitonic_a[ 21 ] + bitonic_a[ 31 ];
return ( ( checksum == bitonic_CHECKSUM ) ? 0 : -1 );
}
/*
Algorithm core functions
*/
/** A comparator is modelled by the procedure compare, where the
parameter dir indicates the sorting direction. If dir is ASCENDING
and a[i] > a[j] is true or dir is DESCENDING and a[i] > a[j] is
false then a[i] and a[j] are interchanged.
**/
void bitonic_compare( int i, int j, int dir )
{
if ( dir == ( bitonic_a[ i ] > bitonic_a[ j ] ) ) {
int h = bitonic_a[ i ];
bitonic_a[ i ] = bitonic_a[ j ];
bitonic_a[ j ] = h;
}
}
/** The procedure bitonicMerge recursively sorts a bitonic sequence in
ascending order, if dir = ASCENDING, and in descending order
otherwise. The sequence to be sorted starts at index position lo,
the number of elements is cnt.
**/
void bitonic_merge( int lo, int cnt, int dir )
{
int k = cnt / 2;
int i;
_Pragma( "loopbound min 0 max 16" )
for ( i = lo; i < lo + k; i++ )
bitonic_compare( i, i + k, dir );
if ( k > 1 ) {
bitonic_merge( lo, k, dir );
bitonic_merge( lo + k, k, dir );
}
}
/** Procedure bitonicSort first produces a bitonic sequence by
recursively sorting its two halves in opposite directions, and then
calls bitonicMerge.
**/
void bitonic_sort( int lo, int cnt, int dir )
{
int k = cnt;
k /= 2;
_Pragma( "marker recMerge" )
if ( cnt > 1 ) {
bitonic_sort( lo, k, bitonic_ASCENDING );
bitonic_sort( lo + k, k, bitonic_DESCENDING );
}
bitonic_merge( lo, cnt, dir );
_Pragma( "flowrestriction 1*bitonicMerge <= 31*recMerge" )
return;
}
/*
Main functions
*/
void _Pragma ( "entrypoint" ) bitonic_main( void )
{
int i;
/** When called with parameters lo = 0, cnt = a.length() and dir =
ASCENDING, procedure bitonicSort sorts the whole array a. **/
_Pragma( "marker recSort" )
bitonic_sort( 0, 32, bitonic_ASCENDING );
_Pragma( "flowrestriction 1*bitonicSort <= 63*recSort" )
/** Loop through array, printing out each element **/
_Pragma( "loopbound min 32 max 32" )
for ( i = 0; i < 32; i++ ) {
}
}
int main( void )
{
bitonic_init();
bitonic_main();
return ( bitonic_return() );
}

View File

@ -0,0 +1,215 @@
(module $bitonic.wasm
(type (;0;) (func (param i32 i32)))
(type (;1;) (func))
(type (;2;) (func (param i32 i32 i32)))
(type (;3;) (func (result i32)))
(import "__pragma" "loopbound" (func $__pragma_loopbound (type 0)))
(func $__wasm_apply_data_relocs (type 1))
(func $bitonic_merge (type 2) (param i32 i32 i32)
(local i32 i32 i32 i32 i32 i32 i32 i32 i32)
i32.const 0
i32.const 16
call $__pragma_loopbound
block ;; label = @1
local.get 1
i32.const 2
i32.lt_s
br_if 0 (;@1;)
local.get 1
i32.const 1
i32.shr_u
local.tee 3
local.get 0
i32.add
local.set 4
loop ;; label = @2
local.get 4
local.set 5
local.get 0
i32.const 2
i32.shl
local.set 4
local.get 3
local.tee 6
i32.const 2
i32.shl
i32.const 1024
i32.add
local.set 7
local.get 0
local.set 3
loop ;; label = @3
block ;; label = @4
local.get 4
i32.const 1024
i32.add
local.tee 8
i32.load
local.tee 9
local.get 7
local.get 4
i32.add
local.tee 10
i32.load
local.tee 11
i32.gt_s
local.get 2
i32.ne
br_if 0 (;@4;)
local.get 8
local.get 11
i32.store
local.get 10
local.get 9
i32.store
end
local.get 4
i32.const 4
i32.add
local.set 4
local.get 3
i32.const 1
i32.add
local.tee 3
local.get 5
i32.lt_s
br_if 0 (;@3;)
end
local.get 1
i32.const 4
i32.lt_s
br_if 1 (;@1;)
local.get 0
local.get 6
local.get 2
call $bitonic_merge
i32.const 0
i32.const 16
call $__pragma_loopbound
local.get 6
i32.const 2
i32.div_s
local.tee 3
local.get 5
i32.add
local.set 4
local.get 6
local.set 1
local.get 5
local.set 0
local.get 6
i32.const 1
i32.gt_s
br_if 0 (;@2;)
end
end)
(func $bitonic_sort (type 2) (param i32 i32 i32)
(local i32)
block ;; label = @1
local.get 1
i32.const 2
i32.lt_s
br_if 0 (;@1;)
local.get 0
local.get 1
i32.const 1
i32.shr_u
local.tee 3
i32.const 1
call $bitonic_sort
local.get 3
local.get 0
i32.add
local.get 3
i32.const 0
call $bitonic_sort
end
local.get 0
local.get 1
local.get 2
call $bitonic_merge)
(func $bitonic_main (type 1)
i32.const 0
i32.const 32
i32.const 1
call $bitonic_sort
i32.const 32
i32.const 32
call $__pragma_loopbound)
(func $__original_main (type 3) (result i32)
i32.const 32
i32.const 32
call $__pragma_loopbound
i32.const 0
i64.const 4294967298
i64.store offset=1144
i32.const 0
i64.const 12884901892
i64.store offset=1136
i32.const 0
i64.const 21474836486
i64.store offset=1128
i32.const 0
i64.const 30064771080
i64.store offset=1120
i32.const 0
i64.const 38654705674
i64.store offset=1112
i32.const 0
i64.const 47244640268
i64.store offset=1104
i32.const 0
i64.const 55834574862
i64.store offset=1096
i32.const 0
i64.const 64424509456
i64.store offset=1088
i32.const 0
i64.const 73014444050
i64.store offset=1080
i32.const 0
i64.const 81604378644
i64.store offset=1072
i32.const 0
i64.const 90194313238
i64.store offset=1064
i32.const 0
i64.const 98784247832
i64.store offset=1056
i32.const 0
i64.const 107374182426
i64.store offset=1048
i32.const 0
i64.const 115964117020
i64.store offset=1040
i32.const 0
i64.const 124554051614
i64.store offset=1032
i32.const 0
i64.const 133143986208
i64.store offset=1024
call $bitonic_main
i32.const -1
i32.const 0
i32.const 0
i32.load offset=1108
i32.const 0
i32.load offset=1024
i32.add
i32.const 0
i32.load offset=1148
i32.add
i32.const 55
i32.ne
select)
(table (;0;) 1 1 funcref)
(memory (;0;) 1)
(global $__stack_pointer (mut i32) (i32.const 5248))
(global (;1;) i32 (i32.const 1152))
(global (;2;) i32 (i32.const 5248))
(export "memory" (memory 0))
(export "__wasm_apply_data_relocs" (func $__wasm_apply_data_relocs))
(export "entrypoint" (func $bitonic_main))
(export "main" (func $__original_main))
(export "__data_end" (global 1))
(export "__heap_base" (global 2)))

View File

@ -0,0 +1,154 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: bitonic
Author: Chris Leger
Function: bitonic implements a recursive sorting network algorithm.
Source: MiBench
http://wwweb.eecs.umich.edu/mibench
Changes: no major functional changes
License: MIT
*/
/*
Forward declaration of functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
void bitonic_init(void);
int bitonic_return(void);
void bitonic_compare(int i, int j, int dir);
void bitonic_merge(int lo, int cnt, int dir);
void bitonic_sort(int lo, int cnt, int dir);
__attribute__((noinline)) __attribute__((export_name("main"))) int main(void);
/*
Declaration of global variables
*/
int bitonic_numiters = 10;
int bitonic_a[32]; // the array to be sorted
const int bitonic_ASCENDING = 1;
const int bitonic_DESCENDING = 0;
const int bitonic_CHECKSUM = 55;
/*
Initialization- and return-value-related functions
*/
void
bitonic_init(void) {
/** Initialize array "a" with data **/
int i;
__pragma_loopbound(32, 32);
for (i = 0; i < 32; i++)
bitonic_a[i] = (32 - i);
}
int
bitonic_return(void) {
int checksum = 0;
checksum += bitonic_a[0] + bitonic_a[21] + bitonic_a[31];
return ((checksum == bitonic_CHECKSUM) ? 0 : -1);
}
/*
Algorithm core functions
*/
/** A comparator is modelled by the procedure compare, where the
parameter dir indicates the sorting direction. If dir is ASCENDING
and a[i] > a[j] is true or dir is DESCENDING and a[i] > a[j] is
false then a[i] and a[j] are interchanged.
**/
void
bitonic_compare(int i, int j, int dir) {
if (dir == (bitonic_a[i] > bitonic_a[j])) {
int h = bitonic_a[i];
bitonic_a[i] = bitonic_a[j];
bitonic_a[j] = h;
}
}
/** The procedure bitonicMerge recursively sorts a bitonic sequence in
ascending order, if dir = ASCENDING, and in descending order
otherwise. The sequence to be sorted starts at index position lo,
the number of elements is cnt.
**/
void
bitonic_merge(int lo, int cnt, int dir) {
int k = cnt / 2;
int i;
__pragma_loopbound(0, 16);
for (i = lo; i < lo + k; i++)
bitonic_compare(i, i + k, dir);
if (k > 1) {
bitonic_merge(lo, k, dir);
bitonic_merge(lo + k, k, dir);
}
}
/** Procedure bitonicSort first produces a bitonic sequence by
recursively sorting its two halves in opposite directions, and then
calls bitonicMerge.
**/
void
bitonic_sort(int lo, int cnt, int dir) {
int k = cnt;
k /= 2;
_Pragma("marker recMerge")
if (cnt > 1) {
bitonic_sort(lo, k, bitonic_ASCENDING);
bitonic_sort(lo + k, k, bitonic_DESCENDING);
}
bitonic_merge(lo, cnt, dir);
_Pragma("flowrestriction 1*bitonicMerge <= 31*recMerge")
return;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
bitonic_main(void) {
int i;
/** When called with parameters lo = 0, cnt = a.length() and dir =
ASCENDING, procedure bitonicSort sorts the whole array a. **/
_Pragma("marker recSort") bitonic_sort(0, 32, bitonic_ASCENDING);
_Pragma("flowrestriction 1*bitonicSort <= 63*recSort")
/** Loop through array, printing out each element **/
__pragma_loopbound(32, 32);
for (i = 0; i < 32; i++) {
}
}
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
bitonic_init();
bitonic_main();
return (bitonic_return());
}

View File

@ -0,0 +1,164 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: bitonic
Author: Chris Leger
Function: bitonic implements a recursive sorting network algorithm.
Source: MiBench
http://wwweb.eecs.umich.edu/mibench
Changes: no major functional changes
License: MIT
*/
/*
Forward declaration of functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline void bitonic_init(void);
__attribute__((always_inline)) static inline int bitonic_return(void);
__attribute__((always_inline)) static inline void bitonic_compare(int i, int j,
int dir);
__attribute__((always_inline)) static inline void bitonic_merge(int lo, int cnt,
int dir);
__attribute__((always_inline)) static inline void bitonic_sort(int lo, int cnt,
int dir);
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void);
/*
Declaration of global variables
*/
int bitonic_numiters = 10;
int bitonic_a[32]; // the array to be sorted
const int bitonic_ASCENDING = 1;
const int bitonic_DESCENDING = 0;
const int bitonic_CHECKSUM = 55;
/*
Initialization- and return-value-related functions
*/
__attribute__((always_inline)) static inline void
bitonic_init(void) {
/** Initialize array "a" with data **/
int i;
__pragma_loopbound(32, 32);
for (i = 0; i < 32; i++)
bitonic_a[i] = (32 - i);
}
__attribute__((always_inline)) static inline int
bitonic_return(void) {
int checksum = 0;
checksum += bitonic_a[0] + bitonic_a[21] + bitonic_a[31];
return ((checksum == bitonic_CHECKSUM) ? 0 : -1);
}
/*
Algorithm core functions
*/
/** A comparator is modelled by the procedure compare, where the
parameter dir indicates the sorting direction. If dir is ASCENDING
and a[i] > a[j] is true or dir is DESCENDING and a[i] > a[j] is
false then a[i] and a[j] are interchanged.
**/
__attribute__((always_inline)) static inline void
bitonic_compare(int i, int j, int dir) {
if (dir == (bitonic_a[i] > bitonic_a[j])) {
int h = bitonic_a[i];
bitonic_a[i] = bitonic_a[j];
bitonic_a[j] = h;
}
}
/** The procedure bitonicMerge recursively sorts a bitonic sequence in
ascending order, if dir = ASCENDING, and in descending order
otherwise. The sequence to be sorted starts at index position lo,
the number of elements is cnt.
**/
__attribute__((always_inline)) static inline void
bitonic_merge(int lo, int cnt, int dir) {
int k = cnt / 2;
int i;
__pragma_loopbound(0, 16);
for (i = lo; i < lo + k; i++)
bitonic_compare(i, i + k, dir);
if (k > 1) {
bitonic_merge(lo, k, dir);
bitonic_merge(lo + k, k, dir);
}
}
/** Procedure bitonicSort first produces a bitonic sequence by
recursively sorting its two halves in opposite directions, and then
calls bitonicMerge.
**/
__attribute__((always_inline)) static inline void
bitonic_sort(int lo, int cnt, int dir) {
int k = cnt;
k /= 2;
_Pragma("marker recMerge")
if (cnt > 1) {
bitonic_sort(lo, k, bitonic_ASCENDING);
bitonic_sort(lo + k, k, bitonic_DESCENDING);
}
bitonic_merge(lo, cnt, dir);
_Pragma("flowrestriction 1*bitonicMerge <= 31*recMerge")
return;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
bitonic_main(void) {
int i;
/** When called with parameters lo = 0, cnt = a.length() and dir =
ASCENDING, procedure bitonicSort sorts the whole array a. **/
_Pragma("marker recSort") bitonic_sort(0, 32, bitonic_ASCENDING);
_Pragma("flowrestriction 1*bitonicSort <= 63*recSort")
/** Loop through array, printing out each element **/
__pragma_loopbound(32, 32);
for (i = 0; i < 32; i++) {
}
}
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
bitonic_init();
bitonic_main();
return (bitonic_return());
}

View File

@ -0,0 +1,21 @@
The MIT License
Copyright (c) <year> <copyright holders>
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.