// 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); )