[dev.ssa] cmd/compile: more combining of ops into instructions

Mostly indexed loads.  A few more LEA cases.

Change-Id: Idc1d447ed0dd6e906cd48e70307a95e77f61cf5f
Reviewed-on: https://go-review.googlesource.com/19172
Reviewed-by: Todd Neal <todd@tneal.org>
Run-TryBot: Keith Randall <khr@golang.org>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 59993c2..8ae02bd 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -4061,7 +4061,7 @@
 		p.From.Index = regnum(v.Args[1])
 		p.To.Type = obj.TYPE_REG
 		p.To.Reg = regnum(v)
-	case ssa.OpAMD64MOVSSloadidx4:
+	case ssa.OpAMD64MOVLloadidx4, ssa.OpAMD64MOVSSloadidx4:
 		p := Prog(v.Op.Asm())
 		p.From.Type = obj.TYPE_MEM
 		p.From.Reg = regnum(v.Args[0])
@@ -4070,6 +4070,24 @@
 		p.From.Index = regnum(v.Args[1])
 		p.To.Type = obj.TYPE_REG
 		p.To.Reg = regnum(v)
+	case ssa.OpAMD64MOVWloadidx2:
+		p := Prog(v.Op.Asm())
+		p.From.Type = obj.TYPE_MEM
+		p.From.Reg = regnum(v.Args[0])
+		addAux(&p.From, v)
+		p.From.Scale = 2
+		p.From.Index = regnum(v.Args[1])
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = regnum(v)
+	case ssa.OpAMD64MOVBloadidx1:
+		p := Prog(v.Op.Asm())
+		p.From.Type = obj.TYPE_MEM
+		p.From.Reg = regnum(v.Args[0])
+		addAux(&p.From, v)
+		p.From.Scale = 1
+		p.From.Index = regnum(v.Args[1])
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = regnum(v)
 	case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore:
 		p := Prog(v.Op.Asm())
 		p.From.Type = obj.TYPE_REG
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules
index ee21e56..692ea46 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64.rules
+++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules
@@ -546,9 +546,34 @@
 (MULQconst [9] x) -> (LEAQ8 x x)
 (MULQconst [c] x) && isPowerOfTwo(c) -> (SHLQconst [log2(c)] x)
 
-// fold add/shift into leaq
+// combine add/shift into LEAQ
 (ADDQ x (SHLQconst [3] y)) -> (LEAQ8 x y)
-(ADDQconst [c] (LEAQ8 [d] x y)) -> (LEAQ8 [addOff(c, d)] x y)
+(ADDQ x (SHLQconst [2] y)) -> (LEAQ4 x y)
+(ADDQ x (SHLQconst [1] y)) -> (LEAQ2 x y)
+(ADDQ x (ADDQ y y)) -> (LEAQ2 x y)
+(ADDQ x (ADDQ x y)) -> (LEAQ2 y x)
+(ADDQ x (ADDQ y x)) -> (LEAQ2 y x)
+
+// fold ADDQ into LEAQ
+(ADDQconst [c] (LEAQ [d] {s} x)) -> (LEAQ [c+d] {s} x)
+(LEAQ [c] {s} (ADDQconst [d] x)) -> (LEAQ [c+d] {s} x)
+(LEAQ [c] {s} (ADDQ x y)) && x.Op != OpSB && y.Op != OpSB -> (LEAQ1 [c] {s} x y)
+(ADDQ x (LEAQ [c] {s} y)) && x.Op != OpSB && y.Op != OpSB -> (LEAQ1 [c] {s} x y)
+(ADDQ (LEAQ [c] {s} x) y) && x.Op != OpSB && y.Op != OpSB -> (LEAQ1 [c] {s} x y)
+
+// fold ADDQconst into leaqX
+(ADDQconst [c] (LEAQ1 [d] {s} x y)) -> (LEAQ1 [c+d] {s} x y)
+(ADDQconst [c] (LEAQ2 [d] {s} x y)) -> (LEAQ2 [c+d] {s} x y)
+(ADDQconst [c] (LEAQ4 [d] {s} x y)) -> (LEAQ4 [c+d] {s} x y)
+(ADDQconst [c] (LEAQ8 [d] {s} x y)) -> (LEAQ8 [c+d] {s} x y)
+(LEAQ1 [c] {s} (ADDQconst [d] x) y) && x.Op != OpSB -> (LEAQ1 [c+d] {s} x y)
+(LEAQ1 [c] {s} x (ADDQconst [d] y)) && y.Op != OpSB -> (LEAQ1 [c+d] {s} x y)
+(LEAQ2 [c] {s} (ADDQconst [d] x) y) && x.Op != OpSB -> (LEAQ2 [c+d] {s} x y)
+(LEAQ2 [c] {s} x (ADDQconst [d] y)) && y.Op != OpSB -> (LEAQ2 [c+2*d] {s} x y)
+(LEAQ4 [c] {s} (ADDQconst [d] x) y) && x.Op != OpSB -> (LEAQ4 [c+d] {s} x y)
+(LEAQ4 [c] {s} x (ADDQconst [d] y)) && y.Op != OpSB -> (LEAQ4 [c+4*d] {s} x y)
+(LEAQ8 [c] {s} (ADDQconst [d] x) y) && x.Op != OpSB -> (LEAQ8 [c+d] {s} x y)
+(LEAQ8 [c] {s} x (ADDQconst [d] y)) && y.Op != OpSB -> (LEAQ8 [c+8*d] {s} x y)
 
 // reverse ordering of compare instruction
 (SETL (InvertFlags x)) -> (SETG x)
