github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/src/cmd/compile/internal/ssa/branchelim_test.go (about) 1 // Copyright 2017 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 "cmd/compile/internal/types" 9 "testing" 10 ) 11 12 // Test that a trivial 'if' is eliminated 13 func TestBranchElimIf(t *testing.T) { 14 c := testConfig(t) 15 c.config.arch = "arm64" // FIXME 16 boolType := types.New(types.TBOOL) 17 intType := types.New(types.TINT32) 18 fun := c.Fun("entry", 19 Bloc("entry", 20 Valu("start", OpInitMem, types.TypeMem, 0, nil), 21 Valu("sb", OpSB, types.TypeInvalid, 0, nil), 22 Valu("const1", OpConst32, intType, 1, nil), 23 Valu("const2", OpConst32, intType, 2, nil), 24 Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"), 25 Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"), 26 If("cond", "b2", "b3")), 27 Bloc("b2", 28 Goto("b3")), 29 Bloc("b3", 30 Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"), 31 Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"), 32 Exit("retstore"))) 33 34 CheckFunc(fun.f) 35 branchelim(fun.f) 36 CheckFunc(fun.f) 37 Deadcode(fun.f) 38 CheckFunc(fun.f) 39 40 if len(fun.f.Blocks) != 1 { 41 t.Errorf("expected 1 block after branchelim and deadcode; found %d", len(fun.f.Blocks)) 42 } 43 if fun.values["phi"].Op != OpCondSelect { 44 t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op) 45 } 46 if fun.values["phi"].Args[2] != fun.values["cond"] { 47 t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2]) 48 } 49 if fun.blocks["entry"].Kind != BlockExit { 50 t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String()) 51 } 52 } 53 54 // Test that a trivial if/else is eliminated 55 func TestBranchElimIfElse(t *testing.T) { 56 c := testConfig(t) 57 c.config.arch = "arm64" // FIXME 58 boolType := types.New(types.TBOOL) 59 intType := types.New(types.TINT32) 60 fun := c.Fun("entry", 61 Bloc("entry", 62 Valu("start", OpInitMem, types.TypeMem, 0, nil), 63 Valu("sb", OpSB, types.TypeInvalid, 0, nil), 64 Valu("const1", OpConst32, intType, 1, nil), 65 Valu("const2", OpConst32, intType, 2, nil), 66 Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"), 67 Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"), 68 If("cond", "b2", "b3")), 69 Bloc("b2", 70 Goto("b4")), 71 Bloc("b3", 72 Goto("b4")), 73 Bloc("b4", 74 Valu("phi", OpPhi, intType, 0, nil, "const1", "const2"), 75 Valu("retstore", OpStore, types.TypeMem, 0, nil, "phi", "sb", "start"), 76 Exit("retstore"))) 77 78 CheckFunc(fun.f) 79 branchelim(fun.f) 80 CheckFunc(fun.f) 81 Deadcode(fun.f) 82 CheckFunc(fun.f) 83 84 if len(fun.f.Blocks) != 1 { 85 t.Errorf("expected 1 block after branchelim; found %d", len(fun.f.Blocks)) 86 } 87 if fun.values["phi"].Op != OpCondSelect { 88 t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op) 89 } 90 if fun.values["phi"].Args[2] != fun.values["cond"] { 91 t.Errorf("expected CondSelect condition to be %s; found %s", fun.values["cond"], fun.values["phi"].Args[2]) 92 } 93 if fun.blocks["entry"].Kind != BlockExit { 94 t.Errorf("expected entry to be BlockExit; found kind %s", fun.blocks["entry"].Kind.String()) 95 } 96 } 97 98 // Test that an if/else CFG that loops back 99 // into itself does *not* get eliminated. 100 func TestNoBranchElimLoop(t *testing.T) { 101 c := testConfig(t) 102 c.config.arch = "arm64" // FIXME 103 boolType := types.New(types.TBOOL) 104 intType := types.New(types.TINT32) 105 106 // The control flow here is totally bogus, 107 // but a dead cycle seems like the only plausible 108 // way to arrive at a diamond CFG that is also a loop. 109 fun := c.Fun("entry", 110 Bloc("entry", 111 Valu("start", OpInitMem, types.TypeMem, 0, nil), 112 Valu("sb", OpSB, types.TypeInvalid, 0, nil), 113 Valu("const2", OpConst32, intType, 2, nil), 114 Valu("const3", OpConst32, intType, 3, nil), 115 Goto("b5")), 116 Bloc("b2", 117 Valu("addr", OpAddr, boolType.PtrTo(), 0, nil, "sb"), 118 Valu("cond", OpLoad, boolType, 0, nil, "addr", "start"), 119 Valu("phi", OpPhi, intType, 0, nil, "const2", "const3"), 120 If("cond", "b3", "b4")), 121 Bloc("b3", 122 Goto("b2")), 123 Bloc("b4", 124 Goto("b2")), 125 Bloc("b5", 126 Exit("start"))) 127 128 CheckFunc(fun.f) 129 branchelim(fun.f) 130 CheckFunc(fun.f) 131 132 if len(fun.f.Blocks) != 5 { 133 t.Errorf("expected 5 block after branchelim; found %d", len(fun.f.Blocks)) 134 } 135 if fun.values["phi"].Op != OpPhi { 136 t.Errorf("expected phi op to be CondSelect; found op %s", fun.values["phi"].Op) 137 } 138 }