github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/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 var max int64 553 switch v.Type.Size() { 554 case 1: 555 max = math.MaxInt8 556 case 2: 557 max = math.MaxInt16 558 case 4: 559 max = math.MaxInt32 560 case 8: 561 max = math.MaxInt64 562 default: 563 panic("unexpected integer size") 564 } 565 566 // Check if the recorded limits can prove that the value is positive 567 if l, has := ft.limits[v.ID]; has && (l.min >= 0 || l.umax <= uint64(max)) { 568 return true 569 } 570 571 // Check if v = x+delta, and we can use x's limits to prove that it's positive 572 if x, delta := isConstDelta(v); x != nil { 573 if l, has := ft.limits[x.ID]; has { 574 if delta > 0 && l.min >= -delta && l.max <= max-delta { 575 return true 576 } 577 if delta < 0 && l.min >= -delta { 578 return true 579 } 580 } 581 } 582 583 return false 584 } 585 586 // checkpoint saves the current state of known relations. 587 // Called when descending on a branch. 588 func (ft *factsTable) checkpoint() { 589 if ft.unsat { 590 ft.unsatDepth++ 591 } 592 ft.stack = append(ft.stack, checkpointFact) 593 ft.limitStack = append(ft.limitStack, checkpointBound) 594 ft.order[0].Checkpoint() 595 ft.order[1].Checkpoint() 596 } 597 598 // restore restores known relation to the state just 599 // before the previous checkpoint. 600 // Called when backing up on a branch. 601 func (ft *factsTable) restore() { 602 if ft.unsatDepth > 0 { 603 ft.unsatDepth-- 604 } else { 605 ft.unsat = false 606 } 607 for { 608 old := ft.stack[len(ft.stack)-1] 609 ft.stack = ft.stack[:len(ft.stack)-1] 610 if old == checkpointFact { 611 break 612 } 613 if old.r == lt|eq|gt { 614 delete(ft.facts, old.p) 615 } else { 616 ft.facts[old.p] = old.r 617 } 618 } 619 for { 620 old := ft.limitStack[len(ft.limitStack)-1] 621 ft.limitStack = ft.limitStack[:len(ft.limitStack)-1] 622 if old.vid == 0 { // checkpointBound 623 break 624 } 625 if old.limit == noLimit { 626 delete(ft.limits, old.vid) 627 } else { 628 ft.limits[old.vid] = old.limit 629 } 630 } 631 ft.order[0].Undo() 632 ft.order[1].Undo() 633 } 634 635 func lessByID(v, w *Value) bool { 636 if v == nil && w == nil { 637 // Should not happen, but just in case. 638 return false 639 } 640 if v == nil { 641 return true 642 } 643 return w != nil && v.ID < w.ID 644 } 645 646 var ( 647 reverseBits = [...]relation{0, 4, 2, 6, 1, 5, 3, 7} 648 649 // maps what we learn when the positive branch is taken. 650 // For example: 651 // OpLess8: {signed, lt}, 652 // v1 = (OpLess8 v2 v3). 653 // If v1 branch is taken then we learn that the rangeMask 654 // can be at most lt. 655 domainRelationTable = map[Op]struct { 656 d domain 657 r relation 658 }{ 659 OpEq8: {signed | unsigned, eq}, 660 OpEq16: {signed | unsigned, eq}, 661 OpEq32: {signed | unsigned, eq}, 662 OpEq64: {signed | unsigned, eq}, 663 OpEqPtr: {pointer, eq}, 664 665 OpNeq8: {signed | unsigned, lt | gt}, 666 OpNeq16: {signed | unsigned, lt | gt}, 667 OpNeq32: {signed | unsigned, lt | gt}, 668 OpNeq64: {signed | unsigned, lt | gt}, 669 OpNeqPtr: {pointer, lt | gt}, 670 671 OpLess8: {signed, lt}, 672 OpLess8U: {unsigned, lt}, 673 OpLess16: {signed, lt}, 674 OpLess16U: {unsigned, lt}, 675 OpLess32: {signed, lt}, 676 OpLess32U: {unsigned, lt}, 677 OpLess64: {signed, lt}, 678 OpLess64U: {unsigned, lt}, 679 680 OpLeq8: {signed, lt | eq}, 681 OpLeq8U: {unsigned, lt | eq}, 682 OpLeq16: {signed, lt | eq}, 683 OpLeq16U: {unsigned, lt | eq}, 684 OpLeq32: {signed, lt | eq}, 685 OpLeq32U: {unsigned, lt | eq}, 686 OpLeq64: {signed, lt | eq}, 687 OpLeq64U: {unsigned, lt | eq}, 688 689 OpGeq8: {signed, eq | gt}, 690 OpGeq8U: {unsigned, eq | gt}, 691 OpGeq16: {signed, eq | gt}, 692 OpGeq16U: {unsigned, eq | gt}, 693 OpGeq32: {signed, eq | gt}, 694 OpGeq32U: {unsigned, eq | gt}, 695 OpGeq64: {signed, eq | gt}, 696 OpGeq64U: {unsigned, eq | gt}, 697 698 OpGreater8: {signed, gt}, 699 OpGreater8U: {unsigned, gt}, 700 OpGreater16: {signed, gt}, 701 OpGreater16U: {unsigned, gt}, 702 OpGreater32: {signed, gt}, 703 OpGreater32U: {unsigned, gt}, 704 OpGreater64: {signed, gt}, 705 OpGreater64U: {unsigned, gt}, 706 707 // For these ops, the negative branch is different: we can only 708 // prove signed/GE (signed/GT) if we can prove that arg0 is non-negative. 709 // See the special case in addBranchRestrictions. 710 OpIsInBounds: {signed | unsigned, lt}, // 0 <= arg0 < arg1 711 OpIsSliceInBounds: {signed | unsigned, lt | eq}, // 0 <= arg0 <= arg1 712 } 713 ) 714 715 // prove removes redundant BlockIf branches that can be inferred 716 // from previous dominating comparisons. 717 // 718 // By far, the most common redundant pair are generated by bounds checking. 719 // For example for the code: 720 // 721 // a[i] = 4 722 // foo(a[i]) 723 // 724 // The compiler will generate the following code: 725 // 726 // if i >= len(a) { 727 // panic("not in bounds") 728 // } 729 // a[i] = 4 730 // if i >= len(a) { 731 // panic("not in bounds") 732 // } 733 // foo(a[i]) 734 // 735 // The second comparison i >= len(a) is clearly redundant because if the 736 // else branch of the first comparison is executed, we already know that i < len(a). 737 // The code for the second panic can be removed. 738 // 739 // prove works by finding contradictions and trimming branches whose 740 // conditions are unsatisfiable given the branches leading up to them. 741 // It tracks a "fact table" of branch conditions. For each branching 742 // block, it asserts the branch conditions that uniquely dominate that 743 // block, and then separately asserts the block's branch condition and 744 // its negation. If either leads to a contradiction, it can trim that 745 // successor. 746 func prove(f *Func) { 747 ft := newFactsTable(f) 748 ft.checkpoint() 749 750 // Find length and capacity ops. 751 var zero *Value 752 for _, b := range f.Blocks { 753 for _, v := range b.Values { 754 // If we found a zero constant, save it (so we don't have 755 // to build one later). 756 if zero == nil && v.Op == OpConst64 && v.AuxInt == 0 { 757 zero = v 758 } 759 if v.Uses == 0 { 760 // We don't care about dead values. 761 // (There can be some that are CSEd but not removed yet.) 762 continue 763 } 764 switch v.Op { 765 case OpStringLen: 766 if zero == nil { 767 zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0) 768 } 769 ft.update(b, v, zero, signed, gt|eq) 770 case OpSliceLen: 771 if ft.lens == nil { 772 ft.lens = map[ID]*Value{} 773 } 774 ft.lens[v.Args[0].ID] = v 775 if zero == nil { 776 zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0) 777 } 778 ft.update(b, v, zero, signed, gt|eq) 779 case OpSliceCap: 780 if ft.caps == nil { 781 ft.caps = map[ID]*Value{} 782 } 783 ft.caps[v.Args[0].ID] = v 784 if zero == nil { 785 zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0) 786 } 787 ft.update(b, v, zero, signed, gt|eq) 788 } 789 } 790 } 791 792 // Find induction variables. Currently, findIndVars 793 // is limited to one induction variable per block. 794 var indVars map[*Block]indVar 795 for _, v := range findIndVar(f) { 796 if indVars == nil { 797 indVars = make(map[*Block]indVar) 798 } 799 indVars[v.entry] = v 800 } 801 802 // current node state 803 type walkState int 804 const ( 805 descend walkState = iota 806 simplify 807 ) 808 // work maintains the DFS stack. 809 type bp struct { 810 block *Block // current handled block 811 state walkState // what's to do 812 } 813 work := make([]bp, 0, 256) 814 work = append(work, bp{ 815 block: f.Entry, 816 state: descend, 817 }) 818 819 idom := f.Idom() 820 sdom := f.sdom() 821 822 // DFS on the dominator tree. 823 // 824 // For efficiency, we consider only the dominator tree rather 825 // than the entire flow graph. On the way down, we consider 826 // incoming branches and accumulate conditions that uniquely 827 // dominate the current block. If we discover a contradiction, 828 // we can eliminate the entire block and all of its children. 829 // On the way back up, we consider outgoing branches that 830 // haven't already been considered. This way we consider each 831 // branch condition only once. 832 for len(work) > 0 { 833 node := work[len(work)-1] 834 work = work[:len(work)-1] 835 parent := idom[node.block.ID] 836 branch := getBranch(sdom, parent, node.block) 837 838 switch node.state { 839 case descend: 840 ft.checkpoint() 841 if iv, ok := indVars[node.block]; ok { 842 addIndVarRestrictions(ft, parent, iv) 843 } 844 845 if branch != unknown { 846 addBranchRestrictions(ft, parent, branch) 847 if ft.unsat { 848 // node.block is unreachable. 849 // Remove it and don't visit 850 // its children. 851 removeBranch(parent, branch) 852 ft.restore() 853 break 854 } 855 // Otherwise, we can now commit to 856 // taking this branch. We'll restore 857 // ft when we unwind. 858 } 859 860 // Add inductive facts for phis in this block. 861 addLocalInductiveFacts(ft, node.block) 862 863 work = append(work, bp{ 864 block: node.block, 865 state: simplify, 866 }) 867 for s := sdom.Child(node.block); s != nil; s = sdom.Sibling(s) { 868 work = append(work, bp{ 869 block: s, 870 state: descend, 871 }) 872 } 873 874 case simplify: 875 simplifyBlock(sdom, ft, node.block) 876 ft.restore() 877 } 878 } 879 880 ft.restore() 881 882 // Return the posets to the free list 883 for _, po := range ft.order { 884 // Make sure it's empty as it should be. A non-empty poset 885 // might cause errors and miscompilations if reused. 886 if checkEnabled { 887 if err := po.CheckEmpty(); err != nil { 888 f.Fatalf("prove poset not empty after function %s: %v", f.Name, err) 889 } 890 } 891 f.retPoset(po) 892 } 893 } 894 895 // getBranch returns the range restrictions added by p 896 // when reaching b. p is the immediate dominator of b. 897 func getBranch(sdom SparseTree, p *Block, b *Block) branch { 898 if p == nil || p.Kind != BlockIf { 899 return unknown 900 } 901 // If p and p.Succs[0] are dominators it means that every path 902 // from entry to b passes through p and p.Succs[0]. We care that 903 // no path from entry to b passes through p.Succs[1]. If p.Succs[0] 904 // has one predecessor then (apart from the degenerate case), 905 // there is no path from entry that can reach b through p.Succs[1]. 906 // TODO: how about p->yes->b->yes, i.e. a loop in yes. 907 if sdom.isAncestorEq(p.Succs[0].b, b) && len(p.Succs[0].b.Preds) == 1 { 908 return positive 909 } 910 if sdom.isAncestorEq(p.Succs[1].b, b) && len(p.Succs[1].b.Preds) == 1 { 911 return negative 912 } 913 return unknown 914 } 915 916 // addIndVarRestrictions updates the factsTables ft with the facts 917 // learned from the induction variable indVar which drives the loop 918 // starting in Block b. 919 func addIndVarRestrictions(ft *factsTable, b *Block, iv indVar) { 920 d := signed 921 if isNonNegative(iv.min) && isNonNegative(iv.max) { 922 d |= unsigned 923 } 924 925 if iv.flags&indVarMinExc == 0 { 926 addRestrictions(b, ft, d, iv.min, iv.ind, lt|eq) 927 } else { 928 addRestrictions(b, ft, d, iv.min, iv.ind, lt) 929 } 930 931 if iv.flags&indVarMaxInc == 0 { 932 addRestrictions(b, ft, d, iv.ind, iv.max, lt) 933 } else { 934 addRestrictions(b, ft, d, iv.ind, iv.max, lt|eq) 935 } 936 } 937 938 // addBranchRestrictions updates the factsTables ft with the facts learned when 939 // branching from Block b in direction br. 940 func addBranchRestrictions(ft *factsTable, b *Block, br branch) { 941 c := b.Control 942 switch br { 943 case negative: 944 addRestrictions(b, ft, boolean, nil, c, eq) 945 case positive: 946 addRestrictions(b, ft, boolean, nil, c, lt|gt) 947 default: 948 panic("unknown branch") 949 } 950 if tr, has := domainRelationTable[b.Control.Op]; has { 951 // When we branched from parent we learned a new set of 952 // restrictions. Update the factsTable accordingly. 953 d := tr.d 954 if d == signed && ft.isNonNegative(c.Args[0]) && ft.isNonNegative(c.Args[1]) { 955 d |= unsigned 956 } 957 switch br { 958 case negative: 959 switch b.Control.Op { // Special cases 960 case OpIsInBounds, OpIsSliceInBounds: 961 // 0 <= a0 < a1 (or 0 <= a0 <= a1) 962 // 963 // On the positive branch, we learn a0 < a1, 964 // both signed and unsigned. 965 // 966 // On the negative branch, we learn (0 > a0 || 967 // a0 >= a1). In the unsigned domain, this is 968 // simply a0 >= a1 (which is the reverse of the 969 // positive branch, so nothing surprising). 970 // But in the signed domain, we can't express the || 971 // condition, so check if a0 is non-negative instead, 972 // to be able to learn something. 973 d = unsigned 974 if ft.isNonNegative(c.Args[0]) { 975 d |= signed 976 } 977 } 978 addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r^(lt|gt|eq)) 979 case positive: 980 addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r) 981 } 982 } 983 } 984 985 // addRestrictions updates restrictions from the immediate 986 // dominating block (p) using r. 987 func addRestrictions(parent *Block, ft *factsTable, t domain, v, w *Value, r relation) { 988 if t == 0 { 989 // Trivial case: nothing to do. 990 // Shoult not happen, but just in case. 991 return 992 } 993 for i := domain(1); i <= t; i <<= 1 { 994 if t&i == 0 { 995 continue 996 } 997 ft.update(parent, v, w, i, r) 998 } 999 } 1000 1001 // addLocalInductiveFacts adds inductive facts when visiting b, where 1002 // b is a join point in a loop. In contrast with findIndVar, this 1003 // depends on facts established for b, which is why it happens when 1004 // visiting b. addLocalInductiveFacts specifically targets the pattern 1005 // created by OFORUNTIL, which isn't detected by findIndVar. 1006 // 1007 // TODO: It would be nice to combine this with findIndVar. 1008 func addLocalInductiveFacts(ft *factsTable, b *Block) { 1009 // This looks for a specific pattern of induction: 1010 // 1011 // 1. i1 = OpPhi(min, i2) in b 1012 // 2. i2 = i1 + 1 1013 // 3. i2 < max at exit from b.Preds[1] 1014 // 4. min < max 1015 // 1016 // If all of these conditions are true, then i1 < max and i1 >= min. 1017 1018 for _, i1 := range b.Values { 1019 if i1.Op != OpPhi { 1020 continue 1021 } 1022 1023 // Check for conditions 1 and 2. This is easy to do 1024 // and will throw out most phis. 1025 min, i2 := i1.Args[0], i1.Args[1] 1026 if i1q, delta := isConstDelta(i2); i1q != i1 || delta != 1 { 1027 continue 1028 } 1029 1030 // Try to prove condition 3. We can't just query the 1031 // fact table for this because we don't know what the 1032 // facts of b.Preds[1] are (in general, b.Preds[1] is 1033 // a loop-back edge, so we haven't even been there 1034 // yet). As a conservative approximation, we look for 1035 // this condition in the predecessor chain until we 1036 // hit a join point. 1037 uniquePred := func(b *Block) *Block { 1038 if len(b.Preds) == 1 { 1039 return b.Preds[0].b 1040 } 1041 return nil 1042 } 1043 pred, child := b.Preds[1].b, b 1044 for ; pred != nil; pred = uniquePred(pred) { 1045 if pred.Kind != BlockIf { 1046 continue 1047 } 1048 1049 br := unknown 1050 if pred.Succs[0].b == child { 1051 br = positive 1052 } 1053 if pred.Succs[1].b == child { 1054 if br != unknown { 1055 continue 1056 } 1057 br = negative 1058 } 1059 1060 tr, has := domainRelationTable[pred.Control.Op] 1061 if !has { 1062 continue 1063 } 1064 r := tr.r 1065 if br == negative { 1066 // Negative branch taken to reach b. 1067 // Complement the relations. 1068 r = (lt | eq | gt) ^ r 1069 } 1070 1071 // Check for i2 < max or max > i2. 1072 var max *Value 1073 if r == lt && pred.Control.Args[0] == i2 { 1074 max = pred.Control.Args[1] 1075 } else if r == gt && pred.Control.Args[1] == i2 { 1076 max = pred.Control.Args[0] 1077 } else { 1078 continue 1079 } 1080 1081 // Check condition 4 now that we have a 1082 // candidate max. For this we can query the 1083 // fact table. We "prove" min < max by showing 1084 // that min >= max is unsat. (This may simply 1085 // compare two constants; that's fine.) 1086 ft.checkpoint() 1087 ft.update(b, min, max, tr.d, gt|eq) 1088 proved := ft.unsat 1089 ft.restore() 1090 1091 if proved { 1092 // We know that min <= i1 < max. 1093 if b.Func.pass.debug > 0 { 1094 printIndVar(b, i1, min, max, 1, 0) 1095 } 1096 ft.update(b, min, i1, tr.d, lt|eq) 1097 ft.update(b, i1, max, tr.d, lt) 1098 } 1099 } 1100 } 1101 } 1102 1103 var ctzNonZeroOp = map[Op]Op{OpCtz8: OpCtz8NonZero, OpCtz16: OpCtz16NonZero, OpCtz32: OpCtz32NonZero, OpCtz64: OpCtz64NonZero} 1104 var mostNegativeDividend = map[Op]int64{ 1105 OpDiv16: -1 << 15, 1106 OpMod16: -1 << 15, 1107 OpDiv32: -1 << 31, 1108 OpMod32: -1 << 31, 1109 OpDiv64: -1 << 63, 1110 OpMod64: -1 << 63} 1111 1112 // simplifyBlock simplifies some constant values in b and evaluates 1113 // branches to non-uniquely dominated successors of b. 1114 func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) { 1115 for _, v := range b.Values { 1116 switch v.Op { 1117 case OpSlicemask: 1118 // Replace OpSlicemask operations in b with constants where possible. 1119 x, delta := isConstDelta(v.Args[0]) 1120 if x == nil { 1121 continue 1122 } 1123 // slicemask(x + y) 1124 // if x is larger than -y (y is negative), then slicemask is -1. 1125 lim, ok := ft.limits[x.ID] 1126 if !ok { 1127 continue 1128 } 1129 if lim.umin > uint64(-delta) { 1130 if v.Args[0].Op == OpAdd64 { 1131 v.reset(OpConst64) 1132 } else { 1133 v.reset(OpConst32) 1134 } 1135 if b.Func.pass.debug > 0 { 1136 b.Func.Warnl(v.Pos, "Proved slicemask not needed") 1137 } 1138 v.AuxInt = -1 1139 } 1140 case OpCtz8, OpCtz16, OpCtz32, OpCtz64: 1141 // On some architectures, notably amd64, we can generate much better 1142 // code for CtzNN if we know that the argument is non-zero. 1143 // Capture that information here for use in arch-specific optimizations. 1144 x := v.Args[0] 1145 lim, ok := ft.limits[x.ID] 1146 if !ok { 1147 continue 1148 } 1149 if lim.umin > 0 || lim.min > 0 || lim.max < 0 { 1150 if b.Func.pass.debug > 0 { 1151 b.Func.Warnl(v.Pos, "Proved %v non-zero", v.Op) 1152 } 1153 v.Op = ctzNonZeroOp[v.Op] 1154 } 1155 1156 case OpLsh8x8, OpLsh8x16, OpLsh8x32, OpLsh8x64, 1157 OpLsh16x8, OpLsh16x16, OpLsh16x32, OpLsh16x64, 1158 OpLsh32x8, OpLsh32x16, OpLsh32x32, OpLsh32x64, 1159 OpLsh64x8, OpLsh64x16, OpLsh64x32, OpLsh64x64, 1160 OpRsh8x8, OpRsh8x16, OpRsh8x32, OpRsh8x64, 1161 OpRsh16x8, OpRsh16x16, OpRsh16x32, OpRsh16x64, 1162 OpRsh32x8, OpRsh32x16, OpRsh32x32, OpRsh32x64, 1163 OpRsh64x8, OpRsh64x16, OpRsh64x32, OpRsh64x64, 1164 OpRsh8Ux8, OpRsh8Ux16, OpRsh8Ux32, OpRsh8Ux64, 1165 OpRsh16Ux8, OpRsh16Ux16, OpRsh16Ux32, OpRsh16Ux64, 1166 OpRsh32Ux8, OpRsh32Ux16, OpRsh32Ux32, OpRsh32Ux64, 1167 OpRsh64Ux8, OpRsh64Ux16, OpRsh64Ux32, OpRsh64Ux64: 1168 // Check whether, for a << b, we know that b 1169 // is strictly less than the number of bits in a. 1170 by := v.Args[1] 1171 lim, ok := ft.limits[by.ID] 1172 if !ok { 1173 continue 1174 } 1175 bits := 8 * v.Args[0].Type.Size() 1176 if lim.umax < uint64(bits) || (lim.max < bits && ft.isNonNegative(by)) { 1177 v.AuxInt = 1 // see shiftIsBounded 1178 if b.Func.pass.debug > 0 { 1179 b.Func.Warnl(v.Pos, "Proved %v bounded", v.Op) 1180 } 1181 } 1182 case OpDiv16, OpDiv32, OpDiv64, OpMod16, OpMod32, OpMod64: 1183 // On amd64 and 386 fix-up code can be avoided if we know 1184 // the divisor is not -1 or the dividend > MinIntNN. 1185 divr := v.Args[1] 1186 divrLim, divrLimok := ft.limits[divr.ID] 1187 divd := v.Args[0] 1188 divdLim, divdLimok := ft.limits[divd.ID] 1189 if (divrLimok && (divrLim.max < -1 || divrLim.min > -1)) || 1190 (divdLimok && divdLim.min > mostNegativeDividend[v.Op]) { 1191 v.AuxInt = 1 // see NeedsFixUp in genericOps - v.AuxInt = 0 means we have not proved 1192 // that the divisor is not -1 and the dividend is not the most negative, 1193 // so we need to add fix-up code. 1194 if b.Func.pass.debug > 0 { 1195 b.Func.Warnl(v.Pos, "Proved %v does not need fix-up", v.Op) 1196 } 1197 } 1198 } 1199 } 1200 1201 if b.Kind != BlockIf { 1202 return 1203 } 1204 1205 // Consider outgoing edges from this block. 1206 parent := b 1207 for i, branch := range [...]branch{positive, negative} { 1208 child := parent.Succs[i].b 1209 if getBranch(sdom, parent, child) != unknown { 1210 // For edges to uniquely dominated blocks, we 1211 // already did this when we visited the child. 1212 continue 1213 } 1214 // For edges to other blocks, this can trim a branch 1215 // even if we couldn't get rid of the child itself. 1216 ft.checkpoint() 1217 addBranchRestrictions(ft, parent, branch) 1218 unsat := ft.unsat 1219 ft.restore() 1220 if unsat { 1221 // This branch is impossible, so remove it 1222 // from the block. 1223 removeBranch(parent, branch) 1224 // No point in considering the other branch. 1225 // (It *is* possible for both to be 1226 // unsatisfiable since the fact table is 1227 // incomplete. We could turn this into a 1228 // BlockExit, but it doesn't seem worth it.) 1229 break 1230 } 1231 } 1232 } 1233 1234 func removeBranch(b *Block, branch branch) { 1235 if b.Func.pass.debug > 0 { 1236 verb := "Proved" 1237 if branch == positive { 1238 verb = "Disproved" 1239 } 1240 c := b.Control 1241 if b.Func.pass.debug > 1 { 1242 b.Func.Warnl(b.Pos, "%s %s (%s)", verb, c.Op, c) 1243 } else { 1244 b.Func.Warnl(b.Pos, "%s %s", verb, c.Op) 1245 } 1246 } 1247 b.Kind = BlockFirst 1248 b.SetControl(nil) 1249 if branch == positive { 1250 b.swapSuccessors() 1251 } 1252 } 1253 1254 // isNonNegative reports whether v is known to be greater or equal to zero. 1255 func isNonNegative(v *Value) bool { 1256 switch v.Op { 1257 case OpConst64: 1258 return v.AuxInt >= 0 1259 1260 case OpConst32: 1261 return int32(v.AuxInt) >= 0 1262 1263 case OpStringLen, OpSliceLen, OpSliceCap, 1264 OpZeroExt8to64, OpZeroExt16to64, OpZeroExt32to64: 1265 return true 1266 1267 case OpRsh64Ux64: 1268 by := v.Args[1] 1269 return by.Op == OpConst64 && by.AuxInt > 0 1270 1271 case OpRsh64x64: 1272 return isNonNegative(v.Args[0]) 1273 } 1274 return false 1275 } 1276 1277 // isConstDelta returns non-nil if v is equivalent to w+delta (signed). 1278 func isConstDelta(v *Value) (w *Value, delta int64) { 1279 cop := OpConst64 1280 switch v.Op { 1281 case OpAdd32, OpSub32: 1282 cop = OpConst32 1283 } 1284 switch v.Op { 1285 case OpAdd64, OpAdd32: 1286 if v.Args[0].Op == cop { 1287 return v.Args[1], v.Args[0].AuxInt 1288 } 1289 if v.Args[1].Op == cop { 1290 return v.Args[0], v.Args[1].AuxInt 1291 } 1292 case OpSub64, OpSub32: 1293 if v.Args[1].Op == cop { 1294 aux := v.Args[1].AuxInt 1295 if aux != -aux { // Overflow; too bad 1296 return v.Args[0], -aux 1297 } 1298 } 1299 } 1300 return nil, 0 1301 }