@@ -672,17 +697,13 @@
 (MOVBstoreconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
 	(MOVBstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
 
-// indexed loads and stores
-(MOVQloadidx8 [off1] {sym} (ADDQconst [off2] ptr) idx mem) -> (MOVQloadidx8 [addOff(off1, off2)] {sym} ptr idx mem)
-(MOVQstoreidx8 [off1] {sym} (ADDQconst [off2] ptr) idx val mem) -> (MOVQstoreidx8 [addOff(off1, off2)] {sym} ptr idx val mem)
-(MOVSSloadidx4 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx mem) -> (MOVSSloadidx4 [addOff(off1, off2)] {sym} ptr idx mem)
-(MOVSSstoreidx4 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx val mem) -> (MOVSSstoreidx4 [addOff(off1, off2)] {sym} ptr idx val mem)
-(MOVSDloadidx8 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx mem) -> (MOVSDloadidx8 [addOff(off1, off2)] {sym} ptr idx mem)
-(MOVSDstoreidx8 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx val mem) -> (MOVSDstoreidx8 [addOff(off1, off2)] {sym} ptr idx val mem)
-(MOVLstoreidx4 [off1] {sym} (ADDQconst [off2] ptr) idx val mem) -> (MOVLstoreidx4 [addOff(off1, off2)] {sym} ptr idx val mem)
-(MOVWstoreidx2 [off1] {sym} (ADDQconst [off2] ptr) idx val mem) -> (MOVWstoreidx2 [addOff(off1, off2)] {sym} ptr idx val mem)
-(MOVBstoreidx1 [off1] {sym} (ADDQconst [off2] ptr) idx val mem) -> (MOVBstoreidx1 [addOff(off1, off2)] {sym} ptr idx val mem)
-
+// generating indexed loads and stores
+(MOVBload [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) ->
+	(MOVBloadidx1 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem)
+(MOVWload [off1] {sym1} (LEAQ2 [off2] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) ->
+	(MOVWloadidx2 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem)
+(MOVLload [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) ->
+	(MOVLloadidx4 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem)
 (MOVQload [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) ->
 	(MOVQloadidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem)
 (MOVSSload [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) ->
@@ -703,7 +724,37 @@
 (MOVSDstore [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) && canMergeSym(sym1, sym2) ->
 	(MOVSDstoreidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx val mem)
 
-(MOVBstore [off] {sym} (ADDQ ptr idx) val mem) -> (MOVBstoreidx1 [off] {sym} ptr idx val mem)
+(MOVBload [off] {sym} (ADDQ ptr idx) mem) && ptr.Op != OpSB -> (MOVBloadidx1 [off] {sym} ptr idx mem)
+(MOVBstore [off] {sym} (ADDQ ptr idx) val mem) && ptr.Op != OpSB -> (MOVBstoreidx1 [off] {sym} ptr idx val mem)
+
+// combine ADDQ into indexed loads and stores
+(MOVBloadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem) -> (MOVBloadidx1 [c+d] {sym} ptr idx mem)
+(MOVWloadidx2 [c] {sym} (ADDQconst [d] ptr) idx mem) -> (MOVWloadidx2 [c+d] {sym} ptr idx mem)
+(MOVLloadidx4 [c] {sym} (ADDQconst [d] ptr) idx mem) -> (MOVLloadidx4 [c+d] {sym} ptr idx mem)
+(MOVQloadidx8 [c] {sym} (ADDQconst [d] ptr) idx mem) -> (MOVQloadidx8 [c+d] {sym} ptr idx mem)
+(MOVSSloadidx4 [c] {sym} (ADDQconst [d] ptr) idx mem) -> (MOVSSloadidx4 [c+d] {sym} ptr idx mem)
+(MOVSDloadidx8 [c] {sym} (ADDQconst [d] ptr) idx mem) -> (MOVSDloadidx8 [c+d] {sym} ptr idx mem)
+
+(MOVBstoreidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem) -> (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
+(MOVWstoreidx2 [c] {sym} (ADDQconst [d] ptr) idx val mem) -> (MOVWstoreidx2 [c+d] {sym} ptr idx val mem)
+(MOVLstoreidx4 [c] {sym} (ADDQconst [d] ptr) idx val mem) -> (MOVLstoreidx4 [c+d] {sym} ptr idx val mem)
+(MOVQstoreidx8 [c] {sym} (ADDQconst [d] ptr) idx val mem) -> (MOVQstoreidx8 [c+d] {sym} ptr idx val mem)
+(MOVSSstoreidx4 [c] {sym} (ADDQconst [d] ptr) idx val mem) -> (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem)
+(MOVSDstoreidx8 [c] {sym} (ADDQconst [d] ptr) idx val mem) -> (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem)
+
+(MOVBloadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem) -> (MOVBloadidx1 [c+d] {sym} ptr idx mem)
+(MOVWloadidx2 [c] {sym} ptr (ADDQconst [d] idx) mem) -> (MOVWloadidx2 [c+2*d] {sym} ptr idx mem)
+(MOVLloadidx4 [c] {sym} ptr (ADDQconst [d] idx) mem) -> (MOVLloadidx4 [c+4*d] {sym} ptr idx mem)
+(MOVQloadidx8 [c] {sym} ptr (ADDQconst [d] idx) mem) -> (MOVQloadidx8 [c+8*d] {sym} ptr idx mem)
+(MOVSSloadidx4 [c] {sym} ptr (ADDQconst [d] idx) mem) -> (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem)
+(MOVSDloadidx8 [c] {sym} ptr (ADDQconst [d] idx) mem) -> (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem)
+
+(MOVBstoreidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem) -> (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
+(MOVWstoreidx2 [c] {sym} ptr (ADDQconst [d] idx) val mem) -> (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem)
+(MOVLstoreidx4 [c] {sym} ptr (ADDQconst [d] idx) val mem) -> (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem)
+(MOVQstoreidx8 [c] {sym} ptr (ADDQconst [d] idx) val mem) -> (MOVQstoreidx8 [c+8*d] {sym} ptr idx val mem)
+(MOVSSstoreidx4 [c] {sym} ptr (ADDQconst [d] idx) val mem) -> (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem)
+(MOVSDstoreidx8 [c] {sym} ptr (ADDQconst [d] idx) val mem) -> (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem)
 
 // fold LEAQs together
 (LEAQ [off1] {sym1} (LEAQ [off2] {sym2} x)) && canMergeSym(sym1, sym2) ->
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
index 1cf44f1..bb7a42e 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
@@ -362,31 +362,37 @@
 		{name: "LEAQ2", reg: gp21sb, aux: "SymOff"},                         // arg0 + 2*arg1 + auxint + aux
 		{name: "LEAQ4", reg: gp21sb, aux: "SymOff"},                         // arg0 + 4*arg1 + auxint + aux
 		{name: "LEAQ8", reg: gp21sb, aux: "SymOff"},                         // arg0 + 8*arg1 + auxint + aux
+		// Note: LEAQ{1,2,4,8} must not have OpSB as either argument.
 
 		// auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
-		{name: "MOVBload", reg: gpload, asm: "MOVB", aux: "SymOff", typ: "UInt8"},  // load byte from arg0+auxint+aux. arg1=mem
-		{name: "MOVBQSXload", reg: gpload, asm: "MOVBQSX", aux: "SymOff"},          // ditto, extend to int64
-		{name: "MOVBQZXload", reg: gpload, asm: "MOVBQZX", aux: "SymOff"},          // ditto, extend to uint64
-		{name: "MOVWload", reg: gpload, asm: "MOVW", aux: "SymOff", typ: "UInt16"}, // load 2 bytes from arg0+auxint+aux. arg1=mem
-		{name: "MOVWQSXload", reg: gpload, asm: "MOVWQSX", aux: "SymOff"},          // ditto, extend to int64
-		{name: "MOVWQZXload", reg: gpload, asm: "MOVWQZX", aux: "SymOff"},          // ditto, extend to uint64
-		{name: "MOVLload", reg: gpload, asm: "MOVL", aux: "SymOff", typ: "UInt32"}, // load 4 bytes from arg0+auxint+aux. arg1=mem
-		{name: "MOVLQSXload", reg: gpload, asm: "MOVLQSX", aux: "SymOff"},          // ditto, extend to int64
-		{name: "MOVLQZXload", reg: gpload, asm: "MOVLQZX", aux: "SymOff"},          // ditto, extend to uint64
-		{name: "MOVQload", reg: gpload, asm: "MOVQ", aux: "SymOff", typ: "UInt64"}, // load 8 bytes from arg0+auxint+aux. arg1=mem
-		{name: "MOVQloadidx8", reg: gploadidx, asm: "MOVQ", aux: "SymOff"},         // load 8 bytes from arg0+8*arg1+auxint+aux. arg2=mem
-		{name: "MOVBstore", reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem"},  // store byte in arg1 to arg0+auxint+aux. arg2=mem
-		{name: "MOVWstore", reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem"},  // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
-		{name: "MOVLstore", reg: gpstore, asm: "MOVL", aux: "SymOff", typ: "Mem"},  // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
-		{name: "MOVQstore", reg: gpstore, asm: "MOVQ", aux: "SymOff", typ: "Mem"},  // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem
+		{name: "MOVBload", reg: gpload, asm: "MOVB", aux: "SymOff", typ: "UInt8"},    // load byte from arg0+auxint+aux. arg1=mem
+		{name: "MOVBQSXload", reg: gpload, asm: "MOVBQSX", aux: "SymOff"},            // ditto, extend to int64
+		{name: "MOVBQZXload", reg: gpload, asm: "MOVBQZX", aux: "SymOff"},            // ditto, extend to uint64
+		{name: "MOVWload", reg: gpload, asm: "MOVW", aux: "SymOff", typ: "UInt16"},   // load 2 bytes from arg0+auxint+aux. arg1=mem
+		{name: "MOVWQSXload", reg: gpload, asm: "MOVWQSX", aux: "SymOff"},            // ditto, extend to int64
+		{name: "MOVWQZXload", reg: gpload, asm: "MOVWQZX", aux: "SymOff"},            // ditto, extend to uint64
+		{name: "MOVLload", reg: gpload, asm: "MOVL", aux: "SymOff", typ: "UInt32"},   // load 4 bytes from arg0+auxint+aux. arg1=mem
+		{name: "MOVLQSXload", reg: gpload, asm: "MOVLQSX", aux: "SymOff"},            // ditto, extend to int64
+		{name: "MOVLQZXload", reg: gpload, asm: "MOVLQZX", aux: "SymOff"},            // ditto, extend to uint64
+		{name: "MOVQload", reg: gpload, asm: "MOVQ", aux: "SymOff", typ: "UInt64"},   // load 8 bytes from arg0+auxint+aux. arg1=mem
+		{name: "MOVBstore", reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem"},    // store byte in arg1 to arg0+auxint+aux. arg2=mem
+		{name: "MOVWstore", reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem"},    // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
+		{name: "MOVLstore", reg: gpstore, asm: "MOVL", aux: "SymOff", typ: "Mem"},    // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
+		{name: "MOVQstore", reg: gpstore, asm: "MOVQ", aux: "SymOff", typ: "Mem"},    // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem
+		{name: "MOVOload", reg: fpload, asm: "MOVUPS", aux: "SymOff", typ: "Int128"}, // load 16 bytes from arg0+auxint+aux. arg1=mem
+		{name: "MOVOstore", reg: fpstore, asm: "MOVUPS", aux: "SymOff", typ: "Mem"},  // store 16 bytes in arg1 to arg0+auxint+aux. arg2=mem
 
+		// indexed loads/stores
+		{name: "MOVBloadidx1", reg: gploadidx, asm: "MOVB", aux: "SymOff"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem
+		{name: "MOVWloadidx2", reg: gploadidx, asm: "MOVW", aux: "SymOff"}, // load 2 bytes from arg0+2*arg1+auxint+aux. arg2=mem
+		{name: "MOVLloadidx4", reg: gploadidx, asm: "MOVL", aux: "SymOff"}, // load 4 bytes from arg0+4*arg1+auxint+aux. arg2=mem
+		{name: "MOVQloadidx8", reg: gploadidx, asm: "MOVQ", aux: "SymOff"}, // load 8 bytes from arg0+8*arg1+auxint+aux. arg2=mem
+		// TODO: sign-extending indexed loads
 		{name: "MOVBstoreidx1", reg: gpstoreidx, asm: "MOVB", aux: "SymOff"}, // store byte in arg2 to arg0+arg1+auxint+aux. arg3=mem
 		{name: "MOVWstoreidx2", reg: gpstoreidx, asm: "MOVW", aux: "SymOff"}, // store 2 bytes in arg2 to arg0+2*arg1+auxint+aux. arg3=mem
 		{name: "MOVLstoreidx4", reg: gpstoreidx, asm: "MOVL", aux: "SymOff"}, // store 4 bytes in arg2 to arg0+4*arg1+auxint+aux. arg3=mem
 		{name: "MOVQstoreidx8", reg: gpstoreidx, asm: "MOVQ", aux: "SymOff"}, // store 8 bytes in arg2 to arg0+8*arg1+auxint+aux. arg3=mem
-
-		{name: "MOVOload", reg: fpload, asm: "MOVUPS", aux: "SymOff", typ: "Int128"}, // load 16 bytes from arg0+auxint+aux. arg1=mem
-		{name: "MOVOstore", reg: fpstore, asm: "MOVUPS", aux: "SymOff", typ: "Mem"},  // store 16 bytes in arg1 to arg0+auxint+aux. arg2=mem
+		// TODO: add size-mismatched indexed loads, like MOVBstoreidx4.
 
 		// For storeconst ops, the AuxInt field encodes both
 		// the value to store and an address offset of the store.
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index 089adfd..219d526 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -260,17 +260,20 @@
 	OpAMD64MOVLQSXload
 	OpAMD64MOVLQZXload
 	OpAMD64MOVQload
-	OpAMD64MOVQloadidx8
 	OpAMD64MOVBstore
 	OpAMD64MOVWstore
 	OpAMD64MOVLstore
 	OpAMD64MOVQstore
+	OpAMD64MOVOload
+	OpAMD64MOVOstore
+	OpAMD64MOVBloadidx1
+	OpAMD64MOVWloadidx2
+	OpAMD64MOVLloadidx4
+	OpAMD64MOVQloadidx8
 	OpAMD64MOVBstoreidx1
 	OpAMD64MOVWstoreidx2
 	OpAMD64MOVLstoreidx4
 	OpAMD64MOVQstoreidx8
-	OpAMD64MOVOload
-	OpAMD64MOVOstore
 	OpAMD64MOVBstoreconst
 	OpAMD64MOVWstoreconst
 	OpAMD64MOVLstoreconst
@@ -3130,20 +3133,6 @@
 		},
 	},
 	{
-		name:    "MOVQloadidx8",
-		auxType: auxSymOff,
-		asm:     x86.AMOVQ,
-		reg: regInfo{
-			inputs: []inputInfo{
-				{1, 65535},      // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
-				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
-			},
-			outputs: []regMask{
-				65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
-			},
-		},
-	},
-	{
 		name:    "MOVBstore",
 		auxType: auxSymOff,
 		asm:     x86.AMOVB,
@@ -3188,6 +3177,86 @@
 		},
 	},
 	{
+		name:    "MOVOload",
+		auxType: auxSymOff,
+		asm:     x86.AMOVUPS,
+		reg: regInfo{
+			inputs: []inputInfo{
+				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
+			},
+			outputs: []regMask{
+				4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15
+			},
+		},
+	},
+	{
+		name:    "MOVOstore",
+		auxType: auxSymOff,
+		asm:     x86.AMOVUPS,
+		reg: regInfo{
+			inputs: []inputInfo{
+				{1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15
+				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
+			},
+		},
+	},
+	{
+		name:    "MOVBloadidx1",
+		auxType: auxSymOff,
+		asm:     x86.AMOVB,
+		reg: regInfo{
+			inputs: []inputInfo{
+				{1, 65535},      // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
+			},
+			outputs: []regMask{
+				65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+			},
+		},
+	},
+	{
+		name:    "MOVWloadidx2",
+		auxType: auxSymOff,
+		asm:     x86.AMOVW,
+		reg: regInfo{
+			inputs: []inputInfo{
+				{1, 65535},      // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
+			},
+			outputs: []regMask{
+				65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+			},
+		},
+	},
+	{
+		name:    "MOVLloadidx4",
+		auxType: auxSymOff,
+		asm:     x86.AMOVL,
+		reg: regInfo{
+			inputs: []inputInfo{
+				{1, 65535},      // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
+			},
+			outputs: []regMask{
+				65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+			},
+		},
+	},
+	{
+		name:    "MOVQloadidx8",
+		auxType: auxSymOff,
+		asm:     x86.AMOVQ,
+		reg: regInfo{
+			inputs: []inputInfo{
+				{1, 65535},      // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
+			},
+			outputs: []regMask{
+				65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
+			},
+		},
+	},
+	{
 		name:    "MOVBstoreidx1",
 		auxType: auxSymOff,
 		asm:     x86.AMOVB,
@@ -3236,30 +3305,6 @@
 		},
 	},
 	{
-		name:    "MOVOload",
-		auxType: auxSymOff,
-		asm:     x86.AMOVUPS,
-		reg: regInfo{
-			inputs: []inputInfo{
-				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
-			},
-			outputs: []regMask{
-				4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15
-			},
-		},
-	},
-	{
-		name:    "MOVOstore",
-		auxType: auxSymOff,
-		asm:     x86.AMOVUPS,
-		reg: regInfo{
-			inputs: []inputInfo{
-				{1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15
-				{0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB
-			},
-		},
-	},
-	{
 		name:    "MOVBstoreconst",
 		auxType: auxSymValAndOff,
 		asm:     x86.AMOVB,
diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go
index 965e9a5..beaf0ac 100644
--- a/src/cmd/compile/internal/ssa/rewriteAMD64.go
+++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go
@@ -329,6 +329,8 @@
 		return rewriteValueAMD64_OpAMD64MOVBQZX(v, config)
 	case OpAMD64MOVBload:
 		return rewriteValueAMD64_OpAMD64MOVBload(v, config)
+	case OpAMD64MOVBloadidx1:
+		return rewriteValueAMD64_OpAMD64MOVBloadidx1(v, config)
 	case OpAMD64MOVBstore:
 		return rewriteValueAMD64_OpAMD64MOVBstore(v, config)
 	case OpAMD64MOVBstoreconst:
@@ -341,6 +343,8 @@
 		return rewriteValueAMD64_OpAMD64MOVLQZX(v, config)
 	case OpAMD64MOVLload:
 		return rewriteValueAMD64_OpAMD64MOVLload(v, config)
+	case OpAMD64MOVLloadidx4:
+		return rewriteValueAMD64_OpAMD64MOVLloadidx4(v, config)
 	case OpAMD64MOVLstore:
 		return rewriteValueAMD64_OpAMD64MOVLstore(v, config)
 	case OpAMD64MOVLstoreconst:
@@ -383,6 +387,8 @@
 		return rewriteValueAMD64_OpAMD64MOVWQZX(v, config)
 	case OpAMD64MOVWload:
 		return rewriteValueAMD64_OpAMD64MOVWload(v, config)
+	case OpAMD64MOVWloadidx2:
+		return rewriteValueAMD64_OpAMD64MOVWloadidx2(v, config)
 	case OpAMD64MOVWstore:
 		return rewriteValueAMD64_OpAMD64MOVWstore(v, config)
 	case OpAMD64MOVWstoreconst:
@@ -1015,6 +1021,154 @@
 	goto endc02313d35a0525d1d680cd58992e820d
 endc02313d35a0525d1d680cd58992e820d:
 	;
+	// match: (ADDQ x (SHLQconst [2] y))
+	// cond:
+	// result: (LEAQ4 x y)
+	{
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64SHLQconst {
+			goto end153955fe292c5ecb20b76bba7da8f451
+		}
+		if v.Args[1].AuxInt != 2 {
+			goto end153955fe292c5ecb20b76bba7da8f451
+		}
+		y := v.Args[1].Args[0]
+		v.reset(OpAMD64LEAQ4)
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end153955fe292c5ecb20b76bba7da8f451
+end153955fe292c5ecb20b76bba7da8f451:
+	;
+	// match: (ADDQ x (SHLQconst [1] y))
+	// cond:
+	// result: (LEAQ2 x y)
+	{
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64SHLQconst {
+			goto enda863d175a7a59f03d4306df57e8351f6
+		}
+		if v.Args[1].AuxInt != 1 {
+			goto enda863d175a7a59f03d4306df57e8351f6
+		}
+		y := v.Args[1].Args[0]
+		v.reset(OpAMD64LEAQ2)
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto enda863d175a7a59f03d4306df57e8351f6
+enda863d175a7a59f03d4306df57e8351f6:
+	;
+	// match: (ADDQ x (ADDQ y y))
+	// cond:
+	// result: (LEAQ2 x y)
+	{
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQ {
+			goto endf7dd9841c41eec66eddd351ee39cfbf3
+		}
+		y := v.Args[1].Args[0]
+		if v.Args[1].Args[1] != y {
+			goto endf7dd9841c41eec66eddd351ee39cfbf3
+		}
+		v.reset(OpAMD64LEAQ2)
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto endf7dd9841c41eec66eddd351ee39cfbf3
+endf7dd9841c41eec66eddd351ee39cfbf3:
+	;
+	// match: (ADDQ x (ADDQ x y))
+	// cond:
+	// result: (LEAQ2 y x)
+	{
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQ {
+			goto end5547794ce29adef7d31260653a56bcb5
+		}
+		if v.Args[1].Args[0] != x {
+			goto end5547794ce29adef7d31260653a56bcb5
+		}
+		y := v.Args[1].Args[1]
+		v.reset(OpAMD64LEAQ2)
+		v.AddArg(y)
+		v.AddArg(x)
+		return true
+	}
+	goto end5547794ce29adef7d31260653a56bcb5
+end5547794ce29adef7d31260653a56bcb5:
+	;
+	// match: (ADDQ x (ADDQ y x))
+	// cond:
+	// result: (LEAQ2 y x)
+	{
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQ {
+			goto end0ef5fb7590c377b6274991aaea41fae2
+		}
+		y := v.Args[1].Args[0]
+		if v.Args[1].Args[1] != x {
+			goto end0ef5fb7590c377b6274991aaea41fae2
+		}
+		v.reset(OpAMD64LEAQ2)
+		v.AddArg(y)
+		v.AddArg(x)
+		return true
+	}
+	goto end0ef5fb7590c377b6274991aaea41fae2
+end0ef5fb7590c377b6274991aaea41fae2:
+	;
+	// match: (ADDQ x (LEAQ [c] {s} y))
+	// cond: x.Op != OpSB && y.Op != OpSB
+	// result: (LEAQ1 [c] {s} x y)
+	{
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64LEAQ {
+			goto endadc48e1a7f3d0a3505b68ffc771bb086
+		}
+		c := v.Args[1].AuxInt
+		s := v.Args[1].Aux
+		y := v.Args[1].Args[0]
+		if !(x.Op != OpSB && y.Op != OpSB) {
+			goto endadc48e1a7f3d0a3505b68ffc771bb086
+		}
+		v.reset(OpAMD64LEAQ1)
+		v.AuxInt = c
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto endadc48e1a7f3d0a3505b68ffc771bb086
+endadc48e1a7f3d0a3505b68ffc771bb086:
+	;
+	// match: (ADDQ (LEAQ [c] {s} x) y)
+	// cond: x.Op != OpSB && y.Op != OpSB
+	// result: (LEAQ1 [c] {s} x y)
+	{
+		if v.Args[0].Op != OpAMD64LEAQ {
+			goto end2696de9ef8f27dbc96dd4ad5878b0779
+		}
+		c := v.Args[0].AuxInt
+		s := v.Args[0].Aux
+		x := v.Args[0].Args[0]
+		y := v.Args[1]
+		if !(x.Op != OpSB && y.Op != OpSB) {
+			goto end2696de9ef8f27dbc96dd4ad5878b0779
+		}
+		v.reset(OpAMD64LEAQ1)
+		v.AuxInt = c
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end2696de9ef8f27dbc96dd4ad5878b0779
+end2696de9ef8f27dbc96dd4ad5878b0779:
+	;
 	// match: (ADDQ x (NEGQ y))
 	// cond:
 	// result: (SUBQ x y)
@@ -1037,25 +1191,113 @@
 func rewriteValueAMD64_OpAMD64ADDQconst(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (ADDQconst [c] (LEAQ8 [d] x y))
+	// match: (ADDQconst [c] (LEAQ [d] {s} x))
 	// cond:
-	// result: (LEAQ8 [addOff(c, d)] x y)
+	// result: (LEAQ [c+d] {s} x)
 	{
 		c := v.AuxInt
-		if v.Args[0].Op != OpAMD64LEAQ8 {
-			goto ende2cc681c9abf9913288803fb1b39e639
+		if v.Args[0].Op != OpAMD64LEAQ {
+			goto end5bfebc265098e6e57905269bb95daa3f
 		}
 		d := v.Args[0].AuxInt
+		s := v.Args[0].Aux
+		x := v.Args[0].Args[0]
+		v.reset(OpAMD64LEAQ)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		return true
+	}
+	goto end5bfebc265098e6e57905269bb95daa3f
+end5bfebc265098e6e57905269bb95daa3f:
+	;
+	// match: (ADDQconst [c] (LEAQ1 [d] {s} x y))
+	// cond:
+	// result: (LEAQ1 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		if v.Args[0].Op != OpAMD64LEAQ1 {
+			goto end71505b5ee2217f51c50569efc37499e7
+		}
+		d := v.Args[0].AuxInt
+		s := v.Args[0].Aux
 		x := v.Args[0].Args[0]
 		y := v.Args[0].Args[1]
-		v.reset(OpAMD64LEAQ8)
-		v.AuxInt = addOff(c, d)
+		v.reset(OpAMD64LEAQ1)
+		v.AuxInt = c + d
+		v.Aux = s
 		v.AddArg(x)
 		v.AddArg(y)
 		return true
 	}
-	goto ende2cc681c9abf9913288803fb1b39e639
-ende2cc681c9abf9913288803fb1b39e639:
+	goto end71505b5ee2217f51c50569efc37499e7
+end71505b5ee2217f51c50569efc37499e7:
+	;
+	// match: (ADDQconst [c] (LEAQ2 [d] {s} x y))
+	// cond:
+	// result: (LEAQ2 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		if v.Args[0].Op != OpAMD64LEAQ2 {
+			goto end9f155ec07598aec52f602a92a5d719a9
+		}
+		d := v.Args[0].AuxInt
+		s := v.Args[0].Aux
+		x := v.Args[0].Args[0]
+		y := v.Args[0].Args[1]
+		v.reset(OpAMD64LEAQ2)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end9f155ec07598aec52f602a92a5d719a9
+end9f155ec07598aec52f602a92a5d719a9:
+	;
+	// match: (ADDQconst [c] (LEAQ4 [d] {s} x y))
+	// cond:
+	// result: (LEAQ4 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		if v.Args[0].Op != OpAMD64LEAQ4 {
+			goto end95f58aac9e8ea7efaef2bec6400cf7f8
+		}
+		d := v.Args[0].AuxInt
+		s := v.Args[0].Aux
+		x := v.Args[0].Args[0]
+		y := v.Args[0].Args[1]
+		v.reset(OpAMD64LEAQ4)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end95f58aac9e8ea7efaef2bec6400cf7f8
+end95f58aac9e8ea7efaef2bec6400cf7f8:
+	;
+	// match: (ADDQconst [c] (LEAQ8 [d] {s} x y))
+	// cond:
+	// result: (LEAQ8 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		if v.Args[0].Op != OpAMD64LEAQ8 {
+			goto end9d4328824aff954a1f47f1109500e826
+		}
+		d := v.Args[0].AuxInt
+		s := v.Args[0].Aux
+		x := v.Args[0].Args[0]
+		y := v.Args[0].Args[1]
+		v.reset(OpAMD64LEAQ8)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end9d4328824aff954a1f47f1109500e826
+end9d4328824aff954a1f47f1109500e826:
 	;
 	// match: (ADDQconst [0] x)
 	// cond:
@@ -4209,6 +4451,50 @@
 func rewriteValueAMD64_OpAMD64LEAQ(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
+	// match: (LEAQ [c] {s} (ADDQconst [d] x))
+	// cond:
+	// result: (LEAQ [c+d] {s} x)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQconst {
+			goto endb764d049517eb7c125b442ec9246c2c6
+		}
+		d := v.Args[0].AuxInt
+		x := v.Args[0].Args[0]
+		v.reset(OpAMD64LEAQ)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		return true
+	}
+	goto endb764d049517eb7c125b442ec9246c2c6
+endb764d049517eb7c125b442ec9246c2c6:
+	;
+	// match: (LEAQ [c] {s} (ADDQ x y))
+	// cond: x.Op != OpSB && y.Op != OpSB
+	// result: (LEAQ1 [c] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQ {
+			goto end8ee88dfb1a197184ebe10e479fafd322
+		}
+		x := v.Args[0].Args[0]
+		y := v.Args[0].Args[1]
+		if !(x.Op != OpSB && y.Op != OpSB) {
+			goto end8ee88dfb1a197184ebe10e479fafd322
+		}
+		v.reset(OpAMD64LEAQ1)
+		v.AuxInt = c
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end8ee88dfb1a197184ebe10e479fafd322
+end8ee88dfb1a197184ebe10e479fafd322:
+	;
 	// match: (LEAQ [off1] {sym1} (LEAQ [off2] {sym2} x))
 	// cond: canMergeSym(sym1, sym2)
 	// result: (LEAQ [addOff(off1,off2)] {mergeSym(sym1,sym2)} x)
@@ -4342,6 +4628,56 @@
 func rewriteValueAMD64_OpAMD64LEAQ1(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
+	// match: (LEAQ1 [c] {s} (ADDQconst [d] x) y)
+	// cond: x.Op != OpSB
+	// result: (LEAQ1 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQconst {
+			goto endcee67e6c005f58a521fc4f33a98b11c6
+		}
+		d := v.Args[0].AuxInt
+		x := v.Args[0].Args[0]
+		y := v.Args[1]
+		if !(x.Op != OpSB) {
+			goto endcee67e6c005f58a521fc4f33a98b11c6
+		}
+		v.reset(OpAMD64LEAQ1)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto endcee67e6c005f58a521fc4f33a98b11c6
+endcee67e6c005f58a521fc4f33a98b11c6:
+	;
+	// match: (LEAQ1 [c] {s} x (ADDQconst [d] y))
+	// cond: y.Op != OpSB
+	// result: (LEAQ1 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto end8ae759893af2b32c6dbcdeeca12ca207
+		}
+		d := v.Args[1].AuxInt
+		y := v.Args[1].Args[0]
+		if !(y.Op != OpSB) {
+			goto end8ae759893af2b32c6dbcdeeca12ca207
+		}
+		v.reset(OpAMD64LEAQ1)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end8ae759893af2b32c6dbcdeeca12ca207
+end8ae759893af2b32c6dbcdeeca12ca207:
+	;
 	// match: (LEAQ1 [off1] {sym1} (LEAQ [off2] {sym2} x) y)
 	// cond: canMergeSym(sym1, sym2) && x.Op != OpSB
 	// result: (LEAQ1 [addOff(off1,off2)] {mergeSym(sym1,sym2)} x y)
@@ -4399,6 +4735,56 @@
 func rewriteValueAMD64_OpAMD64LEAQ2(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
+	// match: (LEAQ2 [c] {s} (ADDQconst [d] x) y)
+	// cond: x.Op != OpSB
+	// result: (LEAQ2 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQconst {
+			goto end32327450a43437ef98ffba85d4f64808
+		}
+		d := v.Args[0].AuxInt
+		x := v.Args[0].Args[0]
+		y := v.Args[1]
+		if !(x.Op != OpSB) {
+			goto end32327450a43437ef98ffba85d4f64808
+		}
+		v.reset(OpAMD64LEAQ2)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end32327450a43437ef98ffba85d4f64808
+end32327450a43437ef98ffba85d4f64808:
+	;
+	// match: (LEAQ2 [c] {s} x (ADDQconst [d] y))
+	// cond: y.Op != OpSB
+	// result: (LEAQ2 [c+2*d] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto end86e05a0977fd26c884c75b29625c6236
+		}
+		d := v.Args[1].AuxInt
+		y := v.Args[1].Args[0]
+		if !(y.Op != OpSB) {
+			goto end86e05a0977fd26c884c75b29625c6236
+		}
+		v.reset(OpAMD64LEAQ2)
+		v.AuxInt = c + 2*d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end86e05a0977fd26c884c75b29625c6236
+end86e05a0977fd26c884c75b29625c6236:
+	;
 	// match: (LEAQ2 [off1] {sym1} (LEAQ [off2] {sym2} x) y)
 	// cond: canMergeSym(sym1, sym2) && x.Op != OpSB
 	// result: (LEAQ2 [addOff(off1,off2)] {mergeSym(sym1,sym2)} x y)
@@ -4430,6 +4816,56 @@
 func rewriteValueAMD64_OpAMD64LEAQ4(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
+	// match: (LEAQ4 [c] {s} (ADDQconst [d] x) y)
+	// cond: x.Op != OpSB
+	// result: (LEAQ4 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQconst {
+			goto end2225ec635a27f55cd2e4ddaf3bebdf5b
+		}
+		d := v.Args[0].AuxInt
+		x := v.Args[0].Args[0]
+		y := v.Args[1]
+		if !(x.Op != OpSB) {
+			goto end2225ec635a27f55cd2e4ddaf3bebdf5b
+		}
+		v.reset(OpAMD64LEAQ4)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end2225ec635a27f55cd2e4ddaf3bebdf5b
+end2225ec635a27f55cd2e4ddaf3bebdf5b:
+	;
+	// match: (LEAQ4 [c] {s} x (ADDQconst [d] y))
+	// cond: y.Op != OpSB
+	// result: (LEAQ4 [c+4*d] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto endd198c6d7b0038f43476fe50d886ed76b
+		}
+		d := v.Args[1].AuxInt
+		y := v.Args[1].Args[0]
+		if !(y.Op != OpSB) {
+			goto endd198c6d7b0038f43476fe50d886ed76b
+		}
+		v.reset(OpAMD64LEAQ4)
+		v.AuxInt = c + 4*d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto endd198c6d7b0038f43476fe50d886ed76b
+endd198c6d7b0038f43476fe50d886ed76b:
+	;
 	// match: (LEAQ4 [off1] {sym1} (LEAQ [off2] {sym2} x) y)
 	// cond: canMergeSym(sym1, sym2) && x.Op != OpSB
 	// result: (LEAQ4 [addOff(off1,off2)] {mergeSym(sym1,sym2)} x y)
@@ -4461,6 +4897,56 @@
 func rewriteValueAMD64_OpAMD64LEAQ8(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
+	// match: (LEAQ8 [c] {s} (ADDQconst [d] x) y)
+	// cond: x.Op != OpSB
+	// result: (LEAQ8 [c+d] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQconst {
+			goto end26e798ad0167e205b8c670f19cef8122
+		}
+		d := v.Args[0].AuxInt
+		x := v.Args[0].Args[0]
+		y := v.Args[1]
+		if !(x.Op != OpSB) {
+			goto end26e798ad0167e205b8c670f19cef8122
+		}
+		v.reset(OpAMD64LEAQ8)
+		v.AuxInt = c + d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end26e798ad0167e205b8c670f19cef8122
+end26e798ad0167e205b8c670f19cef8122:
+	;
+	// match: (LEAQ8 [c] {s} x (ADDQconst [d] y))
+	// cond: y.Op != OpSB
+	// result: (LEAQ8 [c+8*d] {s} x y)
+	{
+		c := v.AuxInt
+		s := v.Aux
+		x := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto end85f87ffff7b951c1d085198e3bee2f09
+		}
+		d := v.Args[1].AuxInt
+		y := v.Args[1].Args[0]
+		if !(y.Op != OpSB) {
+			goto end85f87ffff7b951c1d085198e3bee2f09
+		}
+		v.reset(OpAMD64LEAQ8)
+		v.AuxInt = c + 8*d
+		v.Aux = s
+		v.AddArg(x)
+		v.AddArg(y)
+		return true
+	}
+	goto end85f87ffff7b951c1d085198e3bee2f09
+end85f87ffff7b951c1d085198e3bee2f09:
+	;
 	// match: (LEAQ8 [off1] {sym1} (LEAQ [off2] {sym2} x) y)
 	// cond: canMergeSym(sym1, sym2) && x.Op != OpSB
 	// result: (LEAQ8 [addOff(off1,off2)] {mergeSym(sym1,sym2)} x y)
@@ -5698,6 +6184,113 @@
 	goto end3771a59cf66b0df99120d76f4c358fab
 end3771a59cf66b0df99120d76f4c358fab:
 	;
+	// match: (MOVBload [off1] {sym1} (LEAQ1 [off2] {sym2} ptr idx) mem)
+	// cond: canMergeSym(sym1, sym2)
+	// result: (MOVBloadidx1 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem)
+	{
+		off1 := v.AuxInt
+		sym1 := v.Aux
+		if v.Args[0].Op != OpAMD64LEAQ1 {
+			goto endb5e38220bc6108fb683f1f1e46853bd9
+		}
+		off2 := v.Args[0].AuxInt
+		sym2 := v.Args[0].Aux
+		ptr := v.Args[0].Args[0]
+		idx := v.Args[0].Args[1]
+		mem := v.Args[1]
+		if !(canMergeSym(sym1, sym2)) {
+			goto endb5e38220bc6108fb683f1f1e46853bd9
+		}
+		v.reset(OpAMD64MOVBloadidx1)
+		v.AuxInt = addOff(off1, off2)
+		v.Aux = mergeSym(sym1, sym2)
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto endb5e38220bc6108fb683f1f1e46853bd9
+endb5e38220bc6108fb683f1f1e46853bd9:
+	;
+	// match: (MOVBload [off] {sym} (ADDQ ptr idx) mem)
+	// cond: ptr.Op != OpSB
+	// result: (MOVBloadidx1 [off] {sym} ptr idx mem)
+	{
+		off := v.AuxInt
+		sym := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQ {
+			goto end2abf84efc0e06ed9cda71fb8a1ffaacd
+		}
+		ptr := v.Args[0].Args[0]
+		idx := v.Args[0].Args[1]
+		mem := v.Args[1]
+		if !(ptr.Op != OpSB) {
+			goto end2abf84efc0e06ed9cda71fb8a1ffaacd
+		}
+		v.reset(OpAMD64MOVBloadidx1)
+		v.AuxInt = off
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto end2abf84efc0e06ed9cda71fb8a1ffaacd
+end2abf84efc0e06ed9cda71fb8a1ffaacd:
+	;
+	return false
+}
+func rewriteValueAMD64_OpAMD64MOVBloadidx1(v *Value, config *Config) bool {
+	b := v.Block
+	_ = b
+	// match: (MOVBloadidx1 [c] {sym} (ADDQconst [d] ptr) idx mem)
+	// cond:
+	// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQconst {
+			goto end287a4eb26a59b5f23efa2c6df34711f7
+		}
+		d := v.Args[0].AuxInt
+		ptr := v.Args[0].Args[0]
+		idx := v.Args[1]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVBloadidx1)
+		v.AuxInt = c + d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto end287a4eb26a59b5f23efa2c6df34711f7
+end287a4eb26a59b5f23efa2c6df34711f7:
+	;
+	// match: (MOVBloadidx1 [c] {sym} ptr (ADDQconst [d] idx) mem)
+	// cond:
+	// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto end3d2e4e850c5e8129cd71a8693403b6c1
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVBloadidx1)
+		v.AuxInt = c + d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto end3d2e4e850c5e8129cd71a8693403b6c1
+end3d2e4e850c5e8129cd71a8693403b6c1:
+	;
 	return false
 }
 func rewriteValueAMD64_OpAMD64MOVBstore(v *Value, config *Config) bool {
@@ -5857,18 +6450,21 @@
 ende386ced77f1acdae2e8bbc379803b7cf:
 	;
 	// match: (MOVBstore [off] {sym} (ADDQ ptr idx) val mem)
-	// cond:
+	// cond: ptr.Op != OpSB
 	// result: (MOVBstoreidx1 [off] {sym} ptr idx val mem)
 	{
 		off := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQ {
-			goto endc7abfa0b473c622e6d5aa3b1846fb2b7
+			goto endb43afe2024f68e41f2538876c4bf49cc
 		}
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[0].Args[1]
 		val := v.Args[1]
 		mem := v.Args[2]
+		if !(ptr.Op != OpSB) {
+			goto endb43afe2024f68e41f2538876c4bf49cc
+		}
 		v.reset(OpAMD64MOVBstoreidx1)
 		v.AuxInt = off
 		v.Aux = sym
@@ -5878,8 +6474,8 @@
 		v.AddArg(mem)
 		return true
 	}
-	goto endc7abfa0b473c622e6d5aa3b1846fb2b7
-endc7abfa0b473c622e6d5aa3b1846fb2b7:
+	goto endb43afe2024f68e41f2538876c4bf49cc
+endb43afe2024f68e41f2538876c4bf49cc:
 	;
 	return false
 }
@@ -5942,22 +6538,22 @@
 func rewriteValueAMD64_OpAMD64MOVBstoreidx1(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVBstoreidx1 [off1] {sym} (ADDQconst [off2] ptr) idx val mem)
+	// match: (MOVBstoreidx1 [c] {sym} (ADDQconst [d] ptr) idx val mem)
 	// cond:
-	// result: (MOVBstoreidx1 [addOff(off1, off2)] {sym} ptr idx val mem)
+	// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto endba611397b0dfd416156f29d7bd95b945
+			goto end5e07185968f39170e41a237cc6258752
 		}
-		off2 := v.Args[0].AuxInt
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		val := v.Args[2]
 		mem := v.Args[3]
 		v.reset(OpAMD64MOVBstoreidx1)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
@@ -5965,8 +6561,34 @@
 		v.AddArg(mem)
 		return true
 	}
-	goto endba611397b0dfd416156f29d7bd95b945
-endba611397b0dfd416156f29d7bd95b945:
+	goto end5e07185968f39170e41a237cc6258752
+end5e07185968f39170e41a237cc6258752:
+	;
+	// match: (MOVBstoreidx1 [c] {sym} ptr (ADDQconst [d] idx) val mem)
+	// cond:
+	// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto endf1e4b8d5da2530ca81e2c01dc2892875
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		val := v.Args[2]
+		mem := v.Args[3]
+		v.reset(OpAMD64MOVBstoreidx1)
+		v.AuxInt = c + d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(val)
+		v.AddArg(mem)
+		return true
+	}
+	goto endf1e4b8d5da2530ca81e2c01dc2892875
+endf1e4b8d5da2530ca81e2c01dc2892875:
 	;
 	return false
 }
@@ -6114,6 +6736,87 @@
 	goto enddb9e59335876d8a565c425731438a1b3
 enddb9e59335876d8a565c425731438a1b3:
 	;
+	// match: (MOVLload [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) mem)
+	// cond: canMergeSym(sym1, sym2)
+	// result: (MOVLloadidx4 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem)
+	{
+		off1 := v.AuxInt
+		sym1 := v.Aux
+		if v.Args[0].Op != OpAMD64LEAQ4 {
+			goto end6eed46982cfbceace4784afdf29ba2b9
+		}
+		off2 := v.Args[0].AuxInt
+		sym2 := v.Args[0].Aux
+		ptr := v.Args[0].Args[0]
+		idx := v.Args[0].Args[1]
+		mem := v.Args[1]
+		if !(canMergeSym(sym1, sym2)) {
+			goto end6eed46982cfbceace4784afdf29ba2b9
+		}
+		v.reset(OpAMD64MOVLloadidx4)
+		v.AuxInt = addOff(off1, off2)
+		v.Aux = mergeSym(sym1, sym2)
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto end6eed46982cfbceace4784afdf29ba2b9
+end6eed46982cfbceace4784afdf29ba2b9:
+	;
+	return false
+}
+func rewriteValueAMD64_OpAMD64MOVLloadidx4(v *Value, config *Config) bool {
+	b := v.Block
+	_ = b
+	// match: (MOVLloadidx4 [c] {sym} (ADDQconst [d] ptr) idx mem)
+	// cond:
+	// result: (MOVLloadidx4 [c+d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQconst {
+			goto endcafad33c3669685fdfee020f111fdcb6
+		}
+		d := v.Args[0].AuxInt
+		ptr := v.Args[0].Args[0]
+		idx := v.Args[1]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVLloadidx4)
+		v.AuxInt = c + d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto endcafad33c3669685fdfee020f111fdcb6
+endcafad33c3669685fdfee020f111fdcb6:
+	;
+	// match: (MOVLloadidx4 [c] {sym} ptr (ADDQconst [d] idx) mem)
+	// cond:
+	// result: (MOVLloadidx4 [c+4*d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto endfb8f54bfe07226dcb7d4e2d6df319707
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVLloadidx4)
+		v.AuxInt = c + 4*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto endfb8f54bfe07226dcb7d4e2d6df319707
+endfb8f54bfe07226dcb7d4e2d6df319707:
+	;
 	return false
 }
 func rewriteValueAMD64_OpAMD64MOVLstore(v *Value, config *Config) bool {
@@ -6333,22 +7036,22 @@
 func rewriteValueAMD64_OpAMD64MOVLstoreidx4(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVLstoreidx4 [off1] {sym} (ADDQconst [off2] ptr) idx val mem)
+	// match: (MOVLstoreidx4 [c] {sym} (ADDQconst [d] ptr) idx val mem)
 	// cond:
-	// result: (MOVLstoreidx4 [addOff(off1, off2)] {sym} ptr idx val mem)
+	// result: (MOVLstoreidx4 [c+d] {sym} ptr idx val mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto endf4921486b8eca2abd4a92ffadc6cb52d
+			goto endd72a73ada3e68139d21049bd337bcfd2
 		}
-		off2 := v.Args[0].AuxInt
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		val := v.Args[2]
 		mem := v.Args[3]
 		v.reset(OpAMD64MOVLstoreidx4)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
@@ -6356,8 +7059,34 @@
 		v.AddArg(mem)
 		return true
 	}
-	goto endf4921486b8eca2abd4a92ffadc6cb52d
-endf4921486b8eca2abd4a92ffadc6cb52d:
+	goto endd72a73ada3e68139d21049bd337bcfd2
+endd72a73ada3e68139d21049bd337bcfd2:
+	;
+	// match: (MOVLstoreidx4 [c] {sym} ptr (ADDQconst [d] idx) val mem)
+	// cond:
+	// result: (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto endea783679ed46542bc48309b9fd2f6054
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		val := v.Args[2]
+		mem := v.Args[3]
+		v.reset(OpAMD64MOVLstoreidx4)
+		v.AuxInt = c + 4*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(val)
+		v.AddArg(mem)
+		return true
+	}
+	goto endea783679ed46542bc48309b9fd2f6054
+endea783679ed46542bc48309b9fd2f6054:
 	;
 	return false
 }
