108 lines
2.9 KiB
Plaintext
108 lines
2.9 KiB
Plaintext
|
// 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);
|
||
|
)
|