diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index a324ed2a42..6d3359ad0e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -795,6 +795,15 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{ODIV, TINT64}: ssa.OpDiv64, opAndType{ODIV, TUINT64}: ssa.OpDiv64u, + opAndType{OMOD, TINT8}: ssa.OpMod8, + opAndType{OMOD, TUINT8}: ssa.OpMod8u, + opAndType{OMOD, TINT16}: ssa.OpMod16, + opAndType{OMOD, TUINT16}: ssa.OpMod16u, + opAndType{OMOD, TINT32}: ssa.OpMod32, + opAndType{OMOD, TUINT32}: ssa.OpMod32u, + opAndType{OMOD, TINT64}: ssa.OpMod64, + opAndType{OMOD, TUINT64}: ssa.OpMod64u, + opAndType{OAND, TINT8}: ssa.OpAnd8, opAndType{OAND, TUINT8}: ssa.OpAnd8, opAndType{OAND, TINT16}: ssa.OpAnd16, @@ -1216,7 +1225,7 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Left.Type), Types[TBOOL], a, b) - case OADD, OAND, OMUL, OOR, OSUB, ODIV, OXOR, OHMUL: + case OADD, OAND, OMUL, OOR, OSUB, ODIV, OMOD, OHMUL, OXOR: a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) @@ -2099,57 +2108,58 @@ func genValue(v *ssa.Value) { opregreg(v.Op.Asm(), r, y) case ssa.OpAMD64DIVQ, ssa.OpAMD64DIVL, ssa.OpAMD64DIVW, - ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU: + ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU, + ssa.OpAMD64MODQ, ssa.OpAMD64MODL, ssa.OpAMD64MODW, + ssa.OpAMD64MODQU, ssa.OpAMD64MODLU, ssa.OpAMD64MODWU: // Arg[0] is already in AX as it's the only register we allow // and AX is the only output x := regnum(v.Args[1]) // CPU faults upon signed overflow, which occurs when most - // negative int is divided by -1. So we check for division - // by -1 and negate the input. + // negative int is divided by -1. var j *obj.Prog if v.Op == ssa.OpAMD64DIVQ || v.Op == ssa.OpAMD64DIVL || - v.Op == ssa.OpAMD64DIVW { + v.Op == ssa.OpAMD64DIVW || v.Op == ssa.OpAMD64MODQ || + v.Op == ssa.OpAMD64MODL || v.Op == ssa.OpAMD64MODW { var c *obj.Prog switch v.Op { - case ssa.OpAMD64DIVQ: + case ssa.OpAMD64DIVQ, ssa.OpAMD64MODQ: c = Prog(x86.ACMPQ) - case ssa.OpAMD64DIVL: + j = Prog(x86.AJEQ) + // go ahead and sign extend to save doing it later + Prog(x86.ACQO) + + case ssa.OpAMD64DIVL, ssa.OpAMD64MODL: c = Prog(x86.ACMPL) - case ssa.OpAMD64DIVW: + j = Prog(x86.AJEQ) + Prog(x86.ACDQ) + + case ssa.OpAMD64DIVW, ssa.OpAMD64MODW: c = Prog(x86.ACMPW) + j = Prog(x86.AJEQ) + Prog(x86.ACWD) } c.From.Type = obj.TYPE_REG c.From.Reg = x c.To.Type = obj.TYPE_CONST c.To.Offset = -1 - j = Prog(x86.AJEQ) j.To.Type = obj.TYPE_BRANCH } - // dividend is ax, so we sign extend to - // dx:ax for DIV input - switch v.Op { - case ssa.OpAMD64DIVQU: - fallthrough - case ssa.OpAMD64DIVLU: - fallthrough - case ssa.OpAMD64DIVWU: + // for unsigned ints, we sign extend by setting DX = 0 + // signed ints were sign extended above + if v.Op == ssa.OpAMD64DIVQU || v.Op == ssa.OpAMD64MODQU || + v.Op == ssa.OpAMD64DIVLU || v.Op == ssa.OpAMD64MODLU || + v.Op == ssa.OpAMD64DIVWU || v.Op == ssa.OpAMD64MODWU { c := Prog(x86.AXORQ) c.From.Type = obj.TYPE_REG c.From.Reg = x86.REG_DX c.To.Type = obj.TYPE_REG c.To.Reg = x86.REG_DX - case ssa.OpAMD64DIVQ: - Prog(x86.ACQO) - case ssa.OpAMD64DIVL: - Prog(x86.ACDQ) - case ssa.OpAMD64DIVW: - Prog(x86.ACWD) } p := Prog(v.Op.Asm()) @@ -2161,9 +2171,21 @@ func genValue(v *ssa.Value) { j2 := Prog(obj.AJMP) j2.To.Type = obj.TYPE_BRANCH - n := Prog(x86.ANEGQ) - n.To.Type = obj.TYPE_REG - n.To.Reg = x86.REG_AX + var n *obj.Prog + if v.Op == ssa.OpAMD64DIVQ || v.Op == ssa.OpAMD64DIVL || + v.Op == ssa.OpAMD64DIVW { + // n * -1 = -n + n = Prog(x86.ANEGQ) + n.To.Type = obj.TYPE_REG + n.To.Reg = x86.REG_AX + } else { + // n % -1 == 0 + n = Prog(x86.AXORQ) + n.From.Type = obj.TYPE_REG + n.From.Reg = x86.REG_DX + n.To.Type = obj.TYPE_REG + n.To.Reg = x86.REG_DX + } j.To.Val = n j2.To.Val = Pc diff --git a/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go b/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go index 8f84026a5d..9f1b9a4a60 100644 --- a/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go @@ -3,464 +3,504 @@ package main import "fmt" type utd64 struct { - a, b uint64 - add, sub, mul, div uint64 + a, b uint64 + add, sub, mul, div, mod uint64 } type itd64 struct { - a, b int64 - add, sub, mul, div int64 + a, b int64 + add, sub, mul, div, mod int64 } type utd32 struct { - a, b uint32 - add, sub, mul, div uint32 + a, b uint32 + add, sub, mul, div, mod uint32 } type itd32 struct { - a, b int32 - add, sub, mul, div int32 + a, b int32 + add, sub, mul, div, mod int32 } type utd16 struct { - a, b uint16 - add, sub, mul, div uint16 + a, b uint16 + add, sub, mul, div, mod uint16 } type itd16 struct { - a, b int16 - add, sub, mul, div int16 + a, b int16 + add, sub, mul, div, mod int16 } type utd8 struct { - a, b uint8 - add, sub, mul, div uint8 + a, b uint8 + add, sub, mul, div, mod uint8 } type itd8 struct { - a, b int8 - add, sub, mul, div int8 + a, b int8 + add, sub, mul, div, mod int8 } func add_uint64_ssa(a, b uint64) uint64 { switch { - } + } // prevent inlining return a + b } func sub_uint64_ssa(a, b uint64) uint64 { switch { - } + } // prevent inlining return a - b } func div_uint64_ssa(a, b uint64) uint64 { switch { - } + } // prevent inlining return a / b } +func mod_uint64_ssa(a, b uint64) uint64 { + switch { + } // prevent inlining + return a % b +} func mul_uint64_ssa(a, b uint64) uint64 { switch { - } + } // prevent inlining return a * b } func add_int64_ssa(a, b int64) int64 { switch { - } + } // prevent inlining return a + b } func sub_int64_ssa(a, b int64) int64 { switch { - } + } // prevent inlining return a - b } func div_int64_ssa(a, b int64) int64 { switch { - } + } // prevent inlining return a / b } +func mod_int64_ssa(a, b int64) int64 { + switch { + } // prevent inlining + return a % b +} func mul_int64_ssa(a, b int64) int64 { switch { - } + } // prevent inlining return a * b } func add_uint32_ssa(a, b uint32) uint32 { switch { - } + } // prevent inlining return a + b } func sub_uint32_ssa(a, b uint32) uint32 { switch { - } + } // prevent inlining return a - b } func div_uint32_ssa(a, b uint32) uint32 { switch { - } + } // prevent inlining return a / b } +func mod_uint32_ssa(a, b uint32) uint32 { + switch { + } // prevent inlining + return a % b +} func mul_uint32_ssa(a, b uint32) uint32 { switch { - } + } // prevent inlining return a * b } func add_int32_ssa(a, b int32) int32 { switch { - } + } // prevent inlining return a + b } func sub_int32_ssa(a, b int32) int32 { switch { - } + } // prevent inlining return a - b } func div_int32_ssa(a, b int32) int32 { switch { - } + } // prevent inlining return a / b } +func mod_int32_ssa(a, b int32) int32 { + switch { + } // prevent inlining + return a % b +} func mul_int32_ssa(a, b int32) int32 { switch { - } + } // prevent inlining return a * b } func add_uint16_ssa(a, b uint16) uint16 { switch { - } + } // prevent inlining return a + b } func sub_uint16_ssa(a, b uint16) uint16 { switch { - } + } // prevent inlining return a - b } func div_uint16_ssa(a, b uint16) uint16 { switch { - } + } // prevent inlining return a / b } +func mod_uint16_ssa(a, b uint16) uint16 { + switch { + } // prevent inlining + return a % b +} func mul_uint16_ssa(a, b uint16) uint16 { switch { - } + } // prevent inlining return a * b } func add_int16_ssa(a, b int16) int16 { switch { - } + } // prevent inlining return a + b } func sub_int16_ssa(a, b int16) int16 { switch { - } + } // prevent inlining return a - b } func div_int16_ssa(a, b int16) int16 { switch { - } + } // prevent inlining return a / b } +func mod_int16_ssa(a, b int16) int16 { + switch { + } // prevent inlining + return a % b +} func mul_int16_ssa(a, b int16) int16 { switch { - } + } // prevent inlining return a * b } func add_uint8_ssa(a, b uint8) uint8 { switch { - } + } // prevent inlining return a + b } func sub_uint8_ssa(a, b uint8) uint8 { switch { - } + } // prevent inlining return a - b } func div_uint8_ssa(a, b uint8) uint8 { switch { - } + } // prevent inlining return a / b } +func mod_uint8_ssa(a, b uint8) uint8 { + switch { + } // prevent inlining + return a % b +} func mul_uint8_ssa(a, b uint8) uint8 { switch { - } + } // prevent inlining return a * b } func add_int8_ssa(a, b int8) int8 { switch { - } + } // prevent inlining return a + b } func sub_int8_ssa(a, b int8) int8 { switch { - } + } // prevent inlining return a - b } func div_int8_ssa(a, b int8) int8 { switch { - } + } // prevent inlining return a / b } +func mod_int8_ssa(a, b int8) int8 { + switch { + } // prevent inlining + return a % b +} func mul_int8_ssa(a, b int8) int8 { switch { - } + } // prevent inlining return a * b } var uint64_data []utd64 = []utd64{utd64{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - utd64{a: 0, b: 1, add: 1, sub: 18446744073709551615, mul: 0, div: 0}, - utd64{a: 0, b: 4294967296, add: 4294967296, sub: 18446744069414584320, mul: 0, div: 0}, - utd64{a: 0, b: 18446744073709551615, add: 18446744073709551615, sub: 1, mul: 0, div: 0}, + utd64{a: 0, b: 1, add: 1, sub: 18446744073709551615, mul: 0, div: 0, mod: 0}, + utd64{a: 0, b: 4294967296, add: 4294967296, sub: 18446744069414584320, mul: 0, div: 0, mod: 0}, + utd64{a: 0, b: 18446744073709551615, add: 18446744073709551615, sub: 1, mul: 0, div: 0, mod: 0}, utd64{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - utd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - utd64{a: 1, b: 4294967296, add: 4294967297, sub: 18446744069414584321, mul: 4294967296, div: 0}, - utd64{a: 1, b: 18446744073709551615, add: 0, sub: 2, mul: 18446744073709551615, div: 0}, + utd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + utd64{a: 1, b: 4294967296, add: 4294967297, sub: 18446744069414584321, mul: 4294967296, div: 0, mod: 1}, + utd64{a: 1, b: 18446744073709551615, add: 0, sub: 2, mul: 18446744073709551615, div: 0, mod: 1}, utd64{a: 4294967296, b: 0, add: 4294967296, sub: 4294967296, mul: 0}, - utd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296}, - utd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1}, - utd64{a: 4294967296, b: 18446744073709551615, add: 4294967295, sub: 4294967297, mul: 18446744069414584320, div: 0}, + utd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296, mod: 0}, + utd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1, mod: 0}, + utd64{a: 4294967296, b: 18446744073709551615, add: 4294967295, sub: 4294967297, mul: 18446744069414584320, div: 0, mod: 4294967296}, utd64{a: 18446744073709551615, b: 0, add: 18446744073709551615, sub: 18446744073709551615, mul: 0}, - utd64{a: 18446744073709551615, b: 1, add: 0, sub: 18446744073709551614, mul: 18446744073709551615, div: 18446744073709551615}, - utd64{a: 18446744073709551615, b: 4294967296, add: 4294967295, sub: 18446744069414584319, mul: 18446744069414584320, div: 4294967295}, - utd64{a: 18446744073709551615, b: 18446744073709551615, add: 18446744073709551614, sub: 0, mul: 1, div: 1}, + utd64{a: 18446744073709551615, b: 1, add: 0, sub: 18446744073709551614, mul: 18446744073709551615, div: 18446744073709551615, mod: 0}, + utd64{a: 18446744073709551615, b: 4294967296, add: 4294967295, sub: 18446744069414584319, mul: 18446744069414584320, div: 4294967295, mod: 4294967295}, + utd64{a: 18446744073709551615, b: 18446744073709551615, add: 18446744073709551614, sub: 0, mul: 1, div: 1, mod: 0}, } -var int64_data []itd64 = []itd64{itd64{a: -9223372036854775808, b: -9223372036854775808, add: 0, sub: 0, mul: 0, div: 1}, - itd64{a: -9223372036854775808, b: -9223372036854775807, add: 1, sub: -1, mul: -9223372036854775808, div: 1}, - itd64{a: -9223372036854775808, b: -4294967296, add: 9223372032559808512, sub: -9223372032559808512, mul: 0, div: 2147483648}, - itd64{a: -9223372036854775808, b: -1, add: 9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808}, +var int64_data []itd64 = []itd64{itd64{a: -9223372036854775808, b: -9223372036854775808, add: 0, sub: 0, mul: 0, div: 1, mod: 0}, + itd64{a: -9223372036854775808, b: -9223372036854775807, add: 1, sub: -1, mul: -9223372036854775808, div: 1, mod: -1}, + itd64{a: -9223372036854775808, b: -4294967296, add: 9223372032559808512, sub: -9223372032559808512, mul: 0, div: 2147483648, mod: 0}, + itd64{a: -9223372036854775808, b: -1, add: 9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808, mod: 0}, itd64{a: -9223372036854775808, b: 0, add: -9223372036854775808, sub: -9223372036854775808, mul: 0}, - itd64{a: -9223372036854775808, b: 1, add: -9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808}, - itd64{a: -9223372036854775808, b: 4294967296, add: -9223372032559808512, sub: 9223372032559808512, mul: 0, div: -2147483648}, - itd64{a: -9223372036854775808, b: 9223372036854775806, add: -2, sub: 2, mul: 0, div: -1}, - itd64{a: -9223372036854775808, b: 9223372036854775807, add: -1, sub: 1, mul: -9223372036854775808, div: -1}, - itd64{a: -9223372036854775807, b: -9223372036854775808, add: 1, sub: 1, mul: -9223372036854775808, div: 0}, - itd64{a: -9223372036854775807, b: -9223372036854775807, add: 2, sub: 0, mul: 1, div: 1}, - itd64{a: -9223372036854775807, b: -4294967296, add: 9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 2147483647}, - itd64{a: -9223372036854775807, b: -1, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807}, + itd64{a: -9223372036854775808, b: 1, add: -9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808, mod: 0}, + itd64{a: -9223372036854775808, b: 4294967296, add: -9223372032559808512, sub: 9223372032559808512, mul: 0, div: -2147483648, mod: 0}, + itd64{a: -9223372036854775808, b: 9223372036854775806, add: -2, sub: 2, mul: 0, div: -1, mod: -2}, + itd64{a: -9223372036854775808, b: 9223372036854775807, add: -1, sub: 1, mul: -9223372036854775808, div: -1, mod: -1}, + itd64{a: -9223372036854775807, b: -9223372036854775808, add: 1, sub: 1, mul: -9223372036854775808, div: 0, mod: -9223372036854775807}, + itd64{a: -9223372036854775807, b: -9223372036854775807, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd64{a: -9223372036854775807, b: -4294967296, add: 9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 2147483647, mod: -4294967295}, + itd64{a: -9223372036854775807, b: -1, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807, mod: 0}, itd64{a: -9223372036854775807, b: 0, add: -9223372036854775807, sub: -9223372036854775807, mul: 0}, - itd64{a: -9223372036854775807, b: 1, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807}, - itd64{a: -9223372036854775807, b: 4294967296, add: -9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: -2147483647}, - itd64{a: -9223372036854775807, b: 9223372036854775806, add: -1, sub: 3, mul: 9223372036854775806, div: -1}, - itd64{a: -9223372036854775807, b: 9223372036854775807, add: 0, sub: 2, mul: -1, div: -1}, - itd64{a: -4294967296, b: -9223372036854775808, add: 9223372032559808512, sub: 9223372032559808512, mul: 0, div: 0}, - itd64{a: -4294967296, b: -9223372036854775807, add: 9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 0}, - itd64{a: -4294967296, b: -4294967296, add: -8589934592, sub: 0, mul: 0, div: 1}, - itd64{a: -4294967296, b: -1, add: -4294967297, sub: -4294967295, mul: 4294967296, div: 4294967296}, + itd64{a: -9223372036854775807, b: 1, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807, mod: 0}, + itd64{a: -9223372036854775807, b: 4294967296, add: -9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: -2147483647, mod: -4294967295}, + itd64{a: -9223372036854775807, b: 9223372036854775806, add: -1, sub: 3, mul: 9223372036854775806, div: -1, mod: -1}, + itd64{a: -9223372036854775807, b: 9223372036854775807, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, + itd64{a: -4294967296, b: -9223372036854775808, add: 9223372032559808512, sub: 9223372032559808512, mul: 0, div: 0, mod: -4294967296}, + itd64{a: -4294967296, b: -9223372036854775807, add: 9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 0, mod: -4294967296}, + itd64{a: -4294967296, b: -4294967296, add: -8589934592, sub: 0, mul: 0, div: 1, mod: 0}, + itd64{a: -4294967296, b: -1, add: -4294967297, sub: -4294967295, mul: 4294967296, div: 4294967296, mod: 0}, itd64{a: -4294967296, b: 0, add: -4294967296, sub: -4294967296, mul: 0}, - itd64{a: -4294967296, b: 1, add: -4294967295, sub: -4294967297, mul: -4294967296, div: -4294967296}, - itd64{a: -4294967296, b: 4294967296, add: 0, sub: -8589934592, mul: 0, div: -1}, - itd64{a: -4294967296, b: 9223372036854775806, add: 9223372032559808510, sub: 9223372032559808514, mul: 8589934592, div: 0}, - itd64{a: -4294967296, b: 9223372036854775807, add: 9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: 0}, - itd64{a: -1, b: -9223372036854775808, add: 9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: 0}, - itd64{a: -1, b: -9223372036854775807, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 0}, - itd64{a: -1, b: -4294967296, add: -4294967297, sub: 4294967295, mul: 4294967296, div: 0}, - itd64{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd64{a: -4294967296, b: 1, add: -4294967295, sub: -4294967297, mul: -4294967296, div: -4294967296, mod: 0}, + itd64{a: -4294967296, b: 4294967296, add: 0, sub: -8589934592, mul: 0, div: -1, mod: 0}, + itd64{a: -4294967296, b: 9223372036854775806, add: 9223372032559808510, sub: 9223372032559808514, mul: 8589934592, div: 0, mod: -4294967296}, + itd64{a: -4294967296, b: 9223372036854775807, add: 9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: 0, mod: -4294967296}, + itd64{a: -1, b: -9223372036854775808, add: 9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: 0, mod: -1}, + itd64{a: -1, b: -9223372036854775807, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 0, mod: -1}, + itd64{a: -1, b: -4294967296, add: -4294967297, sub: 4294967295, mul: 4294967296, div: 0, mod: -1}, + itd64{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, itd64{a: -1, b: 0, add: -1, sub: -1, mul: 0}, - itd64{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, - itd64{a: -1, b: 4294967296, add: 4294967295, sub: -4294967297, mul: -4294967296, div: 0}, - itd64{a: -1, b: 9223372036854775806, add: 9223372036854775805, sub: -9223372036854775807, mul: -9223372036854775806, div: 0}, - itd64{a: -1, b: 9223372036854775807, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0}, - itd64{a: 0, b: -9223372036854775808, add: -9223372036854775808, sub: -9223372036854775808, mul: 0, div: 0}, - itd64{a: 0, b: -9223372036854775807, add: -9223372036854775807, sub: 9223372036854775807, mul: 0, div: 0}, - itd64{a: 0, b: -4294967296, add: -4294967296, sub: 4294967296, mul: 0, div: 0}, - itd64{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd64{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd64{a: -1, b: 4294967296, add: 4294967295, sub: -4294967297, mul: -4294967296, div: 0, mod: -1}, + itd64{a: -1, b: 9223372036854775806, add: 9223372036854775805, sub: -9223372036854775807, mul: -9223372036854775806, div: 0, mod: -1}, + itd64{a: -1, b: 9223372036854775807, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0, mod: -1}, + itd64{a: 0, b: -9223372036854775808, add: -9223372036854775808, sub: -9223372036854775808, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: -9223372036854775807, add: -9223372036854775807, sub: 9223372036854775807, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: -4294967296, add: -4294967296, sub: 4294967296, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0, mod: 0}, itd64{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - itd64{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, - itd64{a: 0, b: 4294967296, add: 4294967296, sub: -4294967296, mul: 0, div: 0}, - itd64{a: 0, b: 9223372036854775806, add: 9223372036854775806, sub: -9223372036854775806, mul: 0, div: 0}, - itd64{a: 0, b: 9223372036854775807, add: 9223372036854775807, sub: -9223372036854775807, mul: 0, div: 0}, - itd64{a: 1, b: -9223372036854775808, add: -9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: 0}, - itd64{a: 1, b: -9223372036854775807, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0}, - itd64{a: 1, b: -4294967296, add: -4294967295, sub: 4294967297, mul: -4294967296, div: 0}, - itd64{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd64{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: 4294967296, add: 4294967296, sub: -4294967296, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: 9223372036854775806, add: 9223372036854775806, sub: -9223372036854775806, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: 9223372036854775807, add: 9223372036854775807, sub: -9223372036854775807, mul: 0, div: 0, mod: 0}, + itd64{a: 1, b: -9223372036854775808, add: -9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: 0, mod: 1}, + itd64{a: 1, b: -9223372036854775807, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0, mod: 1}, + itd64{a: 1, b: -4294967296, add: -4294967295, sub: 4294967297, mul: -4294967296, div: 0, mod: 1}, + itd64{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, itd64{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - itd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - itd64{a: 1, b: 4294967296, add: 4294967297, sub: -4294967295, mul: 4294967296, div: 0}, - itd64{a: 1, b: 9223372036854775806, add: 9223372036854775807, sub: -9223372036854775805, mul: 9223372036854775806, div: 0}, - itd64{a: 1, b: 9223372036854775807, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 0}, - itd64{a: 4294967296, b: -9223372036854775808, add: -9223372032559808512, sub: -9223372032559808512, mul: 0, div: 0}, - itd64{a: 4294967296, b: -9223372036854775807, add: -9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: 0}, - itd64{a: 4294967296, b: -4294967296, add: 0, sub: 8589934592, mul: 0, div: -1}, - itd64{a: 4294967296, b: -1, add: 4294967295, sub: 4294967297, mul: -4294967296, div: -4294967296}, + itd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd64{a: 1, b: 4294967296, add: 4294967297, sub: -4294967295, mul: 4294967296, div: 0, mod: 1}, + itd64{a: 1, b: 9223372036854775806, add: 9223372036854775807, sub: -9223372036854775805, mul: 9223372036854775806, div: 0, mod: 1}, + itd64{a: 1, b: 9223372036854775807, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 0, mod: 1}, + itd64{a: 4294967296, b: -9223372036854775808, add: -9223372032559808512, sub: -9223372032559808512, mul: 0, div: 0, mod: 4294967296}, + itd64{a: 4294967296, b: -9223372036854775807, add: -9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: 0, mod: 4294967296}, + itd64{a: 4294967296, b: -4294967296, add: 0, sub: 8589934592, mul: 0, div: -1, mod: 0}, + itd64{a: 4294967296, b: -1, add: 4294967295, sub: 4294967297, mul: -4294967296, div: -4294967296, mod: 0}, itd64{a: 4294967296, b: 0, add: 4294967296, sub: 4294967296, mul: 0}, - itd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296}, - itd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1}, - itd64{a: 4294967296, b: 9223372036854775806, add: -9223372032559808514, sub: -9223372032559808510, mul: -8589934592, div: 0}, - itd64{a: 4294967296, b: 9223372036854775807, add: -9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 0}, - itd64{a: 9223372036854775806, b: -9223372036854775808, add: -2, sub: -2, mul: 0, div: 0}, - itd64{a: 9223372036854775806, b: -9223372036854775807, add: -1, sub: -3, mul: 9223372036854775806, div: 0}, - itd64{a: 9223372036854775806, b: -4294967296, add: 9223372032559808510, sub: -9223372032559808514, mul: 8589934592, div: -2147483647}, - itd64{a: 9223372036854775806, b: -1, add: 9223372036854775805, sub: 9223372036854775807, mul: -9223372036854775806, div: -9223372036854775806}, + itd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296, mod: 0}, + itd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1, mod: 0}, + itd64{a: 4294967296, b: 9223372036854775806, add: -9223372032559808514, sub: -9223372032559808510, mul: -8589934592, div: 0, mod: 4294967296}, + itd64{a: 4294967296, b: 9223372036854775807, add: -9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 0, mod: 4294967296}, + itd64{a: 9223372036854775806, b: -9223372036854775808, add: -2, sub: -2, mul: 0, div: 0, mod: 9223372036854775806}, + itd64{a: 9223372036854775806, b: -9223372036854775807, add: -1, sub: -3, mul: 9223372036854775806, div: 0, mod: 9223372036854775806}, + itd64{a: 9223372036854775806, b: -4294967296, add: 9223372032559808510, sub: -9223372032559808514, mul: 8589934592, div: -2147483647, mod: 4294967294}, + itd64{a: 9223372036854775806, b: -1, add: 9223372036854775805, sub: 9223372036854775807, mul: -9223372036854775806, div: -9223372036854775806, mod: 0}, itd64{a: 9223372036854775806, b: 0, add: 9223372036854775806, sub: 9223372036854775806, mul: 0}, - itd64{a: 9223372036854775806, b: 1, add: 9223372036854775807, sub: 9223372036854775805, mul: 9223372036854775806, div: 9223372036854775806}, - itd64{a: 9223372036854775806, b: 4294967296, add: -9223372032559808514, sub: 9223372032559808510, mul: -8589934592, div: 2147483647}, - itd64{a: 9223372036854775806, b: 9223372036854775806, add: -4, sub: 0, mul: 4, div: 1}, - itd64{a: 9223372036854775806, b: 9223372036854775807, add: -3, sub: -1, mul: -9223372036854775806, div: 0}, - itd64{a: 9223372036854775807, b: -9223372036854775808, add: -1, sub: -1, mul: -9223372036854775808, div: 0}, - itd64{a: 9223372036854775807, b: -9223372036854775807, add: 0, sub: -2, mul: -1, div: -1}, - itd64{a: 9223372036854775807, b: -4294967296, add: 9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: -2147483647}, - itd64{a: 9223372036854775807, b: -1, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807}, + itd64{a: 9223372036854775806, b: 1, add: 9223372036854775807, sub: 9223372036854775805, mul: 9223372036854775806, div: 9223372036854775806, mod: 0}, + itd64{a: 9223372036854775806, b: 4294967296, add: -9223372032559808514, sub: 9223372032559808510, mul: -8589934592, div: 2147483647, mod: 4294967294}, + itd64{a: 9223372036854775806, b: 9223372036854775806, add: -4, sub: 0, mul: 4, div: 1, mod: 0}, + itd64{a: 9223372036854775806, b: 9223372036854775807, add: -3, sub: -1, mul: -9223372036854775806, div: 0, mod: 9223372036854775806}, + itd64{a: 9223372036854775807, b: -9223372036854775808, add: -1, sub: -1, mul: -9223372036854775808, div: 0, mod: 9223372036854775807}, + itd64{a: 9223372036854775807, b: -9223372036854775807, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd64{a: 9223372036854775807, b: -4294967296, add: 9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: -2147483647, mod: 4294967295}, + itd64{a: 9223372036854775807, b: -1, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807, mod: 0}, itd64{a: 9223372036854775807, b: 0, add: 9223372036854775807, sub: 9223372036854775807, mul: 0}, - itd64{a: 9223372036854775807, b: 1, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807}, - itd64{a: 9223372036854775807, b: 4294967296, add: -9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 2147483647}, - itd64{a: 9223372036854775807, b: 9223372036854775806, add: -3, sub: 1, mul: -9223372036854775806, div: 1}, - itd64{a: 9223372036854775807, b: 9223372036854775807, add: -2, sub: 0, mul: 1, div: 1}, + itd64{a: 9223372036854775807, b: 1, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807, mod: 0}, + itd64{a: 9223372036854775807, b: 4294967296, add: -9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 2147483647, mod: 4294967295}, + itd64{a: 9223372036854775807, b: 9223372036854775806, add: -3, sub: 1, mul: -9223372036854775806, div: 1, mod: 1}, + itd64{a: 9223372036854775807, b: 9223372036854775807, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, } var uint32_data []utd32 = []utd32{utd32{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - utd32{a: 0, b: 1, add: 1, sub: 4294967295, mul: 0, div: 0}, - utd32{a: 0, b: 4294967295, add: 4294967295, sub: 1, mul: 0, div: 0}, + utd32{a: 0, b: 1, add: 1, sub: 4294967295, mul: 0, div: 0, mod: 0}, + utd32{a: 0, b: 4294967295, add: 4294967295, sub: 1, mul: 0, div: 0, mod: 0}, utd32{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - utd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - utd32{a: 1, b: 4294967295, add: 0, sub: 2, mul: 4294967295, div: 0}, + utd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + utd32{a: 1, b: 4294967295, add: 0, sub: 2, mul: 4294967295, div: 0, mod: 1}, utd32{a: 4294967295, b: 0, add: 4294967295, sub: 4294967295, mul: 0}, - utd32{a: 4294967295, b: 1, add: 0, sub: 4294967294, mul: 4294967295, div: 4294967295}, - utd32{a: 4294967295, b: 4294967295, add: 4294967294, sub: 0, mul: 1, div: 1}, + utd32{a: 4294967295, b: 1, add: 0, sub: 4294967294, mul: 4294967295, div: 4294967295, mod: 0}, + utd32{a: 4294967295, b: 4294967295, add: 4294967294, sub: 0, mul: 1, div: 1, mod: 0}, } -var int32_data []itd32 = []itd32{itd32{a: -2147483648, b: -2147483648, add: 0, sub: 0, mul: 0, div: 1}, - itd32{a: -2147483648, b: -2147483647, add: 1, sub: -1, mul: -2147483648, div: 1}, - itd32{a: -2147483648, b: -1, add: 2147483647, sub: -2147483647, mul: -2147483648, div: -2147483648}, +var int32_data []itd32 = []itd32{itd32{a: -2147483648, b: -2147483648, add: 0, sub: 0, mul: 0, div: 1, mod: 0}, + itd32{a: -2147483648, b: -2147483647, add: 1, sub: -1, mul: -2147483648, div: 1, mod: -1}, + itd32{a: -2147483648, b: -1, add: 2147483647, sub: -2147483647, mul: -2147483648, div: -2147483648, mod: 0}, itd32{a: -2147483648, b: 0, add: -2147483648, sub: -2147483648, mul: 0}, - itd32{a: -2147483648, b: 1, add: -2147483647, sub: 2147483647, mul: -2147483648, div: -2147483648}, - itd32{a: -2147483648, b: 2147483647, add: -1, sub: 1, mul: -2147483648, div: -1}, - itd32{a: -2147483647, b: -2147483648, add: 1, sub: 1, mul: -2147483648, div: 0}, - itd32{a: -2147483647, b: -2147483647, add: 2, sub: 0, mul: 1, div: 1}, - itd32{a: -2147483647, b: -1, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 2147483647}, + itd32{a: -2147483648, b: 1, add: -2147483647, sub: 2147483647, mul: -2147483648, div: -2147483648, mod: 0}, + itd32{a: -2147483648, b: 2147483647, add: -1, sub: 1, mul: -2147483648, div: -1, mod: -1}, + itd32{a: -2147483647, b: -2147483648, add: 1, sub: 1, mul: -2147483648, div: 0, mod: -2147483647}, + itd32{a: -2147483647, b: -2147483647, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd32{a: -2147483647, b: -1, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 2147483647, mod: 0}, itd32{a: -2147483647, b: 0, add: -2147483647, sub: -2147483647, mul: 0}, - itd32{a: -2147483647, b: 1, add: -2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647}, - itd32{a: -2147483647, b: 2147483647, add: 0, sub: 2, mul: -1, div: -1}, - itd32{a: -1, b: -2147483648, add: 2147483647, sub: 2147483647, mul: -2147483648, div: 0}, - itd32{a: -1, b: -2147483647, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 0}, - itd32{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd32{a: -2147483647, b: 1, add: -2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647, mod: 0}, + itd32{a: -2147483647, b: 2147483647, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, + itd32{a: -1, b: -2147483648, add: 2147483647, sub: 2147483647, mul: -2147483648, div: 0, mod: -1}, + itd32{a: -1, b: -2147483647, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 0, mod: -1}, + itd32{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, itd32{a: -1, b: 0, add: -1, sub: -1, mul: 0}, - itd32{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, - itd32{a: -1, b: 2147483647, add: 2147483646, sub: -2147483648, mul: -2147483647, div: 0}, - itd32{a: 0, b: -2147483648, add: -2147483648, sub: -2147483648, mul: 0, div: 0}, - itd32{a: 0, b: -2147483647, add: -2147483647, sub: 2147483647, mul: 0, div: 0}, - itd32{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd32{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd32{a: -1, b: 2147483647, add: 2147483646, sub: -2147483648, mul: -2147483647, div: 0, mod: -1}, + itd32{a: 0, b: -2147483648, add: -2147483648, sub: -2147483648, mul: 0, div: 0, mod: 0}, + itd32{a: 0, b: -2147483647, add: -2147483647, sub: 2147483647, mul: 0, div: 0, mod: 0}, + itd32{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0, mod: 0}, itd32{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - itd32{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, - itd32{a: 0, b: 2147483647, add: 2147483647, sub: -2147483647, mul: 0, div: 0}, - itd32{a: 1, b: -2147483648, add: -2147483647, sub: -2147483647, mul: -2147483648, div: 0}, - itd32{a: 1, b: -2147483647, add: -2147483646, sub: -2147483648, mul: -2147483647, div: 0}, - itd32{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd32{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0, mod: 0}, + itd32{a: 0, b: 2147483647, add: 2147483647, sub: -2147483647, mul: 0, div: 0, mod: 0}, + itd32{a: 1, b: -2147483648, add: -2147483647, sub: -2147483647, mul: -2147483648, div: 0, mod: 1}, + itd32{a: 1, b: -2147483647, add: -2147483646, sub: -2147483648, mul: -2147483647, div: 0, mod: 1}, + itd32{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, itd32{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - itd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - itd32{a: 1, b: 2147483647, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 0}, - itd32{a: 2147483647, b: -2147483648, add: -1, sub: -1, mul: -2147483648, div: 0}, - itd32{a: 2147483647, b: -2147483647, add: 0, sub: -2, mul: -1, div: -1}, - itd32{a: 2147483647, b: -1, add: 2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647}, + itd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd32{a: 1, b: 2147483647, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 0, mod: 1}, + itd32{a: 2147483647, b: -2147483648, add: -1, sub: -1, mul: -2147483648, div: 0, mod: 2147483647}, + itd32{a: 2147483647, b: -2147483647, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd32{a: 2147483647, b: -1, add: 2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647, mod: 0}, itd32{a: 2147483647, b: 0, add: 2147483647, sub: 2147483647, mul: 0}, - itd32{a: 2147483647, b: 1, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 2147483647}, - itd32{a: 2147483647, b: 2147483647, add: -2, sub: 0, mul: 1, div: 1}, + itd32{a: 2147483647, b: 1, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 2147483647, mod: 0}, + itd32{a: 2147483647, b: 2147483647, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, } var uint16_data []utd16 = []utd16{utd16{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - utd16{a: 0, b: 1, add: 1, sub: 65535, mul: 0, div: 0}, - utd16{a: 0, b: 65535, add: 65535, sub: 1, mul: 0, div: 0}, + utd16{a: 0, b: 1, add: 1, sub: 65535, mul: 0, div: 0, mod: 0}, + utd16{a: 0, b: 65535, add: 65535, sub: 1, mul: 0, div: 0, mod: 0}, utd16{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - utd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - utd16{a: 1, b: 65535, add: 0, sub: 2, mul: 65535, div: 0}, + utd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + utd16{a: 1, b: 65535, add: 0, sub: 2, mul: 65535, div: 0, mod: 1}, utd16{a: 65535, b: 0, add: 65535, sub: 65535, mul: 0}, - utd16{a: 65535, b: 1, add: 0, sub: 65534, mul: 65535, div: 65535}, - utd16{a: 65535, b: 65535, add: 65534, sub: 0, mul: 1, div: 1}, + utd16{a: 65535, b: 1, add: 0, sub: 65534, mul: 65535, div: 65535, mod: 0}, + utd16{a: 65535, b: 65535, add: 65534, sub: 0, mul: 1, div: 1, mod: 0}, } -var int16_data []itd16 = []itd16{itd16{a: -32768, b: -32768, add: 0, sub: 0, mul: 0, div: 1}, - itd16{a: -32768, b: -32767, add: 1, sub: -1, mul: -32768, div: 1}, - itd16{a: -32768, b: -1, add: 32767, sub: -32767, mul: -32768, div: -32768}, +var int16_data []itd16 = []itd16{itd16{a: -32768, b: -32768, add: 0, sub: 0, mul: 0, div: 1, mod: 0}, + itd16{a: -32768, b: -32767, add: 1, sub: -1, mul: -32768, div: 1, mod: -1}, + itd16{a: -32768, b: -1, add: 32767, sub: -32767, mul: -32768, div: -32768, mod: 0}, itd16{a: -32768, b: 0, add: -32768, sub: -32768, mul: 0}, - itd16{a: -32768, b: 1, add: -32767, sub: 32767, mul: -32768, div: -32768}, - itd16{a: -32768, b: 32766, add: -2, sub: 2, mul: 0, div: -1}, - itd16{a: -32768, b: 32767, add: -1, sub: 1, mul: -32768, div: -1}, - itd16{a: -32767, b: -32768, add: 1, sub: 1, mul: -32768, div: 0}, - itd16{a: -32767, b: -32767, add: 2, sub: 0, mul: 1, div: 1}, - itd16{a: -32767, b: -1, add: -32768, sub: -32766, mul: 32767, div: 32767}, + itd16{a: -32768, b: 1, add: -32767, sub: 32767, mul: -32768, div: -32768, mod: 0}, + itd16{a: -32768, b: 32766, add: -2, sub: 2, mul: 0, div: -1, mod: -2}, + itd16{a: -32768, b: 32767, add: -1, sub: 1, mul: -32768, div: -1, mod: -1}, + itd16{a: -32767, b: -32768, add: 1, sub: 1, mul: -32768, div: 0, mod: -32767}, + itd16{a: -32767, b: -32767, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd16{a: -32767, b: -1, add: -32768, sub: -32766, mul: 32767, div: 32767, mod: 0}, itd16{a: -32767, b: 0, add: -32767, sub: -32767, mul: 0}, - itd16{a: -32767, b: 1, add: -32766, sub: -32768, mul: -32767, div: -32767}, - itd16{a: -32767, b: 32766, add: -1, sub: 3, mul: 32766, div: -1}, - itd16{a: -32767, b: 32767, add: 0, sub: 2, mul: -1, div: -1}, - itd16{a: -1, b: -32768, add: 32767, sub: 32767, mul: -32768, div: 0}, - itd16{a: -1, b: -32767, add: -32768, sub: 32766, mul: 32767, div: 0}, - itd16{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd16{a: -32767, b: 1, add: -32766, sub: -32768, mul: -32767, div: -32767, mod: 0}, + itd16{a: -32767, b: 32766, add: -1, sub: 3, mul: 32766, div: -1, mod: -1}, + itd16{a: -32767, b: 32767, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, + itd16{a: -1, b: -32768, add: 32767, sub: 32767, mul: -32768, div: 0, mod: -1}, + itd16{a: -1, b: -32767, add: -32768, sub: 32766, mul: 32767, div: 0, mod: -1}, + itd16{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, itd16{a: -1, b: 0, add: -1, sub: -1, mul: 0}, - itd16{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, - itd16{a: -1, b: 32766, add: 32765, sub: -32767, mul: -32766, div: 0}, - itd16{a: -1, b: 32767, add: 32766, sub: -32768, mul: -32767, div: 0}, - itd16{a: 0, b: -32768, add: -32768, sub: -32768, mul: 0, div: 0}, - itd16{a: 0, b: -32767, add: -32767, sub: 32767, mul: 0, div: 0}, - itd16{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd16{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd16{a: -1, b: 32766, add: 32765, sub: -32767, mul: -32766, div: 0, mod: -1}, + itd16{a: -1, b: 32767, add: 32766, sub: -32768, mul: -32767, div: 0, mod: -1}, + itd16{a: 0, b: -32768, add: -32768, sub: -32768, mul: 0, div: 0, mod: 0}, + itd16{a: 0, b: -32767, add: -32767, sub: 32767, mul: 0, div: 0, mod: 0}, + itd16{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0, mod: 0}, itd16{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - itd16{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, - itd16{a: 0, b: 32766, add: 32766, sub: -32766, mul: 0, div: 0}, - itd16{a: 0, b: 32767, add: 32767, sub: -32767, mul: 0, div: 0}, - itd16{a: 1, b: -32768, add: -32767, sub: -32767, mul: -32768, div: 0}, - itd16{a: 1, b: -32767, add: -32766, sub: -32768, mul: -32767, div: 0}, - itd16{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd16{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0, mod: 0}, + itd16{a: 0, b: 32766, add: 32766, sub: -32766, mul: 0, div: 0, mod: 0}, + itd16{a: 0, b: 32767, add: 32767, sub: -32767, mul: 0, div: 0, mod: 0}, + itd16{a: 1, b: -32768, add: -32767, sub: -32767, mul: -32768, div: 0, mod: 1}, + itd16{a: 1, b: -32767, add: -32766, sub: -32768, mul: -32767, div: 0, mod: 1}, + itd16{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, itd16{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - itd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - itd16{a: 1, b: 32766, add: 32767, sub: -32765, mul: 32766, div: 0}, - itd16{a: 1, b: 32767, add: -32768, sub: -32766, mul: 32767, div: 0}, - itd16{a: 32766, b: -32768, add: -2, sub: -2, mul: 0, div: 0}, - itd16{a: 32766, b: -32767, add: -1, sub: -3, mul: 32766, div: 0}, - itd16{a: 32766, b: -1, add: 32765, sub: 32767, mul: -32766, div: -32766}, + itd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd16{a: 1, b: 32766, add: 32767, sub: -32765, mul: 32766, div: 0, mod: 1}, + itd16{a: 1, b: 32767, add: -32768, sub: -32766, mul: 32767, div: 0, mod: 1}, + itd16{a: 32766, b: -32768, add: -2, sub: -2, mul: 0, div: 0, mod: 32766}, + itd16{a: 32766, b: -32767, add: -1, sub: -3, mul: 32766, div: 0, mod: 32766}, + itd16{a: 32766, b: -1, add: 32765, sub: 32767, mul: -32766, div: -32766, mod: 0}, itd16{a: 32766, b: 0, add: 32766, sub: 32766, mul: 0}, - itd16{a: 32766, b: 1, add: 32767, sub: 32765, mul: 32766, div: 32766}, - itd16{a: 32766, b: 32766, add: -4, sub: 0, mul: 4, div: 1}, - itd16{a: 32766, b: 32767, add: -3, sub: -1, mul: -32766, div: 0}, - itd16{a: 32767, b: -32768, add: -1, sub: -1, mul: -32768, div: 0}, - itd16{a: 32767, b: -32767, add: 0, sub: -2, mul: -1, div: -1}, - itd16{a: 32767, b: -1, add: 32766, sub: -32768, mul: -32767, div: -32767}, + itd16{a: 32766, b: 1, add: 32767, sub: 32765, mul: 32766, div: 32766, mod: 0}, + itd16{a: 32766, b: 32766, add: -4, sub: 0, mul: 4, div: 1, mod: 0}, + itd16{a: 32766, b: 32767, add: -3, sub: -1, mul: -32766, div: 0, mod: 32766}, + itd16{a: 32767, b: -32768, add: -1, sub: -1, mul: -32768, div: 0, mod: 32767}, + itd16{a: 32767, b: -32767, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd16{a: 32767, b: -1, add: 32766, sub: -32768, mul: -32767, div: -32767, mod: 0}, itd16{a: 32767, b: 0, add: 32767, sub: 32767, mul: 0}, - itd16{a: 32767, b: 1, add: -32768, sub: 32766, mul: 32767, div: 32767}, - itd16{a: 32767, b: 32766, add: -3, sub: 1, mul: -32766, div: 1}, - itd16{a: 32767, b: 32767, add: -2, sub: 0, mul: 1, div: 1}, + itd16{a: 32767, b: 1, add: -32768, sub: 32766, mul: 32767, div: 32767, mod: 0}, + itd16{a: 32767, b: 32766, add: -3, sub: 1, mul: -32766, div: 1, mod: 1}, + itd16{a: 32767, b: 32767, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, } var uint8_data []utd8 = []utd8{utd8{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - utd8{a: 0, b: 1, add: 1, sub: 255, mul: 0, div: 0}, - utd8{a: 0, b: 255, add: 255, sub: 1, mul: 0, div: 0}, + utd8{a: 0, b: 1, add: 1, sub: 255, mul: 0, div: 0, mod: 0}, + utd8{a: 0, b: 255, add: 255, sub: 1, mul: 0, div: 0, mod: 0}, utd8{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - utd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - utd8{a: 1, b: 255, add: 0, sub: 2, mul: 255, div: 0}, + utd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + utd8{a: 1, b: 255, add: 0, sub: 2, mul: 255, div: 0, mod: 1}, utd8{a: 255, b: 0, add: 255, sub: 255, mul: 0}, - utd8{a: 255, b: 1, add: 0, sub: 254, mul: 255, div: 255}, - utd8{a: 255, b: 255, add: 254, sub: 0, mul: 1, div: 1}, + utd8{a: 255, b: 1, add: 0, sub: 254, mul: 255, div: 255, mod: 0}, + utd8{a: 255, b: 255, add: 254, sub: 0, mul: 1, div: 1, mod: 0}, } -var int8_data []itd8 = []itd8{itd8{a: -128, b: -128, add: 0, sub: 0, mul: 0, div: 1}, - itd8{a: -128, b: -127, add: 1, sub: -1, mul: -128, div: 1}, - itd8{a: -128, b: -1, add: 127, sub: -127, mul: -128, div: -128}, +var int8_data []itd8 = []itd8{itd8{a: -128, b: -128, add: 0, sub: 0, mul: 0, div: 1, mod: 0}, + itd8{a: -128, b: -127, add: 1, sub: -1, mul: -128, div: 1, mod: -1}, + itd8{a: -128, b: -1, add: 127, sub: -127, mul: -128, div: -128, mod: 0}, itd8{a: -128, b: 0, add: -128, sub: -128, mul: 0}, - itd8{a: -128, b: 1, add: -127, sub: 127, mul: -128, div: -128}, - itd8{a: -128, b: 126, add: -2, sub: 2, mul: 0, div: -1}, - itd8{a: -128, b: 127, add: -1, sub: 1, mul: -128, div: -1}, - itd8{a: -127, b: -128, add: 1, sub: 1, mul: -128, div: 0}, - itd8{a: -127, b: -127, add: 2, sub: 0, mul: 1, div: 1}, - itd8{a: -127, b: -1, add: -128, sub: -126, mul: 127, div: 127}, + itd8{a: -128, b: 1, add: -127, sub: 127, mul: -128, div: -128, mod: 0}, + itd8{a: -128, b: 126, add: -2, sub: 2, mul: 0, div: -1, mod: -2}, + itd8{a: -128, b: 127, add: -1, sub: 1, mul: -128, div: -1, mod: -1}, + itd8{a: -127, b: -128, add: 1, sub: 1, mul: -128, div: 0, mod: -127}, + itd8{a: -127, b: -127, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd8{a: -127, b: -1, add: -128, sub: -126, mul: 127, div: 127, mod: 0}, itd8{a: -127, b: 0, add: -127, sub: -127, mul: 0}, - itd8{a: -127, b: 1, add: -126, sub: -128, mul: -127, div: -127}, - itd8{a: -127, b: 126, add: -1, sub: 3, mul: 126, div: -1}, - itd8{a: -127, b: 127, add: 0, sub: 2, mul: -1, div: -1}, - itd8{a: -1, b: -128, add: 127, sub: 127, mul: -128, div: 0}, - itd8{a: -1, b: -127, add: -128, sub: 126, mul: 127, div: 0}, - itd8{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd8{a: -127, b: 1, add: -126, sub: -128, mul: -127, div: -127, mod: 0}, + itd8{a: -127, b: 126, add: -1, sub: 3, mul: 126, div: -1, mod: -1}, + itd8{a: -127, b: 127, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, + itd8{a: -1, b: -128, add: 127, sub: 127, mul: -128, div: 0, mod: -1}, + itd8{a: -1, b: -127, add: -128, sub: 126, mul: 127, div: 0, mod: -1}, + itd8{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, itd8{a: -1, b: 0, add: -1, sub: -1, mul: 0}, - itd8{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, - itd8{a: -1, b: 126, add: 125, sub: -127, mul: -126, div: 0}, - itd8{a: -1, b: 127, add: 126, sub: -128, mul: -127, div: 0}, - itd8{a: 0, b: -128, add: -128, sub: -128, mul: 0, div: 0}, - itd8{a: 0, b: -127, add: -127, sub: 127, mul: 0, div: 0}, - itd8{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd8{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd8{a: -1, b: 126, add: 125, sub: -127, mul: -126, div: 0, mod: -1}, + itd8{a: -1, b: 127, add: 126, sub: -128, mul: -127, div: 0, mod: -1}, + itd8{a: 0, b: -128, add: -128, sub: -128, mul: 0, div: 0, mod: 0}, + itd8{a: 0, b: -127, add: -127, sub: 127, mul: 0, div: 0, mod: 0}, + itd8{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0, mod: 0}, itd8{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - itd8{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, - itd8{a: 0, b: 126, add: 126, sub: -126, mul: 0, div: 0}, - itd8{a: 0, b: 127, add: 127, sub: -127, mul: 0, div: 0}, - itd8{a: 1, b: -128, add: -127, sub: -127, mul: -128, div: 0}, - itd8{a: 1, b: -127, add: -126, sub: -128, mul: -127, div: 0}, - itd8{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd8{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0, mod: 0}, + itd8{a: 0, b: 126, add: 126, sub: -126, mul: 0, div: 0, mod: 0}, + itd8{a: 0, b: 127, add: 127, sub: -127, mul: 0, div: 0, mod: 0}, + itd8{a: 1, b: -128, add: -127, sub: -127, mul: -128, div: 0, mod: 1}, + itd8{a: 1, b: -127, add: -126, sub: -128, mul: -127, div: 0, mod: 1}, + itd8{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, itd8{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - itd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - itd8{a: 1, b: 126, add: 127, sub: -125, mul: 126, div: 0}, - itd8{a: 1, b: 127, add: -128, sub: -126, mul: 127, div: 0}, - itd8{a: 126, b: -128, add: -2, sub: -2, mul: 0, div: 0}, - itd8{a: 126, b: -127, add: -1, sub: -3, mul: 126, div: 0}, - itd8{a: 126, b: -1, add: 125, sub: 127, mul: -126, div: -126}, + itd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd8{a: 1, b: 126, add: 127, sub: -125, mul: 126, div: 0, mod: 1}, + itd8{a: 1, b: 127, add: -128, sub: -126, mul: 127, div: 0, mod: 1}, + itd8{a: 126, b: -128, add: -2, sub: -2, mul: 0, div: 0, mod: 126}, + itd8{a: 126, b: -127, add: -1, sub: -3, mul: 126, div: 0, mod: 126}, + itd8{a: 126, b: -1, add: 125, sub: 127, mul: -126, div: -126, mod: 0}, itd8{a: 126, b: 0, add: 126, sub: 126, mul: 0}, - itd8{a: 126, b: 1, add: 127, sub: 125, mul: 126, div: 126}, - itd8{a: 126, b: 126, add: -4, sub: 0, mul: 4, div: 1}, - itd8{a: 126, b: 127, add: -3, sub: -1, mul: -126, div: 0}, - itd8{a: 127, b: -128, add: -1, sub: -1, mul: -128, div: 0}, - itd8{a: 127, b: -127, add: 0, sub: -2, mul: -1, div: -1}, - itd8{a: 127, b: -1, add: 126, sub: -128, mul: -127, div: -127}, + itd8{a: 126, b: 1, add: 127, sub: 125, mul: 126, div: 126, mod: 0}, + itd8{a: 126, b: 126, add: -4, sub: 0, mul: 4, div: 1, mod: 0}, + itd8{a: 126, b: 127, add: -3, sub: -1, mul: -126, div: 0, mod: 126}, + itd8{a: 127, b: -128, add: -1, sub: -1, mul: -128, div: 0, mod: 127}, + itd8{a: 127, b: -127, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd8{a: 127, b: -1, add: 126, sub: -128, mul: -127, div: -127, mod: 0}, itd8{a: 127, b: 0, add: 127, sub: 127, mul: 0}, - itd8{a: 127, b: 1, add: -128, sub: 126, mul: 127, div: 127}, - itd8{a: 127, b: 126, add: -3, sub: 1, mul: -126, div: 1}, - itd8{a: 127, b: 127, add: -2, sub: 0, mul: 1, div: 1}, + itd8{a: 127, b: 1, add: -128, sub: 126, mul: 127, div: 127, mod: 0}, + itd8{a: 127, b: 126, add: -3, sub: 1, mul: -126, div: 1, mod: 1}, + itd8{a: 127, b: 127, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, } var failed bool @@ -481,6 +521,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_uint64_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_uint64 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_uint64_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_uint64 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -502,6 +549,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_int64_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_int64 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_int64_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_int64 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -523,6 +577,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_uint32_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_uint32 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_uint32_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_uint32 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -544,6 +605,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_int32_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_int32 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_int32_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_int32 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -565,6 +633,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_uint16_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_uint16 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_uint16_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_uint16 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -586,6 +661,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_int16_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_int16 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_int16_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_int16 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -607,6 +689,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_uint8_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_uint8 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_uint8_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_uint8 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -628,6 +717,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_int8_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_int8 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_int8_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_int8 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) diff --git a/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go b/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go new file mode 100644 index 0000000000..19bb04b6f1 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go @@ -0,0 +1,214 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This program generates a test to verify that the standard arithmetic +// operators properly handle some special cases. The test file should be +// generated with a known working version of go. +// launch with `go run arithBoundaryGen.go` a file called arithBoundary_ssa.go +// will be written into the parent directory containing the tests + +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "log" + "text/template" +) + +// used for interpolation in a text template +type tmplData struct { + Name, Stype, Symbol string +} + +// used to work around an issue with the mod symbol being +// interpreted as part of a format string +func (s tmplData) SymFirst() string { + return string(s.Symbol[0]) +} + +// ucast casts an unsigned int to the size in s +func ucast(i uint64, s sizedTestData) uint64 { + switch s.name { + case "uint32": + return uint64(uint32(i)) + case "uint16": + return uint64(uint16(i)) + case "uint8": + return uint64(uint8(i)) + } + return i +} + +// icast casts a signed int to the size in s +func icast(i int64, s sizedTestData) int64 { + switch s.name { + case "int32": + return int64(int32(i)) + case "int16": + return int64(int16(i)) + case "int8": + return int64(int8(i)) + } + return i +} + +type sizedTestData struct { + name string + sn string + u []uint64 + i []int64 +} + +// values to generate tests. these should include the smallest and largest values, along +// with any other values that might cause issues. we generate n^2 tests for each size to +// cover all cases. +var szs = []sizedTestData{ + sizedTestData{name: "uint64", sn: "64", u: []uint64{0, 1, 4294967296, 0xffffFFFFffffFFFF}}, + sizedTestData{name: "int64", sn: "64", i: []int64{-0x8000000000000000, -0x7FFFFFFFFFFFFFFF, + -4294967296, -1, 0, 1, 4294967296, 0x7FFFFFFFFFFFFFFE, 0x7FFFFFFFFFFFFFFF}}, + + sizedTestData{name: "uint32", sn: "32", u: []uint64{0, 1, 4294967295}}, + sizedTestData{name: "int32", sn: "32", i: []int64{-0x80000000, -0x7FFFFFFF, -1, 0, + 1, 0x7FFFFFFF}}, + + sizedTestData{name: "uint16", sn: "16", u: []uint64{0, 1, 65535}}, + sizedTestData{name: "int16", sn: "16", i: []int64{-32768, -32767, -1, 0, 1, 32766, 32767}}, + + sizedTestData{name: "uint8", sn: "8", u: []uint64{0, 1, 255}}, + sizedTestData{name: "int8", sn: "8", i: []int64{-128, -127, -1, 0, 1, 126, 127}}, +} + +type op struct { + name, symbol string +} + +// ops that we will be generating tests for +var ops = []op{op{"add", "+"}, op{"sub", "-"}, op{"div", "/"}, op{"mod", "%%"}, op{"mul", "*"}} + +func main() { + + w := new(bytes.Buffer) + fmt.Fprintf(w, "package main;\n") + fmt.Fprintf(w, "import \"fmt\"\n") + + for _, sz := range []int{64, 32, 16, 8} { + fmt.Fprintf(w, "type utd%d struct {\n", sz) + fmt.Fprintf(w, " a,b uint%d\n", sz) + fmt.Fprintf(w, " add,sub,mul,div,mod uint%d\n", sz) + fmt.Fprintf(w, "}\n") + + fmt.Fprintf(w, "type itd%d struct {\n", sz) + fmt.Fprintf(w, " a,b int%d\n", sz) + fmt.Fprintf(w, " add,sub,mul,div,mod int%d\n", sz) + fmt.Fprintf(w, "}\n") + } + + // the function being tested + testFunc, err := template.New("testFunc").Parse( + `func {{.Name}}_{{.Stype}}_ssa(a, b {{.Stype}}) {{.Stype}} { + switch{} // prevent inlining + return a {{.SymFirst}} b +} +`) + if err != nil { + panic(err) + } + + // generate our functions to be tested + for _, s := range szs { + for _, o := range ops { + fd := tmplData{o.name, s.name, o.symbol} + err = testFunc.Execute(w, fd) + if err != nil { + panic(err) + } + } + } + + // generate the test data + for _, s := range szs { + if len(s.u) > 0 { + fmt.Fprintf(w, "var %s_data []utd%s = []utd%s{", s.name, s.sn, s.sn) + for _, i := range s.u { + for _, j := range s.u { + fmt.Fprintf(w, "utd%s{a: %d, b: %d, add: %d, sub: %d, mul: %d", s.sn, i, j, ucast(i+j, s), ucast(i-j, s), ucast(i*j, s)) + if j != 0 { + fmt.Fprintf(w, ", div: %d, mod: %d", ucast(i/j, s), ucast(i%j, s)) + } + fmt.Fprint(w, "},\n") + } + } + fmt.Fprintf(w, "}\n") + } else { + // TODO: clean up this duplication + fmt.Fprintf(w, "var %s_data []itd%s = []itd%s{", s.name, s.sn, s.sn) + for _, i := range s.i { + for _, j := range s.i { + fmt.Fprintf(w, "itd%s{a: %d, b: %d, add: %d, sub: %d, mul: %d", s.sn, i, j, icast(i+j, s), icast(i-j, s), icast(i*j, s)) + if j != 0 { + fmt.Fprintf(w, ", div: %d, mod: %d", icast(i/j, s), icast(i%j, s)) + } + fmt.Fprint(w, "},\n") + } + } + fmt.Fprintf(w, "}\n") + } + } + + fmt.Fprintf(w, "var failed bool\n\n") + fmt.Fprintf(w, "func main() {\n\n") + + verify, err := template.New("tst").Parse( + `if got := {{.Name}}_{{.Stype}}_ssa(v.a, v.b); got != v.{{.Name}} { + fmt.Printf("{{.Name}}_{{.Stype}} %d{{.Symbol}}%d = %d, wanted %d\n",v.a,v.b,got,v.{{.Name}}) + failed = true +} +`) + + for _, s := range szs { + fmt.Fprintf(w, "for _, v := range %s_data {\n", s.name) + + for _, o := range ops { + // avoid generating tests that divide by zero + if o.name == "div" || o.name == "mod" { + fmt.Fprint(w, "if v.b != 0 {") + } + + err = verify.Execute(w, tmplData{o.name, s.name, o.symbol}) + + if o.name == "div" || o.name == "mod" { + fmt.Fprint(w, "\n}\n") + } + + if err != nil { + panic(err) + } + + } + fmt.Fprint(w, " }\n") + } + + fmt.Fprintf(w, `if failed { + panic("tests failed") + } +`) + fmt.Fprintf(w, "}\n") + + // gofmt result + b := w.Bytes() + src, err := format.Source(b) + if err != nil { + fmt.Printf("%s\n", b) + panic(err) + } + + // write to file + err = ioutil.WriteFile("../arithBoundary_ssa.go", src, 0666) + if err != nil { + log.Fatalf("can't write output: %v\n", err) + } +} diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 919336e869..582528801a 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -52,6 +52,15 @@ (Hmul8 x y) -> (HMULB x y) (Hmul8u x y) -> (HMULBU x y) +(Mod64 x y) -> (MODQ x y) +(Mod64u x y) -> (MODQU x y) +(Mod32 x y) -> (MODL x y) +(Mod32u x y) -> (MODLU x y) +(Mod16 x y) -> (MODW x y) +(Mod16u x y) -> (MODWU x y) +(Mod8 x y) -> (MODW (SignExt8to16 x) (SignExt8to16 y)) +(Mod8u x y) -> (MODWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + (And64 x y) -> (ANDQ x y) (And32 x y) -> (ANDL x y) (And16 x y) -> (ANDW x y) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index b218c66a64..7469601fc7 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -103,6 +103,8 @@ func init() { clobbers: dx | flags} gp11hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx}, clobbers: ax | flags} + gp11mod = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{dx}, + clobbers: ax | flags} gp10 = regInfo{inputs: []regMask{gp}} gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly} @@ -202,6 +204,13 @@ func init() { {name: "DIVLU", reg: gp11div, asm: "DIVL"}, // arg0 / arg1 {name: "DIVWU", reg: gp11div, asm: "DIVW"}, // arg0 / arg1 + {name: "MODQ", reg: gp11mod, asm: "IDIVQ"}, // arg0 % arg1 + {name: "MODL", reg: gp11mod, asm: "IDIVL"}, // arg0 % arg1 + {name: "MODW", reg: gp11mod, asm: "IDIVW"}, // arg0 % arg1 + {name: "MODQU", reg: gp11mod, asm: "DIVQ"}, // arg0 % arg1 + {name: "MODLU", reg: gp11mod, asm: "DIVL"}, // arg0 % arg1 + {name: "MODWU", reg: gp11mod, asm: "DIVW"}, // arg0 % arg1 + {name: "ANDQ", reg: gp21, asm: "ANDQ"}, // arg0 & arg1 {name: "ANDL", reg: gp21, asm: "ANDL"}, // arg0 & arg1 {name: "ANDW", reg: gp21, asm: "ANDW"}, // arg0 & arg1 diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 5b8b064bb5..78524a5e6b 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -35,7 +35,6 @@ var genericOps = []opData{ {name: "Div32F"}, // arg0 / arg1 {name: "Div64F"}, - // TODO: Div8, Div16, Div32, Div64 and unsigned {name: "Hmul8"}, // (arg0 * arg1) >> width {name: "Hmul8u"}, @@ -54,6 +53,15 @@ var genericOps = []opData{ {name: "Div64"}, {name: "Div64u"}, + {name: "Mod8"}, // arg0 % arg1 + {name: "Mod8u"}, + {name: "Mod16"}, + {name: "Mod16u"}, + {name: "Mod32"}, + {name: "Mod32u"}, + {name: "Mod64"}, + {name: "Mod64u"}, + {name: "And8"}, // arg0 & arg1 {name: "And16"}, {name: "And32"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index a2e087246d..11fc3180cf 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -105,6 +105,12 @@ const ( OpAMD64DIVQU OpAMD64DIVLU OpAMD64DIVWU + OpAMD64MODQ + OpAMD64MODL + OpAMD64MODW + OpAMD64MODQU + OpAMD64MODLU + OpAMD64MODWU OpAMD64ANDQ OpAMD64ANDL OpAMD64ANDW @@ -267,6 +273,14 @@ const ( OpDiv32u OpDiv64 OpDiv64u + OpMod8 + OpMod8u + OpMod16 + OpMod16u + OpMod32 + OpMod32u + OpMod64 + OpMod64u OpAnd8 OpAnd16 OpAnd32 @@ -1165,6 +1179,90 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "MODQ", + asm: x86.AIDIVQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODL", + asm: x86.AIDIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODW", + asm: x86.AIDIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODQU", + asm: x86.ADIVQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODLU", + asm: x86.ADIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODWU", + asm: x86.ADIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, { name: "ANDQ", asm: x86.AANDQ, @@ -2852,6 +2950,38 @@ var opcodeTable = [...]opInfo{ name: "Div64u", generic: true, }, + { + name: "Mod8", + generic: true, + }, + { + name: "Mod8u", + generic: true, + }, + { + name: "Mod16", + generic: true, + }, + { + name: "Mod16u", + generic: true, + }, + { + name: "Mod32", + generic: true, + }, + { + name: "Mod32u", + generic: true, + }, + { + name: "Mod64", + generic: true, + }, + { + name: "Mod64u", + generic: true, + }, { name: "And8", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 4265cfcb84..3b2b7f03a7 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -4734,6 +4734,162 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end61dbc9d9e93dd6946a20a1f475b3f74b end61dbc9d9e93dd6946a20a1f475b3f74b: ; + case OpMod16: + // match: (Mod16 x y) + // cond: + // result: (MODW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end036bac694be9fe0d6b00b86c2e625990 + end036bac694be9fe0d6b00b86c2e625990: + ; + case OpMod16u: + // match: (Mod16u x y) + // cond: + // result: (MODWU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODWU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto enda75d900097f1510ca1c6df786bef0c24 + enda75d900097f1510ca1c6df786bef0c24: + ; + case OpMod32: + // match: (Mod32 x y) + // cond: + // result: (MODL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end12c8c0ecf3296810b8217cd4e40f7707 + end12c8c0ecf3296810b8217cd4e40f7707: + ; + case OpMod32u: + // match: (Mod32u x y) + // cond: + // result: (MODLU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODLU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end1f0892076cfd58733a08d3ab175a3c1c + end1f0892076cfd58733a08d3ab175a3c1c: + ; + case OpMod64: + // match: (Mod64 x y) + // cond: + // result: (MODQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endaae75f449baf5dc108be4e0439af97f2 + endaae75f449baf5dc108be4e0439af97f2: + ; + case OpMod64u: + // match: (Mod64u x y) + // cond: + // result: (MODQU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODQU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end0d4c8b9df77e59289fb14e2496559d1d + end0d4c8b9df77e59289fb14e2496559d1d: + ; + case OpMod8: + // match: (Mod8 x y) + // cond: + // result: (MODW (SignExt8to16 x) (SignExt8to16 y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpSignExt8to16, TypeInvalid) + v0.Type = config.Frontend().TypeInt16() + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpSignExt8to16, TypeInvalid) + v1.Type = config.Frontend().TypeInt16() + v1.AddArg(y) + v.AddArg(v1) + return true + } + goto end13bfd4e75ea363f7b6926fa05136e193 + end13bfd4e75ea363f7b6926fa05136e193: + ; + case OpMod8u: + // match: (Mod8u x y) + // cond: + // result: (MODWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODWU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpZeroExt8to16, TypeInvalid) + v0.Type = config.Frontend().TypeUInt16() + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpZeroExt8to16, TypeInvalid) + v1.Type = config.Frontend().TypeUInt16() + v1.AddArg(y) + v.AddArg(v1) + return true + } + goto end4c0e16e55b5f8f6d19811fc8d07eacf2 + end4c0e16e55b5f8f6d19811fc8d07eacf2: + ; case OpMove: // match: (Move [size] dst src mem) // cond: