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@@ 28import sys 29fd = sys.stderr 30def debug(msg="", trailer="\n"): 31 fd.write("[DBG] " + msg + trailer) 32def low_bits_count(value): 33 bits_count = 0 34 while (value & (1 << bits_count)): 35 bits_count += 1 36 return bits_count 37def Mn(order): # Mersenne number 38 return (1 << order) - 1 39 40@match@ 41identifier ret; 42metavariable arg; 43constant ofs, msk; 44position 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@ 63ret_s << match.ret; 64msk_s << match.msk; 65shr_p << match.shr_p; 66extract_len; 67@@ 68is_optimizable = False 69debug("candidate at %s:%s" % (shr_p[0].file, shr_p[0].line)) 70try: # 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")) 80except: 81 debug(" ERROR (check included headers?)") 82cocci.include_match(is_optimizable) 83debug() 84 85@replacement depends on verify_len@ 86identifier match.ret; 87metavariable match.arg; 88constant match.ofs, match.msk; 89position match.shr_p, match.and_p; 90identifier 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) 108