import (
"cmd/compile/internal/base"
+ "cmd/compile/internal/types"
"fmt"
- "math"
)
type indVarFlags uint8
return
}
- if n := ind.Args[0]; n.Op == OpAdd64 && (n.Args[0] == ind || n.Args[1] == ind) {
+ if n := ind.Args[0]; (n.Op == OpAdd64 || n.Op == OpAdd32 || n.Op == OpAdd16 || n.Op == OpAdd8) && (n.Args[0] == ind || n.Args[1] == ind) {
min, nxt = ind.Args[1], n
- } else if n := ind.Args[1]; n.Op == OpAdd64 && (n.Args[0] == ind || n.Args[1] == ind) {
+ } else if n := ind.Args[1]; (n.Op == OpAdd64 || n.Op == OpAdd32 || n.Op == OpAdd16 || n.Op == OpAdd8) && (n.Args[0] == ind || n.Args[1] == ind) {
min, nxt = ind.Args[0], n
} else {
// Not a recognized induction variable.
// goto loop
//
// exit_loop:
-//
-// TODO: handle 32 bit operations
func findIndVar(f *Func) []indVar {
var iv []indVar
sdom := f.Sdom()
var limit *Value // ending value
// Check thet the control if it either ind </<= limit or limit </<= ind.
- // TODO: Handle 32-bit comparisons.
// TODO: Handle unsigned comparisons?
c := b.Controls[0]
inclusive := false
switch c.Op {
- case OpLeq64:
+ case OpLeq64, OpLeq32, OpLeq16, OpLeq8:
inclusive = true
fallthrough
- case OpLess64:
+ case OpLess64, OpLess32, OpLess16, OpLess8:
ind, limit = c.Args[0], c.Args[1]
default:
continue
}
// Expect the increment to be a nonzero constant.
- if inc.Op != OpConst64 {
+ if !inc.isGenericIntConst() {
continue
}
step := inc.AuxInt
// This function returns true if the increment will never overflow/underflow.
ok := func() bool {
if step > 0 {
- if limit.Op == OpConst64 {
+ if limit.isGenericIntConst() {
// Figure out the actual largest value.
v := limit.AuxInt
if !inclusive {
- if v == math.MinInt64 {
+ if v == minSignedValue(limit.Type) {
return false // < minint is never satisfiable.
}
v--
}
- if init.Op == OpConst64 {
+ if init.isGenericIntConst() {
// Use stride to compute a better lower limit.
if init.AuxInt > v {
return false
}
if inclusive && v != limit.AuxInt || !inclusive && v+1 != limit.AuxInt {
// We know a better limit than the programmer did. Use our limit instead.
- limit = f.ConstInt64(f.Config.Types.Int64, v)
+ limit = f.constVal(limit.Op, limit.Type, v, true)
inclusive = true
}
return true
return step <= k
}
// ind < knn - k cannot overflow if step is at most k+1
- return step <= k+1 && k != math.MaxInt64
+ return step <= k+1 && k != maxSignedValue(limit.Type)
} else { // step < 0
if limit.Op == OpConst64 {
// Figure out the actual smallest value.
v := limit.AuxInt
if !inclusive {
- if v == math.MaxInt64 {
+ if v == maxSignedValue(limit.Type) {
return false // > maxint is never satisfiable.
}
v++
}
- if init.Op == OpConst64 {
+ if init.isGenericIntConst() {
// Use stride to compute a better lower limit.
if init.AuxInt < v {
return false
}
if inclusive && v != limit.AuxInt || !inclusive && v-1 != limit.AuxInt {
// We know a better limit than the programmer did. Use our limit instead.
- limit = f.ConstInt64(f.Config.Types.Int64, v)
+ limit = f.constVal(limit.Op, limit.Type, v, true)
inclusive = true
}
return true
var x, y *Value
x = v
switch v.Op {
- case OpSub64:
+ case OpSub64, OpSub32, OpSub16, OpSub8:
x = v.Args[0]
y = v.Args[1]
- case OpAdd64:
+ case OpAdd64, OpAdd32, OpAdd16, OpAdd8:
x = v.Args[0]
y = v.Args[1]
- if x.Op == OpConst64 {
+ if x.isGenericIntConst() {
x, y = y, x
}
}
if y == nil {
return x, 0
}
- if y.Op != OpConst64 {
+ if !y.isGenericIntConst() {
return nil, 0
}
- if v.Op == OpAdd64 {
+ if v.Op == OpAdd64 || v.Op == OpAdd32 || v.Op == OpAdd16 || v.Op == OpAdd8 {
return x, -y.AuxInt
}
return x, y.AuxInt
}
b.Func.Warnl(b.Pos, "Induction variable: limits %v%v,%v%v, increment %d%s", mb1, mlim1, mlim2, mb2, inc, extra)
}
+
+func minSignedValue(t *types.Type) int64 {
+ return -1 << (t.Size()*8 - 1)
+}
+
+func maxSignedValue(t *types.Type) int64 {
+ return 1<<((t.Size()*8)-1) - 1
+}