diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2024-05-27 14:23:08 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2024-05-27 13:05:20 +0000 |
| commit | 8bbf94ce31b652c168de6ea784942b54ea09e80c (patch) | |
| tree | 55bb8625c738e8b917384334437a5cd83b8247b1 /prog/minimization.go | |
| parent | 3eba45d51db7adab6fb1d3c7e71d699ca6bea4b3 (diff) | |
prog: make minimization parameters explicit
Add an explicit parameter to only run call removal.
Diffstat (limited to 'prog/minimization.go')
| -rw-r--r-- | prog/minimization.go | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/prog/minimization.go b/prog/minimization.go index 1760d180f..abd0a4a3d 100644 --- a/prog/minimization.go +++ b/prog/minimization.go @@ -9,11 +9,25 @@ import ( "reflect" ) +type MinimizeParams struct { + // CallIndex was intentionally not included in this struct, since its + // default value should be -1, while the default value of 0 would introduce a bug. + + // If RemoveCallsOnly is set to true, Minimize() focuses only on removing whole calls. + RemoveCallsOnly bool + + // Light speeds up the minimization by + // 1. Not removing array elements one by one. + // 2. Not bisecting blobs too much. + // 3. Not minimizing integer values. + Light bool +} + // Minimize minimizes program p into an equivalent program using the equivalence // predicate pred. It iteratively generates simpler programs and asks pred // whether it is equal to the original program or not. If it is equivalent then // the simplification attempt is committed and the process continues. -func Minimize(p0 *Prog, callIndex0 int, crash bool, pred0 func(*Prog, int) bool) (*Prog, int) { +func Minimize(p0 *Prog, callIndex0 int, params MinimizeParams, pred0 func(*Prog, int) bool) (*Prog, int) { pred := func(p *Prog, callIndex int) bool { p.sanitizeFix() p.debugValidate() @@ -28,33 +42,35 @@ func Minimize(p0 *Prog, callIndex0 int, crash bool, pred0 func(*Prog, int) bool) } // Try to remove all calls except the last one one-by-one. - p0, callIndex0 = removeCalls(p0, callIndex0, crash, pred) + p0, callIndex0 = removeCalls(p0, callIndex0, pred) - // Try to reset all call props to their default values. - p0 = resetCallProps(p0, callIndex0, pred) + if !params.RemoveCallsOnly { + // Try to reset all call props to their default values. + p0 = resetCallProps(p0, callIndex0, pred) - // Try to minimize individual calls. - for i := 0; i < len(p0.Calls); i++ { - if p0.Calls[i].Meta.Attrs.NoMinimize { - continue - } - ctx := &minimizeArgsCtx{ - target: p0.Target, - p0: &p0, - callIndex0: callIndex0, - crash: crash, - pred: pred, - triedPaths: make(map[string]bool), - } - again: - ctx.p = p0.Clone() - ctx.call = ctx.p.Calls[i] - for j, field := range ctx.call.Meta.Args { - if ctx.do(ctx.call.Args[j], field.Name, "") { - goto again + // Try to minimize individual calls. + for i := 0; i < len(p0.Calls); i++ { + if p0.Calls[i].Meta.Attrs.NoMinimize { + continue + } + ctx := &minimizeArgsCtx{ + target: p0.Target, + p0: &p0, + callIndex0: callIndex0, + params: params, + pred: pred, + triedPaths: make(map[string]bool), + } + again: + ctx.p = p0.Clone() + ctx.call = ctx.p.Calls[i] + for j, field := range ctx.call.Meta.Args { + if ctx.do(ctx.call.Args[j], field.Name, "") { + goto again + } } + p0 = minimizeCallProps(p0, i, callIndex0, pred) } - p0 = minimizeCallProps(p0, i, callIndex0, pred) } if callIndex0 != -1 { @@ -66,7 +82,7 @@ func Minimize(p0 *Prog, callIndex0 int, crash bool, pred0 func(*Prog, int) bool) return p0, callIndex0 } -func removeCalls(p0 *Prog, callIndex0 int, crash bool, pred func(*Prog, int) bool) (*Prog, int) { +func removeCalls(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool) (*Prog, int) { if callIndex0 >= 0 && callIndex0+2 < len(p0.Calls) { // It's frequently the case that all subsequent calls were not necessary. // Try to drop them all at once. @@ -153,7 +169,7 @@ type minimizeArgsCtx struct { p *Prog call *Call callIndex0 int - crash bool + params MinimizeParams pred func(*Prog, int) bool triedPaths map[string]bool } @@ -225,7 +241,7 @@ func (typ *ArrayType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool elem := a.Inner[i] elemPath := fmt.Sprintf("%v-%v", path, i) // Try to remove individual elements one-by-one. - if !ctx.crash && !ctx.triedPaths[elemPath] && + if !ctx.params.Light && !ctx.triedPaths[elemPath] && (typ.Kind == ArrayRandLen || typ.Kind == ArrayRangeLen && uint64(len(a.Inner)) > typ.RangeBegin) { ctx.triedPaths[elemPath] = true @@ -268,7 +284,7 @@ func (typ *ProcType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool { func minimizeInt(ctx *minimizeArgsCtx, arg Arg, path string) bool { // TODO: try to reset bits in ints // TODO: try to set separate flags - if ctx.crash { + if ctx.params.Light { return false } a := arg.(*ConstArg) @@ -296,7 +312,7 @@ func minimizeInt(ctx *minimizeArgsCtx, arg Arg, path string) bool { } func (typ *ResourceType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool { - if ctx.crash { + if ctx.params.Light { return false } a := arg.(*ResultArg) @@ -340,7 +356,7 @@ func (typ *BufferType) minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool ctx.target.assignSizesCall(ctx.call) } step /= 2 - if ctx.crash { + if ctx.params.Light { break } } |
