[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v6 08/20] tcg-arm: Improve constant generation
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH v6 08/20] tcg-arm: Improve constant generation |
Date: |
Tue, 23 Apr 2013 13:46:40 -0700 |
Try fully rotated arguments to mov and mvn before trying movt
or full decomposition. Begin decomposition with mvn when it
looks like it'll help. Examples include
-: mov r9, #0x00000fa0
-: orr r9, r9, #0x000ee000
-: orr r9, r9, #0x0ff00000
-: orr r9, r9, #0xf0000000
+: mvn r9, #0x0000005f
+: eor r9, r9, #0x00011000
Reviewed-by: Aurelien Jarno <address@hidden>
Signed-off-by: Richard Henderson <address@hidden>
---
tcg/arm/tcg-target.c | 67 ++++++++++++++++++++++++++++++++++------------------
1 file changed, 44 insertions(+), 23 deletions(-)
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 1a236c2..dfcc8e6 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -427,15 +427,31 @@ static inline void tcg_out_dat_imm(TCGContext *s,
(rn << 16) | (rd << 12) | im);
}
-static inline void tcg_out_movi32(TCGContext *s,
- int cond, int rd, uint32_t arg)
-{
- /* TODO: This is very suboptimal, we can easily have a constant
- * pool somewhere after all the instructions. */
- if ((int)arg < 0 && (int)arg >= -0x100) {
- tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
- } else if (use_armv7_instructions) {
- /* use movw/movt */
+static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
+{
+ int rot, opc, rn;
+
+ /* For armv7, make sure not to use movw+movt when mov/mvn would do.
+ Speed things up by only checking when movt would be required.
+ Prior to armv7, have one go at fully rotated immediates before
+ doing the decomposition thing below. */
+ if (!use_armv7_instructions || (arg & 0xffff0000)) {
+ rot = encode_imm(arg);
+ if (rot >= 0) {
+ tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0,
+ rotl(arg, rot) | (rot << 7));
+ return;
+ }
+ rot = encode_imm(~arg);
+ if (rot >= 0) {
+ tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0,
+ rotl(~arg, rot) | (rot << 7));
+ return;
+ }
+ }
+
+ /* Use movw + movt. */
+ if (use_armv7_instructions) {
/* movw */
tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
| ((arg << 4) & 0x000f0000) | (arg & 0xfff));
@@ -444,22 +460,27 @@ static inline void tcg_out_movi32(TCGContext *s,
tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
| ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
}
- } else {
- int opc = ARITH_MOV;
- int rn = 0;
-
- do {
- int i, rot;
-
- i = ctz32(arg) & ~1;
- rot = ((32 - i) << 7) & 0xf00;
- tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
- arg &= ~(0xff << i);
+ return;
+ }
- opc = ARITH_ORR;
- rn = rd;
- } while (arg);
+ /* TODO: This is very suboptimal, we can easily have a constant
+ pool somewhere after all the instructions. */
+ opc = ARITH_MOV;
+ rn = 0;
+ /* If we have lots of leading 1's, we can shorten the sequence by
+ beginning with mvn and then clearing higher bits with eor. */
+ if (clz32(~arg) > clz32(arg)) {
+ opc = ARITH_MVN, arg = ~arg;
}
+ do {
+ int i = ctz32(arg) & ~1;
+ rot = ((32 - i) << 7) & 0xf00;
+ tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
+ arg &= ~(0xff << i);
+
+ opc = ARITH_EOR;
+ rn = rd;
+ } while (arg);
}
static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
--
1.8.1.4
- [Qemu-devel] [PATCH v6 00/20] tcg-arm improvments, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 01/20] tcg-arm: Fix local stack frame, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 02/20] tcg: Log the contents of the prologue with -d out_asm, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 03/20] tcg-arm: Use bic to implement and with constant, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 04/20] tcg-arm: Handle negated constant arguments to and/sub, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 05/20] tcg-arm: Allow constant first argument to sub, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 06/20] tcg-arm: Use tcg_out_dat_rIN for compares, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 08/20] tcg-arm: Improve constant generation,
Richard Henderson <=
- [Qemu-devel] [PATCH v6 07/20] tcg-arm: Handle constant arguments to add2/sub2, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 09/20] tcg-arm: Implement deposit for armv7, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 10/20] tcg-arm: Implement division instructions, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 12/20] tcg-arm: Use R12 for the tcg temporary, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 11/20] tcg-arm: Use TCG_REG_TMP name for the tcg temporary, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 13/20] tcg-arm: Cleanup multiply subroutines, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 14/20] tcg-arm: Cleanup most primitive load store subroutines, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 15/20] tcg-arm: Split out tcg_out_tlb_read, Richard Henderson, 2013/04/23
- [Qemu-devel] [PATCH v6 17/20] tcg-arm: Delete the 'S' constraint, Richard Henderson, 2013/04/23