]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't shuffle rematerializeable values around
authorKeith Randall <khr@golang.org>
Wed, 5 Oct 2016 21:35:47 +0000 (14:35 -0700)
committerKeith Randall <khr@golang.org>
Thu, 6 Oct 2016 02:46:43 +0000 (02:46 +0000)
Better to just rematerialize them when needed instead of
cross-register spilling or other techniques for keeping them in
registers.

This helps for amd64 code that does 1 << x. It is better to do
  loop:
    MOVQ $1, AX  // materialize arg to SLLQ
    SLLQ CX, AX
    ...
    goto loop
than to do
  MOVQ $1, AX    // materialize outsize of loop
  loop:
    MOVQ AX, DX  // save value that's about to be clobbered
    SLLQ CX, AX
    MOVQ DX, AX  // move it back to the correct register
    goto loop

Update #16092

Change-Id: If7ac290208f513061ebb0736e8a79dcb0ba338c0
Reviewed-on: https://go-review.googlesource.com/30471
TryBot-Result: Gobot Gobot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/ssa/regalloc.go

index 3b9f49d9dffb412a2451f4e684c292f75c7993bc..4cf957a41a3660d0f5b55acdb1d60822a5373d87 100644 (file)
@@ -389,7 +389,7 @@ func (s *regAllocState) allocReg(mask regMask, v *Value) register {
        // We generate a Copy and record it. It will be deleted if never used.
        v2 := s.regs[r].v
        m := s.compatRegs(v2.Type) &^ s.used &^ s.tmpused &^ (regMask(1) << r)
-       if countRegs(s.values[v2.ID].regs) == 1 && m != 0 {
+       if m != 0 && !s.values[v2.ID].rematerializeable && countRegs(s.values[v2.ID].regs) == 1 {
                r2 := pickReg(m)
                c := s.curBlock.NewValue1(v2.Line, OpCopy, v2.Type, s.regs[r].c)
                s.copies[c] = false
@@ -1146,6 +1146,10 @@ func (s *regAllocState) regalloc(f *Func) {
                                        // arg0 is dead.  We can clobber its register.
                                        goto ok
                                }
+                               if s.values[v.Args[0].ID].rematerializeable {
+                                       // We can rematerialize the input, don't worry about clobbering it.
+                                       goto ok
+                               }
                                if countRegs(s.values[v.Args[0].ID].regs) >= 2 {
                                        // we have at least 2 copies of arg0.  We can afford to clobber one.
                                        goto ok
@@ -1155,6 +1159,10 @@ func (s *regAllocState) regalloc(f *Func) {
                                                args[0], args[1] = args[1], args[0]
                                                goto ok
                                        }
+                                       if s.values[v.Args[1].ID].rematerializeable {
+                                               args[0], args[1] = args[1], args[0]
+                                               goto ok
+                                       }
                                        if countRegs(s.values[v.Args[1].ID].regs) >= 2 {
                                                args[0], args[1] = args[1], args[0]
                                                goto ok
@@ -1389,6 +1397,9 @@ func (s *regAllocState) regalloc(f *Func) {
                                if vi.regs != 0 {
                                        continue
                                }
+                               if vi.rematerializeable {
+                                       continue
+                               }
                                v := s.orig[vid]
                                if s.f.Config.use387 && v.Type.IsFloat() {
                                        continue // 387 can't handle floats in registers between blocks