// 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 ssacompile

import (
	"cmd/compile/internal/ssa"
	"cmd/compile/internal/ssa/block"
	"cmd/compile/internal/ssa/ssaop"
)

// phiopt eliminates boolean Phis based on the previous if.
//
// Main use case is to transform:
//
//	x := false
//	if b {
//	  x = true
//	}
//
// into x = b.
//
// In SSA code this appears as
//
//	b0
//	  If b -> b1 b2
//	b1
//	  Plain -> b2
//	b2
//	  x = (OpPhi (ConstBool [true]) (ConstBool [false]))
//
// In this case we can replace x with a copy of b.
func phiopt(f *ssa.Func) {
	sdom := f.Sdom()
	for _, b := range f.Blocks {
		if len(b.Preds) != 2 || len(b.Values) == 0 {
			// TODO: handle more than 2 predecessors, e.g. a || b || c.
			continue
		}

		pb0, b0 := b, b.Preds[0].B
		for len(b0.Succs) == 1 && len(b0.Preds) == 1 {
			pb0, b0 = b0, b0.Preds[0].B
		}
		if b0.Kind != block.BlockIf {
			continue
		}
		pb1, b1 := b, b.Preds[1].B
		for len(b1.Succs) == 1 && len(b1.Preds) == 1 {
			pb1, b1 = b1, b1.Preds[0].B
		}
		if b1 != b0 {
			continue
		}
		// b0 is the if block giving the boolean value.
		// reverse is the predecessor from which the truth value comes.
		var reverse int
		if b0.Succs[0].B == pb0 && b0.Succs[1].B == pb1 {
			reverse = 0
		} else if b0.Succs[0].B == pb1 && b0.Succs[1].B == pb0 {
			reverse = 1
		} else {
			b.Fatalf("invalid predecessors\n")
		}

		for _, v := range b.Values {
			if v.Op != ssaop.OpPhi {
				continue
			}

			// Look for conversions from bool to 0/1.
			if v.Type.IsInteger() {
				phioptint(v, b0, reverse)
			}

			if !v.Type.IsBoolean() {
				continue
			}

			// Replaces
			//   if a { x = true } else { x = false } with x = a
			// and
			//   if a { x = false } else { x = true } with x = !a
			if v.Args[0].Op == ssaop.OpConstBool && v.Args[1].Op == ssaop.OpConstBool {
				if v.Args[reverse].AuxInt != v.Args[1-reverse].AuxInt {
					ops := [2]ssaop.Op{ssaop.OpNot, ssaop.OpCopy}
					v.Reset(ops[v.Args[reverse].AuxInt])
					v.AddArg(b0.Controls[0])
					if f.Pass.Debug > 0 {
						f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
					}
					continue
				}
			}

			// Replaces
			//   if a { x = true } else { x = value } with x = a || value.
			// Requires that value dominates x, meaning that regardless of a,
			// value is always computed. This guarantees that the side effects
			// of value are not seen if a is false.
			if v.Args[reverse].Op == ssaop.OpConstBool && v.Args[reverse].AuxInt == 1 {
				if tmp := v.Args[1-reverse]; sdom.IsAncestorEq(tmp.Block, b) {
					v.Reset(ssaop.OpOrB)
					v.SetArgs2(b0.Controls[0], tmp)
					if f.Pass.Debug > 0 {
						f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
					}
					continue
				}
			}

			// Replaces
			//   if a { x = value } else { x = false } with x = a && value.
			// Requires that value dominates x, meaning that regardless of a,
			// value is always computed. This guarantees that the side effects
			// of value are not seen if a is false.
			if v.Args[1-reverse].Op == ssaop.OpConstBool && v.Args[1-reverse].AuxInt == 0 {
				if tmp := v.Args[reverse]; sdom.IsAncestorEq(tmp.Block, b) {
					v.Reset(ssaop.OpAndB)
					v.SetArgs2(b0.Controls[0], tmp)
					if f.Pass.Debug > 0 {
						f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
					}
					continue
				}
			}
			// Replaces
			//   if a { x = value } else { x = a } with x = a && value.
			// Requires that value dominates x.
			if v.Args[1-reverse] == b0.Controls[0] {
				if tmp := v.Args[reverse]; sdom.IsAncestorEq(tmp.Block, b) {
					v.Reset(ssaop.OpAndB)
					v.SetArgs2(b0.Controls[0], tmp)
					if f.Pass.Debug > 0 {
						f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
					}
					continue
				}
			}

			// Replaces
			//   if a { x = a } else { x = value } with x = a || value.
			// Requires that value dominates x.
			if v.Args[reverse] == b0.Controls[0] {
				if tmp := v.Args[1-reverse]; sdom.IsAncestorEq(tmp.Block, b) {
					v.Reset(ssaop.OpOrB)
					v.SetArgs2(b0.Controls[0], tmp)
					if f.Pass.Debug > 0 {
						f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
					}
					continue
				}
			}
		}
	}
	// strengthen phi optimization.
	// Main use case is to transform:
	//   x := false
	//   if c {
	//     x = true
	//     ...
	//   }
	// into
	//   x := c
	//   if x { ... }
	//
	// For example, in SSA code a case appears as
	// b0
	//   If c -> b, sb0
	// sb0
	//   If d -> sd0, sd1
	// sd1
	//   ...
	// sd0
	//   Plain -> b
	// b
	//   x = (OpPhi (ConstBool [true]) (ConstBool [false]))
	//
	// In this case we can also replace x with a copy of c.
	//
	// The optimization idea:
	// 1. block b has a phi value x, x = OpPhi (ConstBool [true]) (ConstBool [false]),
	//    and len(b.Preds) is equal to 2.
	// 2. find the common dominator(b0) of the predecessors(pb0, pb1) of block b, and the
	//    dominator(b0) is a If block.
	//    Special case: one of the predecessors(pb0 or pb1) is the dominator(b0).
	// 3. the successors(sb0, sb1) of the dominator need to dominate the predecessors(pb0, pb1)
	//    of block b respectively.
	// 4. replace this boolean Phi based on dominator block.
	//
	//     b0(pb0)            b0(pb1)          b0
	//    |  \               /  |             /  \
	//    |  sb1           sb0  |           sb0  sb1
	//    |  ...           ...  |           ...   ...
	//    |  pb1           pb0  |           pb0  pb1
	//    |  /               \  |            \   /
	//     b                   b               b
	//
	var lca *lcaRange
	for _, b := range f.Blocks {
		if len(b.Preds) != 2 || len(b.Values) == 0 {
			// TODO: handle more than 2 predecessors, e.g. a || b || c.
			continue
		}

		for _, v := range b.Values {
			// find a phi value v = OpPhi (ConstBool [true]) (ConstBool [false]).
			// TODO: v = OpPhi (ConstBool [true]) (Arg <bool> {value})
			if v.Op != ssaop.OpPhi {
				continue
			}
			if v.Args[0].Op != ssaop.OpConstBool || v.Args[1].Op != ssaop.OpConstBool {
				continue
			}
			if v.Args[0].AuxInt == v.Args[1].AuxInt {
				continue
			}

			pb0 := b.Preds[0].B
			pb1 := b.Preds[1].B
			if pb0.Kind == block.BlockIf && pb0 == sdom.Parent(b) {
				// special case: pb0 is the dominator block b0.
				//     b0(pb0)
				//    |  \
				//    |  sb1
				//    |  ...
				//    |  pb1
				//    |  /
				//     b
				// if another successor sb1 of b0(pb0) dominates pb1, do replace.
				ei := b.Preds[0].I
				sb1 := pb0.Succs[1-ei].B
				if sdom.IsAncestorEq(sb1, pb1) {
					convertPhi(pb0, v, ei)
					break
				}
			} else if pb1.Kind == block.BlockIf && pb1 == sdom.Parent(b) {
				// special case: pb1 is the dominator block b0.
				//       b0(pb1)
				//     /   |
				//    sb0  |
				//    ...  |
				//    pb0  |
				//      \  |
				//        b
				// if another successor sb0 of b0(pb0) dominates pb0, do replace.
				ei := b.Preds[1].I
				sb0 := pb1.Succs[1-ei].B
				if sdom.IsAncestorEq(sb0, pb0) {
					convertPhi(pb1, v, 1-ei)
					break
				}
			} else {
				//      b0
				//     /   \
				//    sb0  sb1
				//    ...  ...
				//    pb0  pb1
				//      \   /
				//        b
				//
				// Build data structure for fast least-common-ancestor queries.
				if lca == nil {
					lca = makeLCArange(f)
				}
				b0 := lca.find(pb0, pb1)
				if b0.Kind != block.BlockIf {
					break
				}
				sb0 := b0.Succs[0].B
				sb1 := b0.Succs[1].B
				var reverse int
				if sdom.IsAncestorEq(sb0, pb0) && sdom.IsAncestorEq(sb1, pb1) {
					reverse = 0
				} else if sdom.IsAncestorEq(sb1, pb0) && sdom.IsAncestorEq(sb0, pb1) {
					reverse = 1
				} else {
					break
				}
				if len(sb0.Preds) != 1 || len(sb1.Preds) != 1 {
					// we can not replace phi value x in the following case.
					//   if gp == nil || sp < lo { x = true}
					//   if a || b { x = true }
					// so the if statement can only have one condition.
					break
				}
				convertPhi(b0, v, reverse)
			}
		}
	}
}

