]>
Commit | Line | Data |
---|---|---|
d97dd988 PMD |
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 | ) |