summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/parallel_move_resolver.h
diff options
context:
space:
mode:
authorMark Mendell <mark.p.mendell@intel.com>2015-04-01 12:51:05 -0400
committerMark Mendell <mark.p.mendell@intel.com>2015-04-10 12:08:31 -0400
commita5c19ce8d200d68a528f2ce0ebff989106c4a933 (patch)
tree4638a8d8e5b1562ec5ed05967490fec1ef7f0d17 /compiler/optimizing/parallel_move_resolver.h
parent6d80318c382a3490ab605b46fa7cb22c5e823fec (diff)
downloadart-a5c19ce8d200d68a528f2ce0ebff989106c4a933.zip
art-a5c19ce8d200d68a528f2ce0ebff989106c4a933.tar.gz
art-a5c19ce8d200d68a528f2ce0ebff989106c4a933.tar.bz2
[optimizing] Improve x86 parallel moves/swaps
Add a new constructor to ScratchRegisterScope that will supply a register if there is a free one, but not spill to force one. Use this to generated alternate code that doesn't use a temporary, as the spill/restore of a register generates extra instructions that aren't necessary on x86. Here is the benefit for a 32 bit memory-to-memory exchange with no free registers: < 50 push eax < 53 push ebx < 8B44244C mov eax, [esp + 76] < 8B5C246C mov ebx, [esp + 108] < 8944246C mov [esp + 108], eax < 895C244C mov [esp + 76], ebx < 5B pop ebx < 58 pop eax --- > FF742444 push [esp + 68] > FF742468 push [esp + 104] > 8F44244C pop [esp + 72] > 8F442468 pop [esp + 100] Avoid using xchg instruction, as it is slow on smaller processors. Change-Id: Id29ee3abd998577baaee552d55d23e60ae0c7871 Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
Diffstat (limited to 'compiler/optimizing/parallel_move_resolver.h')
-rw-r--r--compiler/optimizing/parallel_move_resolver.h7
1 files changed, 7 insertions, 0 deletions
diff --git a/compiler/optimizing/parallel_move_resolver.h b/compiler/optimizing/parallel_move_resolver.h
index 3fa1b37..173cffc 100644
--- a/compiler/optimizing/parallel_move_resolver.h
+++ b/compiler/optimizing/parallel_move_resolver.h
@@ -42,10 +42,15 @@ class ParallelMoveResolver : public ValueObject {
protected:
class ScratchRegisterScope : public ValueObject {
public:
+ // Spill a scratch register if no regs are free.
ScratchRegisterScope(ParallelMoveResolver* resolver,
int blocked,
int if_scratch,
int number_of_registers);
+ // Grab a scratch register only if available.
+ ScratchRegisterScope(ParallelMoveResolver* resolver,
+ int blocked,
+ int number_of_registers);
~ScratchRegisterScope();
int GetRegister() const { return reg_; }
@@ -62,6 +67,8 @@ class ParallelMoveResolver : public ValueObject {
// Allocate a scratch register for performing a move. The method will try to use
// a register that is the destination of a move, but that move has not been emitted yet.
int AllocateScratchRegister(int blocked, int if_scratch, int register_count, bool* spilled);
+ // As above, but return -1 if no free register.
+ int AllocateScratchRegister(int blocked, int register_count);
// Emit a move.
virtual void EmitMove(size_t index) = 0;