mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Declare a function's arguments as having already been spilled so their use just requires a restore. Allow spill locations to be portions of larger objects the stack. Required to load portions of compound input arguments. Rename the memory input to InputMem. Use Arg for the pre-spilled argument values. Change-Id: I8fe2a03ffbba1022d98bfae2052b376b96d32dda Reviewed-on: https://go-review.googlesource.com/16536 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
134 lines
2.8 KiB
Go
134 lines
2.8 KiB
Go
// Copyright 2015 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 "testing"
|
|
|
|
func TestDeadLoop(t *testing.T) {
|
|
c := testConfig(t)
|
|
fun := Fun(c, "entry",
|
|
Bloc("entry",
|
|
Valu("mem", OpInitMem, TypeMem, 0, ".mem"),
|
|
Goto("exit")),
|
|
Bloc("exit",
|
|
Exit("mem")),
|
|
// dead loop
|
|
Bloc("deadblock",
|
|
// dead value in dead block
|
|
Valu("deadval", OpConstBool, TypeBool, 1, nil),
|
|
If("deadval", "deadblock", "exit")))
|
|
|
|
CheckFunc(fun.f)
|
|
Deadcode(fun.f)
|
|
CheckFunc(fun.f)
|
|
|
|
for _, b := range fun.f.Blocks {
|
|
if b == fun.blocks["deadblock"] {
|
|
t.Errorf("dead block not removed")
|
|
}
|
|
for _, v := range b.Values {
|
|
if v == fun.values["deadval"] {
|
|
t.Errorf("control value of dead block not removed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDeadValue(t *testing.T) {
|
|
c := testConfig(t)
|
|
fun := Fun(c, "entry",
|
|
Bloc("entry",
|
|
Valu("mem", OpInitMem, TypeMem, 0, ".mem"),
|
|
Valu("deadval", OpConst64, TypeInt64, 37, nil),
|
|
Goto("exit")),
|
|
Bloc("exit",
|
|
Exit("mem")))
|
|
|
|
CheckFunc(fun.f)
|
|
Deadcode(fun.f)
|
|
CheckFunc(fun.f)
|
|
|
|
for _, b := range fun.f.Blocks {
|
|
for _, v := range b.Values {
|
|
if v == fun.values["deadval"] {
|
|
t.Errorf("dead value not removed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNeverTaken(t *testing.T) {
|
|
c := testConfig(t)
|
|
fun := Fun(c, "entry",
|
|
Bloc("entry",
|
|
Valu("cond", OpConstBool, TypeBool, 0, nil),
|
|
Valu("mem", OpInitMem, TypeMem, 0, ".mem"),
|
|
If("cond", "then", "else")),
|
|
Bloc("then",
|
|
Goto("exit")),
|
|
Bloc("else",
|
|
Goto("exit")),
|
|
Bloc("exit",
|
|
Exit("mem")))
|
|
|
|
CheckFunc(fun.f)
|
|
Opt(fun.f)
|
|
Deadcode(fun.f)
|
|
CheckFunc(fun.f)
|
|
|
|
if fun.blocks["entry"].Kind != BlockPlain {
|
|
t.Errorf("if(false) not simplified")
|
|
}
|
|
for _, b := range fun.f.Blocks {
|
|
if b == fun.blocks["then"] {
|
|
t.Errorf("then block still present")
|
|
}
|
|
for _, v := range b.Values {
|
|
if v == fun.values["cond"] {
|
|
t.Errorf("constant condition still present")
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestNestedDeadBlocks(t *testing.T) {
|
|
c := testConfig(t)
|
|
fun := Fun(c, "entry",
|
|
Bloc("entry",
|
|
Valu("mem", OpInitMem, TypeMem, 0, ".mem"),
|
|
Valu("cond", OpConstBool, TypeBool, 0, nil),
|
|
If("cond", "b2", "b4")),
|
|
Bloc("b2",
|
|
If("cond", "b3", "b4")),
|
|
Bloc("b3",
|
|
If("cond", "b3", "b4")),
|
|
Bloc("b4",
|
|
If("cond", "b3", "exit")),
|
|
Bloc("exit",
|
|
Exit("mem")))
|
|
|
|
CheckFunc(fun.f)
|
|
Opt(fun.f)
|
|
CheckFunc(fun.f)
|
|
Deadcode(fun.f)
|
|
CheckFunc(fun.f)
|
|
if fun.blocks["entry"].Kind != BlockPlain {
|
|
t.Errorf("if(false) not simplified")
|
|
}
|
|
for _, b := range fun.f.Blocks {
|
|
if b == fun.blocks["b2"] {
|
|
t.Errorf("b2 block still present")
|
|
}
|
|
if b == fun.blocks["b3"] {
|
|
t.Errorf("b3 block still present")
|
|
}
|
|
for _, v := range b.Values {
|
|
if v == fun.values["cond"] {
|
|
t.Errorf("constant condition still present")
|
|
}
|
|
}
|
|
}
|
|
}
|