1// Copyright 2015 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// Test control flow
6
7package main
8
9import "testing"
10
11// nor_ssa calculates NOR(a, b).
12// It is implemented in a way that generates
13// phi control values.
14func nor_ssa(a, b bool) bool {
15	var c bool
16	if a {
17		c = true
18	}
19	if b {
20		c = true
21	}
22	if c {
23		return false
24	}
25	return true
26}
27
28func testPhiControl(t *testing.T) {
29	tests := [...][3]bool{ // a, b, want
30		{false, false, true},
31		{true, false, false},
32		{false, true, false},
33		{true, true, false},
34	}
35	for _, test := range tests {
36		a, b := test[0], test[1]
37		got := nor_ssa(a, b)
38		want := test[2]
39		if want != got {
40			t.Errorf("nor(%t, %t)=%t got %t", a, b, want, got)
41		}
42	}
43}
44
45func emptyRange_ssa(b []byte) bool {
46	for _, x := range b {
47		_ = x
48	}
49	return true
50}
51
52func testEmptyRange(t *testing.T) {
53	if !emptyRange_ssa([]byte{}) {
54		t.Errorf("emptyRange_ssa([]byte{})=false, want true")
55	}
56}
57
58func switch_ssa(a int) int {
59	ret := 0
60	switch a {
61	case 5:
62		ret += 5
63	case 4:
64		ret += 4
65	case 3:
66		ret += 3
67	case 2:
68		ret += 2
69	case 1:
70		ret += 1
71	}
72	return ret
73
74}
75
76func fallthrough_ssa(a int) int {
77	ret := 0
78	switch a {
79	case 5:
80		ret++
81		fallthrough
82	case 4:
83		ret++
84		fallthrough
85	case 3:
86		ret++
87		fallthrough
88	case 2:
89		ret++
90		fallthrough
91	case 1:
92		ret++
93	}
94	return ret
95
96}
97
98func testFallthrough(t *testing.T) {
99	for i := 0; i < 6; i++ {
100		if got := fallthrough_ssa(i); got != i {
101			t.Errorf("fallthrough_ssa(i) = %d, wanted %d", got, i)
102		}
103	}
104}
105
106func testSwitch(t *testing.T) {
107	for i := 0; i < 6; i++ {
108		if got := switch_ssa(i); got != i {
109			t.Errorf("switch_ssa(i) = %d, wanted %d", got, i)
110		}
111	}
112}
113
114type junk struct {
115	step int
116}
117
118// flagOverwrite_ssa is intended to reproduce an issue seen where a XOR
119// was scheduled between a compare and branch, clearing flags.
120//go:noinline
121func flagOverwrite_ssa(s *junk, c int) int {
122	if '0' <= c && c <= '9' {
123		s.step = 0
124		return 1
125	}
126	if c == 'e' || c == 'E' {
127		s.step = 0
128		return 2
129	}
130	s.step = 0
131	return 3
132}
133
134func testFlagOverwrite(t *testing.T) {
135	j := junk{}
136	if got := flagOverwrite_ssa(&j, ' '); got != 3 {
137		t.Errorf("flagOverwrite_ssa = %d, wanted 3", got)
138	}
139}
140
141func TestCtl(t *testing.T) {
142	testPhiControl(t)
143	testEmptyRange(t)
144
145	testSwitch(t)
146	testFallthrough(t)
147
148	testFlagOverwrite(t)
149}
150