@@ -6555,29 +7284,53 @@
 func rewriteValueAMD64_OpAMD64MOVQloadidx8(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVQloadidx8 [off1] {sym} (ADDQconst [off2] ptr) idx mem)
+	// match: (MOVQloadidx8 [c] {sym} (ADDQconst [d] ptr) idx mem)
 	// cond:
-	// result: (MOVQloadidx8 [addOff(off1, off2)] {sym} ptr idx mem)
+	// result: (MOVQloadidx8 [c+d] {sym} ptr idx mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto endb138bf9b0b33ec824bf0aff619f8bafa
+			goto end012c0c0292dbfd55f520e4d88d9247e4
 		}
-		off2 := v.Args[0].AuxInt
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		mem := v.Args[2]
 		v.reset(OpAMD64MOVQloadidx8)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
 		v.AddArg(mem)
 		return true
 	}
-	goto endb138bf9b0b33ec824bf0aff619f8bafa
-endb138bf9b0b33ec824bf0aff619f8bafa:
+	goto end012c0c0292dbfd55f520e4d88d9247e4
+end012c0c0292dbfd55f520e4d88d9247e4:
+	;
+	// match: (MOVQloadidx8 [c] {sym} ptr (ADDQconst [d] idx) mem)
+	// cond:
+	// result: (MOVQloadidx8 [c+8*d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto endd36e82450f4737c06501b7bc9e881d13
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVQloadidx8)
+		v.AuxInt = c + 8*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto endd36e82450f4737c06501b7bc9e881d13
+endd36e82450f4737c06501b7bc9e881d13:
 	;
 	return false
 }
