mirror of https://github.com/golang/go.git
[dev.ssa] cmd/compile: allow control values to be CSEd
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>
This commit is contained in:
parent
c140df0326
commit
4989337192
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@
|
|||
(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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -3177,7 +3177,7 @@ var opcodeTable = [...]opInfo{
|
|||
{0, 128}, // .DI
|
||||
{1, 64}, // .SI
|
||||
},
|
||||
clobbers: 65728, // .SI .DI .X0
|
||||
clobbers: 8590000320, // .SI .DI .X0 .FLAGS
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue