// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssa

// Shortcircuit finds situations where branch directions
// are always correlated and rewrites the CFG to take
// advantage of that fact.
// This optimization is useful for compiling && and || expressions.
func shortcircuit(f *Func) {
	// Step 1: Replace a phi arg with a constant if that arg
	// is the control value of a preceding If block.
	// b1:
	//    If a goto b2 else b3
	// b2: <- b1 ...
	//    x = phi(a, ...)
	//
	// We can replace the "a" in the phi with the constant true.
	ct := f.ConstBool(f.Entry.Line, f.Config.fe.TypeBool(), true)
	cf := f.ConstBool(f.Entry.Line, f.Config.fe.TypeBool(), false)
	for _, b := range f.Blocks {
		for _, v := range b.Values {
			if v.Op != OpPhi {
				continue
			}
			if !v.Type.IsBoolean() {
				continue
			}
			for i, a := range v.Args {
				p := b.Preds[i]
				if p.Kind != BlockIf {
					continue
				}
				if p.Control != a {
					continue
				}
				if p.Succs[0] == b {
					v.SetArg(i, ct)
				} else {
					v.SetArg(i, cf)
				}
			}
		}
	}

	// Step 2: Compute which values are live across blocks.
	live := make([]bool, f.NumValues())
	for _, b := range f.Blocks {
		for _, v := range b.Values {
			for _, a := range v.Args {
				if a.Block != v.Block {
					live[a.ID] = true
				}
			}
		}
		if b.Control != nil && b.Control.Block != b {
			live[b.Control.ID] = true
		}
	}

	// Step 3: Redirect control flow around known branches.
	// p:
	//   ... goto b ...
	// b: <- p ...
	//   v = phi(true, ...)
	//   if v goto t else u
	// We can redirect p to go directly to t instead of b.
	// (If v is not live after b).
	for _, b := range f.Blocks {
		if b.Kind != BlockIf {
			continue
		}
		if len(b.Values) != 1 {
			continue
		}
		v := b.Values[0]
		if v.Op != OpPhi {
			continue
		}
		if b.Control != v {
			continue
		}
		if live[v.ID] {
			continue
		}
		for i := 0; i < len(v.Args); i++ {
			a := v.Args[i]
			if a.Op != OpConstBool {
				continue
			}

			// The predecessor we come in from.
			p := b.Preds[i]
			// The successor we always go to when coming in
			// from that predecessor.
			t := b.Succs[1-a.AuxInt]

			// Change the edge p->b to p->t.
			for j, x := range p.Succs {
				if x == b {
					p.Succs[j] = t
					break
				}
			}

			// Fix up t to have one more predecessor.
			j := predIdx(t, b)
			t.Preds = append(t.Preds, p)
			for _, w := range t.Values {
				if w.Op != OpPhi {
					continue
				}
				w.AddArg(w.Args[j])
			}

			// Fix up b to have one less predecessor.
			n := len(b.Preds) - 1
			b.Preds[i] = b.Preds[n]
			b.Preds[n] = nil
			b.Preds = b.Preds[:n]
			v.Args[i].Uses--
			v.Args[i] = v.Args[n]
			v.Args[n] = nil
			v.Args = v.Args[:n]
			if n == 1 {
				v.Op = OpCopy
				// No longer a phi, stop optimizing here.
				break
			}
			i--
		}
	}
}

// predIdx returns the index where p appears in the predecessor list of b.
// p must be in the predecessor list of b.
func predIdx(b, p *Block) int {
	for i, x := range b.Preds {
		if x == p {
			return i
		}
	}
	panic("predecessor not found")
}
