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