diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go
index 54b07c39f4940516cc047b4a5b9dd70ba575bd31..f391339c365047e6664baafb5c83b87119b00e6e 100644
--- a/src/cmd/compile/internal/noder/expr.go
+++ b/src/cmd/compile/internal/noder/expr.go
@@ -27,10 +27,7 @@ func (g *irgen) expr(expr syntax.Expr) ir.Node {
 		return ir.BlankNode
 	}
 
-	tv, ok := g.info.Types[expr]
-	if !ok {
-		base.FatalfAt(g.pos(expr), "missing type for %v (%T)", expr, expr)
-	}
+	tv := g.typeAndValue(expr)
 	switch {
 	case tv.IsBuiltin():
 		// Qualified builtins, such as unsafe.Add and unsafe.Slice.
@@ -105,8 +102,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
 	case *syntax.IndexExpr:
 		args := unpackListExpr(expr.Index)
 		if len(args) == 1 {
-			tv, ok := g.info.Types[args[0]]
-			assert(ok)
+			tv := g.typeAndValue(args[0])
 			if tv.IsValue() {
 				// This is just a normal index expression
 				n := Index(pos, g.typ(typ), g.expr(expr.X), g.expr(args[0]))
diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go
index bf471e08fa076efe0a5463d5cba09def5244b1be..e867594620d72b2e5671a6209c19c245059ea85b 100644
--- a/src/cmd/compile/internal/noder/irgen.go
+++ b/src/cmd/compile/internal/noder/irgen.go
@@ -390,3 +390,19 @@ func (g *irgen) unhandled(what string, p poser) {
 func (g *irgen) delayTransform() bool {
 	return g.topFuncIsGeneric
 }
+
+func (g *irgen) typeAndValue(x syntax.Expr) types2.TypeAndValue {
+	tv, ok := g.info.Types[x]
+	if !ok {
+		base.FatalfAt(g.pos(x), "missing type for %v (%T)", x, x)
+	}
+	return tv
+}
+
+func (g *irgen) type2(x syntax.Expr) types2.Type {
+	tv, ok := g.info.Types[x]
+	if !ok {
+		base.FatalfAt(g.pos(x), "missing type for %v (%T)", x, x)
+	}
+	return tv.Type
+}
diff --git a/src/cmd/compile/internal/noder/validate.go b/src/cmd/compile/internal/noder/validate.go
index dcacae7480c2975c50182aeb72d46d31e374d4f4..baf8bd307678a8cc2a42794ebafe744971e30298 100644
--- a/src/cmd/compile/internal/noder/validate.go
+++ b/src/cmd/compile/internal/noder/validate.go
@@ -53,7 +53,7 @@ func (g *irgen) match(t1 *types.Type, t2 types2.Type, hasOK bool) bool {
 func (g *irgen) validate(n syntax.Node) {
 	switch n := n.(type) {
 	case *syntax.CallExpr:
-		tv := g.info.Types[n.Fun]
+		tv := g.typeAndValue(n.Fun)
 		if tv.IsBuiltin() {
 			fun := n.Fun
 			for {
@@ -81,7 +81,7 @@ func (g *irgen) validateBuiltin(name string, call *syntax.CallExpr) {
 		// Check that types2+gcSizes calculates sizes the same
 		// as cmd/compile does.
 
-		tv := g.info.Types[call]
+		tv := g.typeAndValue(call)
 		if !tv.IsValue() {
 			base.FatalfAt(g.pos(call), "expected a value")
 		}
@@ -106,9 +106,9 @@ func (g *irgen) validateBuiltin(name string, call *syntax.CallExpr) {
 func (g *irgen) unsafeExpr(name string, arg syntax.Expr) int64 {
 	switch name {
 	case "Alignof":
-		return g.typ(g.info.Types[arg].Type).Alignment()
+		return g.typ(g.type2(arg)).Alignment()
 	case "Sizeof":
-		return g.typ(g.info.Types[arg].Type).Size()
+		return g.typ(g.type2(arg)).Size()
 	}
 
 	// Offsetof
@@ -116,7 +116,7 @@ func (g *irgen) unsafeExpr(name string, arg syntax.Expr) int64 {
 	sel := arg.(*syntax.SelectorExpr)
 	selection := g.info.Selections[sel]
 
-	typ := g.typ(g.info.Types[sel.X].Type)
+	typ := g.typ(g.type2(sel.X))
 	typ = deref(typ)
 
 	var offset int64
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index 198bae71903da00b8b9b744dd2a0fa52ff35cadc..b39a57a13f4ae82f7b0d9563d71d8c5946edf58d 100644
--- a/src/cmd/compile/internal/noder/writer.go
+++ b/src/cmd/compile/internal/noder/writer.go
@@ -120,12 +120,21 @@ func (pw *pkgWriter) unexpected(what string, p poser) {
 	pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
 }
 
-// typeOf returns the Type of the given value expression.
-func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type {
-	tv, ok := pw.info.Types[expr]
+func (pw *pkgWriter) typeAndValue(x syntax.Expr) types2.TypeAndValue {
+	tv, ok := pw.info.Types[x]
 	if !ok {
-		pw.fatalf(expr, "missing Types entry: %v", syntax.String(expr))
+		pw.fatalf(x, "missing Types entry: %v", syntax.String(x))
 	}
+	return tv
+}
+func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (types2.TypeAndValue, bool) {
+	tv, ok := pw.info.Types[x]
+	return tv, ok
+}
+
+// typeOf returns the Type of the given value expression.
+func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type {
+	tv := pw.typeAndValue(expr)
 	if !tv.IsValue() {
 		pw.fatalf(expr, "expected value: %v", syntax.String(expr))
 	}
@@ -811,8 +820,7 @@ func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
 //
 // TODO(mdempsky): Document how this differs from exprType.
 func (w *writer) typExpr(expr syntax.Expr) {
-	tv, ok := w.p.info.Types[expr]
-	assert(ok)
+	tv := w.p.typeAndValue(expr)
 	assert(tv.IsType())
 	w.typ(tv.Type)
 }
@@ -1533,7 +1541,7 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
 		if iface != nil {
 			w.Len(len(cases))
 			for _, cas := range cases {
-				if w.Bool(isNil(w.p.info, cas)) {
+				if w.Bool(isNil(w.p, cas)) {
 					continue
 				}
 				w.exprType(iface, cas)
@@ -1598,10 +1606,10 @@ func (w *writer) expr(expr syntax.Expr) {
 
 	expr = unparen(expr) // skip parens; unneeded after typecheck
 
-	obj, inst := lookupObj(w.p.info, expr)
+	obj, inst := lookupObj(w.p, expr)
 	targs := inst.TypeArgs
 
-	if tv, ok := w.p.info.Types[expr]; ok {
+	if tv, ok := w.p.maybeTypeAndValue(expr); ok {
 		if tv.IsType() {
 			w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
 		}
@@ -1698,8 +1706,7 @@ func (w *writer) expr(expr syntax.Expr) {
 		case types2.MethodExpr:
 			w.Code(exprMethodExpr)
 
-			tv, ok := w.p.info.Types[expr.X]
-			assert(ok)
+			tv := w.p.typeAndValue(expr.X)
 			assert(tv.IsType())
 
 			index := sel.Index()
@@ -1793,8 +1800,7 @@ func (w *writer) expr(expr syntax.Expr) {
 		w.implicitConvExpr(commonType, expr.Y)
 
 	case *syntax.CallExpr:
-		tv, ok := w.p.info.Types[expr.Fun]
-		assert(ok)
+		tv := w.p.typeAndValue(expr.Fun)
 		if tv.IsType() {
 			assert(len(expr.ArgList) == 1)
 			assert(!expr.HasDots)
@@ -1804,7 +1810,7 @@ func (w *writer) expr(expr syntax.Expr) {
 
 		var rtype types2.Type
 		if tv.IsBuiltin() {
-			switch obj, _ := lookupObj(w.p.info, expr.Fun); obj.Name() {
+			switch obj, _ := lookupObj(w.p, expr.Fun); obj.Name() {
 			case "make":
 				assert(len(expr.ArgList) >= 1)
 				assert(!expr.HasDots)
@@ -1870,7 +1876,7 @@ func (w *writer) expr(expr syntax.Expr) {
 
 			w.Bool(false) // not a method call (i.e., normal function call)
 
-			if obj, inst := lookupObj(w.p.info, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
+			if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
 				obj := obj.(*types2.Func)
 
 				w.pos(fun)
@@ -2244,8 +2250,7 @@ func (w *writer) convRTTI(src, dst types2.Type) {
 func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
 	base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)
 
-	tv, ok := w.p.info.Types[typ]
-	assert(ok)
+	tv := w.p.typeAndValue(typ)
 	assert(tv.IsType())
 
 	w.Sync(pkgbits.SyncExprType)
@@ -2597,12 +2602,11 @@ func isGlobal(obj types2.Object) bool {
 // lookupObj returns the object that expr refers to, if any. If expr
 // is an explicit instantiation of a generic object, then the instance
 // object is returned as well.
-func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
+func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
 	if index, ok := expr.(*syntax.IndexExpr); ok {
 		args := unpackListExpr(index.Index)
 		if len(args) == 1 {
-			tv, ok := info.Types[args[0]]
-			assert(ok)
+			tv := p.typeAndValue(args[0])
 			if tv.IsValue() {
 				return // normal index expression
 			}
@@ -2613,15 +2617,15 @@ func lookupObj(info *types2.Info, expr syntax.Expr) (obj types2.Object, inst typ
 
 	// Strip package qualifier, if present.
 	if sel, ok := expr.(*syntax.SelectorExpr); ok {
-		if !isPkgQual(info, sel) {
+		if !isPkgQual(p.info, sel) {
 			return // normal selector expression
 		}
 		expr = sel.Sel
 	}
 
 	if name, ok := expr.(*syntax.Name); ok {
-		obj = info.Uses[name]
-		inst = info.Instances[name]
+		obj = p.info.Uses[name]
+		inst = p.info.Instances[name]
 	}
 	return
 }
@@ -2636,24 +2640,10 @@ func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
 	return false
 }
 
-// isMultiValueExpr reports whether expr is a function call expression
-// that yields multiple values.
-func isMultiValueExpr(info *types2.Info, expr syntax.Expr) bool {
-	tv, ok := info.Types[expr]
-	assert(ok)
-	assert(tv.IsValue())
-	if tuple, ok := tv.Type.(*types2.Tuple); ok {
-		assert(tuple.Len() > 1)
-		return true
-	}
-	return false
-}
-
 // isNil reports whether expr is a (possibly parenthesized) reference
 // to the predeclared nil value.
-func isNil(info *types2.Info, expr syntax.Expr) bool {
-	tv, ok := info.Types[expr]
-	assert(ok)
+func isNil(p *pkgWriter, expr syntax.Expr) bool {
+	tv := p.typeAndValue(expr)
 	return tv.IsNil()
 }