github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/compile/internal/ssa/prove.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa 6 7 import ( 8 "fmt" 9 "math" 10 ) 11 12 type branch int 13 14 const ( 15 unknown branch = iota 16 positive 17 negative 18 ) 19 20 // relation represents the set of possible relations between 21 // pairs of variables (v, w). Without a priori knowledge the 22 // mask is lt | eq | gt meaning v can be less than, equal to or 23 // greater than w. When the execution path branches on the condition 24 // `v op w` the set of relations is updated to exclude any 25 // relation not possible due to `v op w` being true (or false). 26 // 27 // E.g. 28 // 29 // r := relation(...) 30 // 31 // if v < w { 32 // newR := r & lt 33 // } 34 // if v >= w { 35 // newR := r & (eq|gt) 36 // } 37 // if v != w { 38 // newR := r & (lt|gt) 39 // } 40 type relation uint 41 42 const ( 43 lt relation = 1 << iota 44 eq 45 gt 46 ) 47 48 var relationStrings = [...]string{ 49 0: "none", lt: "<", eq: "==", lt | eq: "<=", 50 gt: ">", gt | lt: "!=", gt | eq: ">=", gt | eq | lt: "any", 51 } 52 53 func (r relation) String() string { 54 if r < relation(len(relationStrings)) { 55 return relationStrings[r] 56 } 57 return fmt.Sprintf("relation(%d)", uint(r)) 58 } 59 60 // domain represents the domain of a variable pair in which a set 61 // of relations is known. For example, relations learned for unsigned 62 // pairs cannot be transferred to signed pairs because the same bit 63 // representation can mean something else. 64 type domain uint 65 66 const ( 67 signed domain = 1 << iota 68 unsigned 69 pointer 70 boolean 71 ) 72 73 var domainStrings = [...]string{ 74 "signed", "unsigned", "pointer", "boolean", 75 } 76 77 func (d domain) String() string { 78 s := "" 79 for i, ds := range domainStrings { 80 if d&(1<<uint(i)) != 0 { 81 if len(s) != 0 { 82 s += "|" 83 } 84 s += ds 85 d &^= 1 << uint(i) 86 } 87 } 88 if d != 0 { 89 if len(s) != 0 { 90 s += "|" 91 } 92 s += fmt.Sprintf("0x%x", uint(d)) 93 } 94 return s 95 } 96 97 type pair struct { 98 v, w *Value // a pair of values, ordered by ID. 99 // v can be nil, to mean the zero value. 100 // for booleans the zero value (v == nil) is false. 101 d domain 102 } 103 104 // fact is a pair plus a relation for that pair. 105 type fact struct { 106 p pair 107 r relation 108 } 109 110 // a limit records known upper and lower bounds for a value. 111 type limit struct { 112 min, max int64 // min <= value <= max, signed 113 umin, umax uint64 // umin <= value <= umax, unsigned 114 } 115 116 func (l limit) String() string { 117 return fmt.Sprintf("sm,SM,um,UM=%d,%d,%d,%d", l.min, l.max, l.umin, l.umax) 118 } 119 120 func (l limit) intersect(l2 limit) limit { 121 if l.min < l2.min { 122 l.min = l2.min 123 } 124 if l.umin < l2.umin { 125 l.umin = l2.umin 126 } 127 if l.max > l2.max { 128 l.max = l2.max 129 } 130 if l.umax > l2.umax { 131 l.umax = l2.umax 132 } 133 return l 134 } 135 136 var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64} 137 138 // a limitFact is a limit known for a particular value. 139 type limitFact struct { 140 vid ID 141 limit limit 142 } 143 144 // factsTable keeps track of relations between pairs of values. 145 // 146 // The fact table logic is sound, but incomplete. Outside of a few 147 // special cases, it performs no deduction or arithmetic. While there 148 // are known decision procedures for this, the ad hoc approach taken 149 // by the facts table is effective for real code while remaining very 150 // efficient. 151 type factsTable struct { 152 // unsat is true if facts contains a contradiction. 153 // 154 // Note that the factsTable logic is incomplete, so if unsat 155 // is false, the assertions in factsTable could be satisfiable 156 // *or* unsatisfiable. 157 unsat bool // true if facts contains a contradiction 158 unsatDepth int // number of unsat checkpoints 159 160 facts map[pair]relation // current known set of relation 161 stack []fact // previous sets of relations 162 163 // order is a couple of partial order sets that record information 164 // about relations between SSA values in the signed and unsigned 165 // domain. 166 order [2]*poset 167 168 // known lower and upper bounds on individual values. 169 limits map[ID]limit 170 limitStack []limitFact // previous entries 171 172 // For each slice s, a map from s to a len(s)/cap(s) value (if any) 173 // TODO: check if there are cases that matter where we have 174 // more than one len(s) for a slice. We could keep a list if necessary. 175 lens map[ID]*Value 176 caps map[ID]*Value 177 } 178 179 // checkpointFact is an invalid value used for checkpointing 180 // and restoring factsTable. 181 var checkpointFact = fact{} 182 var checkpointBound = limitFact{} 183 184 func newFactsTable(f *Func) *factsTable { 185 ft := &factsTable{} 186 ft.order[0] = f.newPoset() // signed 187 ft.order[1] = f.newPoset() // unsigned 188 ft.order[0].SetUnsigned(false) 189 ft.order[1].SetUnsigned(true) 190 ft.facts = make(map[pair]relation) 191 ft.stack = make([]fact, 4) 192 ft.limits = make(map[ID]limit) 193 ft.limitStack = make([]limitFact, 4) 194 return ft 195 } 196 197 // update updates the set of relations between v and w in domain d 198 // restricting it to r. 199 func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) { 200 if parent.Func.pass.debug > 2 { 201 parent.Func.Warnl(parent.Pos, "parent=%s, update %s %s %s", parent, v, w, r) 202 } 203 // No need to do anything else if we already found unsat. 204 if ft.unsat { 205 return 206 } 207 208 // Self-fact. It's wasteful to register it into the facts 209 // table, so just note whether it's satisfiable 210 if v == w { 211 if r&eq == 0 { 212 ft.unsat = true 213 } 214 return 215 } 216 217 if d == signed || d == unsigned { 218 var ok bool 219 idx := 0 220 if d == unsigned { 221 idx = 1 222 } 223 switch r { 224 case lt: 225 ok = ft.order[idx].SetOrder(v, w) 226 case gt: 227 ok = ft.order[idx].SetOrder(w, v) 228 case lt | eq: 229 ok = ft.order[idx].SetOrderOrEqual(v, w) 230 case gt | eq: 231 ok = ft.order[idx].SetOrderOrEqual(w, v) 232 case eq: 233 ok = ft.order[idx].SetEqual(v, w) 234 case lt | gt: 235 ok = ft.order[idx].SetNonEqual(v, w) 236 default: 237 panic("unknown relation") 238 } 239 if !ok { 240 if parent.Func.pass.debug > 2 { 241 parent.Func.Warnl(parent.Pos, "unsat %s %s %s", v, w, r) 242 } 243 ft.unsat = true 244 return 245 } 246 } else { 247 if lessByID(w, v) { 248 v, w = w, v 249 r = reverseBits[r] 250 } 251 252 p := pair{v, w, d} 253 oldR, ok := ft.facts[p] 254 if !ok { 255 if v == w { 256 oldR = eq 257 } else { 258 oldR = lt | eq | gt 259 } 260 } 261 // No changes compared to information already in facts table. 262 if oldR == r { 263 return 264 } 265 ft.stack = append(ft.stack, fact{p, oldR}) 266 ft.facts[p] = oldR & r 267 // If this relation is not satisfiable, mark it and exit right away 268 if oldR&r == 0 { 269 if parent.Func.pass.debug > 2 { 270 parent.Func.Warnl(parent.Pos, "unsat %s %s %s", v, w, r) 271 } 272 ft.unsat = true 273 return 274 } 275 } 276 277 // Extract bounds when comparing against constants 278 if v.isGenericIntConst() { 279 v, w = w, v 280 r = reverseBits[r] 281 } 282 if v != nil && w.isGenericIntConst() { 283 // Note: all the +1/-1 below could overflow/underflow. Either will 284 // still generate correct results, it will just lead to imprecision. 285 // In fact if there is overflow/underflow, the corresponding 286 // code is unreachable because the known range is outside the range 287 // of the value's type. 288 old, ok := ft.limits[v.ID] 289 if !ok { 290 old = noLimit 291 if v.isGenericIntConst() { 292 switch d { 293 case signed: 294 old.min, old.max = v.AuxInt, v.AuxInt 295 if v.AuxInt >= 0 { 296 old.umin, old.umax = uint64(v.AuxInt), uint64(v.AuxInt) 297 } 298 case unsigned: 299 old.umin = v.AuxUnsigned() 300 old.umax = old.umin 301 if int64(old.umin) >= 0 { 302 old.min, old.max = int64(old.umin), int64(old.umin) 303 } 304 } 305 } 306 } 307 lim := noLimit 308 switch d { 309 case signed: 310 c := w.AuxInt 311 switch r { 312 case lt: 313 lim.max = c - 1 314 case lt | eq: 315 lim.max = c 316 case gt | eq: 317 lim.min = c 318 case gt: 319 lim.min = c + 1 320 case lt | gt: 321 lim = old 322 if c == lim.min { 323 lim.min++ 324 } 325 if c == lim.max { 326 lim.max-- 327 } 328 case eq: 329 lim.min = c 330 lim.max = c 331 } 332 if lim.min >= 0 { 333 // int(x) >= 0 && int(x) >= N ⇒ uint(x) >= N 334 lim.umin = uint64(lim.min) 335 } 336 if lim.max != noLimit.max && old.min >= 0 && lim.max >= 0 { 337 // 0 <= int(x) <= N ⇒ 0 <= uint(x) <= N 338 // This is for a max update, so the lower bound 339 // comes from what we already know (old). 340 lim.umax = uint64(lim.max) 341 } 342 case unsigned: 343 uc := w.AuxUnsigned() 344 switch r { 345 case lt: 346 lim.umax = uc - 1 347 case lt | eq: 348 lim.umax = uc 349 case gt | eq: 350 lim.umin = uc 351 case gt: 352 lim.umin = uc + 1 353 case lt | gt: 354 lim = old 355 if uc == lim.umin { 356 lim.umin++ 357 } 358 if uc == lim.umax { 359 lim.umax-- 360 } 361 case eq: 362 lim.umin = uc 363 lim.umax = uc 364 } 365 // We could use the contrapositives of the 366 // signed implications to derive signed facts, 367 // but it turns out not to matter. 368 } 369 ft.limitStack = append(ft.limitStack, limitFact{v.ID, old}) 370 lim = old.intersect(lim) 371 ft.limits[v.ID] = lim 372 if v.Block.Func.pass.debug > 2 { 373 v.Block.Func.Warnl(parent.Pos, "parent=%s, new limits %s %s %s %s", parent, v, w, r, lim.String()) 374 } 375 if lim.min > lim.max || lim.umin > lim.umax { 376 ft.unsat = true 377 return 378 } 379 } 380 381 // Derived facts below here are only about numbers. 382 if d != signed && d != unsigned { 383 return 384 } 385 386 // Additional facts we know given the relationship between len and cap. 387 // 388 // TODO: Since prove now derives transitive relations, it 389 // should be sufficient to learn that len(w) <= cap(w) at the 390 // beginning of prove where we look for all len/cap ops. 391 if v.Op == OpSliceLen && r< == 0 && ft.caps[v.Args[0].ID] != nil { 392 // len(s) > w implies cap(s) > w 393 // len(s) >= w implies cap(s) >= w 394 // len(s) == w implies cap(s) >= w 395 ft.update(parent, ft.caps[v.Args[0].ID], w, d, r|gt) 396 } 397 if w.Op == OpSliceLen && r> == 0 && ft.caps[w.Args[0].ID] != nil { 398 // same, length on the RHS. 399 ft.update(parent, v, ft.caps[w.Args[0].ID], d, r|lt) 400 } 401 if v.Op == OpSliceCap && r> == 0 && ft.lens[v.Args[0].ID] != nil { 402 // cap(s) < w implies len(s) < w 403 // cap(s) <= w implies len(s) <= w 404 // cap(s) == w implies len(s) <= w 405 ft.update(parent, ft.lens[v.Args[0].ID], w, d, r|lt) 406 } 407 if w.Op == OpSliceCap && r< == 0 && ft.lens[w.Args[0].ID] != nil { 408 // same, capacity on the RHS. 409 ft.update(parent, v, ft.lens[w.Args[0].ID], d, r|gt) 410 } 411 412 // Process fence-post implications. 413 // 414 // First, make the condition > or >=. 415 if r == lt || r == lt|eq { 416 v, w = w, v 417 r = reverseBits[r] 418 } 419 switch r { 420 case gt: 421 if x, delta := isConstDelta(v); x != nil && delta == 1 { 422 // x+1 > w ⇒ x >= w 423 // 424 // This is useful for eliminating the 425 // growslice branch of append. 426 ft.update(parent, x, w, d, gt|eq) 427 } else if x, delta := isConstDelta(w); x != nil && delta == -1 { 428 // v > x-1 ⇒ v >= x 429 ft.update(parent, v, x, d, gt|eq) 430 } 431 case gt | eq: 432 if x, delta := isConstDelta(v); x != nil && delta == -1 { 433 // x-1 >= w && x > min ⇒ x > w 434 // 435 // Useful for i > 0; s[i-1]. 436 lim, ok := ft.limits[x.ID] 437 if ok && ((d == signed && lim.min > opMin[v.Op]) || (d == unsigned && lim.umin > 0)) { 438 ft.update(parent, x, w, d, gt) 439 } 440 } else if x, delta := isConstDelta(w); x != nil && delta == 1 { 441 // v >= x+1 && x < max ⇒ v > x 442 lim, ok := ft.limits[x.ID] 443 if ok && ((d == signed && lim.max < opMax[w.Op]) || (d == unsigned && lim.umax < opUMax[w.Op])) { 444 ft.update(parent, v, x, d, gt) 445 } 446 } 447 } 448 449 // Process: x+delta > w (with delta constant) 450 // Only signed domain for now (useful for accesses to slices in loops). 451 if r == gt || r == gt|eq { 452 if x, delta := isConstDelta(v); x != nil && d == signed { 453 if parent.Func.pass.debug > 1 { 454 parent.Func.Warnl(parent.Pos, "x+d %s w; x:%v %v delta:%v w:%v d:%v", r, x, parent.String(), delta, w.AuxInt, d) 455 } 456 if !w.isGenericIntConst() { 457 // If we know that x+delta > w but w is not constant, we can derive: 458 // if delta < 0 and x > MinInt - delta, then x > w (because x+delta cannot underflow) 459 // This is useful for loops with bounds "len(slice)-K" (delta = -K) 460 if l, has := ft.limits[x.ID]; has && delta < 0 { 461 if (x.Type.Size() == 8 && l.min >= math.MinInt64-delta) || 462 (x.Type.Size() == 4 && l.min >= math.MinInt32-delta) { 463 ft.update(parent, x, w, signed, r) 464 } 465 } 466 } else { 467 // With w,delta constants, we want to derive: x+delta > w ⇒ x > w-delta 468 // 469 // We compute (using integers of the correct size): 470 // min = w - delta 471 // max = MaxInt - delta 472 // 473 // And we prove that: 474 // if min<max: min < x AND x <= max 475 // if min>max: min < x OR x <= max 476 // 477 // This is always correct, even in case of overflow. 478 // 479 // If the initial fact is x+delta >= w instead, the derived conditions are: 480 // if min<max: min <= x AND x <= max 481 // if min>max: min <= x OR x <= max 482 // 483 // Notice the conditions for max are still <=, as they handle overflows. 484 var min, max int64 485 var vmin, vmax *Value 486 switch x.Type.Size() { 487 case 8: 488 min = w.AuxInt - delta 489 max = int64(^uint64(0)>>1) - delta 490 491 vmin = parent.NewValue0I(parent.Pos, OpConst64, parent.Func.Config.Types.Int64, min) 492 vmax = parent.NewValue0I(parent.Pos, OpConst64, parent.Func.Config.Types.Int64, max) 493 494 case 4: 495 min = int64(int32(w.AuxInt) - int32(delta)) 496 max = int64(int32(^uint32(0)>>1) - int32(delta)) 497 498 vmin = parent.NewValue0I(parent.Pos, OpConst32, parent.Func.Config.Types.Int32, min) 499 vmax = parent.NewValue0I(parent.Pos, OpConst32, parent.Func.Config.Types.Int32, max) 500 501 default: 502 panic("unimplemented") 503 } 504 505 if min < max { 506 // Record that x > min and max >= x 507 ft.update(parent, x, vmin, d, r) 508 ft.update(parent, vmax, x, d, r|eq) 509 } else { 510 // We know that either x>min OR x<=max. factsTable cannot record OR conditions, 511 // so let's see if we can already prove that one of them is false, in which case 512 // the other must be true 513 if l, has := ft.limits[x.ID]; has { 514 if l.max <= min { 515 if r&eq == 0 || l.max < min { 516 // x>min (x>=min) is impossible, so it must be x<=max 517 ft.update(parent, vmax, x, d, r|eq) 518 } 519 } else if l.min > max { 520 // x<=max is impossible, so it must be x>min 521 ft.update(parent, x, vmin, d, r) 522 } 523 } 524 } 525 } 526 } 527 } 528 529 } 530 531 var opMin = map[Op]int64{ 532 OpAdd64: math.MinInt64, OpSub64: math.MinInt64, 533 OpAdd32: math.MinInt32, OpSub32: math.MinInt32, 534 } 535 536 var opMax = map[Op]int64{ 537 OpAdd64: math.MaxInt64, OpSub64: math.MaxInt64, 538 OpAdd32: math.MaxInt32, OpSub32: math.MaxInt32, 539 } 540 541 var opUMax = map[Op]uint64{ 542 OpAdd64: math.MaxUint64, OpSub64: math.MaxUint64, 543 OpAdd32: math.MaxUint32, OpSub32: math.MaxUint32, 544 } 545 546 // isNonNegative reports whether v is known to be non-negative. 547 func (ft *factsTable) isNonNegative(v *Value) bool { 548 if isNonNegative(v) { 549 return true 550 } 551 552 // Check if the recorded limits can prove that the value is positive 553 if l, has := ft.limits[v.ID]; has && (l.min >= 0 || l.umax <= math.MaxInt64) { 554 return true 555 } 556 557 // Check if v = x+delta, and we can use x's limits to prove that it's positive 558 if x, delta := isConstDelta(v); x != nil { 559 if l, has := ft.limits[x.ID]; has { 560 if delta > 0 && l.min >= -delta && l.max <= math.MaxInt64-delta { 561 return true 562 } 563 if delta < 0 && l.min >= -delta { 564 return true 565 } 566 } 567 } 568 569 return false 570 } 571 572 // checkpoint saves the current state of known relations. 573 // Called when descending on a branch. 574 func (ft *factsTable) checkpoint() { 575 if ft.unsat { 576 ft.unsatDepth++ 577 } 578 ft.stack = append(ft.stack, checkpointFact) 579 ft.limitStack = append(ft.limitStack, checkpointBound) 580 ft.order[0].Checkpoint() 581 ft.order[1].Checkpoint() 582 } 583 584 // restore restores known relation to the state just 585 // before the previous checkpoint. 586 // Called when backing up on a branch. 587 func (ft *factsTable) restore() { 588 if ft.unsatDepth > 0 { 589 ft.unsatDepth-- 590 } else { 591 ft.unsat = false 592 } 593 for { 594 old := ft.stack[len(ft.stack)-1] 595 ft.stack = ft.stack[:len(ft.stack)-1] 596 if old == checkpointFact { 597 break 598 } 599 if old.r == lt|eq|gt { 600 delete(ft.facts, old.p) 601 } else { 602 ft.facts[old.p] = old.r 603 } 604 } 605 for { 606 old := ft.limitStack[len(ft.limitStack)-1] 607 ft.limitStack = ft.limitStack[:len(ft.limitStack)-1] 608 if old.vid == 0 { // checkpointBound 609 break 610 } 611 if old.limit == noLimit { 612 delete(ft.limits, old.vid) 613 } else { 614 ft.limits[old.vid] = old.limit 615 } 616 } 617 ft.order[0].Undo() 618 ft.order[1].Undo() 619 } 620 621 func lessByID(v, w *Value) bool { 622 if v == nil && w == nil { 623 // Should not happen, but just in case. 624 return false 625 } 626 if v == nil { 627 return true 628 } 629 return w != nil && v.ID < w.ID 630 } 631 632 var ( 633 reverseBits = [...]relation{0, 4, 2, 6, 1, 5, 3, 7} 634 635 // maps what we learn when the positive branch is taken. 636 // For example: 637 // OpLess8: {signed, lt}, 638 // v1 = (OpLess8 v2 v3). 639 // If v1 branch is taken then we learn that the rangeMask 640 // can be at most lt. 641 domainRelationTable = map[Op]struct { 642 d domain 643 r relation 644 }{ 645 OpEq8: {signed | unsigned, eq}, 646 OpEq16: {signed | unsigned, eq}, 647 OpEq32: {signed | unsigned, eq}, 648 OpEq64: {signed | unsigned, eq}, 649 OpEqPtr: {pointer, eq}, 650 651 OpNeq8: {signed | unsigned, lt | gt}, 652 OpNeq16: {signed | unsigned, lt | gt}, 653 OpNeq32: {signed | unsigned, lt | gt}, 654 OpNeq64: {signed | unsigned, lt | gt}, 655 OpNeqPtr: {pointer, lt | gt}, 656 657 OpLess8: {signed, lt}, 658 OpLess8U: {unsigned, lt}, 659 OpLess16: {signed, lt}, 660 OpLess16U: {unsigned, lt}, 661 OpLess32: {signed, lt}, 662 OpLess32U: {unsigned, lt}, 663 OpLess64: {signed, lt}, 664 OpLess64U: {unsigned, lt}, 665 666 OpLeq8: {signed, lt | eq}, 667 OpLeq8U: {unsigned, lt | eq}, 668 OpLeq16: {signed, lt | eq}, 669 OpLeq16U: {unsigned, lt | eq}, 670 OpLeq32: {signed, lt | eq}, 671 OpLeq32U: {unsigned, lt | eq}, 672 OpLeq64: {signed, lt | eq}, 673 OpLeq64U: {unsigned, lt | eq}, 674 675 OpGeq8: {signed, eq | gt}, 676 OpGeq8U: {unsigned, eq | gt}, 677 OpGeq16: {signed, eq | gt}, 678 OpGeq16U: {unsigned, eq | gt}, 679 OpGeq32: {signed, eq | gt}, 680 OpGeq32U: {unsigned, eq | gt}, 681 OpGeq64: {signed, eq | gt}, 682 OpGeq64U: {unsigned, eq | gt}, 683 684 OpGreater8: {signed, gt}, 685 OpGreater8U: {unsigned, gt}, 686 OpGreater16: {signed, gt}, 687 OpGreater16U: {unsigned, gt}, 688 OpGreater32: {signed, gt}, 689 OpGreater32U: {unsigned, gt}, 690 OpGreater64: {signed, gt}, 691 OpGreater64U: {unsigned, gt}, 692 693 // For these ops, the negative branch is different: we can only 694 // prove signed/GE (signed/GT) if we can prove that arg0 is non-negative. 695 // See the special case in addBranchRestrictions. 696 OpIsInBounds: {signed | unsigned, lt}, // 0 <= arg0 < arg1 697 OpIsSliceInBounds: {signed | unsigned, lt | eq}, // 0 <= arg0 <= arg1 698 } 699 ) 700 701 // prove removes redundant BlockIf branches that can be inferred 702 // from previous dominating comparisons. 703 // 704 // By far, the most common redundant pair are generated by bounds checking. 705 // For example for the code: 706 // 707 // a[i] = 4 708 // foo(a[i]) 709 // 710 // The compiler will generate the following code: 711 // 712 // if i >= len(a) { 713 // panic("not in bounds") 714 // } 715 // a[i] = 4 716 // if i >= len(a) { 717 // panic("not in bounds") 718 // } 719 // foo(a[i]) 720 // 721 // The second comparison i >= len(a) is clearly redundant because if the 722 // else branch of the first comparison is executed, we already know that i < len(a). 723 // The code for the second panic can be removed. 724 // 725 // prove works by finding contradictions and trimming branches whose 726 // conditions are unsatisfiable given the branches leading up to them. 727 // It tracks a "fact table" of branch conditions. For each branching 728 // block, it asserts the branch conditions that uniquely dominate that 729 // block, and then separately asserts the block's branch condition and 730 // its negation. If either leads to a contradiction, it can trim that 731 // successor. 732 func prove(f *Func) { 733 ft := newFactsTable(f) 734 ft.checkpoint() 735 736 // Find length and capacity ops. 737 var zero *Value 738 for _, b := range f.Blocks { 739 for _, v := range b.Values { 740 // If we found a zero constant, save it (so we don't have 741 // to build one later). 742 if zero == nil && v.Op == OpConst64 && v.AuxInt == 0 { 743 zero = v 744 } 745 if v.Uses == 0 { 746 // We don't care about dead values. 747 // (There can be some that are CSEd but not removed yet.) 748 continue 749 } 750 switch v.Op { 751 case OpStringLen: 752 if zero == nil { 753 zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0) 754 } 755 ft.update(b, v, zero, signed, gt|eq) 756 case OpSliceLen: 757 if ft.lens == nil { 758 ft.lens = map[ID]*Value{} 759 } 760 ft.lens[v.Args[0].ID] = v 761 if zero == nil { 762 zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0) 763 } 764 ft.update(b, v, zero, signed, gt|eq) 765 case OpSliceCap: 766 if ft.caps == nil { 767 ft.caps = map[ID]*Value{} 768 } 769 ft.caps[v.Args[0].ID] = v 770 if zero == nil { 771 zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0) 772 } 773 ft.update(b, v, zero, signed, gt|eq) 774 } 775 } 776 } 777 778 // Find induction variables. Currently, findIndVars 779 // is limited to one induction variable per block. 780 var indVars map[*Block]indVar 781 for _, v := range findIndVar(f) { 782 if indVars == nil { 783 indVars = make(map[*Block]indVar) 784 } 785 indVars[v.entry] = v 786 } 787 788 // current node state 789 type walkState int 790 const ( 791 descend walkState = iota 792 simplify 793 ) 794 // work maintains the DFS stack. 795 type bp struct { 796 block *Block // current handled block 797 state walkState // what's to do 798 } 799 work := make([]bp, 0, 256) 800 work = append(work, bp{ 801 block: f.Entry, 802 state: descend, 803 }) 804 805 idom := f.Idom() 806 sdom := f.sdom() 807 808 // DFS on the dominator tree. 809 // 810 // For efficiency, we consider only the dominator tree rather 811 // than the entire flow graph. On the way down, we consider 812 // incoming branches and accumulate conditions that uniquely 813 // dominate the current block. If we discover a contradiction, 814 // we can eliminate the entire block and all of its children. 815 // On the way back up, we consider outgoing branches that 816 // haven't already been considered. This way we consider each 817 // branch condition only once. 818 for len(work) > 0 { 819 node := work[len(work)-1] 820 work = work[:len(work)-1] 821 parent := idom[node.block.ID] 822 branch := getBranch(sdom, parent, node.block) 823 824 switch node.state { 825 case descend: 826 ft.checkpoint() 827 if iv, ok := indVars[node.block]; ok { 828 addIndVarRestrictions(ft, parent, iv) 829 } 830 831 if branch != unknown { 832 addBranchRestrictions(ft, parent, branch) 833 if ft.unsat { 834 // node.block is unreachable. 835 // Remove it and don't visit 836 // its children. 837 removeBranch(parent, branch) 838 ft.restore() 839 break 840 } 841 // Otherwise, we can now commit to 842 // taking this branch. We'll restore 843 // ft when we unwind. 844 } 845 846 // Add inductive facts for phis in this block. 847 addLocalInductiveFacts(ft, node.block) 848 849 work = append(work, bp{ 850 block: node.block, 851 state: simplify, 852 }) 853 for s := sdom.Child(node.block); s != nil; s = sdom.Sibling(s) { 854 work = append(work, bp{ 855 block: s, 856 state: descend, 857 }) 858 } 859 860 case simplify: 861 simplifyBlock(sdom, ft, node.block) 862 ft.restore() 863 } 864 } 865 866 ft.restore() 867 868 // Return the posets to the free list 869 for _, po := range ft.order { 870 // Make sure it's empty as it should be. A non-empty poset 871 // might cause errors and miscompilations if reused. 872 if checkEnabled { 873 if err := po.CheckEmpty(); err != nil { 874 f.Fatalf("prove poset not empty after function %s: %v", f.Name, err) 875 } 876 } 877 f.retPoset(po) 878 } 879 } 880 881 // getBranch returns the range restrictions added by p 882 // when reaching b. p is the immediate dominator of b. 883 func getBranch(sdom SparseTree, p *Block, b *Block) branch { 884 if p == nil || p.Kind != BlockIf { 885 return unknown 886 } 887 // If p and p.Succs[0] are dominators it means that every path 888 // from entry to b passes through p and p.Succs[0]. We care that 889 // no path from entry to b passes through p.Succs[1]. If p.Succs[0] 890 // has one predecessor then (apart from the degenerate case), 891 // there is no path from entry that can reach b through p.Succs[1]. 892 // TODO: how about p->yes->b->yes, i.e. a loop in yes. 893 if sdom.isAncestorEq(p.Succs[0].b, b) && len(p.Succs[0].b.Preds) == 1 { 894 return positive 895 } 896 if sdom.isAncestorEq(p.Succs[1].b, b) && len(p.Succs[1].b.Preds) == 1 { 897 return negative 898 } 899 return unknown 900 } 901 902 // addIndVarRestrictions updates the factsTables ft with the facts 903 // learned from the induction variable indVar which drives the loop 904 // starting in Block b. 905 func addIndVarRestrictions(ft *factsTable, b *Block, iv indVar) { 906 d := signed 907 if isNonNegative(iv.min) && isNonNegative(iv.max) { 908 d |= unsigned 909 } 910 911 if iv.flags&indVarMinExc == 0 { 912 addRestrictions(b, ft, d, iv.min, iv.ind, lt|eq) 913 } else { 914 addRestrictions(b, ft, d, iv.min, iv.ind, lt) 915 } 916 917 if iv.flags&indVarMaxInc == 0 { 918 addRestrictions(b, ft, d, iv.ind, iv.max, lt) 919 } else { 920 addRestrictions(b, ft, d, iv.ind, iv.max, lt|eq) 921 } 922 } 923 924 // addBranchRestrictions updates the factsTables ft with the facts learned when 925 // branching from Block b in direction br. 926 func addBranchRestrictions(ft *factsTable, b *Block, br branch) { 927 c := b.Control 928 switch br { 929 case negative: 930 addRestrictions(b, ft, boolean, nil, c, eq) 931 case positive: 932 addRestrictions(b, ft, boolean, nil, c, lt|gt) 933 default: 934 panic("unknown branch") 935 } 936 if tr, has := domainRelationTable[b.Control.Op]; has { 937 // When we branched from parent we learned a new set of 938 // restrictions. Update the factsTable accordingly. 939 d := tr.d 940 if d == signed && ft.isNonNegative(c.Args[0]) && ft.isNonNegative(c.Args[1]) { 941 d |= unsigned 942 } 943 switch br { 944 case negative: 945 switch b.Control.Op { // Special cases 946 case OpIsInBounds, OpIsSliceInBounds: 947 // 0 <= a0 < a1 (or 0 <= a0 <= a1) 948 // 949 // On the positive branch, we learn a0 < a1, 950 // both signed and unsigned. 951 // 952 // On the negative branch, we learn (0 > a0 || 953 // a0 >= a1). In the unsigned domain, this is 954 // simply a0 >= a1 (which is the reverse of the 955 // positive branch, so nothing surprising). 956 // But in the signed domain, we can't express the || 957 // condition, so check if a0 is non-negative instead, 958 // to be able to learn something. 959 d = unsigned 960 if ft.isNonNegative(c.Args[0]) { 961 d |= signed 962 } 963 } 964 addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r^(lt|gt|eq)) 965 case positive: 966 addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r) 967 } 968 } 969 } 970 971 // addRestrictions updates restrictions from the immediate 972 // dominating block (p) using r. 973 func addRestrictions(parent *Block, ft *factsTable, t domain, v, w *Value, r relation) { 974 if t == 0 { 975 // Trivial case: nothing to do. 976 // Shoult not happen, but just in case. 977 return 978 } 979 for i := domain(1); i <= t; i <<= 1 { 980 if t&i == 0 { 981 continue 982 } 983 ft.update(parent, v, w, i, r) 984 } 985 } 986 987 // addLocalInductiveFacts adds inductive facts when visiting b, where 988 // b is a join point in a loop. In contrast with findIndVar, this 989 // depends on facts established for b, which is why it happens when 990 // visiting b. addLocalInductiveFacts specifically targets the pattern 991 // created by OFORUNTIL, which isn't detected by findIndVar. 992 // 993 // TODO: It would be nice to combine this with findIndVar. 994 func addLocalInductiveFacts(ft *factsTable, b *Block) { 995 // This looks for a specific pattern of induction: 996 // 997 // 1. i1 = OpPhi(min, i2) in b 998 // 2. i2 = i1 + 1 999 // 3. i2 < max at exit from b.Preds[1] 1000 // 4. min < max 1001 // 1002 // If all of these conditions are true, then i1 < max and i1 >= min. 1003 1004 for _, i1 := range b.Values { 1005 if i1.Op != OpPhi { 1006 continue 1007 } 1008 1009 // Check for conditions 1 and 2. This is easy to do 1010 // and will throw out most phis. 1011 min, i2 := i1.Args[0], i1.Args[1] 1012 if i1q, delta := isConstDelta(i2); i1q != i1 || delta != 1 { 1013 continue 1014 } 1015 1016 // Try to prove condition 3. We can't just query the 1017 // fact table for this because we don't know what the 1018 // facts of b.Preds[1] are (in general, b.Preds[1] is 1019 // a loop-back edge, so we haven't even been there 1020 // yet). As a conservative approximation, we look for 1021 // this condition in the predecessor chain until we 1022 // hit a join point. 1023 uniquePred := func(b *Block) *Block { 1024 if len(b.Preds) == 1 { 1025 return b.Preds[0].b 1026 } 1027 return nil 1028 } 1029 pred, child := b.Preds[1].b, b 1030 for ; pred != nil; pred = uniquePred(pred) { 1031 if pred.Kind != BlockIf { 1032 continue 1033 } 1034 1035 br := unknown 1036 if pred.Succs[0].b == child { 1037 br = positive 1038 } 1039 if pred.Succs[1].b == child { 1040 if br != unknown { 1041 continue 1042 } 1043 br = negative 1044 } 1045 1046 tr, has := domainRelationTable[pred.Control.Op] 1047 if !has { 1048 continue 1049 } 1050 r := tr.r 1051 if br == negative { 1052 // Negative branch taken to reach b. 1053 // Complement the relations. 1054 r = (lt | eq | gt) ^ r 1055 } 1056 1057 // Check for i2 < max or max > i2. 1058 var max *Value 1059 if r == lt && pred.Control.Args[0] == i2 { 1060 max = pred.Control.Args[1] 1061 } else if r == gt && pred.Control.Args[1] == i2 { 1062 max = pred.Control.Args[0] 1063 } else { 1064 continue 1065 } 1066 1067 // Check condition 4 now that we have a 1068 // candidate max. For this we can query the 1069 // fact table. We "prove" min < max by showing 1070 // that min >= max is unsat. (This may simply 1071 // compare two constants; that's fine.) 1072 ft.checkpoint() 1073 ft.update(b, min, max, tr.d, gt|eq) 1074 proved := ft.unsat 1075 ft.restore() 1076 1077 if proved { 1078 // We know that min <= i1 < max. 1079 if b.Func.pass.debug > 0 { 1080 printIndVar(b, i1, min, max, 1, 0) 1081 } 1082 ft.update(b, min, i1, tr.d, lt|eq) 1083 ft.update(b, i1, max, tr.d, lt) 1084 } 1085 } 1086 } 1087 } 1088 1089 var ctzNonZeroOp = map[Op]Op{OpCtz8: OpCtz8NonZero, OpCtz16: OpCtz16NonZero, OpCtz32: OpCtz32NonZero, OpCtz64: OpCtz64NonZero} 1090 var mostNegativeDividend = map[Op]int64{ 1091 OpDiv16: -1 << 15, 1092 OpMod16: -1 << 15, 1093 OpDiv32: -1 << 31, 1094 OpMod32: -1 << 31, 1095 OpDiv64: -1 << 63, 1096 OpMod64: -1 << 63} 1097 1098 // simplifyBlock simplifies some constant values in b and evaluates 1099 // branches to non-uniquely dominated successors of b. 1100 func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) { 1101 for _, v := range b.Values { 1102 switch v.Op { 1103 case OpSlicemask: 1104 // Replace OpSlicemask operations in b with constants where possible. 1105 x, delta := isConstDelta(v.Args[0]) 1106 if x == nil { 1107 continue 1108 } 1109 // slicemask(x + y) 1110 // if x is larger than -y (y is negative), then slicemask is -1. 1111 lim, ok := ft.limits[x.ID] 1112 if !ok { 1113 continue 1114 } 1115 if lim.umin > uint64(-delta) { 1116 if v.Args[0].Op == OpAdd64 { 1117 v.reset(OpConst64) 1118 } else { 1119 v.reset(OpConst32) 1120 } 1121 if b.Func.pass.debug > 0 { 1122 b.Func.Warnl(v.Pos, "Proved slicemask not needed") 1123 } 1124 v.AuxInt = -1 1125 } 1126 case OpCtz8, OpCtz16, OpCtz32, OpCtz64: 1127 // On some architectures, notably amd64, we can generate much better 1128 // code for CtzNN if we know that the argument is non-zero. 1129 // Capture that information here for use in arch-specific optimizations. 1130 x := v.Args[0] 1131 lim, ok := ft.limits[x.ID] 1132 if !ok { 1133 continue 1134 } 1135 if lim.umin > 0 || lim.min > 0 || lim.max < 0 { 1136 if b.Func.pass.debug > 0 { 1137 b.Func.Warnl(v.Pos, "Proved %v non-zero", v.Op) 1138 } 1139 v.Op = ctzNonZeroOp[v.Op] 1140 } 1141 1142 case OpLsh8x8, OpLsh8x16, OpLsh8x32, OpLsh8x64, 1143 OpLsh16x8, OpLsh16x16, OpLsh16x32, OpLsh16x64, 1144 OpLsh32x8, OpLsh32x16, OpLsh32x32, OpLsh32x64, 1145 OpLsh64x8, OpLsh64x16, OpLsh64x32, OpLsh64x64, 1146 OpRsh8x8, OpRsh8x16, OpRsh8x32, OpRsh8x64, 1147 OpRsh16x8, OpRsh16x16, OpRsh16x32, OpRsh16x64, 1148 OpRsh32x8, OpRsh32x16, OpRsh32x32, OpRsh32x64, 1149 OpRsh64x8, OpRsh64x16, OpRsh64x32, OpRsh64x64, 1150 OpRsh8Ux8, OpRsh8Ux16, OpRsh8Ux32, OpRsh8Ux64, 1151 OpRsh16Ux8, OpRsh16Ux16, OpRsh16Ux32, OpRsh16Ux64, 1152 OpRsh32Ux8, OpRsh32Ux16, OpRsh32Ux32, OpRsh32Ux64, 1153 OpRsh64Ux8, OpRsh64Ux16, OpRsh64Ux32, OpRsh64Ux64: 1154 // Check whether, for a << b, we know that b 1155 // is strictly less than the number of bits in a. 1156 by := v.Args[1] 1157 lim, ok := ft.limits[by.ID] 1158 if !ok { 1159 continue 1160 } 1161 bits := 8 * v.Args[0].Type.Size() 1162 if lim.umax < uint64(bits) || (lim.max < bits && ft.isNonNegative(by)) { 1163 v.AuxInt = 1 // see shiftIsBounded 1164 if b.Func.pass.debug > 0 { 1165 b.Func.Warnl(v.Pos, "Proved %v bounded", v.Op) 1166 } 1167 } 1168 case OpDiv16, OpDiv32, OpDiv64, OpMod16, OpMod32, OpMod64: 1169 // On amd64 and 386 fix-up code can be avoided if we know 1170 // the divisor is not -1 or the dividend > MinIntNN. 1171 divr := v.Args[1] 1172 divrLim, divrLimok := ft.limits[divr.ID] 1173 divd := v.Args[0] 1174 divdLim, divdLimok := ft.limits[divd.ID] 1175 if (divrLimok && (divrLim.max < -1 || divrLim.min > -1)) || 1176 (divdLimok && divdLim.min > mostNegativeDividend[v.Op]) { 1177 v.AuxInt = 1 // see NeedsFixUp in genericOps - v.AuxInt = 0 means we have not proved 1178 // that the divisor is not -1 and the dividend is not the most negative, 1179 // so we need to add fix-up code. 1180 if b.Func.pass.debug > 0 { 1181 b.Func.Warnl(v.Pos, "Proved %v does not need fix-up", v.Op) 1182 } 1183 } 1184 } 1185 } 1186 1187 if b.Kind != BlockIf { 1188 return 1189 } 1190 1191 // Consider outgoing edges from this block. 1192 parent := b 1193 for i, branch := range [...]branch{positive, negative} { 1194 child := parent.Succs[i].b 1195 if getBranch(sdom, parent, child) != unknown { 1196 // For edges to uniquely dominated blocks, we 1197 // already did this when we visited the child. 1198 continue 1199 } 1200 // For edges to other blocks, this can trim a branch 1201 // even if we couldn't get rid of the child itself. 1202 ft.checkpoint() 1203 addBranchRestrictions(ft, parent, branch) 1204 unsat := ft.unsat 1205 ft.restore() 1206 if unsat { 1207 // This branch is impossible, so remove it 1208 // from the block. 1209 removeBranch(parent, branch) 1210 // No point in considering the other branch. 1211 // (It *is* possible for both to be 1212 // unsatisfiable since the fact table is 1213 // incomplete. We could turn this into a 1214 // BlockExit, but it doesn't seem worth it.) 1215 break 1216 } 1217 } 1218 } 1219 1220 func removeBranch(b *Block, branch branch) { 1221 if b.Func.pass.debug > 0 { 1222 verb := "Proved" 1223 if branch == positive { 1224 verb = "Disproved" 1225 } 1226 c := b.Control 1227 if b.Func.pass.debug > 1 { 1228 b.Func.Warnl(b.Pos, "%s %s (%s)", verb, c.Op, c) 1229 } else { 1230 b.Func.Warnl(b.Pos, "%s %s", verb, c.Op) 1231 } 1232 } 1233 b.Kind = BlockFirst 1234 b.SetControl(nil) 1235 if branch == positive { 1236 b.swapSuccessors() 1237 } 1238 } 1239 1240 // isNonNegative reports whether v is known to be greater or equal to zero. 1241 func isNonNegative(v *Value) bool { 1242 switch v.Op { 1243 case OpConst64: 1244 return v.AuxInt >= 0 1245 1246 case OpConst32: 1247 return int32(v.AuxInt) >= 0 1248 1249 case OpStringLen, OpSliceLen, OpSliceCap, 1250 OpZeroExt8to64, OpZeroExt16to64, OpZeroExt32to64: 1251 return true 1252 1253 case OpRsh64Ux64: 1254 by := v.Args[1] 1255 return by.Op == OpConst64 && by.AuxInt > 0 1256 1257 case OpRsh64x64: 1258 return isNonNegative(v.Args[0]) 1259 } 1260 return false 1261 } 1262 1263 // isConstDelta returns non-nil if v is equivalent to w+delta (signed). 1264 func isConstDelta(v *Value) (w *Value, delta int64) { 1265 cop := OpConst64 1266 switch v.Op { 1267 case OpAdd32, OpSub32: 1268 cop = OpConst32 1269 } 1270 switch v.Op { 1271 case OpAdd64, OpAdd32: 1272 if v.Args[0].Op == cop { 1273 return v.Args[1], v.Args[0].AuxInt 1274 } 1275 if v.Args[1].Op == cop { 1276 return v.Args[0], v.Args[1].AuxInt 1277 } 1278 case OpSub64, OpSub32: 1279 if v.Args[1].Op == cop { 1280 aux := v.Args[1].AuxInt 1281 if aux != -aux { // Overflow; too bad 1282 return v.Args[0], -aux 1283 } 1284 } 1285 } 1286 return nil, 0 1287 }