// 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 ssa import ( "cmd/compile/internal/types" "testing" ) func TestLICM(t *testing.T) { c := testConfig(t) fun := c.Fun("entry", Bloc("entry", Valu("mem", OpInitMem, types.TypeMem, 0, nil), Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil), Valu("a", OpConst64, c.config.Types.Int64, 14, nil), Goto("loop")), Bloc("loop", Valu("b", OpConst64, c.config.Types.Int64, 26, nil), Valu("sum", OpAdd64, c.config.Types.Int64, 0, nil, "a", "b"), Valu("load", OpLoad, c.config.Types.BytePtr, 0, nil, "sp", "mem"), Valu("nilptr", OpConstNil, c.config.Types.BytePtr, 0, nil), Valu("bool", OpNeqPtr, c.config.Types.Bool, 0, nil, "load", "nilptr"), If("bool", "loop", "exit")), Bloc("exit", Exit("mem"))) CheckFunc(fun.f) licm(fun.f) CheckFunc(fun.f) b := fun.blocks["entry"] if len(b.Values) != 5 { // b,sum should have been moved from loop to entry t.Errorf("loop invariant code wasn't lifted, but should have") } } func TestLICMNewBlock(t *testing.T) { c := testConfig(t) fun := c.Fun("entry", Bloc("entry", Valu("mem", OpInitMem, types.TypeMem, 0, nil), Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil), Valu("a", OpConst64, c.config.Types.Int64, 14, nil), Valu("bool2", OpConstBool, c.config.Types.Bool, 0, nil), If("bool2", "loop", "exit")), Bloc("loop", Valu("b", OpConst64, c.config.Types.Int64, 26, nil), Valu("sum", OpAdd64, c.config.Types.Int64, 0, nil, "a", "b"), Valu("load", OpLoad, c.config.Types.BytePtr, 0, nil, "sp", "mem"), Valu("nilptr", OpConstNil, c.config.Types.BytePtr, 0, nil), Valu("bool", OpNeqPtr, c.config.Types.Bool, 0, nil, "load", "nilptr"), If("bool", "loop", "exit")), Bloc("exit", Exit("mem"))) CheckFunc(fun.f) licm(fun.f) CheckFunc(fun.f) b := fun.blocks["entry"].Succs[0].b if len(b.Values) != 2 { // b,sum should have been moved from loop to new block between entry & loop t.Errorf("loop invariant code wasn't lifted, but should have") } }