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 75func fallthrough_ssa(a int) int { 76 ret := 0 77 switch a { 78 case 5: 79 ret++ 80 fallthrough 81 case 4: 82 ret++ 83 fallthrough 84 case 3: 85 ret++ 86 fallthrough 87 case 2: 88 ret++ 89 fallthrough 90 case 1: 91 ret++ 92 } 93 return ret 94} 95 96func testFallthrough(t *testing.T) { 97 for i := 0; i < 6; i++ { 98 if got := fallthrough_ssa(i); got != i { 99 t.Errorf("fallthrough_ssa(i) = %d, wanted %d", got, i) 100 } 101 } 102} 103 104func testSwitch(t *testing.T) { 105 for i := 0; i < 6; i++ { 106 if got := switch_ssa(i); got != i { 107 t.Errorf("switch_ssa(i) = %d, wanted %d", got, i) 108 } 109 } 110} 111 112type junk struct { 113 step int 114} 115 116// flagOverwrite_ssa is intended to reproduce an issue seen where a XOR 117// was scheduled between a compare and branch, clearing flags. 118// 119//go:noinline 120func flagOverwrite_ssa(s *junk, c int) int { 121 if '0' <= c && c <= '9' { 122 s.step = 0 123 return 1 124 } 125 if c == 'e' || c == 'E' { 126 s.step = 0 127 return 2 128 } 129 s.step = 0 130 return 3 131} 132 133func testFlagOverwrite(t *testing.T) { 134 j := junk{} 135 if got := flagOverwrite_ssa(&j, ' '); got != 3 { 136 t.Errorf("flagOverwrite_ssa = %d, wanted 3", got) 137 } 138} 139 140func TestCtl(t *testing.T) { 141 testPhiControl(t) 142 testEmptyRange(t) 143 144 testSwitch(t) 145 testFallthrough(t) 146 147 testFlagOverwrite(t) 148} 149