@@ -6752,22 +7505,22 @@
 func rewriteValueAMD64_OpAMD64MOVQstoreidx8(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVQstoreidx8 [off1] {sym} (ADDQconst [off2] ptr) idx val mem)
+	// match: (MOVQstoreidx8 [c] {sym} (ADDQconst [d] ptr) idx val mem)
 	// cond:
-	// result: (MOVQstoreidx8 [addOff(off1, off2)] {sym} ptr idx val mem)
+	// result: (MOVQstoreidx8 [c+d] {sym} ptr idx val mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto end50671766fdab364c1edbd2072fb8e525
+			goto end775cfe4359adc4bffc346289df14bbc3
 		}
-		off2 := v.Args[0].AuxInt
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		val := v.Args[2]
 		mem := v.Args[3]
 		v.reset(OpAMD64MOVQstoreidx8)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
@@ -6775,8 +7528,34 @@
 		v.AddArg(mem)
 		return true
 	}
-	goto end50671766fdab364c1edbd2072fb8e525
-end50671766fdab364c1edbd2072fb8e525:
+	goto end775cfe4359adc4bffc346289df14bbc3
+end775cfe4359adc4bffc346289df14bbc3:
+	;
+	// match: (MOVQstoreidx8 [c] {sym} ptr (ADDQconst [d] idx) val mem)
+	// cond:
+	// result: (MOVQstoreidx8 [c+8*d] {sym} ptr idx val mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto end20281fb6ccf09a9b56abdba46f443232
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		val := v.Args[2]
+		mem := v.Args[3]
+		v.reset(OpAMD64MOVQstoreidx8)
+		v.AuxInt = c + 8*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(val)
+		v.AddArg(mem)
+		return true
+	}
+	goto end20281fb6ccf09a9b56abdba46f443232
+end20281fb6ccf09a9b56abdba46f443232:
 	;
 	return false
 }