func phioptint(v *ssa.Value, b0 *ssa.Block, reverse int) {
	a0 := v.Args[0]
	a1 := v.Args[1]
	if a0.Op != a1.Op {
		return
	}

	switch a0.Op {
	case ssaop.OpConst8, ssaop.OpConst16, ssaop.OpConst32, ssaop.OpConst64:
	default:
		return
	}

	negate := false
	switch {
	case a0.AuxInt == 0 && a1.AuxInt == 1:
		negate = true
	case a0.AuxInt == 1 && a1.AuxInt == 0:
	default:
		return
	}

	if reverse == 1 {
		negate = !negate
	}

	a := b0.Controls[0]
	if negate {
		a = v.Block.NewValue1(v.Pos, ssaop.OpNot, a.Type, a)
	}
	v.AddArg(a)

	cvt := v.Block.NewValue1(v.Pos, ssaop.OpCvtBoolToUint8, v.Block.Func.Config.Types.UInt8, a)
	switch v.Type.Size() {
	case 1:
		v.Reset(ssaop.OpCopy)
	case 2:
		v.Reset(ssaop.OpZeroExt8to16)
	case 4:
		v.Reset(ssaop.OpZeroExt8to32)
	case 8:
		v.Reset(ssaop.OpZeroExt8to64)
	default:
		v.Fatalf("bad int size %d", v.Type.Size())
	}
	v.AddArg(cvt)

	f := b0.Func
	if f.Pass.Debug > 0 {
		f.Warnl(v.Block.Pos, "converted OpPhi bool -> int%d", v.Type.Size()*8)
	}
}

// b is the If block giving the boolean value.
// v is the phi value v = (OpPhi (ConstBool [true]) (ConstBool [false])).
// reverse is the predecessor from which the truth value comes.
func convertPhi(b *ssa.Block, v *ssa.Value, reverse int) {
	f := b.Func
	ops := [2]ssaop.Op{ssaop.OpNot, ssaop.OpCopy}
	v.Reset(ops[v.Args[reverse].AuxInt])
	v.AddArg(b.Controls[0])
	if f.Pass.Debug > 0 {
		f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
	}
}
