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