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