@@ -6864,32 +7643,53 @@
 func rewriteValueAMD64_OpAMD64MOVSDloadidx8(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVSDloadidx8 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx mem)
+	// match: (MOVSDloadidx8 [c] {sym} (ADDQconst [d] ptr) idx mem)
 	// cond:
-	// result: (MOVSDloadidx8 [addOff(off1, off2)] {sym} ptr idx mem)
+	// result: (MOVSDloadidx8 [c+d] {sym} ptr idx mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto end84f0f457e271104a92343e3b1d2804c6
+			goto endb313602cfa64c282cc86c27c7183c507
 		}
-		off2 := v.Args[0].AuxInt
-		if v.Args[0].Aux != v.Aux {
-			goto end84f0f457e271104a92343e3b1d2804c6
-		}
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		mem := v.Args[2]
 		v.reset(OpAMD64MOVSDloadidx8)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
 		v.AddArg(mem)
 		return true
 	}
-	goto end84f0f457e271104a92343e3b1d2804c6
-end84f0f457e271104a92343e3b1d2804c6:
+	goto endb313602cfa64c282cc86c27c7183c507
+endb313602cfa64c282cc86c27c7183c507:
+	;
+	// match: (MOVSDloadidx8 [c] {sym} ptr (ADDQconst [d] idx) mem)
+	// cond:
+	// result: (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto endfb406e2cba383116291b60825765637c
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVSDloadidx8)
+		v.AuxInt = c + 8*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto endfb406e2cba383116291b60825765637c
+endfb406e2cba383116291b60825765637c:
 	;
 	return false
 }
