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