@samitouri / QOSamiQemu / commits / bfe9264835

tcg: target-dependent lowering of extract to shr/and

Instead of assuming only small immediates are available for AND, consult the backend in order to decide between SHL/SHR and SHR/AND. Reviewed-by: Jim MacArthur <jim.macarthur@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> [rth: Split from a larger patch] Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20260303010833.1115741-7-richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Paolo Bonzini committed Feb 3, 2026 at 09:18 UTC bfe92648358ae56c367dbdc7393333b3cc7ca689
1 file changed +16 -20
tcg/tcg-op.c
+16 -20
@@ -907,6 +907,8 @@ void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
907 void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
908 unsigned int ofs, unsigned int len)
909 {
910 + uint32_t mask;
911 +
912 tcg_debug_assert(ofs < 32);
913 tcg_debug_assert(len > 0);
914 tcg_debug_assert(len <= 32);
@@ -922,8 +924,10 @@ void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
924 tcg_gen_op4ii_i32(INDEX_op_extract, ret, arg, ofs, len);
925 return;
926 }
927 +
928 + mask = (1u << len) - 1;
929 if (ofs == 0) {
926 - tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
930 + tcg_gen_andi_i32(ret, arg, mask);
931 return;
932 }
933
@@ -934,18 +938,12 @@ void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg,
938 return;
939 }
940
937 - /* ??? Ideally we'd know what values are available for immediate AND.
938 - Assume that 8 bits are available, plus the special case of 16,
939 - so that we get ext8u, ext16u. */
940 - switch (len) {
941 - case 1 ... 8: case 16:
941 + if (tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I32, mask)) {
942 tcg_gen_shri_i32(ret, arg, ofs);
943 - tcg_gen_andi_i32(ret, ret, (1u << len) - 1);
944 - break;
945 - default:
943 + tcg_gen_andi_i32(ret, ret, mask);
944 + } else {
945 tcg_gen_shli_i32(ret, arg, 32 - len - ofs);
946 tcg_gen_shri_i32(ret, ret, 32 - len);
948 - break;
947 }
948 }
949
@@ -2121,6 +2119,8 @@ void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
2119 void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
2120 unsigned int ofs, unsigned int len)
2121 {
2122 + uint64_t mask;
2123 +
2124 tcg_debug_assert(ofs < 64);
2125 tcg_debug_assert(len > 0);
2126 tcg_debug_assert(len <= 64);
@@ -2136,8 +2136,10 @@ void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
2136 tcg_gen_op4ii_i64(INDEX_op_extract, ret, arg, ofs, len);
2137 return;
2138 }
2139 +
2140 + mask = (1ull << len) - 1;
2141 if (ofs == 0) {
2140 - tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
2142 + tcg_gen_andi_i64(ret, arg, mask);
2143 return;
2144 }
2145
@@ -2148,18 +2150,12 @@ void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg,
2150 return;
2151 }
2152
2151 - /* ??? Ideally we'd know what values are available for immediate AND.
2152 - Assume that 8 bits are available, plus the special cases of 16 and 32,
2153 - so that we get ext8u, ext16u, and ext32u. */
2154 - switch (len) {
2155 - case 1 ... 8: case 16: case 32:
2153 + if (tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I64, mask)) {
2154 tcg_gen_shri_i64(ret, arg, ofs);
2157 - tcg_gen_andi_i64(ret, ret, (1ull << len) - 1);
2158 - break;
2159 - default:
2155 + tcg_gen_andi_i64(ret, ret, mask);
2156 + } else {
2157 tcg_gen_shli_i64(ret, arg, 64 - len - ofs);
2158 tcg_gen_shri_i64(ret, ret, 64 - len);
2162 - break;
2159 }
2160 }
2161