@@ -6983,25 +7783,22 @@
 func rewriteValueAMD64_OpAMD64MOVSDstoreidx8(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVSDstoreidx8 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx val mem)
+	// match: (MOVSDstoreidx8 [c] {sym} (ADDQconst [d] ptr) idx val mem)
 	// cond:
-	// result: (MOVSDstoreidx8 [addOff(off1, off2)] {sym} ptr idx val mem)
+	// result: (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto endc0e28f57697cb6038d5d09eafe26c947
+			goto end8b8f41236593d5d5e83663cc14350fe8
 		}
-		off2 := v.Args[0].AuxInt
-		if v.Args[0].Aux != v.Aux {
-			goto endc0e28f57697cb6038d5d09eafe26c947
-		}
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		val := v.Args[2]
 		mem := v.Args[3]
 		v.reset(OpAMD64MOVSDstoreidx8)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
@@ -7009,8 +7806,34 @@
 		v.AddArg(mem)
 		return true
 	}
-	goto endc0e28f57697cb6038d5d09eafe26c947
-endc0e28f57697cb6038d5d09eafe26c947:
+	goto end8b8f41236593d5d5e83663cc14350fe8
+end8b8f41236593d5d5e83663cc14350fe8:
+	;
+	// match: (MOVSDstoreidx8 [c] {sym} ptr (ADDQconst [d] idx) val mem)
+	// cond:
+	// result: (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto end94b7159715acb6ebb94b08b3a826f5fe
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		val := v.Args[2]
+		mem := v.Args[3]
+		v.reset(OpAMD64MOVSDstoreidx8)
+		v.AuxInt = c + 8*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(val)
+		v.AddArg(mem)
+		return true
+	}
+	goto end94b7159715acb6ebb94b08b3a826f5fe
+end94b7159715acb6ebb94b08b3a826f5fe:
 	;
 	return false
 }
