diff --git a/scripts/coccinelle/tcg_gen_extract.cocci b/scripts/coccinelle/tcg_gen_extract.cocci new file mode 100644 index 0000000000000000000000000000000000000000..81e66a35ae14bb86bcbf0c1888282283f208a8ad --- /dev/null +++ b/scripts/coccinelle/tcg_gen_extract.cocci @@ -0,0 +1,107 @@ +// optimize TCG using extract op +// +// Copyright: (C) 2017 Philippe Mathieu-Daudé. GPLv2+. +// Confidence: High +// Options: --macro-file scripts/cocci-macro-file.h +// +// Nikunj A Dadhania optimization: +// http://lists.nongnu.org/archive/html/qemu-devel/2017-02/msg05211.html +// Aurelien Jarno optimization: +// http://lists.nongnu.org/archive/html/qemu-devel/2017-05/msg01466.html +// +// This script can be run either using spatch locally or via a docker image: +// +// $ spatch \ +// --macro-file scripts/cocci-macro-file.h \ +// --sp-file scripts/coccinelle/tcg_gen_extract.cocci \ +// --keep-comments --in-place \ +// --use-gitgrep --dir target +// +// $ docker run --rm -v `pwd`:`pwd` -w `pwd` philmd/coccinelle \ +// --macro-file scripts/cocci-macro-file.h \ +// --sp-file scripts/coccinelle/tcg_gen_extract.cocci \ +// --keep-comments --in-place \ +// --use-gitgrep --dir target + +@initialize:python@ +@@ +import sys +fd = sys.stderr +def debug(msg="", trailer="\n"): + fd.write("[DBG] " + msg + trailer) +def low_bits_count(value): + bits_count = 0 + while (value & (1 << bits_count)): + bits_count += 1 + return bits_count +def Mn(order): # Mersenne number + return (1 << order) - 1 + +@match@ +identifier ret; +metavariable arg; +constant ofs, msk; +position shr_p, and_p; +@@ +( + tcg_gen_shri_i32@shr_p +| + tcg_gen_shri_i64@shr_p +| + tcg_gen_shri_tl@shr_p +)(ret, arg, ofs); +... WHEN != ret +( + tcg_gen_andi_i32@and_p +| + tcg_gen_andi_i64@and_p +| + tcg_gen_andi_tl@and_p +)(ret, ret, msk); + +@script:python verify_len depends on match@ +ret_s << match.ret; +msk_s << match.msk; +shr_p << match.shr_p; +extract_len; +@@ +is_optimizable = False +debug("candidate at %s:%s" % (shr_p[0].file, shr_p[0].line)) +try: # only eval integer, no #define like 'SR_M' (cpp did this, else some headers are missing). + msk_v = long(msk_s.strip("UL"), 0) + msk_b = low_bits_count(msk_v) + if msk_b == 0: + debug(" value: 0x%x low_bits: %d" % (msk_v, msk_b)) + else: + debug(" value: 0x%x low_bits: %d [Mersenne number: 0x%x]" % (msk_v, msk_b, Mn(msk_b))) + is_optimizable = Mn(msk_b) == msk_v # check low_bits + coccinelle.extract_len = "%d" % msk_b + debug(" candidate %s optimizable" % ("IS" if is_optimizable else "is NOT")) +except: + debug(" ERROR (check included headers?)") +cocci.include_match(is_optimizable) +debug() + +@replacement depends on verify_len@ +identifier match.ret; +metavariable match.arg; +constant match.ofs, match.msk; +position match.shr_p, match.and_p; +identifier verify_len.extract_len; +@@ +( +-tcg_gen_shri_i32@shr_p(ret, arg, ofs); ++tcg_gen_extract_i32(ret, arg, ofs, extract_len); +... WHEN != ret +-tcg_gen_andi_i32@and_p(ret, ret, msk); +| +-tcg_gen_shri_i64@shr_p(ret, arg, ofs); ++tcg_gen_extract_i64(ret, arg, ofs, extract_len); +... WHEN != ret +-tcg_gen_andi_i64@and_p(ret, ret, msk); +| +-tcg_gen_shri_tl@shr_p(ret, arg, ofs); ++tcg_gen_extract_tl(ret, arg, ofs, extract_len); +... WHEN != ret +-tcg_gen_andi_tl@and_p(ret, ret, msk); +)