freeValues *Value // free Values linked by argstorage[0].  All other fields except ID are 0/nil.
        freeBlocks *Block // free Blocks linked by succstorage[0].  All other fields except ID are 0/nil.
+
+       constants map[int64][]*Value // constants cache, keyed by constant value; users must check value's Op and Type
 }
 
 // NumBlocks returns an integer larger than the id of any Block in the Func.
        return v
 }
 
+// constVal returns a constant value for c.
+func (f *Func) constVal(line int32, op Op, t Type, c int64) *Value {
+       if f.constants == nil {
+               f.constants = make(map[int64][]*Value)
+       }
+       vv := f.constants[c]
+       for _, v := range vv {
+               if v.Op == op && v.Type.Equal(t) {
+                       return v
+               }
+       }
+       v := f.Entry.NewValue0I(line, op, t, c)
+       f.constants[c] = append(vv, v)
+       return v
+}
+
 // ConstInt returns an int constant representing its argument.
 func (f *Func) ConstBool(line int32, t Type, c bool) *Value {
-       // TODO: cache?
        i := int64(0)
        if c {
                i = 1
        }
-       return f.Entry.NewValue0I(line, OpConstBool, t, i)
+       return f.constVal(line, OpConstBool, t, i)
 }
 func (f *Func) ConstInt8(line int32, t Type, c int8) *Value {
-       // TODO: cache?
-       return f.Entry.NewValue0I(line, OpConst8, t, int64(c))
+       return f.constVal(line, OpConst8, t, int64(c))
 }
 func (f *Func) ConstInt16(line int32, t Type, c int16) *Value {
-       // TODO: cache?
-       return f.Entry.NewValue0I(line, OpConst16, t, int64(c))
+       return f.constVal(line, OpConst16, t, int64(c))
 }
 func (f *Func) ConstInt32(line int32, t Type, c int32) *Value {
-       // TODO: cache?
-       return f.Entry.NewValue0I(line, OpConst32, t, int64(c))
+       return f.constVal(line, OpConst32, t, int64(c))
 }
 func (f *Func) ConstInt64(line int32, t Type, c int64) *Value {
-       // TODO: cache?
-       return f.Entry.NewValue0I(line, OpConst64, t, c)
+       return f.constVal(line, OpConst64, t, c)
 }
 func (f *Func) ConstFloat32(line int32, t Type, c float64) *Value {
-       // TODO: cache?
-       return f.Entry.NewValue0I(line, OpConst32F, t, int64(math.Float64bits(c)))
+       return f.constVal(line, OpConst32F, t, int64(math.Float64bits(c)))
 }
 func (f *Func) ConstFloat64(line int32, t Type, c float64) *Value {
-       // TODO: cache?
-       return f.Entry.NewValue0I(line, OpConst64F, t, int64(math.Float64bits(c)))
+       return f.constVal(line, OpConst64F, t, int64(math.Float64bits(c)))
 }
 
 func (f *Func) Logf(msg string, args ...interface{})   { f.Config.Logf(msg, args...) }