@@ -7098,32 +7921,53 @@
 func rewriteValueAMD64_OpAMD64MOVSSloadidx4(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVSSloadidx4 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx mem)
+	// match: (MOVSSloadidx4 [c] {sym} (ADDQconst [d] ptr) idx mem)
 	// cond:
-	// result: (MOVSSloadidx4 [addOff(off1, off2)] {sym} ptr idx mem)
+	// result: (MOVSSloadidx4 [c+d] {sym} ptr idx mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto end7eb5a1ab1e2508683d879ec25286754b
+			goto end2317614a112d773b1209327d552bb022
 		}
-		off2 := v.Args[0].AuxInt
-		if v.Args[0].Aux != v.Aux {
-			goto end7eb5a1ab1e2508683d879ec25286754b
-		}
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		mem := v.Args[2]
 		v.reset(OpAMD64MOVSSloadidx4)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
 		v.AddArg(mem)
 		return true
 	}
-	goto end7eb5a1ab1e2508683d879ec25286754b
-end7eb5a1ab1e2508683d879ec25286754b:
+	goto end2317614a112d773b1209327d552bb022
+end2317614a112d773b1209327d552bb022:
+	;
+	// match: (MOVSSloadidx4 [c] {sym} ptr (ADDQconst [d] idx) mem)
+	// cond:
+	// result: (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto endd3063853eaa3813f3c95eedeba23e391
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVSSloadidx4)
+		v.AuxInt = c + 4*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto endd3063853eaa3813f3c95eedeba23e391
+endd3063853eaa3813f3c95eedeba23e391:
 	;
 	return false
 }
