]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: allow control values to be CSEd
authorKeith Randall <khr@golang.org>
Fri, 11 Dec 2015 22:59:01 +0000 (14:59 -0800)
committerKeith Randall <khr@golang.org>
Sat, 12 Dec 2015 06:41:05 +0000 (06:41 +0000)
With the separate flagalloc pass, it should be fine to
allow CSE of control values.  The worst that can happen
is that the comparison gets un-CSEd by flagalloc.

Fix bug in flagalloc where flag restores were getting
clobbered by rematerialization during register allocation.

Change-Id: If476cf98b69973e8f1a8eb29441136dd12fab8ad
Reviewed-on: https://go-review.googlesource.com/17760
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Keith Randall <khr@golang.org>

src/cmd/compile/internal/ssa/cse.go
src/cmd/compile/internal/ssa/flagalloc.go
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/gen/AMD64Ops.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteAMD64.go

index 25f424fbee3f109c31da9d7eef1b16c7dc0641f2..58c52f23e68c7e0b9c56fdd1d8c1630832530b11 100644 (file)
@@ -153,7 +153,6 @@ func cse(f *Func) {
                                        i++
                                }
                        }
-                       // TODO(khr): if value is a control value, do we need to keep it block-local?
                }
        }
 
@@ -166,6 +165,16 @@ func cse(f *Func) {
                                }
                        }
                }
+               if v := b.Control; v != nil {
+                       if x := rewrite[v.ID]; x != nil {
+                               if v.Op == OpNilCheck {
+                                       // nilcheck pass will remove the nil checks and log
+                                       // them appropriately, so don't mess with them here.
+                                       continue
+                               }
+                               b.Control = x
+                       }
+               }
        }
 }
 
index c0881580571c072765333385dcc86a0920da56c3..714ac016a2fcb877e63c666206dfa5aa3f27b4d7 100644 (file)
@@ -21,6 +21,15 @@ func flagalloc(f *Func) {
                // Walk blocks backwards.  Poor-man's postorder traversal.
                for i := len(f.Blocks) - 1; i >= 0; i-- {
                        b := f.Blocks[i]
+                       if len(b.Preds) > 1 {
+                               // Don't use any flags register at the start
+                               // of a merge block.  This causes problems
+                               // in regalloc because some of the rematerialization
+                               // instructions used on incoming merge edges clobber
+                               // the flags register.
+                               // TODO: only for architectures where this matters?
+                               continue
+                       }
                        // Walk values backwards to figure out what flag
                        // value we want in the flag register at the start
                        // of the block.
index 7d0aa4b2d3f44eb73c171ef261b90641b9918a09..0edbfdaa1a2930947968517afafc5dd85cddb0ff 100644 (file)
 (If (SETGF  cmp) yes no) -> (UGT  cmp yes no)
 (If (SETGEF cmp) yes no) -> (UGE  cmp yes no)
 (If (SETEQF cmp) yes no) -> (EQF  cmp yes no)
-(If (SETNEF cmp) yes no) -> (EQF  cmp yes no)
+(If (SETNEF cmp) yes no) -> (NEF  cmp yes no)
 
 (If cond yes no) -> (NE (TESTB cond cond) yes no)
 
index ba53e81ddd187d27dea87ea923b82b074e8e20b6..461026bd7b825387f50c968c86b109687d5f7e80 100644 (file)
@@ -433,7 +433,7 @@ func init() {
                        name: "DUFFCOPY",
                        reg: regInfo{
                                inputs:   []regMask{buildReg("DI"), buildReg("SI")},
-                               clobbers: buildReg("DI SI X0"), // uses X0 as a temporary
+                               clobbers: buildReg("DI SI X0 FLAGS"), // uses X0 as a temporary
                        },
                },
 
index 132ca83f95160bda70e5402a0ff444dadf838091..bbedf2fb64dec41dd7c4fd5aa3f318addc6ee3e7 100644 (file)
@@ -3177,7 +3177,7 @@ var opcodeTable = [...]opInfo{
                                {0, 128}, // .DI
                                {1, 64},  // .SI
                        },
-                       clobbers: 65728, // .SI .DI .X0
+                       clobbers: 8590000320, // .SI .DI .X0 .FLAGS
                },
        },
        {
index 3be94e37e73b9c3ad7915326d01e631136998239..5c2f3db4b270871b7af7c3935c65709e81d469c3 100644 (file)
@@ -14213,23 +14213,23 @@ func rewriteBlockAMD64(b *Block) bool {
                ;
                // match: (If (SETNEF cmp) yes no)
                // cond:
-               // result: (EQF  cmp yes no)
+               // result: (NEF  cmp yes no)
                {
                        v := b.Control
                        if v.Op != OpAMD64SETNEF {
-                               goto endfe25939ca97349543bc2d2ce4f97ba41
+                               goto endaa989df10b5bbc5fdf8f7f0b81767e86
                        }
                        cmp := v.Args[0]
                        yes := b.Succs[0]
                        no := b.Succs[1]
-                       b.Kind = BlockAMD64EQF
+                       b.Kind = BlockAMD64NEF
                        b.Control = cmp
                        b.Succs[0] = yes
                        b.Succs[1] = no
                        return true
                }
-               goto endfe25939ca97349543bc2d2ce4f97ba41
-       endfe25939ca97349543bc2d2ce4f97ba41:
+               goto endaa989df10b5bbc5fdf8f7f0b81767e86
+       endaa989df10b5bbc5fdf8f7f0b81767e86:
                ;
                // match: (If cond yes no)
                // cond: