diff options
author | Keith Randall <khr@golang.org> | 2015-05-28 13:49:20 -0700 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2015-05-28 13:51:18 -0700 |
commit | 067e8dfd82163ddcbde248dbe5a1187a417e5d36 (patch) | |
tree | 7bfb46b901d03498c7739c92bec21d81d3a2c485 /src/cmd/compile/internal/ssa/lower.go | |
parent | 247786c1745abc0c7185f7c15ca256edf68ed6d6 (diff) | |
parent | ccc037699e2966b7c79ba84c67471cef5e67a3b8 (diff) | |
download | go-067e8dfd82163ddcbde248dbe5a1187a417e5d36.tar.gz go-067e8dfd82163ddcbde248dbe5a1187a417e5d36.zip |
[dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch
Semi-regular merge of tip to dev.ssa.
Complicated a bit by the move of cmd/internal/* to cmd/compile/internal/*.
Change-Id: I1c66d3c29bb95cce4a53c5a3476373aa5245303d
Diffstat (limited to 'src/cmd/compile/internal/ssa/lower.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/lower.go | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/lower.go b/src/cmd/compile/internal/ssa/lower.go new file mode 100644 index 0000000000..44f0b83fa8 --- /dev/null +++ b/src/cmd/compile/internal/ssa/lower.go @@ -0,0 +1,112 @@ +// 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 "log" + +//go:generate go run rulegen/rulegen.go rulegen/lower_amd64.rules lowerAmd64 lowerAmd64.go + +// convert to machine-dependent ops +func lower(f *Func) { + // repeat rewrites until we find no more rewrites + applyRewrite(f, f.Config.lower) + + // Check for unlowered opcodes, fail if we find one. + for _, b := range f.Blocks { + for _, v := range b.Values { + if v.Op < OpGenericEnd && v.Op != OpFP && v.Op != OpSP && v.Op != OpArg && v.Op != OpCopy && v.Op != OpPhi { + log.Panicf("%s not lowered", v.LongString()) + } + } + } + + // additional pass for 386/amd64, link condition codes directly to blocks + // TODO: do generically somehow? Special "block" rewrite rules? + for _, b := range f.Blocks { + for { + switch b.Kind { + case BlockIf: + switch b.Control.Op { + case OpSETL: + b.Kind = BlockLT + b.Control = b.Control.Args[0] + continue + case OpSETNE: + b.Kind = BlockNE + b.Control = b.Control.Args[0] + continue + case OpSETB: + b.Kind = BlockULT + b.Control = b.Control.Args[0] + continue + case OpMOVBload: + b.Kind = BlockNE + b.Control = b.NewValue2(OpTESTB, TypeFlags, nil, b.Control, b.Control) + continue + // TODO: others + } + case BlockLT: + if b.Control.Op == OpInvertFlags { + b.Kind = BlockGT + b.Control = b.Control.Args[0] + continue + } + case BlockGT: + if b.Control.Op == OpInvertFlags { + b.Kind = BlockLT + b.Control = b.Control.Args[0] + continue + } + case BlockLE: + if b.Control.Op == OpInvertFlags { + b.Kind = BlockGE + b.Control = b.Control.Args[0] + continue + } + case BlockGE: + if b.Control.Op == OpInvertFlags { + b.Kind = BlockLE + b.Control = b.Control.Args[0] + continue + } + case BlockULT: + if b.Control.Op == OpInvertFlags { + b.Kind = BlockUGT + b.Control = b.Control.Args[0] + continue + } + case BlockUGT: + if b.Control.Op == OpInvertFlags { + b.Kind = BlockULT + b.Control = b.Control.Args[0] + continue + } + case BlockULE: + if b.Control.Op == OpInvertFlags { + b.Kind = BlockUGE + b.Control = b.Control.Args[0] + continue + } + case BlockUGE: + if b.Control.Op == OpInvertFlags { + b.Kind = BlockULE + b.Control = b.Control.Args[0] + continue + } + case BlockEQ: + if b.Control.Op == OpInvertFlags { + b.Control = b.Control.Args[0] + continue + } + case BlockNE: + if b.Control.Op == OpInvertFlags { + b.Control = b.Control.Args[0] + continue + } + } + break + } + } +} |