| #!/bin/bash |
| |
| # Script to measure memset and memcpy for different sizes and strategies. |
| # |
| # Contributed by Jan Hubicka <jh@suse.cz> |
| # |
| # Copyright (C) 2019 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 COPYING. If not, write to |
| # the Free Software Foundation, 51 Franklin Street, Fifth Floor, |
| # Boston, MA 02110-1301, USA. |
| |
| # This script will search a line starting with 'spawn' that includes the |
| # pattern you are looking for (typically a source file name). |
| # |
| # Once it finds that pattern, it re-executes the whole command |
| # in the spawn line. If the pattern matches more than one spawn |
| # command, it asks which one you want. |
| |
| test() |
| { |
| rm -f a.out |
| cat <<END | $1 -x c -O3 $3 -DAVG_SIZE=$2 $STRINGOP -DMEMORY_COPIES=$memsize - |
| #define BUFFER_SIZE (16*1024*1024 + AVG_SIZE*2) |
| /*#define MEMORY_COPIES (1024*1024*64*(long long)10)*/ |
| $type t[BUFFER_SIZE]; |
| int main() |
| { |
| unsigned int i; |
| for (i=0;i<((long long)MEMORY_COPIES + AVG_SIZE * 2 - 1)/AVG_SIZE*2;i++) |
| #ifdef test_memset |
| __builtin_memset (t+(i*1024*1024+i*1)%(BUFFER_SIZE - AVG_SIZE*2), i, (AVG_SIZE + i) % (AVG_SIZE * 2 + 0)); |
| #else |
| __builtin_memcpy (t+(i*1024*1024+i*1)%(BUFFER_SIZE - AVG_SIZE*2), t+((i+1)*1024*1024*4+i*1)%(BUFFER_SIZE - AVG_SIZE *2), (AVG_SIZE + i) % (AVG_SIZE * 2 + 0)); |
| #endif |
| return 0; |
| } |
| END |
| TIME=`/usr/bin/time -f "%E" ./a.out 2>&1` |
| echo -n " "$TIME |
| echo $TIME $4 >>/tmp/accum |
| } |
| |
| test2() |
| { |
| rm -f a.out |
| cat <<END | clang -x c -O3 $3 -DAVG_SIZE=$2 $STRINGOP -DMEMORY_COPIES=$memsize 2>/dev/null - |
| #define BUFFER_SIZE (16*1024*1024 + AVG_SIZE*2) |
| /*#define MEMORY_COPIES (1024*1024*64*(long long)10)*/ |
| $type t[BUFFER_SIZE]; |
| int main() |
| { |
| unsigned int i; |
| for (i=0;i<((long long)MEMORY_COPIES + AVG_SIZE * 2 - 1)/AVG_SIZE*2;i++) |
| #ifdef test_memset |
| __builtin_memset (t+(i*1024*1024+i*1)%(BUFFER_SIZE - AVG_SIZE*2), i, (AVG_SIZE + i) % (AVG_SIZE * 2 + 0)); |
| #else |
| __builtin_memcpy (t+(i*1024*1024+i*1)%(BUFFER_SIZE - AVG_SIZE*2), t+((i+1)*1024*1024*4+i*1)%(BUFFER_SIZE - AVG_SIZE *2), (AVG_SIZE + i) % (AVG_SIZE * 2 + 0)); |
| #endif |
| return 0; |
| } |
| END |
| TIME=`/usr/bin/time -f "%E" ./a.out 2>&1` |
| echo -n " "$TIME |
| echo $TIME $4 >>/tmp/accum |
| } |
| |
| testrow() |
| { |
| echo -n "" >/tmp/accum |
| printf "%12i " $3 |
| test "$2" "$3" "-mstringop-strategy=libcall" libcall |
| test "$2" "$3" "-mstringop-strategy=rep_byte -malign-stringops" rep1 |
| test "$2" "$3" "-mstringop-strategy=rep_byte -mno-align-stringops" rep1noalign |
| test "$2" "$3" "-mstringop-strategy=rep_4byte -malign-stringops" rep4 |
| test "$2" "$3" "-mstringop-strategy=rep_4byte -mno-align-stringops" rep4noalign |
| if [ "$mode" == 64 ] |
| then |
| test "$2" "$3" "-mstringop-strategy=rep_8byte -malign-stringops" rep8 |
| test "$2" "$3" "-mstringop-strategy=rep_8byte -mno-align-stringops" rep8noalign |
| fi |
| test "$2" "$3" "-mstringop-strategy=loop -malign-stringops" loop |
| test "$2" "$3" "-mstringop-strategy=loop -mno-align-stringops" loopnoalign |
| test "$2" "$3" "-mstringop-strategy=unrolled_loop -malign-stringops" unrl |
| test "$2" "$3" "-mstringop-strategy=unrolled_loop -mno-align-stringops" unrlnoalign |
| test "$2" "$3" "-mstringop-strategy=vector_loop -malign-stringops" sse |
| test "$2" "$3" "-mstringop-strategy=vector_loop -mno-align-stringops -msse2" ssenoalign |
| #test2 "$2" "$3" "" |
| test "$2" "$3" "-mstringop-strategy=byte_loop" byte |
| best=`cat /tmp/accum | sort | head -1` |
| test "$2" "$3" " -fprofile-generate" >/dev/null 2>&1 |
| test "$2" "$3" " -fprofile-use" |
| test "$2" "$3" " -minline-stringops-dynamically" |
| echo " $best" |
| } |
| |
| test_all_sizes() |
| { |
| if [ "$mode" == 64 ] |
| then |
| echo " block size libcall rep1 noalg rep4 noalg rep8 noalg loop noalg unrl noalg sse noalg byte PGO dynamic BEST" |
| else |
| echo " block size libcall rep1 noalg rep4 noalg loop noalg unrl noalg sse noalg byte PGO dynamic BEST" |
| fi |
| #for size in 1 2 3 4 6 8 10 12 14 16 24 32 48 64 128 256 512 1024 4096 8192 81920 819200 8192000 |
| #for size in 8192000 819200 81920 8192 4096 2048 1024 512 256 128 64 48 32 24 16 14 12 10 8 6 5 4 3 2 1 |
| for size in 8192000 819200 81920 20480 8192 4096 2048 1024 512 256 128 64 48 32 24 16 14 12 10 8 6 4 1 |
| #for size in 128 256 1024 4096 8192 81920 819200 |
| do |
| testrow "$1" "$2" $size |
| done |
| } |
| |
| mode=$1 |
| shift |
| export memsize=$1 |
| shift |
| cmdline=$* |
| if [ "$mode" != 32 ] |
| then |
| if [ "$mode" != 64 ] |
| then |
| echo "Usage:" |
| echo "test_stringop mode size cmdline" |
| echo "mode is either 32 or 64" |
| echo "size is amount of memory copied in each test. Should be chosed small enough so runtime is less than minute for each test and sorting works" |
| echo "Example: test_stringop 32 640000000 ./xgcc -B ./ -march=pentium3" |
| exit |
| fi |
| fi |
| |
| echo "memcpy" |
| export STRINGOP="" |
| type=char |
| test_all_sizes $mode "$cmdline -m$mode" |
| echo "Aligned" |
| type=long |
| test_all_sizes $mode "$cmdline -m$mode" |
| echo "memset" |
| export STRINGOP="-Dtest_memset=1" |
| type=char |
| test_all_sizes $mode "$cmdline -m$mode" |
| echo "Aligned" |
| type=long |
| test_all_sizes $mode "$cmdline -m$mode" |