@@ -7217,25 +8061,22 @@
 func rewriteValueAMD64_OpAMD64MOVSSstoreidx4(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVSSstoreidx4 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx val mem)
+	// match: (MOVSSstoreidx4 [c] {sym} (ADDQconst [d] ptr) idx val mem)
 	// cond:
-	// result: (MOVSSstoreidx4 [addOff(off1, off2)] {sym} ptr idx val mem)
+	// result: (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto end66e4853026306cd46f414c22d281254f
+			goto end5995724dec9833993ca0b1c827919b6a
 		}
-		off2 := v.Args[0].AuxInt
-		if v.Args[0].Aux != v.Aux {
-			goto end66e4853026306cd46f414c22d281254f
-		}
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		val := v.Args[2]
 		mem := v.Args[3]
 		v.reset(OpAMD64MOVSSstoreidx4)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
@@ -7243,8 +8084,34 @@
 		v.AddArg(mem)
 		return true
 	}
-	goto end66e4853026306cd46f414c22d281254f
-end66e4853026306cd46f414c22d281254f:
+	goto end5995724dec9833993ca0b1c827919b6a
+end5995724dec9833993ca0b1c827919b6a:
+	;
+	// match: (MOVSSstoreidx4 [c] {sym} ptr (ADDQconst [d] idx) val mem)
+	// cond:
+	// result: (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto endad50732309bcc958cffc54992194cdd6
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		val := v.Args[2]
+		mem := v.Args[3]
+		v.reset(OpAMD64MOVSSstoreidx4)
+		v.AuxInt = c + 4*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(val)
+		v.AddArg(mem)
+		return true
+	}
+	goto endad50732309bcc958cffc54992194cdd6
+endad50732309bcc958cffc54992194cdd6:
 	;
 	return false
 }
@@ -7392,6 +8259,87 @@
 	goto end7a79314cb49bf53d79c38c3077d87457
 end7a79314cb49bf53d79c38c3077d87457:
 	;
+	// match: (MOVWload [off1] {sym1} (LEAQ2 [off2] {sym2} ptr idx) mem)
+	// cond: canMergeSym(sym1, sym2)
+	// result: (MOVWloadidx2 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem)
+	{
+		off1 := v.AuxInt
+		sym1 := v.Aux
+		if v.Args[0].Op != OpAMD64LEAQ2 {
+			goto end1a7be5e27e24f56f760b50d4d2f2a8da
+		}
+		off2 := v.Args[0].AuxInt
+		sym2 := v.Args[0].Aux
+		ptr := v.Args[0].Args[0]
+		idx := v.Args[0].Args[1]
+		mem := v.Args[1]
+		if !(canMergeSym(sym1, sym2)) {
+			goto end1a7be5e27e24f56f760b50d4d2f2a8da
+		}
+		v.reset(OpAMD64MOVWloadidx2)
+		v.AuxInt = addOff(off1, off2)
+		v.Aux = mergeSym(sym1, sym2)
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto end1a7be5e27e24f56f760b50d4d2f2a8da
+end1a7be5e27e24f56f760b50d4d2f2a8da:
+	;
+	return false
+}
+func rewriteValueAMD64_OpAMD64MOVWloadidx2(v *Value, config *Config) bool {
+	b := v.Block
+	_ = b
+	// match: (MOVWloadidx2 [c] {sym} (ADDQconst [d] ptr) idx mem)
+	// cond:
+	// result: (MOVWloadidx2 [c+d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		if v.Args[0].Op != OpAMD64ADDQconst {
+			goto end1a8b9db99bc480ce4f8cc0fa0e6024ea
+		}
+		d := v.Args[0].AuxInt
+		ptr := v.Args[0].Args[0]
+		idx := v.Args[1]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVWloadidx2)
+		v.AuxInt = c + d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto end1a8b9db99bc480ce4f8cc0fa0e6024ea
+end1a8b9db99bc480ce4f8cc0fa0e6024ea:
+	;
+	// match: (MOVWloadidx2 [c] {sym} ptr (ADDQconst [d] idx) mem)
+	// cond:
+	// result: (MOVWloadidx2 [c+2*d] {sym} ptr idx mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto end38e4b4448cc3c61b0691bc11c61c7098
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		mem := v.Args[2]
+		v.reset(OpAMD64MOVWloadidx2)
+		v.AuxInt = c + 2*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(mem)
+		return true
+	}
+	goto end38e4b4448cc3c61b0691bc11c61c7098
+end38e4b4448cc3c61b0691bc11c61c7098:
+	;
 	return false
 }
 func rewriteValueAMD64_OpAMD64MOVWstore(v *Value, config *Config) bool {
@@ -7611,22 +8559,22 @@
 func rewriteValueAMD64_OpAMD64MOVWstoreidx2(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
-	// match: (MOVWstoreidx2 [off1] {sym} (ADDQconst [off2] ptr) idx val mem)
+	// match: (MOVWstoreidx2 [c] {sym} (ADDQconst [d] ptr) idx val mem)
 	// cond:
-	// result: (MOVWstoreidx2 [addOff(off1, off2)] {sym} ptr idx val mem)
+	// result: (MOVWstoreidx2 [c+d] {sym} ptr idx val mem)
 	{
-		off1 := v.AuxInt
+		c := v.AuxInt
 		sym := v.Aux
 		if v.Args[0].Op != OpAMD64ADDQconst {
-			goto end7ab3a4fbfc9bac9d46ba72d40f667794
+			goto end8e684d397fadfa1c3f0783597ca01cc7
 		}
-		off2 := v.Args[0].AuxInt
+		d := v.Args[0].AuxInt
 		ptr := v.Args[0].Args[0]
 		idx := v.Args[1]
 		val := v.Args[2]
 		mem := v.Args[3]
 		v.reset(OpAMD64MOVWstoreidx2)
-		v.AuxInt = addOff(off1, off2)
+		v.AuxInt = c + d
 		v.Aux = sym
 		v.AddArg(ptr)
 		v.AddArg(idx)
@@ -7634,8 +8582,34 @@
 		v.AddArg(mem)
 		return true
 	}
-	goto end7ab3a4fbfc9bac9d46ba72d40f667794
-end7ab3a4fbfc9bac9d46ba72d40f667794:
+	goto end8e684d397fadfa1c3f0783597ca01cc7
+end8e684d397fadfa1c3f0783597ca01cc7:
+	;
+	// match: (MOVWstoreidx2 [c] {sym} ptr (ADDQconst [d] idx) val mem)
+	// cond:
+	// result: (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem)
+	{
+		c := v.AuxInt
+		sym := v.Aux
+		ptr := v.Args[0]
+		if v.Args[1].Op != OpAMD64ADDQconst {
+			goto end9701df480a14263338b1d37a15b59eb5
+		}
+		d := v.Args[1].AuxInt
+		idx := v.Args[1].Args[0]
+		val := v.Args[2]
+		mem := v.Args[3]
+		v.reset(OpAMD64MOVWstoreidx2)
+		v.AuxInt = c + 2*d
+		v.Aux = sym
+		v.AddArg(ptr)
+		v.AddArg(idx)
+		v.AddArg(val)
+		v.AddArg(mem)
+		return true
+	}
+	goto end9701df480a14263338b1d37a15b59eb5
+end9701df480a14263338b1d37a15b59eb5:
 	;
 	return false
 }
diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go
index d71fd8f..0d6c19b 100644
--- a/src/cmd/compile/internal/ssa/value.go
+++ b/src/cmd/compile/internal/ssa/value.go
@@ -117,7 +117,7 @@
 		if v.Aux != nil {
 			s += fmt.Sprintf(" {%s}", v.Aux)
 		}
-		s += fmt.Sprintf(" [%s]", v.AuxInt)
+		s += fmt.Sprintf(" [%d]", v.AuxInt)
 	case auxSymValAndOff:
 		if v.Aux != nil {
 			s += fmt.Sprintf(" {%s}", v.Aux)