| 1 | // optimize TCG using extract op |
| 2 | // |
| 3 | // Copyright: (C) 2017 Philippe Mathieu-Daudé. GPLv2+. |
| 4 | // Confidence: High |
| 5 | // Options: --macro-file scripts/cocci-macro-file.h |
| 6 | // |
| 7 | // Nikunj A Dadhania optimization: |
| 8 | // http://lists.nongnu.org/archive/html/qemu-devel/2017-02/msg05211.html |
| 9 | // Aurelien Jarno optimization: |
| 10 | // http://lists.nongnu.org/archive/html/qemu-devel/2017-05/msg01466.html |
| 11 | // |
| 12 | // This script can be run either using spatch locally or via a docker image: |
| 13 | // |
| 14 | // $ spatch \ |
| 15 | // --macro-file scripts/cocci-macro-file.h \ |
| 16 | // --sp-file scripts/coccinelle/tcg_gen_extract.cocci \ |
| 17 | // --keep-comments --in-place \ |
| 18 | // --use-gitgrep --dir target |
| 19 | // |
| 20 | // $ docker run --rm -v $PWD:$PWD -w $PWD philmd/coccinelle \ |
| 21 | // --macro-file scripts/cocci-macro-file.h \ |
| 22 | // --sp-file scripts/coccinelle/tcg_gen_extract.cocci \ |
| 23 | // --keep-comments --in-place \ |
| 24 | // --use-gitgrep --dir target |
| 25 | |
| 26 | @initialize:python@ |
| 27 | @@ |
| 28 | import sys |
| 29 | fd = sys.stderr |
| 30 | def debug(msg="", trailer="\n"): |
| 31 | fd.write("[DBG] " + msg + trailer) |
| 32 | def low_bits_count(value): |
| 33 | bits_count = 0 |
| 34 | while (value & (1 << bits_count)): |
| 35 | bits_count += 1 |
| 36 | return bits_count |
| 37 | def Mn(order): # Mersenne number |
| 38 | return (1 << order) - 1 |
| 39 | |
| 40 | @match@ |
| 41 | identifier ret; |
| 42 | metavariable arg; |
| 43 | constant ofs, msk; |
| 44 | position shr_p, and_p; |
| 45 | @@ |
| 46 | ( |
| 47 | tcg_gen_shri_i32@shr_p |
| 48 | | |
| 49 | tcg_gen_shri_i64@shr_p |
| 50 | | |
| 51 | tcg_gen_shri_tl@shr_p |
| 52 | )(ret, arg, ofs); |
| 53 | ... WHEN != ret |
| 54 | ( |
| 55 | tcg_gen_andi_i32@and_p |
| 56 | | |
| 57 | tcg_gen_andi_i64@and_p |
| 58 | | |
| 59 | tcg_gen_andi_tl@and_p |
| 60 | )(ret, ret, msk); |
| 61 | |
| 62 | @script:python verify_len depends on match@ |
| 63 | ret_s << match.ret; |
| 64 | msk_s << match.msk; |
| 65 | shr_p << match.shr_p; |
| 66 | extract_len; |
| 67 | @@ |
| 68 | is_optimizable = False |
| 69 | debug("candidate at %s:%s" % (shr_p[0].file, shr_p[0].line)) |
| 70 | try: # only eval integer, no #define like 'SR_M' (cpp did this, else some headers are missing). |
| 71 | msk_v = long(msk_s.strip("UL"), 0) |
| 72 | msk_b = low_bits_count(msk_v) |
| 73 | if msk_b == 0: |
| 74 | debug(" value: 0x%x low_bits: %d" % (msk_v, msk_b)) |
| 75 | else: |
| 76 | debug(" value: 0x%x low_bits: %d [Mersenne number: 0x%x]" % (msk_v, msk_b, Mn(msk_b))) |
| 77 | is_optimizable = Mn(msk_b) == msk_v # check low_bits |
| 78 | coccinelle.extract_len = "%d" % msk_b |
| 79 | debug(" candidate %s optimizable" % ("IS" if is_optimizable else "is NOT")) |
| 80 | except: |
| 81 | debug(" ERROR (check included headers?)") |
| 82 | cocci.include_match(is_optimizable) |
| 83 | debug() |
| 84 | |
| 85 | @replacement depends on verify_len@ |
| 86 | identifier match.ret; |
| 87 | metavariable match.arg; |
| 88 | constant match.ofs, match.msk; |
| 89 | position match.shr_p, match.and_p; |
| 90 | identifier verify_len.extract_len; |
| 91 | @@ |
| 92 | ( |
| 93 | -tcg_gen_shri_i32@shr_p(ret, arg, ofs); |
| 94 | +tcg_gen_extract_i32(ret, arg, ofs, extract_len); |
| 95 | ... WHEN != ret |
| 96 | -tcg_gen_andi_i32@and_p(ret, ret, msk); |
| 97 | | |
| 98 | -tcg_gen_shri_i64@shr_p(ret, arg, ofs); |
| 99 | +tcg_gen_extract_i64(ret, arg, ofs, extract_len); |
| 100 | ... WHEN != ret |
| 101 | -tcg_gen_andi_i64@and_p(ret, ret, msk); |
| 102 | | |
| 103 | -tcg_gen_shri_tl@shr_p(ret, arg, ofs); |
| 104 | +tcg_gen_extract_tl(ret, arg, ofs, extract_len); |
| 105 | ... WHEN != ret |
| 106 | -tcg_gen_andi_tl@and_p(ret, ret, msk); |
| 107 | ) |