[dev.ssa] cmd/compile: Use ADD instead of LEA when we can
If the output register is one of the input registers,
we can use a real add instead of LEA.
Change-Id: Ide58f1536afb077c0b939d3a8c7555807fd1c5e3
Reviewed-on: https://go-review.googlesource.com/19234
Reviewed-by: Alexandru Moșoi <alexandru@mosoi.ro>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 8ae02bd..7b85b2f 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -3689,31 +3689,41 @@
func (s *genState) genValue(v *ssa.Value) {
lineno = v.Line
switch v.Op {
- case ssa.OpAMD64ADDQ:
- // TODO: use addq instead of leaq if target is in the right register.
- p := Prog(x86.ALEAQ)
- p.From.Type = obj.TYPE_MEM
- p.From.Reg = regnum(v.Args[0])
- p.From.Scale = 1
- p.From.Index = regnum(v.Args[1])
- p.To.Type = obj.TYPE_REG
- p.To.Reg = regnum(v)
- case ssa.OpAMD64ADDL:
- p := Prog(x86.ALEAL)
- p.From.Type = obj.TYPE_MEM
- p.From.Reg = regnum(v.Args[0])
- p.From.Scale = 1
- p.From.Index = regnum(v.Args[1])
- p.To.Type = obj.TYPE_REG
- p.To.Reg = regnum(v)
- case ssa.OpAMD64ADDW:
- p := Prog(x86.ALEAW)
- p.From.Type = obj.TYPE_MEM
- p.From.Reg = regnum(v.Args[0])
- p.From.Scale = 1
- p.From.Index = regnum(v.Args[1])
- p.To.Type = obj.TYPE_REG
- p.To.Reg = regnum(v)
+ case ssa.OpAMD64ADDQ, ssa.OpAMD64ADDL, ssa.OpAMD64ADDW:
+ r := regnum(v)
+ r1 := regnum(v.Args[0])
+ r2 := regnum(v.Args[1])
+ switch {
+ case r == r1:
+ p := Prog(v.Op.Asm())
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = r2
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = r
+ case r == r2:
+ p := Prog(v.Op.Asm())
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = r1
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = r
+ default:
+ var asm int
+ switch v.Op {
+ case ssa.OpAMD64ADDQ:
+ asm = x86.ALEAQ
+ case ssa.OpAMD64ADDL:
+ asm = x86.ALEAL
+ case ssa.OpAMD64ADDW:
+ asm = x86.ALEAW
+ }
+ p := Prog(asm)
+ p.From.Type = obj.TYPE_MEM
+ p.From.Reg = r1
+ p.From.Scale = 1
+ p.From.Index = r2
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = r
+ }
// 2-address opcode arithmetic, symmetric
case ssa.OpAMD64ADDB, ssa.OpAMD64ADDSS, ssa.OpAMD64ADDSD,
ssa.OpAMD64ANDQ, ssa.OpAMD64ANDL, ssa.OpAMD64ANDW, ssa.OpAMD64ANDB,
@@ -3903,7 +3913,16 @@
p.To.Type = obj.TYPE_REG
p.To.Reg = r
case ssa.OpAMD64ADDQconst, ssa.OpAMD64ADDLconst, ssa.OpAMD64ADDWconst:
- // TODO: use addq instead of leaq if target is in the right register.
+ r := regnum(v)
+ a := regnum(v.Args[0])
+ if r == a {
+ p := Prog(v.Op.Asm())
+ p.From.Type = obj.TYPE_CONST
+ p.From.Offset = v.AuxInt
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = r
+ return
+ }
var asm int
switch v.Op {
case ssa.OpAMD64ADDQconst:
@@ -3915,10 +3934,10 @@
}
p := Prog(asm)
p.From.Type = obj.TYPE_MEM
- p.From.Reg = regnum(v.Args[0])
+ p.From.Reg = a
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
- p.To.Reg = regnum(v)
+ p.To.Reg = r
case ssa.OpAMD64MULQconst, ssa.OpAMD64MULLconst, ssa.OpAMD64MULWconst, ssa.OpAMD64MULBconst:
r := regnum(v)
x := regnum(v.Args[0])