Skip to content

Commit

Permalink
cmd/compile: expand calls cleanup
Browse files Browse the repository at this point in the history
Convert expand calls into a smaller number of focused
recursive rewrites, and rely on an enhanced version of
"decompose" to clean up afterwards.

Debugging information seems to emerge intact.

Change-Id: Ic46da4207e3a4da5c8e2c47b637b0e35abbe56bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/507295
Run-TryBot: David Chase <[email protected]>
Reviewed-by: Cherry Mui <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
  • Loading branch information
dr2chase authored and pull[bot] committed Feb 1, 2024
1 parent fcc3818 commit 73150de
Show file tree
Hide file tree
Showing 10 changed files with 1,639 additions and 1,608 deletions.
106 changes: 106 additions & 0 deletions src/cmd/compile/internal/ssa/_gen/dec.rules
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,109 @@
(OffPtr <typ.BytePtrPtr> [config.PtrSize] dst)
data
(Store {typ.Uintptr} dst itab mem))

// Helpers for expand calls
// Some of these are copied from generic.rules

(IMake _typ (StructMake1 val)) => (IMake _typ val)
(StructSelect [0] (IData x)) => (IData x)

(StructSelect (StructMake1 x)) => x
(StructSelect [0] (StructMake2 x _)) => x
(StructSelect [1] (StructMake2 _ x)) => x
(StructSelect [0] (StructMake3 x _ _)) => x
(StructSelect [1] (StructMake3 _ x _)) => x
(StructSelect [2] (StructMake3 _ _ x)) => x
(StructSelect [0] (StructMake4 x _ _ _)) => x
(StructSelect [1] (StructMake4 _ x _ _)) => x
(StructSelect [2] (StructMake4 _ _ x _)) => x
(StructSelect [3] (StructMake4 _ _ _ x)) => x

// Special case coming from immediate interface rewriting
// Typical case: (StructSelect [0] (IData (IMake typ dat)) rewrites to (StructSelect [0] dat)
// but because the interface is immediate, the type of "IData" is a one-element struct containing
// a pointer that is not the pointer type of dat (can be a *uint8).
// More annoying case: (ArraySelect[0] (StructSelect[0] isAPtr))
// There, result of the StructSelect is an Array (not a pointer) and
// the pre-rewrite input to the ArraySelect is a struct, not a pointer.
(StructSelect [0] x) && x.Type.IsPtr() => x
(ArraySelect [0] x) && x.Type.IsPtr() => x

// These, too. Bits is bits.
(ArrayMake1 x) && x.Type.IsPtr() => x
(StructMake1 x) && x.Type.IsPtr() => x

(Store dst (StructMake1 <t> f0) mem) =>
(Store {t.FieldType(0)} (OffPtr <t.FieldType(0).PtrTo()> [0] dst) f0 mem)
(Store dst (StructMake2 <t> f0 f1) mem) =>
(Store {t.FieldType(1)}
(OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
f1
(Store {t.FieldType(0)}
(OffPtr <t.FieldType(0).PtrTo()> [0] dst)
f0 mem))
(Store dst (StructMake3 <t> f0 f1 f2) mem) =>
(Store {t.FieldType(2)}
(OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
f2
(Store {t.FieldType(1)}
(OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
f1
(Store {t.FieldType(0)}
(OffPtr <t.FieldType(0).PtrTo()> [0] dst)
f0 mem)))
(Store dst (StructMake4 <t> f0 f1 f2 f3) mem) =>
(Store {t.FieldType(3)}
(OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst)
f3
(Store {t.FieldType(2)}
(OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
f2
(Store {t.FieldType(1)}
(OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
f1
(Store {t.FieldType(0)}
(OffPtr <t.FieldType(0).PtrTo()> [0] dst)
f0 mem))))

(ArraySelect (ArrayMake1 x)) => x
(ArraySelect [0] (IData x)) => (IData x)

(Store dst (ArrayMake1 e) mem) => (Store {e.Type} dst e mem)

// NOTE removed must-not-be-SSA condition.
(ArraySelect [i] x:(Load <t> ptr mem)) =>
@x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.Elem().Size()*i] ptr) mem)

(StringPtr x:(Load <t> ptr mem)) && t.IsString() => @x.Block (Load <typ.BytePtr> ptr mem)
(StringLen x:(Load <t> ptr mem)) && t.IsString() => @x.Block (Load <typ.Int>
(OffPtr <typ.IntPtr> [config.PtrSize] ptr)
mem)

// NOTE removed must-not-be-SSA condition.
(StructSelect [i] x:(Load <t> ptr mem)) =>
@x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)

(ITab x:(Load <t> ptr mem)) && t.IsInterface() => @x.Block (Load <typ.Uintptr> ptr mem)

(IData x:(Load <t> ptr mem)) && t.IsInterface() => @x.Block (Load <typ.BytePtr>
(OffPtr <typ.BytePtrPtr> [config.PtrSize] ptr)
mem)

(SlicePtr x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <t.Elem().PtrTo()> ptr mem)
(SliceLen x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <typ.Int>
(OffPtr <typ.IntPtr> [config.PtrSize] ptr)
mem)
(SliceCap x:(Load <t> ptr mem)) && t.IsSlice() => @x.Block (Load <typ.Int>
(OffPtr <typ.IntPtr> [2*config.PtrSize] ptr)
mem)

(ComplexReal x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 8 => @x.Block (Load <typ.Float32> ptr mem)
(ComplexImag x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 8 => @x.Block (Load <typ.Float32>
(OffPtr <typ.Float32Ptr> [4] ptr)
mem)

(ComplexReal x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 16 => @x.Block (Load <typ.Float64> ptr mem)
(ComplexImag x:(Load <t> ptr mem)) && t.IsComplex() && t.Size() == 16 => @x.Block (Load <typ.Float64>
(OffPtr <typ.Float64Ptr> [8] ptr)
mem)
4 changes: 3 additions & 1 deletion src/cmd/compile/internal/ssa/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,8 @@ var passes = [...]pass{
{name: "nilcheckelim", fn: nilcheckelim},
{name: "prove", fn: prove},
{name: "early fuse", fn: fuseEarly},
{name: "decompose builtin", fn: decomposeBuiltIn, required: true},
{name: "expand calls", fn: expandCalls, required: true},
{name: "decompose builtin", fn: postExpandCallsDecompose, required: true},
{name: "softfloat", fn: softfloat, required: true},
{name: "late opt", fn: opt, required: true}, // TODO: split required rules and optimizing rules
{name: "dead auto elim", fn: elimDeadAutosGeneric},
Expand Down Expand Up @@ -547,6 +547,8 @@ var passOrder = [...]constraint{
{"generic cse", "tighten"},
// checkbce needs the values removed
{"generic deadcode", "check bce"},
// decompose builtin now also cleans up after expand calls
{"expand calls", "decompose builtin"},
// don't run optimization pass until we've decomposed builtin objects
{"decompose builtin", "late opt"},
// decompose builtin is the last pass that may introduce new float ops, so run softfloat after it
Expand Down
Loading

0 comments on commit 73150de

Please sign in to comment.