Skip to content

Commit 0591876

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 13795fc + 336626b commit 0591876

File tree

11 files changed

+126
-23
lines changed

11 files changed

+126
-23
lines changed

src/cmd/compile/internal/escape/graph.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ type location struct {
7575
captured bool // has a closure captured this variable?
7676
reassigned bool // has this variable been reassigned?
7777
addrtaken bool // has this variable's address been taken?
78+
param bool // is this variable a parameter (ONAME of class ir.PPARAM)?
79+
paramOut bool // is this variable an out parameter (ONAME of class ir.PPARAMOUT)?
7880
}
7981

8082
type locAttr uint8
@@ -281,6 +283,11 @@ func (e *escape) newLoc(n ir.Node, persists bool) *location {
281283
curfn: e.curfn,
282284
loopDepth: e.loopDepth,
283285
}
286+
if loc.isName(ir.PPARAM) {
287+
loc.param = true
288+
} else if loc.isName(ir.PPARAMOUT) {
289+
loc.paramOut = true
290+
}
284291
if persists {
285292
loc.attrs |= attrPersists
286293
}

src/cmd/compile/internal/escape/solve.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location))
126126
// corresponding result parameter, then record
127127
// that value flow for tagging the function
128128
// later.
129-
if l.isName(ir.PPARAM) {
129+
if l.param {
130130
if b.outlives(root, l) {
131131
if !l.hasAttr(attrEscapes) && (logopt.Enabled() || base.Flag.LowerM >= 2) {
132132
if base.Flag.LowerM >= 2 {
@@ -270,7 +270,7 @@ func (b *batch) outlives(l, other *location) bool {
270270
// We don't know what callers do with returned values, so
271271
// pessimistically we need to assume they flow to the heap and
272272
// outlive everything too.
273-
if l.isName(ir.PPARAMOUT) {
273+
if l.paramOut {
274274
// Exception: Closures can return locations allocated outside of
275275
// them without forcing them to the heap, if we can statically
276276
// identify all call sites. For example:

src/cmd/compile/internal/ssa/nilcheck.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,12 @@ func nilcheckelim2(f *Func) {
217217
f.Warnl(v.Pos, "removed nil check")
218218
}
219219
// For bug 33724, policy is that we might choose to bump an existing position
220-
// off the faulting load/store in favor of the one from the nil check.
220+
// off the faulting load in favor of the one from the nil check.
221221

222222
// Iteration order means that first nilcheck in the chain wins, others
223223
// are bumped into the ordinary statement preservation algorithm.
224224
u := b.Values[unnecessary.get(v.Args[0].ID)]
225-
if !u.Pos.SameFileAndLine(v.Pos) {
225+
if !u.Type.IsMemory() && !u.Pos.SameFileAndLine(v.Pos) {
226226
if u.Pos.IsStmt() == src.PosIsStmt {
227227
pendingLines.add(u.Pos)
228228
}

src/cmd/compile/internal/ssagen/ssa.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3469,19 +3469,28 @@ func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value {
34693469

34703470
case ir.OLEN, ir.OCAP:
34713471
n := n.(*ir.UnaryExpr)
3472+
// Note: all constant cases are handled by the frontend. If len or cap
3473+
// makes it here, we want the side effects of the argument. See issue 72844.
3474+
a := s.expr(n.X)
3475+
t := n.X.Type()
34723476
switch {
3473-
case n.X.Type().IsSlice():
3477+
case t.IsSlice():
34743478
op := ssa.OpSliceLen
34753479
if n.Op() == ir.OCAP {
34763480
op = ssa.OpSliceCap
34773481
}
3478-
return s.newValue1(op, types.Types[types.TINT], s.expr(n.X))
3479-
case n.X.Type().IsString(): // string; not reachable for OCAP
3480-
return s.newValue1(ssa.OpStringLen, types.Types[types.TINT], s.expr(n.X))
3481-
case n.X.Type().IsMap(), n.X.Type().IsChan():
3482-
return s.referenceTypeBuiltin(n, s.expr(n.X))
3483-
default: // array
3484-
return s.constInt(types.Types[types.TINT], n.X.Type().NumElem())
3482+
return s.newValue1(op, types.Types[types.TINT], a)
3483+
case t.IsString(): // string; not reachable for OCAP
3484+
return s.newValue1(ssa.OpStringLen, types.Types[types.TINT], a)
3485+
case t.IsMap(), t.IsChan():
3486+
return s.referenceTypeBuiltin(n, a)
3487+
case t.IsArray():
3488+
return s.constInt(types.Types[types.TINT], t.NumElem())
3489+
case t.IsPtr() && t.Elem().IsArray():
3490+
return s.constInt(types.Types[types.TINT], t.Elem().NumElem())
3491+
default:
3492+
s.Fatalf("bad type in len/cap: %v", t)
3493+
return nil
34853494
}
34863495

34873496
case ir.OSPTR:

src/cmd/compile/internal/types2/range.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package types2
88

99
import (
1010
"cmd/compile/internal/syntax"
11+
"go/constant"
1112
"internal/buildcfg"
1213
. "internal/types/errors"
1314
)
@@ -23,8 +24,32 @@ import (
2324
func (check *Checker) rangeStmt(inner stmtContext, rangeStmt *syntax.ForStmt, noNewVarPos poser, sKey, sValue, sExtra, rangeVar syntax.Expr, isDef bool) {
2425
// check expression to iterate over
2526
var x operand
27+
28+
// From the spec:
29+
// The range expression x is evaluated before beginning the loop,
30+
// with one exception: if at most one iteration variable is present
31+
// and x or len(x) is constant, the range expression is not evaluated.
32+
// So we have to be careful not to evaluate the arg in the
33+
// described situation.
34+
35+
check.hasCallOrRecv = false
2636
check.expr(nil, &x, rangeVar)
2737

38+
if isTypes2 && x.mode != invalid && sValue == nil && !check.hasCallOrRecv {
39+
if t, ok := arrayPtrDeref(under(x.typ)).(*Array); ok {
40+
// Override type of rangeVar to be a constant
41+
// (and thus side-effects will not be computed
42+
// by the backend).
43+
check.record(&operand{
44+
mode: constant_,
45+
expr: rangeVar,
46+
typ: Typ[Int],
47+
val: constant.MakeInt64(t.len),
48+
id: x.id,
49+
})
50+
}
51+
}
52+
2853
// determine key/value types
2954
var key, val Type
3055
if x.mode != invalid {

src/cmd/compile/internal/walk/builtin.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,13 @@ func walkLenCap(n *ir.UnaryExpr, init *ir.Nodes) ir.Node {
278278
// replace len(*[10]int) with 10.
279279
// delayed until now to preserve side effects.
280280
t := n.X.Type()
281-
282281
if t.IsPtr() {
283282
t = t.Elem()
284283
}
285284
if t.IsArray() {
286-
safeExpr(n.X, init)
285+
// evaluate any side effects in n.X. See issue 72844.
286+
appendWalkStmt(init, ir.NewAssignStmt(base.Pos, ir.BlankNode, n.X))
287+
287288
con := ir.NewConstExpr(constant.MakeInt64(t.NumElem()), n)
288289
con.SetTypecheck(1)
289290
return con

src/cmd/compile/internal/walk/range.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package walk
66

77
import (
8+
"go/constant"
89
"internal/buildcfg"
910
"unicode/utf8"
1011

@@ -80,6 +81,10 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
8081
base.Fatalf("walkRange")
8182

8283
case types.IsInt[k]:
84+
if nn := arrayRangeClear(nrange, v1, v2, a); nn != nil {
85+
base.Pos = lno
86+
return nn
87+
}
8388
hv1 := typecheck.TempAt(base.Pos, ir.CurFunc, t)
8489
hn := typecheck.TempAt(base.Pos, ir.CurFunc, t)
8590

@@ -519,21 +524,41 @@ func arrayRangeClear(loop *ir.RangeStmt, v1, v2, a ir.Node) ir.Node {
519524
}
520525
lhs := stmt.X.(*ir.IndexExpr)
521526
x := lhs.X
522-
if a.Type().IsPtr() && a.Type().Elem().IsArray() {
523-
if s, ok := x.(*ir.StarExpr); ok && s.Op() == ir.ODEREF {
524-
x = s.X
527+
528+
// Get constant number of iterations for int and array cases.
529+
n := int64(-1)
530+
if ir.IsConst(a, constant.Int) {
531+
n = ir.Int64Val(a)
532+
} else if a.Type().IsArray() {
533+
n = a.Type().NumElem()
534+
} else if a.Type().IsPtr() && a.Type().Elem().IsArray() {
535+
n = a.Type().Elem().NumElem()
536+
}
537+
538+
if n >= 0 {
539+
// Int/Array case.
540+
if !x.Type().IsArray() {
541+
return nil
542+
}
543+
if x.Type().NumElem() != n {
544+
return nil
545+
}
546+
} else {
547+
// Slice case.
548+
if !ir.SameSafeExpr(x, a) {
549+
return nil
525550
}
526551
}
527552

528-
if !ir.SameSafeExpr(x, a) || !ir.SameSafeExpr(lhs.Index, v1) {
553+
if !ir.SameSafeExpr(lhs.Index, v1) {
529554
return nil
530555
}
531556

532557
if !ir.IsZero(stmt.Y) {
533558
return nil
534559
}
535560

536-
return arrayClear(stmt.Pos(), a, loop)
561+
return arrayClear(stmt.Pos(), x, loop)
537562
}
538563

539564
// arrayClear constructs a call to runtime.memclr for fast zeroing of slices and arrays.

src/crypto/internal/fips140/sha512/sha512block_riscv64.s

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,8 @@
138138
#define SHA512ROUND(index, a, b, c, d, e, f, g, h) \
139139
SHA512T1(index, e, f, g, h); \
140140
SHA512T2(a, b, c); \
141-
MOV X6, h; \
142141
ADD X5, d; \
143-
ADD X5, h
142+
ADD X6, X5, h
144143

145144
#define SHA512ROUND0(index, a, b, c, d, e, f, g, h) \
146145
MSGSCHEDULE0(index); \

src/go/types/range.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/codegen/issue52635.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ package codegen
1212
type T struct {
1313
a *[10]int
1414
b [10]int
15+
s []int
1516
}
1617

1718
func (t *T) f() {
@@ -38,4 +39,15 @@ func (t *T) f() {
3839
for i := range *t.a {
3940
(*t.a)[i] = 0
4041
}
42+
43+
// amd64:-".*runtime.memclrNoHeapPointers"
44+
// amd64:"DUFFZERO"
45+
for i := range t.b {
46+
t.b[i] = 0
47+
}
48+
49+
// amd64:".*runtime.memclrNoHeapPointers"
50+
for i := range t.s {
51+
t.s[i] = 0
52+
}
4153
}

0 commit comments

Comments
 (0)