github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/cmd/compile/internal/ssa/schedule_test.go (about) 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 package ssa 6 7 import ( 8 "cmd/compile/internal/types" 9 "testing" 10 ) 11 12 func TestSchedule(t *testing.T) { 13 c := testConfig(t) 14 cases := []fun{ 15 c.Fun("entry", 16 Bloc("entry", 17 Valu("mem0", OpInitMem, types.TypeMem, 0, nil), 18 Valu("ptr", OpConst64, c.config.Types.Int64, 0xABCD, nil), 19 Valu("v", OpConst64, c.config.Types.Int64, 12, nil), 20 Valu("mem1", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "v", "mem0"), 21 Valu("mem2", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "v", "mem1"), 22 Valu("mem3", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "sum", "mem2"), 23 Valu("l1", OpLoad, c.config.Types.Int64, 0, nil, "ptr", "mem1"), 24 Valu("l2", OpLoad, c.config.Types.Int64, 0, nil, "ptr", "mem2"), 25 Valu("sum", OpAdd64, c.config.Types.Int64, 0, nil, "l1", "l2"), 26 Goto("exit")), 27 Bloc("exit", 28 Exit("mem3"))), 29 } 30 for _, c := range cases { 31 schedule(c.f) 32 if !isSingleLiveMem(c.f) { 33 t.Error("single-live-mem restriction not enforced by schedule for func:") 34 printFunc(c.f) 35 } 36 } 37 } 38 39 func isSingleLiveMem(f *Func) bool { 40 for _, b := range f.Blocks { 41 var liveMem *Value 42 for _, v := range b.Values { 43 for _, w := range v.Args { 44 if w.Type.IsMemory() { 45 if liveMem == nil { 46 liveMem = w 47 continue 48 } 49 if w != liveMem { 50 return false 51 } 52 } 53 } 54 if v.Type.IsMemory() { 55 liveMem = v 56 } 57 } 58 } 59 return true 60 } 61 62 func TestStoreOrder(t *testing.T) { 63 // In the function below, v2 depends on v3 and v4, v4 depends on v3, and v3 depends on store v5. 64 // storeOrder did not handle this case correctly. 65 c := testConfig(t) 66 fun := c.Fun("entry", 67 Bloc("entry", 68 Valu("mem0", OpInitMem, types.TypeMem, 0, nil), 69 Valu("a", OpAdd64, c.config.Types.Int64, 0, nil, "b", "c"), // v2 70 Valu("b", OpLoad, c.config.Types.Int64, 0, nil, "ptr", "mem1"), // v3 71 Valu("c", OpNeg64, c.config.Types.Int64, 0, nil, "b"), // v4 72 Valu("mem1", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "v", "mem0"), // v5 73 Valu("mem2", OpStore, types.TypeMem, 0, c.config.Types.Int64, "ptr", "a", "mem1"), 74 Valu("ptr", OpConst64, c.config.Types.Int64, 0xABCD, nil), 75 Valu("v", OpConst64, c.config.Types.Int64, 12, nil), 76 Goto("exit")), 77 Bloc("exit", 78 Exit("mem2"))) 79 80 CheckFunc(fun.f) 81 order := storeOrder(fun.f.Blocks[0].Values, fun.f.newSparseSet(fun.f.NumValues()), make([]int32, fun.f.NumValues())) 82 83 // check that v2, v3, v4 is sorted after v5 84 var ai, bi, ci, si int 85 for i, v := range order { 86 switch v.ID { 87 case 2: 88 ai = i 89 case 3: 90 bi = i 91 case 4: 92 ci = i 93 case 5: 94 si = i 95 } 96 } 97 if ai < si || bi < si || ci < si { 98 t.Logf("Func: %s", fun.f) 99 t.Errorf("store order is wrong: got %v, want v2 v3 v4 after v5", order) 100 } 101 }