]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd: remove GOEXPERIMENT=nounified knob
authorMatthew Dempsky <mdempsky@google.com>
Fri, 2 Dec 2022 00:14:11 +0000 (16:14 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 25 Jan 2023 21:16:32 +0000 (21:16 +0000)
This CL removes the GOEXPERIMENT=nounified knob, and any conditional
statements that depend on that knob. Further CLs to remove unreachable
code follow this one.

Updates #57410.

Change-Id: I39c147e1a83601c73f8316a001705778fee64a91
Reviewed-on: https://go-review.googlesource.com/c/go/+/458615
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
32 files changed:
src/cmd/compile/internal/base/debug.go
src/cmd/compile/internal/base/flag.go
src/cmd/compile/internal/devirtualize/devirtualize.go
src/cmd/compile/internal/importer/gcimporter_test.go
src/cmd/compile/internal/inline/inl.go
src/cmd/compile/internal/noder/export.go
src/cmd/compile/internal/noder/import.go
src/cmd/compile/internal/noder/noder.go
src/cmd/compile/internal/noder/reader.go
src/cmd/compile/internal/reflectdata/helpers.go
src/cmd/compile/internal/reflectdata/reflect.go
src/cmd/compile/internal/ssa/debug_lines_test.go
src/cmd/compile/internal/staticinit/sched.go
src/cmd/compile/internal/test/inl_test.go
src/cmd/compile/internal/typecheck/crawler.go
src/cmd/compile/internal/typecheck/subr.go
src/cmd/compile/internal/walk/closure.go
src/cmd/compile/internal/walk/convert.go
src/cmd/link/link_test.go
src/go/importer/importer_test.go
src/go/internal/gcimporter/gcimporter_test.go
src/internal/buildcfg/exp.go
src/internal/goexperiment/exp_unified_off.go [deleted file]
src/internal/goexperiment/exp_unified_on.go [deleted file]
src/internal/goexperiment/flags.go
test/escape_iface_nounified.go [deleted file]
test/escape_iface_unified.go
test/fixedbugs/issue46903.go
test/fixedbugs/issue53439.go
test/inline_nounified.go [deleted file]
test/inline_unified.go
test/run.go

index ee42696ad270a1be99480269ebbf52d44890fc8f..b1dc9bc211d79778a25df23a0e164d1e827f15e4 100644 (file)
@@ -47,7 +47,6 @@ type DebugFlags struct {
        SyncFrames            int    `help:"how many writer stack frames to include at sync points in unified export data"`
        TypeAssert            int    `help:"print information about type assertion inlining"`
        TypecheckInl          int    `help:"eager typechecking of inline function bodies" concurrent:"ok"`
-       Unified               int    `help:"enable unified IR construction"`
        WB                    int    `help:"print information about write barriers"`
        ABIWrap               int    `help:"print information about ABI wrapper generation"`
        MayMoreStack          string `help:"call named function before all stack growth checks" concurrent:"ok"`
index eb3d34f0b1e39bd155ebb57b7d746c8dba6016ee..d6b5b90aaa22bbed331491d29bb0a4013e91e4b8 100644 (file)
@@ -167,9 +167,6 @@ func ParseFlags() {
        Debug.ConcurrentOk = true
        Debug.InlFuncsWithClosures = 1
        Debug.InlStaticInit = 1
-       if buildcfg.Experiment.Unified {
-               Debug.Unified = 1
-       }
        Debug.SyncFrames = -1 // disable sync markers by default
 
        Debug.Checkptr = -1 // so we can tell whether it is set explicitly
index 554e935c3e4072f54bc40e9519b416e52e0acf6f..6c41d4efd8b27d78e4a2ec481297f20e52d06b9c 100644 (file)
@@ -57,58 +57,52 @@ func Call(call *ir.CallExpr) {
                return
        }
 
-       if base.Debug.Unified != 0 {
-               // N.B., stencil.go converts shape-typed values to interface type
-               // using OEFACE instead of OCONVIFACE, so devirtualization fails
-               // above instead. That's why this code is specific to unified IR.
-
-               // If typ is a shape type, then it was a type argument originally
-               // and we'd need an indirect call through the dictionary anyway.
-               // We're unable to devirtualize this call.
-               if typ.IsShape() {
-                       return
-               }
+       // If typ is a shape type, then it was a type argument originally
+       // and we'd need an indirect call through the dictionary anyway.
+       // We're unable to devirtualize this call.
+       if typ.IsShape() {
+               return
+       }
 
-               // If typ *has* a shape type, then it's an shaped, instantiated
-               // type like T[go.shape.int], and its methods (may) have an extra
-               // dictionary parameter. We could devirtualize this call if we
-               // could derive an appropriate dictionary argument.
-               //
-               // TODO(mdempsky): If typ has has a promoted non-generic method,
-               // then that method won't require a dictionary argument. We could
-               // still devirtualize those calls.
-               //
-               // TODO(mdempsky): We have the *runtime.itab in recv.TypeWord. It
-               // should be possible to compute the represented type's runtime
-               // dictionary from this (e.g., by adding a pointer from T[int]'s
-               // *runtime._type to .dict.T[int]; or by recognizing static
-               // references to go:itab.T[int],iface and constructing a direct
-               // reference to .dict.T[int]).
-               if typ.HasShape() {
-                       if base.Flag.LowerM != 0 {
-                               base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped receiver %v", call, typ)
-                       }
-                       return
+       // If typ *has* a shape type, then it's an shaped, instantiated
+       // type like T[go.shape.int], and its methods (may) have an extra
+       // dictionary parameter. We could devirtualize this call if we
+       // could derive an appropriate dictionary argument.
+       //
+       // TODO(mdempsky): If typ has has a promoted non-generic method,
+       // then that method won't require a dictionary argument. We could
+       // still devirtualize those calls.
+       //
+       // TODO(mdempsky): We have the *runtime.itab in recv.TypeWord. It
+       // should be possible to compute the represented type's runtime
+       // dictionary from this (e.g., by adding a pointer from T[int]'s
+       // *runtime._type to .dict.T[int]; or by recognizing static
+       // references to go:itab.T[int],iface and constructing a direct
+       // reference to .dict.T[int]).
+       if typ.HasShape() {
+               if base.Flag.LowerM != 0 {
+                       base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped receiver %v", call, typ)
                }
+               return
+       }
 
-               // Further, if sel.X's type has a shape type, then it's a shaped
-               // interface type. In this case, the (non-dynamic) TypeAssertExpr
-               // we construct below would attempt to create an itab
-               // corresponding to this shaped interface type; but the actual
-               // itab pointer in the interface value will correspond to the
-               // original (non-shaped) interface type instead. These are
-               // functionally equivalent, but they have distinct pointer
-               // identities, which leads to the type assertion failing.
-               //
-               // TODO(mdempsky): We know the type assertion here is safe, so we
-               // could instead set a flag so that walk skips the itab check. For
-               // now, punting is easy and safe.
-               if sel.X.Type().HasShape() {
-                       if base.Flag.LowerM != 0 {
-                               base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped interface %v", call, sel.X.Type())
-                       }
-                       return
+       // Further, if sel.X's type has a shape type, then it's a shaped
+       // interface type. In this case, the (non-dynamic) TypeAssertExpr
+       // we construct below would attempt to create an itab
+       // corresponding to this shaped interface type; but the actual
+       // itab pointer in the interface value will correspond to the
+       // original (non-shaped) interface type instead. These are
+       // functionally equivalent, but they have distinct pointer
+       // identities, which leads to the type assertion failing.
+       //
+       // TODO(mdempsky): We know the type assertion here is safe, so we
+       // could instead set a flag so that walk skips the itab check. For
+       // now, punting is easy and safe.
+       if sel.X.Type().HasShape() {
+               if base.Flag.LowerM != 0 {
+                       base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped interface %v", call, sel.X.Type())
                }
+               return
        }
 
        dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, nil)
index 387c7c03fe922543d842f7cebce9113e5807974f..fec6737c1dc79e9783bb65bb790399d4799771d4 100644 (file)
@@ -9,7 +9,6 @@ import (
        "cmd/compile/internal/types2"
        "fmt"
        "go/build"
-       "internal/goexperiment"
        "internal/testenv"
        "os"
        "os/exec"
@@ -98,7 +97,7 @@ func TestImportTestdata(t *testing.T) {
                "exports.go":  {"go/ast", "go/token"},
                "generics.go": nil,
        }
-       if goexperiment.Unified {
+       if true /* was goexperiment.Unified */ {
                // TODO(mdempsky): Fix test below to flatten the transitive
                // Package.Imports graph. Unified IR is more precise about
                // recreating the package import graph.
@@ -343,8 +342,12 @@ func verifyInterfaceMethodRecvs(t *testing.T, named *types2.Named, level int) {
        // The unified IR importer always sets interface method receiver
        // parameters to point to the Interface type, rather than the Named.
        // See #49906.
+       //
+       // TODO(mdempsky): This is only true for the types2 importer. For
+       // the go/types importer, we duplicate the Interface and rewrite its
+       // receiver methods to match historical behavior.
        var want types2.Type = named
-       if goexperiment.Unified {
+       if true /* was goexperiment.Unified */ {
                want = iface
        }
 
index e3b2e44f61ab351e83773063708fb410a021d50a..de25d451ebb053369c8167e69c7ffc6b74815ee4 100644 (file)
@@ -645,15 +645,13 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
                // minimize impact to the existing inlining heuristics (in
                // particular, to avoid breaking the existing inlinability regress
                // tests), we need to compensate for this here.
-               if base.Debug.Unified != 0 {
-                       if init := n.Rhs[0].Init(); len(init) == 1 {
-                               if _, ok := init[0].(*ir.AssignListStmt); ok {
-                                       // 4 for each value, because each temporary variable now
-                                       // appears 3 times (DCL, LHS, RHS), plus an extra DCL node.
-                                       //
-                                       // 1 for the extra "tmp1, tmp2 = f()" assignment statement.
-                                       v.budget += 4*int32(len(n.Lhs)) + 1
-                               }
+               if init := n.Rhs[0].Init(); len(init) == 1 {
+                       if _, ok := init[0].(*ir.AssignListStmt); ok {
+                               // 4 for each value, because each temporary variable now
+                               // appears 3 times (DCL, LHS, RHS), plus an extra DCL node.
+                               //
+                               // 1 for the extra "tmp1, tmp2 = f()" assignment statement.
+                               v.budget += 4*int32(len(n.Lhs)) + 1
                        }
                }
 
@@ -958,49 +956,6 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlCalls *[]*ir.Inlin
                return n
        }
 
-       // The non-unified frontend has issues with inlining and shape parameters.
-       if base.Debug.Unified == 0 {
-               // Don't inline a function fn that has no shape parameters, but is passed at
-               // least one shape arg. This means we must be inlining a non-generic function
-               // fn that was passed into a generic function, and can be called with a shape
-               // arg because it matches an appropriate type parameters. But fn may include
-               // an interface conversion (that may be applied to a shape arg) that was not
-               // apparent when we first created the instantiation of the generic function.
-               // We can't handle this if we actually do the inlining, since we want to know
-               // all interface conversions immediately after stenciling. So, we avoid
-               // inlining in this case, see issue #49309. (1)
-               //
-               // See discussion on go.dev/cl/406475 for more background.
-               if !fn.Type().Params().HasShape() {
-                       for _, arg := range n.Args {
-                               if arg.Type().HasShape() {
-                                       if logopt.Enabled() {
-                                               logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc),
-                                                       fmt.Sprintf("inlining function %v has no-shape params with shape args", ir.FuncName(fn)))
-                                       }
-                                       return n
-                               }
-                       }
-               } else {
-                       // Don't inline a function fn that has shape parameters, but is passed no shape arg.
-                       // See comments (1) above, and issue #51909.
-                       inlineable := len(n.Args) == 0 // Function has shape in type, with no arguments can always be inlined.
-                       for _, arg := range n.Args {
-                               if arg.Type().HasShape() {
-                                       inlineable = true
-                                       break
-                               }
-                       }
-                       if !inlineable {
-                               if logopt.Enabled() {
-                                       logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc),
-                                               fmt.Sprintf("inlining function %v has shape params with no-shape args", ir.FuncName(fn)))
-                               }
-                               return n
-                       }
-               }
-       }
-
        if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) {
                // Runtime package must not be instrumented.
                // Instrument skips runtime package. However, some runtime code can be
index 263cdc262bb88d0ec1662b7f229b8f6027f38686..e1f289b56f8c9c9174b4a71aa9c07a7c9fbb3a4a 100644 (file)
@@ -10,19 +10,14 @@ import (
        "io"
 
        "cmd/compile/internal/base"
-       "cmd/compile/internal/typecheck"
        "cmd/internal/bio"
 )
 
 func WriteExports(out *bio.Writer) {
        var data bytes.Buffer
 
-       if base.Debug.Unified != 0 {
-               data.WriteByte('u')
-               writeUnifiedExport(&data)
-       } else {
-               typecheck.WriteExports(&data, true)
-       }
+       data.WriteByte('u')
+       writeUnifiedExport(&data)
 
        // The linker also looks for the $$ marker - use char after $$ to distinguish format.
        out.WriteString("\n$$B\n") // indicate binary export format
index 8b017ecfd59b2931aacff1abce3e782b387f5760..b7008ac5e8b565001c9ee26780d0647edfe63a8e 100644 (file)
@@ -231,10 +231,6 @@ func readImportFile(path string, target *ir.Package, env *types2.Context, packag
 
        switch c {
        case 'u':
-               if !buildcfg.Experiment.Unified {
-                       base.Fatalf("unexpected export data format")
-               }
-
                // TODO(mdempsky): This seems a bit clunky.
                data = strings.TrimSuffix(data, "\n$$\n")
 
@@ -244,20 +240,6 @@ func readImportFile(path string, target *ir.Package, env *types2.Context, packag
                readPackage(newPkgReader(pr), pkg1, false)
                pkg2 = importer.ReadPackage(env, packages, pr)
 
-       case 'i':
-               if buildcfg.Experiment.Unified {
-                       base.Fatalf("unexpected export data format")
-               }
-
-               typecheck.ReadImports(pkg1, data)
-
-               if packages != nil {
-                       pkg2, err = importer.ImportData(packages, data, path)
-                       if err != nil {
-                               return
-                       }
-               }
-
        default:
                // Indexed format is distinguished by an 'i' byte,
                // whereas previous export formats started with 'c', 'd', or 'v'.
index d0d95451ac0d35244a98fc39b26fc0ac64377479..1db9618d96dba93f0ef3bf9e58be7938c824400d 100644 (file)
@@ -73,13 +73,7 @@ func LoadPackage(filenames []string) {
        }
        base.Timer.AddEvent(int64(lines), "lines")
 
-       if base.Debug.Unified != 0 {
-               unified(noders)
-               return
-       }
-
-       // Use types2 to type-check and generate IR.
-       check2(noders)
+       unified(noders)
 }
 
 func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
index bd15729171e37f0f55be83d66fe2e1077f53131f..bdec467f90ab72286f95c624aa6346b42c811aa4 100644 (file)
@@ -3688,11 +3688,6 @@ func (r *reader) importedDef() bool {
 }
 
 func MakeWrappers(target *ir.Package) {
-       // Only unified IR emits its own wrappers.
-       if base.Debug.Unified == 0 {
-               return
-       }
-
        // always generate a wrapper for error.Error (#29304)
        needWrapperTypes = append(needWrapperTypes, types.ErrorType)
 
index 99461cff52bacdd20ae941fb4e74be808806e2f6..f2d69cd256e9e8dcd84c556beb82ed0a0494ba87 100644 (file)
@@ -21,7 +21,7 @@ func hasRType(n, rtype ir.Node, fieldName string) bool {
        // gets confused by implicit conversions. Also, because
        // package-scope statements can never be generic, so they'll never
        // require dictionary lookups.
-       if base.Debug.Unified != 0 && ir.CurFunc.Nname.Sym().Name != "init" {
+       if ir.CurFunc.Nname.Sym().Name != "init" {
                ir.Dump("CurFunc", ir.CurFunc)
                base.FatalfAt(n.Pos(), "missing %s in %v: %+v", fieldName, ir.CurFunc, n)
        }
index 088a879175714a94dc69bdaa152f5845383fabc3..6746ac90676d47707b06e1817ccf32a66409425c 100644 (file)
@@ -16,8 +16,6 @@ import (
        "cmd/compile/internal/base"
        "cmd/compile/internal/bitvec"
        "cmd/compile/internal/compare"
-       "cmd/compile/internal/escape"
-       "cmd/compile/internal/inline"
        "cmd/compile/internal/ir"
        "cmd/compile/internal/objw"
        "cmd/compile/internal/typebits"
@@ -1868,199 +1866,14 @@ func NeedEmit(typ *types.Type) bool {
 //
 // These wrappers are always fully stenciled.
 func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym {
-       orig := rcvr
        if forItab && !types.IsDirectIface(rcvr) {
                rcvr = rcvr.PtrTo()
        }
 
-       generic := false
-       // We don't need a dictionary if we are reaching a method (possibly via an
-       // embedded field) which is an interface method.
-       if !types.IsInterfaceMethod(method.Type) {
-               rcvr1 := deref(rcvr)
-               if len(rcvr1.RParams()) > 0 {
-                       // If rcvr has rparams, remember method as generic, which
-                       // means we need to add a dictionary to the wrapper.
-                       generic = true
-                       if rcvr.HasShape() {
-                               base.Fatalf("method on type instantiated with shapes, rcvr:%+v", rcvr)
-                       }
-               }
-       }
-
        newnam := ir.MethodSym(rcvr, method.Sym)
        lsym := newnam.Linksym()
 
        // Unified IR creates its own wrappers.
-       if base.Debug.Unified != 0 {
-               return lsym
-       }
-
-       if newnam.Siggen() {
-               return lsym
-       }
-       newnam.SetSiggen(true)
-
-       methodrcvr := method.Type.Recv().Type
-       // For generic methods, we need to generate the wrapper even if the receiver
-       // types are identical, because we want to add the dictionary.
-       if !generic && types.Identical(rcvr, methodrcvr) {
-               return lsym
-       }
-
-       if !NeedEmit(rcvr) || rcvr.IsPtr() && !NeedEmit(rcvr.Elem()) {
-               return lsym
-       }
-
-       base.Pos = base.AutogeneratedPos
-       typecheck.DeclContext = ir.PEXTERN
-
-       // TODO(austin): SelectorExpr may have created one or more
-       // ir.Names for these already with a nil Func field. We should
-       // consolidate these and always attach a Func to the Name.
-       fn := typecheck.DeclFunc(newnam, ir.NewField(base.Pos, typecheck.Lookup(".this"), rcvr),
-               typecheck.NewFuncParams(method.Type.Params(), true),
-               typecheck.NewFuncParams(method.Type.Results(), false))
-
-       fn.SetDupok(true)
-
-       nthis := ir.AsNode(fn.Type().Recv().Nname)
-
-       indirect := rcvr.IsPtr() && rcvr.Elem() == methodrcvr
-
-       // generate nil pointer check for better error
-       if indirect {
-               // generating wrapper from *T to T.
-               n := ir.NewIfStmt(base.Pos, nil, nil, nil)
-               n.Cond = ir.NewBinaryExpr(base.Pos, ir.OEQ, nthis, typecheck.NodNil())
-               call := ir.NewCallExpr(base.Pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)
-               n.Body = []ir.Node{call}
-               fn.Body.Append(n)
-       }
-
-       dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym))
-       // generate call
-       // It's not possible to use a tail call when dynamic linking on ppc64le. The
-       // bad scenario is when a local call is made to the wrapper: the wrapper will
-       // call the implementation, which might be in a different module and so set
-       // the TOC to the appropriate value for that module. But if it returns
-       // directly to the wrapper's caller, nothing will reset it to the correct
-       // value for that function.
-       var call *ir.CallExpr
-       if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic {
-               call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
-               call.Args = ir.ParamNames(fn.Type())
-               call.IsDDD = fn.Type().IsVariadic()
-               fn.Body.Append(ir.NewTailCallStmt(base.Pos, call))
-       } else {
-               fn.SetWrapper(true) // ignore frame for panic+recover matching
-
-               if generic && dot.X != nthis {
-                       // If there is embedding involved, then we should do the
-                       // normal non-generic embedding wrapper below, which calls
-                       // the wrapper for the real receiver type using dot as an
-                       // argument. There is no need for generic processing (adding
-                       // a dictionary) for this wrapper.
-                       generic = false
-               }
-
-               if generic {
-                       targs := deref(rcvr).RParams()
-                       // The wrapper for an auto-generated pointer/non-pointer
-                       // receiver method should share the same dictionary as the
-                       // corresponding original (user-written) method.
-                       baseOrig := orig
-                       if baseOrig.IsPtr() && !methodrcvr.IsPtr() {
-                               baseOrig = baseOrig.Elem()
-                       } else if !baseOrig.IsPtr() && methodrcvr.IsPtr() {
-                               baseOrig = types.NewPtr(baseOrig)
-                       }
-                       args := []ir.Node{getDictionary(ir.MethodSym(baseOrig, method.Sym), targs)}
-                       if indirect {
-                               args = append(args, ir.NewStarExpr(base.Pos, dot.X))
-                       } else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() {
-                               // Case where method call is via a non-pointer
-                               // embedded field with a pointer method.
-                               args = append(args, typecheck.NodAddrAt(base.Pos, dot.X))
-                       } else {
-                               args = append(args, dot.X)
-                       }
-                       args = append(args, ir.ParamNames(fn.Type())...)
-
-                       // Target method uses shaped names.
-                       targs2 := make([]*types.Type, len(targs))
-                       origRParams := deref(orig).OrigType().RParams()
-                       for i, t := range targs {
-                               targs2[i] = typecheck.Shapify(t, i, origRParams[i])
-                       }
-                       targs = targs2
-
-                       sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true)
-                       if sym.Def == nil {
-                               // Currently we make sure that we have all the
-                               // instantiations we need by generating them all in
-                               // ../noder/stencil.go:instantiateMethods
-                               // Extra instantiations because of an inlined function
-                               // should have been exported, and so available via
-                               // Resolve.
-                               in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
-                               if in.Op() == ir.ONONAME {
-                                       base.Fatalf("instantiation %s not found", sym.Name)
-                               }
-                               sym = in.Sym()
-                       }
-                       target := ir.AsNode(sym.Def)
-                       call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args)
-                       // Fill-in the generic method node that was not filled in
-                       // in instantiateMethod.
-                       method.Nname = fn.Nname
-               } else {
-                       call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
-                       call.Args = ir.ParamNames(fn.Type())
-               }
-               call.IsDDD = fn.Type().IsVariadic()
-               if method.Type.NumResults() > 0 {
-                       ret := ir.NewReturnStmt(base.Pos, nil)
-                       ret.Results = []ir.Node{call}
-                       fn.Body.Append(ret)
-               } else {
-                       fn.Body.Append(call)
-               }
-       }
-
-       typecheck.FinishFuncBody()
-       if base.Debug.DclStack != 0 {
-               types.CheckDclstack()
-       }
-
-       typecheck.Func(fn)
-       ir.CurFunc = fn
-       typecheck.Stmts(fn.Body)
-
-       if AfterGlobalEscapeAnalysis {
-               // Inlining the method may reveal closures, which require walking all function bodies
-               // to decide whether to capture free variables by value or by ref. So we only do inline
-               // if the method do not contain any closures, otherwise, the escape analysis may make
-               // dead variables resurrected, and causing liveness analysis confused, see issue #53702.
-               var canInline bool
-               switch x := call.X.(type) {
-               case *ir.Name:
-                       canInline = len(x.Func.Closures) == 0
-               case *ir.SelectorExpr:
-                       if x.Op() == ir.OMETHEXPR {
-                               canInline = x.FuncName().Func != nil && len(x.FuncName().Func.Closures) == 0
-                       }
-               }
-               if canInline {
-                       // TODO(prattmic): plumb PGO.
-                       inline.InlineCalls(fn, nil)
-               }
-               escape.Batch([]*ir.Func{fn}, false)
-       }
-
-       ir.CurFunc = nil
-       typecheck.Target.Decls = append(typecheck.Target.Decls, fn)
-
        return lsym
 }
 
index a9d33b6b0a667c80c06a019e55cb81eb3233091f..268c4c41db6cd50fa8f15b4cd6eb88e9feb6f28a 100644 (file)
@@ -9,7 +9,6 @@ import (
        "bytes"
        "flag"
        "fmt"
-       "internal/buildcfg"
        "internal/testenv"
        "os"
        "path/filepath"
@@ -84,7 +83,7 @@ func TestDebugLinesPushback(t *testing.T) {
 
        case "arm64", "amd64": // register ABI
                fn := "(*List[go.shape.int_0]).PushBack"
-               if buildcfg.Experiment.Unified {
+               if true /* was buildcfg.Experiment.Unified */ {
                        // Unified mangles differently
                        fn = "(*List[go.shape.int]).PushBack"
                }
@@ -101,7 +100,7 @@ func TestDebugLinesConvert(t *testing.T) {
 
        case "arm64", "amd64": // register ABI
                fn := "G[go.shape.int_0]"
-               if buildcfg.Experiment.Unified {
+               if true /* was buildcfg.Experiment.Unified */ {
                        // Unified mangles differently
                        fn = "G[go.shape.int]"
                }
index bd1bf4114d334ce3ac635cb064dba6bcdee660c0..3747656d5870a6ee613b6daa21bbe62b02d1abaf 100644 (file)
@@ -333,7 +333,7 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
                        return val.Op() == ir.ONIL
                }
 
-               if base.Debug.Unified != 0 && val.Type().HasShape() {
+               if val.Type().HasShape() {
                        // See comment in cmd/compile/internal/walk/convert.go:walkConvInterface
                        return false
                }
index e59104df531c38abd08023bb7829634547ef1eda..eacbe62e68747f79bf175f1c6667839ce8b8ae19 100644 (file)
@@ -6,7 +6,6 @@ package test
 
 import (
        "bufio"
-       "internal/buildcfg"
        "internal/goexperiment"
        "internal/testenv"
        "io"
@@ -235,7 +234,7 @@ func TestIntendedInlining(t *testing.T) {
                // (*Bool).CompareAndSwap is just over budget on 32-bit systems (386, arm).
                want["sync/atomic"] = append(want["sync/atomic"], "(*Bool).CompareAndSwap")
        }
-       if buildcfg.Experiment.Unified {
+       if true /* was buildcfg.Experiment.Unified */ {
                // Non-unified IR does not report "inlining call ..." for atomic.Pointer[T]'s methods.
                // TODO(cuonglm): remove once non-unified IR frontend gone.
                want["sync/atomic"] = append(want["sync/atomic"], "(*Pointer[go.shape.int]).CompareAndSwap")
index f14d885564230b4345c8da85591915a454289b15..a4a507dfecaba5e39cfd78871747a28c62c8281d 100644 (file)
@@ -336,27 +336,6 @@ func (p *crawler) markInlBody(n *ir.Name) {
                        } else {
                                p.checkForFullyInst(t)
                        }
-                       if base.Debug.Unified == 0 {
-                               // If a method of un-exported type is promoted and accessible by
-                               // embedding in an exported type, it makes that type reachable.
-                               //
-                               // Example:
-                               //
-                               //     type t struct {}
-                               //     func (t) M() {}
-                               //
-                               //     func F() interface{} { return struct{ t }{} }
-                               //
-                               // We generate the wrapper for "struct{ t }".M, and inline call
-                               // to "struct{ t }".M, which makes "t.M" reachable.
-                               if t.IsStruct() {
-                                       for _, f := range t.FieldSlice() {
-                                               if f.Embedded != 0 {
-                                                       p.markEmbed(f.Type)
-                                               }
-                                       }
-                               }
-                       }
                }
 
                switch n.Op() {
index bfe27cb60d054c738a15c18029ba6abadff9ba0b..96ad6af42da27ff9f7abb4bb97b1000173dd972e 100644 (file)
@@ -382,7 +382,7 @@ func Assignop1(src, dst *types.Type) (ir.Op, string) {
                        // don't have the methods for them.
                        return ir.OCONVIFACE, ""
                }
-               if base.Debug.Unified != 0 && src.HasShape() {
+               if src.HasShape() {
                        // Unified IR uses OCONVIFACE for converting all derived types
                        // to interface type, not just type arguments themselves.
                        return ir.OCONVIFACE, ""
index 590c9a3ad46cf8d889e9f59fcc7f7c4f42b9a1fe..42750c21256f0701bd3f3b34851e7a6786efb968 100644 (file)
@@ -217,7 +217,6 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Name {
                base.Fatalf("methodValueWrapper: unexpected %v (%v)", dot, dot.Op())
        }
 
-       t0 := dot.Type()
        meth := dot.Sel
        rcvrtype := dot.X.Type()
        sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm")
@@ -227,48 +226,6 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Name {
        }
        sym.SetUniq(true)
 
-       if base.Debug.Unified != 0 {
-               base.FatalfAt(dot.Pos(), "missing wrapper for %v", meth)
-       }
-
-       savecurfn := ir.CurFunc
-       saveLineNo := base.Pos
-       ir.CurFunc = nil
-
-       base.Pos = base.AutogeneratedPos
-
-       fn := typecheck.DeclFunc(sym, nil,
-               typecheck.NewFuncParams(t0.Params(), true),
-               typecheck.NewFuncParams(t0.Results(), false))
-       fn.SetDupok(true)
-       fn.SetWrapper(true)
-
-       // Declare and initialize variable holding receiver.
-       ptr := ir.NewHiddenParam(base.Pos, fn, typecheck.Lookup(".this"), rcvrtype)
-
-       call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil)
-       call.Args = ir.ParamNames(fn.Type())
-       call.IsDDD = fn.Type().IsVariadic()
-
-       var body ir.Node = call
-       if t0.NumResults() != 0 {
-               ret := ir.NewReturnStmt(base.Pos, nil)
-               ret.Results = []ir.Node{call}
-               body = ret
-       }
-
-       fn.Body = []ir.Node{body}
-       typecheck.FinishFuncBody()
-
-       typecheck.Func(fn)
-       // Need to typecheck the body of the just-generated wrapper.
-       // typecheckslice() requires that Curfn is set when processing an ORETURN.
-       ir.CurFunc = fn
-       typecheck.Stmts(fn.Body)
-       sym.Def = fn.Nname
-       typecheck.Target.Decls = append(typecheck.Target.Decls, fn)
-       ir.CurFunc = savecurfn
-       base.Pos = saveLineNo
-
-       return fn.Nname
+       base.FatalfAt(dot.Pos(), "missing wrapper for %v", meth)
+       panic("unreachable")
 }
index bf06ed6f4679b7c54edde99b91f588681588e23e..629dd9af4fec395a0d68d28275659b201fa57671 100644 (file)
@@ -45,7 +45,7 @@ func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
        toType := n.Type()
        if !fromType.IsInterface() && !ir.IsBlank(ir.CurFunc.Nname) {
                // skip unnamed functions (func _())
-               if base.Debug.Unified != 0 && fromType.HasShape() {
+               if fromType.HasShape() {
                        // Unified IR uses OCONVIFACE for converting all derived types
                        // to interface type. Avoid assertion failure in
                        // MarkTypeUsedInInterface, because we've marked used types
index 7d0033f1d12bcb4dacc60d191a4cf0fada3f6516..4dca2e20d61c5a4927e6964bdd343d0c3a3a5163 100644 (file)
@@ -8,7 +8,6 @@ import (
        "bufio"
        "bytes"
        "debug/macho"
-       "internal/buildcfg"
        "internal/platform"
        "internal/testenv"
        "os"
@@ -1094,7 +1093,7 @@ func TestUnlinkableObj(t *testing.T) {
        testenv.MustHaveGoBuild(t)
        t.Parallel()
 
-       if buildcfg.Experiment.Unified {
+       if true /* was buildcfg.Experiment.Unified */ {
                t.Skip("TODO(mdempsky): Fix ICE when importing unlinkable objects for GOEXPERIMENT=unified")
        }
 
index 142efd30f46e67190f6b3626c4158f8dc53dee92..e5c50f687ba7586fb5937b2e9d879e1d97772442 100644 (file)
@@ -7,7 +7,6 @@ package importer
 import (
        "go/build"
        "go/token"
-       "internal/buildcfg"
        "internal/testenv"
        "io"
        "os"
@@ -68,7 +67,7 @@ func TestForCompiler(t *testing.T) {
                // support for it in unified IR. It's not clear that we actually
                // need to support importing "math/big" as "math/bigger", for
                // example. cmd/link no longer supports that.
-               if buildcfg.Experiment.Unified {
+               if true /* was buildcfg.Experiment.Unified */ {
                        t.Skip("not supported by GOEXPERIMENT=unified; see go.dev/cl/406319")
                }
 
index f2202ab478849807cab1ef6607d4af03ddeed3b4..3270f3d68292a57b85c73d914a191d1b25f8eb7c 100644 (file)
@@ -7,7 +7,6 @@ package gcimporter_test
 import (
        "bytes"
        "fmt"
-       "internal/goexperiment"
        "internal/goroot"
        "internal/testenv"
        "os"
@@ -108,7 +107,7 @@ func TestImportTestdata(t *testing.T) {
                "exports.go":  {"go/ast", "go/token"},
                "generics.go": nil,
        }
-       if goexperiment.Unified {
+       if true /* was goexperiment.Unified */ {
                // TODO(mdempsky): Fix test below to flatten the transitive
                // Package.Imports graph. Unified IR is more precise about
                // recreating the package import graph.
@@ -168,17 +167,6 @@ func TestImportTypeparamTests(t *testing.T) {
                t.Fatal(err)
        }
 
-       var skip map[string]string
-       if !goexperiment.Unified {
-               // The Go 1.18 frontend still fails several cases.
-               skip = map[string]string{
-                       "equal.go":      "inconsistent embedded sorting", // TODO(rfindley): investigate this.
-                       "nested.go":     "fails to compile",              // TODO(rfindley): investigate this.
-                       "issue47631.go": "can not handle local type declarations",
-                       "issue55101.go": "fails to compile",
-               }
-       }
-
        for _, entry := range list {
                if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
                        // For now, only consider standalone go files.
@@ -186,10 +174,6 @@ func TestImportTypeparamTests(t *testing.T) {
                }
 
                t.Run(entry.Name(), func(t *testing.T) {
-                       if reason, ok := skip[entry.Name()]; ok {
-                               t.Skip(reason)
-                       }
-
                        filename := filepath.Join(rootDir, entry.Name())
                        src, err := os.ReadFile(filename)
                        if err != nil {
index 71f8f5648d4c2d12bd240c3afafcc55182af026b..513070c8af7b57afbe2ea30fb27d625fbb278d6c 100644 (file)
@@ -70,7 +70,6 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) {
        baseline := goexperiment.Flags{
                RegabiWrappers:   regabiSupported,
                RegabiArgs:       regabiSupported,
-               Unified:          true,
                CoverageRedesign: true,
        }
 
diff --git a/src/internal/goexperiment/exp_unified_off.go b/src/internal/goexperiment/exp_unified_off.go
deleted file mode 100644 (file)
index 4c16fd8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// Code generated by mkconsts.go. DO NOT EDIT.
-
-//go:build !goexperiment.unified
-// +build !goexperiment.unified
-
-package goexperiment
-
-const Unified = false
-const UnifiedInt = 0
diff --git a/src/internal/goexperiment/exp_unified_on.go b/src/internal/goexperiment/exp_unified_on.go
deleted file mode 100644 (file)
index 2b17ba3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// Code generated by mkconsts.go. DO NOT EDIT.
-
-//go:build goexperiment.unified
-// +build goexperiment.unified
-
-package goexperiment
-
-const Unified = true
-const UnifiedInt = 1
index 02e744362c30d599e68738e98b094946ce1117d0..8292f97b719314b068a7a0211b8b94e0fc896051 100644 (file)
@@ -60,10 +60,6 @@ type Flags struct {
        StaticLockRanking bool
        BoringCrypto      bool
 
-       // Unified enables the compiler's unified IR construction
-       // experiment.
-       Unified bool
-
        // Regabi is split into several sub-experiments that can be
        // enabled individually. Not all combinations work.
        // The "regabi" GOEXPERIMENT is an alias for all "working"
diff --git a/test/escape_iface_nounified.go b/test/escape_iface_nounified.go
deleted file mode 100644 (file)
index 1d267bc..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// errorcheck -0 -m -l
-//go:build !goexperiment.unified
-// +build !goexperiment.unified
-
-// 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.
-
-package escape
-
-var sink interface{}
-
-func dotTypeEscape2() { // #13805, #15796
-       {
-               i := 0
-               j := 0
-               var ok bool
-               var x interface{} = i // ERROR "i does not escape"
-               var y interface{} = j // ERROR "j does not escape"
-
-               sink = x.(int) // ERROR "x.\(int\) escapes to heap"
-               // BAD: should be "y.\(int\) escapes to heap" too
-               sink, *(&ok) = y.(int)
-       }
-}
index 80222dae5fe035cf92472f7d658c2cd30288d10f..80dc80ca7ba70d4e410dff230343e30efd6e6f92 100644 (file)
@@ -1,6 +1,4 @@
 // errorcheck -0 -m -l
-//go:build goexperiment.unified
-// +build goexperiment.unified
 
 // Copyright 2015 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
index 28cb43df3bab447283dd740000df438055de80dc..3a0b6049fd55882b213a6962aed85cdb575a197b 100644 (file)
@@ -1,8 +1,5 @@
 // run
-//go:build goexperiment.unified && cgo
-
-// TODO(mdempsky): Enable test unconditionally. This test should pass
-// for non-unified mode too.
+//go:build cgo
 
 // Copyright 2021 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
index dc444b889a1153fc05a5e2e406613ec960618506..f366a44183fd3b2c505213b256af30ba033ede0f 100644 (file)
@@ -1,5 +1,4 @@
 // compile
-//go:build goexperiment.unified
 
 // Copyright 2022 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/inline_nounified.go b/test/inline_nounified.go
deleted file mode 100644 (file)
index 7a9fc10..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1
-//go:build !goexperiment.unified
-// +build !goexperiment.unified
-
-// Copyright 2022 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.
-
-package foo
-
-func r(z int) int {
-       foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape"
-               return x + z
-       }
-       bar := func(x int) int { // ERROR "func literal does not escape" "can inline r.func2"
-               return x + func(y int) int { // ERROR "can inline r.func2.1" "can inline r.func3"
-                       return 2*y + x*z
-               }(x) // ERROR "inlining call to r.func2.1"
-       }
-       return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "inlining call to r.func3"
-}
index 5dc43ab070cd36049206c43a2645a86bca78c01f..dad11827d79d74c2c353d9196b2f717d7139aaf8 100644 (file)
@@ -1,6 +1,4 @@
 // errorcheckwithauto -0 -m -d=inlfuncswithclosures=1
-//go:build goexperiment.unified
-// +build goexperiment.unified
 
 // Copyright 2022 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
index 9a18f136721495cb89e1552eb9add86cdc5c91f8..8eff84d92de9e2eb1116eaccd2198c3c1d4d5717 100644 (file)
@@ -76,15 +76,6 @@ var env = func() (res envVars) {
        return
 }()
 
-var unifiedEnabled = func() bool {
-       for _, tag := range build.Default.ToolTags {
-               if tag == "goexperiment.unified" {
-                       return true
-               }
-       }
-       return false
-}()
-
 // defaultAllCodeGen returns the default value of the -all_codegen
 // flag. By default, we prefer to be fast (returning false), except on
 // the linux-amd64 builder that's already very fast, so we get more
@@ -374,10 +365,6 @@ func (t *test) initExpectFail() {
                failureSets = append(failureSets, types2Failures32Bit)
        }
 
-       if !unifiedEnabled {
-               failureSets = append(failureSets, go118Failures)
-       }
-
        filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows
 
        for _, set := range failureSets {
@@ -2037,21 +2024,6 @@ var types2Failures32Bit = setOf(
        "fixedbugs/issue23305.go", // large untyped int passed to println (32-bit)
 )
 
-var go118Failures = setOf(
-       "fixedbugs/issue54343.go",  // 1.18 compiler assigns receiver parameter to global variable
-       "fixedbugs/issue56280.go",  // 1.18 compiler doesn't support inlining generic functions
-       "typeparam/nested.go",      // 1.18 compiler doesn't support function-local types with generics
-       "typeparam/issue47631.go",  // 1.18 can not handle local type declarations
-       "typeparam/issue51521.go",  // 1.18 compiler produces bad panic message and link error
-       "typeparam/issue54456.go",  // 1.18 compiler fails to distinguish local generic types
-       "typeparam/issue54497.go",  // 1.18 compiler is more conservative about inlining due to repeated issues
-       "typeparam/issue55101.go",  // 1.18 compiler ICEs writing export data
-       "typeparam/mdempsky/16.go", // 1.18 compiler uses interface shape type in failed type assertions
-       "typeparam/mdempsky/17.go", // 1.18 compiler mishandles implicit conversions from range loops
-       "typeparam/mdempsky/18.go", // 1.18 compiler mishandles implicit conversions in select statements
-       "typeparam/mdempsky/20.go", // 1.18 compiler crashes on method expressions promoted to derived types
-)
-
 // In all of these cases, the 1.17 compiler reports reasonable errors, but either the
 // 1.17 or 1.18 compiler report extra errors, so we can't match correctly on both. We
 // now set the patterns to match correctly on all the 1.18 errors.