1 #!/bin/bash 2 # 3 # Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. 4 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 # 6 # This code is free software; you can redistribute it and/or modify it 7 # under the terms of the GNU General Public License version 2 only, as 8 # published by the Free Software Foundation. Oracle designates this 9 # particular file as subject to the "Classpath" exception as provided 10 # by Oracle in the LICENSE file that accompanied this code. 11 # 12 # This code is distributed in the hope that it will be useful, but WITHOUT 13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 # version 2 for more details (a copy is included in the LICENSE file that 16 # accompanied this code). 17 # 18 # You should have received a copy of the GNU General Public License version 19 # 2 along with this work; if not, write to the Free Software Foundation, 20 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 # 22 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 # or visit www.oracle.com if you need additional information or have any 24 # questions. 25 # 26 27 generate_perf_tests=$1 28 29 TEMPLATE_FOLDER="templates/" 30 31 unit_output="unit_tests.template" 32 perf_output="perf_tests.template" 33 perf_scalar_output="perf_scalar_tests.template" 34 35 unary="Unary-op" 36 unary_masked="Unary-Masked-op" 37 unary_scalar="Unary-Scalar-op" 38 ternary="Ternary-op" 39 ternary_masked="Ternary-Masked-op" 40 ternary_scalar="Ternary-Scalar-op" 41 binary="Binary-op" 42 binary_masked="Binary-Masked-op" 43 binary_broadcast="Binary-Broadcast-op" 44 binary_broadcast_masked="Binary-Broadcast-Masked-op" 45 binary_scalar="Binary-Scalar-op" 46 blend="Blend-op" 47 test_template="Test" 48 compare_template="Compare" 49 reduction_scalar="Reduction-Scalar-op" 50 reduction_scalar_min="Reduction-Scalar-Min-op" 51 reduction_scalar_max="Reduction-Scalar-Max-op" 52 reduction_scalar_masked="Reduction-Scalar-Masked-op" 53 reduction_scalar_min_masked="Reduction-Scalar-Masked-Min-op" 54 reduction_scalar_max_masked="Reduction-Scalar-Masked-Max-op" 55 reduction_op="Reduction-op" 56 reduction_op_min="Reduction-Min-op" 57 reduction_op_max="Reduction-Max-op" 58 reduction_op_masked="Reduction-Masked-op" 59 reduction_op_min_masked="Reduction-Masked-Min-op" 60 reduction_op_max_masked="Reduction-Masked-Max-op" 61 unary_math_template="Unary-op-math" 62 binary_math_template="Binary-op-math" 63 bool_reduction_scalar="BoolReduction-Scalar-op" 64 bool_reduction_template="BoolReduction-op" 65 with_op_template="With-Op" 66 shift_template="Shift-op" 67 shift_masked_template="Shift-Masked-op" 68 gather_template="Gather-op" 69 gather_masked_template="Gather-Masked-op" 70 scatter_template="Scatter-op" 71 scatter_masked_template="Scatter-Masked-op" 72 get_template="Get-op" 73 rearrange_template="Rearrange" 74 broadcast_template="Broadcast" 75 zero_template="Zero" 76 slice_template="Slice-op" 77 slice1_template="Slice-bop" 78 slice1_masked_template="Slice-Masked-bop" 79 unslice_template="Unslice-op" 80 unslice1_template="Unslice-bop" 81 unslice1_masked_template="Unslice-Masked-bop" 82 83 function replace_variables { 84 local filename=$1 85 local output=$2 86 local kernel=$3 87 local test=$4 88 local op=$5 89 local init=$6 90 local guard=$7 91 local masked=$8 92 local op_name=$9 93 94 if [ "x${kernel}" != "x" ]; then 95 local kernel_escaped=$(echo -e "$kernel" | tr '\n' '|') 96 sed "s/\[\[KERNEL\]\]/${kernel_escaped}/g" $filename > ${filename}.current1 97 cat ${filename}.current1 | tr '|' "\n" > ${filename}.current 98 rm -f "${filename}.current1" 99 else 100 cp $filename ${filename}.current 101 fi 102 103 # Check if we need to do multiple replacements 104 # If you want to emit for an operation using lanewise(VectorOperator.**, ..) and also using dedicated instruction (e.g. add(..)), then 105 # pass the 'test' argument as "OPERATOR_NAME+func_Name" (e.g. "ADD+add") 106 # if there is a masked version available for the operation add "withMask" to 'test' argument (e.g. "ADD+add+withMask") 107 local test_func="" 108 local withMask="" 109 local tests=($(awk -F+ '{$1=$1} 1' <<< $test)) 110 if [ "${tests[2]}" == "withMask" ]; then 111 test=${tests[0]} 112 test_func=${tests[1]} 113 withMask=${tests[2]} 114 elif [ "${tests[1]}" == "withMask" ]; then 115 test="" 116 test_func=${tests[0]} 117 withMask=${tests[1]} 118 elif [ "${tests[1]}" != "" ]; then 119 test=${tests[0]} 120 test_func=${tests[1]} 121 fi 122 123 sed_prog=" 124 s/\<OPTIONAL\>\(.*\)\<\\OPTIONAL\>/\1/g 125 s/\[\[TEST_TYPE\]\]/${masked}/g 126 s/\[\[TEST_OP\]\]/${op}/g 127 s/\[\[TEST_INIT\]\]/${init}/g 128 s/\[\[OP_NAME\]\]/${op_name}/g 129 " 130 sed_prog_2="$sed_prog 131 s/\[\[TEST\]\]/${test_func}/g 132 s/[.][^(]*(VectorOperators.$test_func, /.$test_func(/g 133 s/[.][^(]*(VectorOperators.$test_func,/.$test_func(/g 134 s/[.][^(]*(VectorOperators.$test_func/.$test_func(/g 135 " 136 sed_prog=" 137 $sed_prog 138 s/\[\[TEST\]\]/${test}/g 139 " 140 141 # Guard the test if necessary 142 if [ "$guard" != "" ]; then 143 echo -e "#if[${guard}]\n" >> $output 144 fi 145 if [ "$test" != "" ]; then 146 sed -e "$sed_prog" < ${filename}.current >> $output 147 fi 148 # If we also have a dedicated function for the operation then use 2nd sed expression 149 if [[ "$filename" == *"Unit"* ]] && [ "$test_func" != "" ]; then 150 if [ "$masked" == "" ] || [ "$withMask" != "" ]; then 151 sed -e "$sed_prog_2" < ${filename}.current >> $output 152 fi 153 fi 154 if [ "$guard" != "" ]; then 155 echo -e "#end[${guard}]\n" >> $output 156 fi 157 158 rm -f ${filename}.current 159 } 160 161 function gen_op_tmpl { 162 local template=$1 163 local test=$2 164 local op=$3 165 local guard="" 166 local init="" 167 if [ $# -gt 3 ]; then 168 guard=$4 169 fi 170 if [ $# == 5 ]; then 171 init=$5 172 fi 173 174 local masked="" 175 if [[ $template == *"Masked"* ]]; then 176 masked="Masked" 177 fi 178 179 local op_name="" 180 if [[ $template == *"Shift"* ]]; then 181 op_name="Shift" 182 elif [[ $template == *"Get"* ]]; then 183 op_name="extract" 184 fi 185 186 local kernel_filename="${TEMPLATE_FOLDER}/Kernel-${template}.template" 187 local unit_filename="${TEMPLATE_FOLDER}/Unit-${template}.template" 188 if [ ! -f $unit_filename ]; then 189 # Leverage general unit code snippet if no specialization exists 190 unit_filename="${TEMPLATE_FOLDER}/Unit-${template%_*}.template" 191 echo $unit_filename 192 fi 193 194 local kernel="" 195 if [ -f $kernel_filename ]; then 196 kernel="$(cat $kernel_filename)" 197 fi 198 199 # Replace template variables in unit test files (if any) 200 replace_variables $unit_filename $unit_output "$kernel" "$test" "$op" "$init" "$guard" "$masked" "$op_name" 201 202 local gen_perf_tests=$generate_perf_tests 203 if [[ $template == *"-Broadcast-"* ]]; then 204 gen_perf_tests=false 205 fi 206 if [ $gen_perf_tests == true ]; then 207 # Replace template variables in performance test files (if any) 208 local perf_wrapper_filename="${TEMPLATE_FOLDER}/Perf-wrapper.template" 209 local perf_vector_filename="${TEMPLATE_FOLDER}/Perf-${template}.template" 210 local perf_scalar_filename="${TEMPLATE_FOLDER}/Perf-Scalar-${template}.template" 211 212 if [ -f $perf_vector_filename ]; then 213 replace_variables $perf_vector_filename $perf_output "$kernel" "$test" "$op" "$init" "$guard" "$masked" "$op_name" 214 elif [ -f $kernel_filename ]; then 215 replace_variables $perf_wrapper_filename $perf_output "$kernel" "$test" "$op" "$init" "$guard" "$masked" "$op_name" 216 elif [[ $template != *"-Scalar-"* ]] && [[ $template != "Get-op" ]] && [[ $template != "With-Op" ]]; then 217 echo "Warning: missing perf: $@" 218 fi 219 220 if [ -f $perf_scalar_filename ]; then 221 replace_variables $perf_scalar_filename $perf_scalar_output "$kernel" "$test" "$op" "$init" "$guard" "$masked" "$op_name" 222 elif [[ $template != *"-Scalar-"* ]] && [[ $template != "Get-op" ]] && [[ $template != "With-Op" ]]; then 223 echo "Warning: Missing PERF SCALAR: $perf_scalar_filename" 224 fi 225 fi 226 } 227 228 function gen_binary_alu_op { 229 echo "Generating binary op $1 ($2)..." 230 gen_op_tmpl $binary "$@" 231 gen_op_tmpl $binary_masked "$@" 232 } 233 234 function gen_binary_alu_bcst_op { 235 echo "Generating binary broadcast op $1 ($2)..." 236 gen_op_tmpl $binary_broadcast "$@" 237 gen_op_tmpl $binary_broadcast_masked "$@" 238 } 239 240 function gen_shift_cst_op { 241 echo "Generating Shift constant op $1 ($2)..." 242 gen_op_tmpl $shift_template "$@" 243 gen_op_tmpl $shift_masked_template "$@" 244 } 245 246 function gen_unary_alu_op { 247 echo "Generating unary op $1 ($2)..." 248 gen_op_tmpl $unary_scalar "$@" 249 gen_op_tmpl $unary "$@" 250 gen_op_tmpl $unary_masked "$@" 251 } 252 253 function gen_ternary_alu_op { 254 echo "Generating ternary op $1 ($2)..." 255 gen_op_tmpl $ternary_scalar "$@" 256 gen_op_tmpl $ternary "$@" 257 gen_op_tmpl $ternary_masked "$@" 258 } 259 260 function gen_binary_op { 261 echo "Generating binary op $1 ($2)..." 262 # gen_op_tmpl $binary_scalar "$@" 263 gen_op_tmpl $binary "$@" 264 gen_op_tmpl $binary_masked "$@" 265 } 266 267 function gen_binary_op_no_masked { 268 echo "Generating binary op $1 ($2)..." 269 # gen_op_tmpl $binary_scalar "$@" 270 gen_op_tmpl $binary "$@" 271 } 272 273 function gen_binary_bcst_op_no_masked { 274 echo "Generating binary op $1 ($2)..." 275 gen_op_tmpl $binary_broadcast "$@" 276 } 277 278 function gen_reduction_op { 279 echo "Generating reduction op $1 ($2)..." 280 gen_op_tmpl $reduction_scalar "$@" 281 gen_op_tmpl $reduction_op "$@" 282 gen_op_tmpl $reduction_scalar_masked "$@" 283 gen_op_tmpl $reduction_op_masked "$@" 284 } 285 286 function gen_reduction_op_min { 287 echo "Generating reduction op $1 ($2)..." 288 gen_op_tmpl $reduction_scalar_min "$@" 289 gen_op_tmpl $reduction_op_min "$@" 290 gen_op_tmpl $reduction_scalar_min_masked "$@" 291 gen_op_tmpl $reduction_op_min_masked "$@" 292 } 293 294 function gen_reduction_op_max { 295 echo "Generating reduction op $1 ($2)..." 296 gen_op_tmpl $reduction_scalar_max "$@" 297 gen_op_tmpl $reduction_op_max "$@" 298 gen_op_tmpl $reduction_scalar_max_masked "$@" 299 gen_op_tmpl $reduction_op_max_masked "$@" 300 } 301 302 function gen_bool_reduction_op { 303 echo "Generating boolean reduction op $1 ($2)..." 304 gen_op_tmpl $bool_reduction_scalar "$@" 305 gen_op_tmpl $bool_reduction_template "$@" 306 } 307 308 function gen_with_op { 309 echo "Generating with op $1 ($2)..." 310 gen_op_tmpl $with_op_template "$@" 311 } 312 313 function gen_get_op { 314 echo "Generating get op $1 ($2)..." 315 gen_op_tmpl $get_template "$@" 316 } 317 318 function gen_unit_header { 319 cat $TEMPLATE_FOLDER/Unit-header.template > $1 320 } 321 322 function gen_unit_footer { 323 cat $TEMPLATE_FOLDER/Unit-footer.template >> $1 324 } 325 326 function gen_perf_header { 327 cat $TEMPLATE_FOLDER/Perf-header.template > $1 328 } 329 330 function gen_perf_footer { 331 cat $TEMPLATE_FOLDER/Perf-footer.template >> $1 332 } 333 334 function gen_perf_scalar_header { 335 cat $TEMPLATE_FOLDER/Perf-Scalar-header.template > $1 336 } 337 338 function gen_perf_scalar_footer { 339 cat $TEMPLATE_FOLDER/Perf-Scalar-footer.template >> $1 340 } 341 342 gen_unit_header $unit_output 343 344 if [ $generate_perf_tests == true ]; then 345 gen_perf_header $perf_output 346 gen_perf_scalar_header $perf_scalar_output 347 fi 348 349 # ALU binary ops. 350 # Here "ADD+add+withMask" says VectorOperator name is "ADD", and we have a dedicate method too named 'add', and add() is also available with mask variant. 351 gen_binary_alu_op "ADD+add+withMask" "a + b" 352 gen_binary_alu_op "SUB+sub+withMask" "a - b" 353 gen_binary_alu_op "MUL+mul+withMask" "a \* b" 354 gen_binary_alu_op "DIV+div+withMask" "a \/ b" "FP" 355 gen_op_tmpl "Binary-op_bitwise-div" "DIV+div+withMask" "a \/ b" "BITWISE" 356 gen_op_tmpl "Binary-Masked-op_bitwise-div" "DIV+div+withMask" "a \/ b" "BITWISE" 357 gen_binary_alu_op "FIRST_NONZERO" "{#if[FP]?Double.doubleToLongBits}(a)!=0?a:b" 358 gen_binary_alu_op "AND+and" "a \& b" "BITWISE" 359 gen_binary_alu_op "AND_NOT" "a \& ~b" "BITWISE" 360 gen_binary_alu_op "OR+or" "a | b" "BITWISE" 361 # Missing: "OR_UNCHECKED" 362 gen_binary_alu_op "XOR" "a ^ b" "BITWISE" 363 # Generate the broadcast versions 364 gen_binary_alu_bcst_op "add+withMask" "a + b" 365 gen_binary_alu_bcst_op "sub+withMask" "a - b" 366 gen_binary_alu_bcst_op "mul+withMask" "a \* b" 367 gen_binary_alu_bcst_op "div+withMask" "a \/ b" "FP" 368 gen_op_tmpl "Binary-op_bitwise-Broadcast-div" "div+withMask" "a \/ b" "BITWISE" 369 gen_op_tmpl "Binary-Masked-op_bitwise-Broadcast-div" "div+withMask" "a \/ b" "BITWISE" 370 gen_binary_alu_bcst_op "OR+or" "a | b" "BITWISE" 371 372 # Shifts 373 gen_binary_alu_op "LSHL" "(a << b)" "intOrLong" 374 gen_binary_alu_op "LSHL" "(a << (b \& 0x7))" "byte" 375 gen_binary_alu_op "LSHL" "(a << (b \& 0xF))" "short" 376 gen_binary_alu_op "ASHR" "(a >> b)" "intOrLong" 377 gen_binary_alu_op "ASHR" "(a >> (b \& 0x7))" "byte" 378 gen_binary_alu_op "ASHR" "(a >> (b \& 0xF))" "short" 379 gen_binary_alu_op "LSHR" "(a >>> b)" "intOrLong" 380 gen_binary_alu_op "LSHR" "((a \& 0xFF) >>> (b \& 0x7))" "byte" 381 gen_binary_alu_op "LSHR" "((a \& 0xFFFF) >>> (b \& 0xF))" "short" 382 gen_shift_cst_op "LSHL" "(a << b)" "intOrLong" 383 gen_shift_cst_op "LSHL" "(a << (b \& 7))" "byte" 384 gen_shift_cst_op "LSHL" "(a << (b \& 15))" "short" 385 gen_shift_cst_op "LSHR" "(a >>> b)" "intOrLong" 386 gen_shift_cst_op "LSHR" "((a \& 0xFF) >>> (b \& 7))" "byte" 387 gen_shift_cst_op "LSHR" "((a \& 0xFFFF) >>> (b \& 15))" "short" 388 gen_shift_cst_op "ASHR" "(a >> b)" "intOrLong" 389 gen_shift_cst_op "ASHR" "(a >> (b \& 7))" "byte" 390 gen_shift_cst_op "ASHR" "(a >> (b \& 15))" "short" 391 392 # Masked reductions. 393 gen_binary_op_no_masked "MIN+min" "Math.min(a, b)" 394 gen_binary_op_no_masked "MAX+max" "Math.max(a, b)" 395 gen_binary_bcst_op_no_masked "MIN+min" "Math.min(a, b)" 396 gen_binary_bcst_op_no_masked "MAX+max" "Math.max(a, b)" 397 398 # Reductions. 399 gen_reduction_op "AND" "\&" "BITWISE" "-1" 400 gen_reduction_op "OR" "|" "BITWISE" "0" 401 gen_reduction_op "XOR" "^" "BITWISE" "0" 402 gen_reduction_op "ADD" "+" "" "0" 403 gen_reduction_op "MUL" "*" "" "1" 404 gen_reduction_op_min "MIN" "" "" "\$Wideboxtype\$.\$MaxValue\$" 405 gen_reduction_op_max "MAX" "" "" "\$Wideboxtype\$.\$MinValue\$" 406 #gen_reduction_op "reduce_FIRST_NONZERO" "lanewise_FIRST_NONZERO" "{#if[FP]?Double.doubleToLongBits}(a)=0?a:b" "" "1" 407 408 # Boolean reductions. 409 gen_bool_reduction_op "anyTrue" "|" "BITWISE" "false" 410 gen_bool_reduction_op "allTrue" "\&" "BITWISE" "true" 411 412 #Insert 413 gen_with_op "withLane" "" "" "" 414 415 # Tests 416 gen_op_tmpl $test_template "IS_DEFAULT" "bits(a)==0" 417 gen_op_tmpl $test_template "IS_NEGATIVE" "bits(a)<0" 418 gen_op_tmpl $test_template "IS_FINITE" "\$Boxtype\$.isFinite(a)" "FP" 419 gen_op_tmpl $test_template "IS_NAN" "\$Boxtype\$.isNaN(a)" "FP" 420 gen_op_tmpl $test_template "IS_INFINITE" "\$Boxtype\$.isInfinite(a)" "FP" 421 422 # Compares 423 gen_op_tmpl $compare_template "LT+lt" "<" 424 gen_op_tmpl $compare_template "GT" ">" 425 gen_op_tmpl $compare_template "EQ+eq" "==" 426 gen_op_tmpl $compare_template "NE" "!=" 427 gen_op_tmpl $compare_template "LE" "<=" 428 gen_op_tmpl $compare_template "GE" ">=" 429 430 # Blend. 431 gen_op_tmpl $blend "blend" "" 432 433 # Rearrange 434 gen_op_tmpl $rearrange_template "rearrange" "" 435 436 # Get 437 gen_get_op "lane" "" 438 439 # Broadcast 440 gen_op_tmpl $broadcast_template "broadcast" "" 441 442 # Zero 443 gen_op_tmpl $zero_template "zero" "" 444 445 # Slice 446 gen_op_tmpl $slice_template "sliceUnary" "" 447 gen_op_tmpl $slice1_template "sliceBinary" "" 448 gen_op_tmpl $slice1_masked_template "slice" "" 449 450 # Unslice 451 gen_op_tmpl $unslice_template "unsliceUnary" "" 452 gen_op_tmpl $unslice1_template "unsliceBinary" "" 453 gen_op_tmpl $unslice1_masked_template "unslice" "" 454 455 # Math 456 gen_op_tmpl $unary_math_template "SIN" "Math.sin((double)a)" "FP" 457 gen_op_tmpl $unary_math_template "EXP" "Math.exp((double)a)" "FP" 458 gen_op_tmpl $unary_math_template "LOG1P" "Math.log1p((double)a)" "FP" 459 gen_op_tmpl $unary_math_template "LOG" "Math.log((double)a)" "FP" 460 gen_op_tmpl $unary_math_template "LOG10" "Math.log10((double)a)" "FP" 461 gen_op_tmpl $unary_math_template "EXPM1" "Math.expm1((double)a)" "FP" 462 gen_op_tmpl $unary_math_template "COS" "Math.cos((double)a)" "FP" 463 gen_op_tmpl $unary_math_template "TAN" "Math.tan((double)a)" "FP" 464 gen_op_tmpl $unary_math_template "SINH" "Math.sinh((double)a)" "FP" 465 gen_op_tmpl $unary_math_template "COSH" "Math.cosh((double)a)" "FP" 466 gen_op_tmpl $unary_math_template "TANH" "Math.tanh((double)a)" "FP" 467 gen_op_tmpl $unary_math_template "ASIN" "Math.asin((double)a)" "FP" 468 gen_op_tmpl $unary_math_template "ACOS" "Math.acos((double)a)" "FP" 469 gen_op_tmpl $unary_math_template "ATAN" "Math.atan((double)a)" "FP" 470 gen_op_tmpl $unary_math_template "CBRT" "Math.cbrt((double)a)" "FP" 471 gen_op_tmpl $binary_math_template "HYPOT" "Math.hypot((double)a, (double)b)" "FP" 472 gen_op_tmpl $binary_math_template "POW" "Math.pow((double)a, (double)b)" "FP" 473 gen_op_tmpl $binary_math_template "ATAN2" "Math.atan2((double)a, (double)b)" "FP" 474 475 # Ternary operations. 476 gen_ternary_alu_op "FMA" "Math.fma(a, b, c)" "FP" 477 gen_ternary_alu_op "BITWISE_BLEND" "(a\&~(c))|(b\&c)" "BITWISE" 478 479 # Unary operations. 480 gen_unary_alu_op "NEG+neg" "-((\$type\$)a)" 481 gen_unary_alu_op "ABS+abs" "Math.abs((\$type\$)a)" 482 gen_unary_alu_op "NOT+not" "~((\$type\$)a)" "BITWISE" 483 gen_unary_alu_op "ZOMO" "(a==0?0:-1)" "BITWISE" 484 gen_unary_alu_op "SQRT" "Math.sqrt((double)a)" "FP" 485 486 # Gather Scatter operations. 487 gen_op_tmpl $gather_template "gather" "" 488 gen_op_tmpl $gather_masked_template "gather" "" 489 gen_op_tmpl $scatter_template "scatter" "" 490 gen_op_tmpl $scatter_masked_template "scatter" "" 491 492 gen_unit_footer $unit_output 493 494 if [ $generate_perf_tests == true ]; then 495 gen_perf_footer $perf_output 496 gen_perf_scalar_footer $perf_scalar_output 497 fi 498 499 rm -f templates/*.current*