From: Heschi Kreinick Date: Wed, 31 Jan 2018 22:56:14 +0000 (-0500) Subject: cmd/compile/internal/ssa: shrink commonly-used structs X-Git-Tag: go1.11beta1~1509 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=108efc79c726402e13acae0299e9a7597a4d33ce;p=gostls13.git cmd/compile/internal/ssa: shrink commonly-used structs Replace the OnStack boolean in VarLoc with a flag bit in StackOffset. This doesn't get much memory savings since it's still 64-bit aligned, but does seem to help a bit anyway. Change liveSlot to fit into 16 bytes. Because nested structs still get padding, this required inlining it. Fortunately there's not much logic to copy. Change-Id: Ie19a409daa41aa310275c4517a021eecf8886441 Reviewed-on: https://go-review.googlesource.com/92401 Reviewed-by: David Chase --- diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index 661fc8f930..b58a90be5f 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -39,8 +39,27 @@ type BlockDebug struct { // A liveSlot is a slot that's live in loc at entry/exit of a block. type liveSlot struct { + // An inlined VarLoc, so it packs into 16 bytes instead of 20. + Registers RegisterSet + StackOffset + slot SlotID - loc VarLoc +} + +func (loc liveSlot) absent() bool { + return loc.Registers == 0 && !loc.onStack() +} + +// StackOffset encodes whether a value is on the stack and if so, where. It is +// a 31-bit integer followed by a presence flag at the low-order bit. +type StackOffset int32 + +func (s StackOffset) onStack() bool { + return s != 0 +} + +func (s StackOffset) stackOffsetValue() int32 { + return int32(s) >> 1 } // stateAtPC is the current state of all variables at some point. @@ -61,12 +80,12 @@ func (state *stateAtPC) reset(live []liveSlot) { registers[i] = registers[i][:0] } for _, live := range live { - slots[live.slot] = live.loc - if live.loc.Registers == 0 { + slots[live.slot] = VarLoc{live.Registers, live.StackOffset} + if live.Registers == 0 { continue } - mask := uint64(live.loc.Registers) + mask := uint64(live.Registers) for { if mask == 0 { break @@ -86,7 +105,7 @@ func (s *debugState) LocString(loc VarLoc) string { } var storage []string - if loc.OnStack { + if loc.onStack() { storage = append(storage, "stack") } @@ -100,9 +119,6 @@ func (s *debugState) LocString(loc VarLoc) string { storage = append(storage, s.registers[reg].String()) } - if len(storage) == 0 { - storage = append(storage, "!!!no storage!!!") - } return strings.Join(storage, ",") } @@ -111,13 +127,12 @@ type VarLoc struct { // The registers this variable is available in. There can be more than // one in various situations, e.g. it's being moved between registers. Registers RegisterSet - // OnStack indicates that the variable is on the stack at StackOffset. - OnStack bool - StackOffset int32 + + StackOffset } -func (loc *VarLoc) absent() bool { - return loc.Registers == 0 && !loc.OnStack +func (loc VarLoc) absent() bool { + return loc.Registers == 0 && !loc.onStack() } var BlockStart = &Value{ @@ -243,7 +258,7 @@ func (state *debugState) allocBlock(b *Block) *BlockDebug { } func (s *debugState) blockEndStateString(b *BlockDebug) string { - endState := stateAtPC{slots: make([]VarLoc, len(s.slots)), registers: make([][]SlotID, len(s.slots))} + endState := stateAtPC{slots: make([]VarLoc, len(s.slots)), registers: make([][]SlotID, len(s.registers))} endState.reset(b.endState) return s.stateString(endState) } @@ -411,7 +426,7 @@ func (state *debugState) liveness() []*BlockDebug { if slotLoc.absent() { continue } - state.cache.AppendLiveSlot(liveSlot{SlotID(slotID), slotLoc}) + state.cache.AppendLiveSlot(liveSlot{slot: SlotID(slotID), Registers: slotLoc.Registers, StackOffset: slotLoc.StackOffset}) } locs.endState = state.cache.GetLiveSlotSlice() } @@ -460,7 +475,7 @@ func (state *debugState) mergePredecessors(b *Block, blockLocs []*BlockDebug) ([ slotLocs := state.currentState.slots for _, predSlot := range p0 { - slotLocs[predSlot.slot] = predSlot.loc + slotLocs[predSlot.slot] = VarLoc{predSlot.Registers, predSlot.StackOffset} state.liveCount[predSlot.slot] = 1 } for i := 1; i < len(preds); i++ { @@ -470,11 +485,10 @@ func (state *debugState) mergePredecessors(b *Block, blockLocs []*BlockDebug) ([ for _, predSlot := range blockLocs[preds[i].ID].endState { state.liveCount[predSlot.slot]++ liveLoc := slotLocs[predSlot.slot] - if !liveLoc.OnStack || !predSlot.loc.OnStack || liveLoc.StackOffset != predSlot.loc.StackOffset { - liveLoc.OnStack = false + if !liveLoc.onStack() || !predSlot.onStack() || liveLoc.StackOffset != predSlot.StackOffset { liveLoc.StackOffset = 0 } - liveLoc.Registers &= predSlot.loc.Registers + liveLoc.Registers &= predSlot.Registers slotLocs[predSlot.slot] = liveLoc } } @@ -484,7 +498,9 @@ func (state *debugState) mergePredecessors(b *Block, blockLocs []*BlockDebug) ([ // but it's probably not worth checking more than the first. unchanged := true for _, predSlot := range p0 { - if state.liveCount[predSlot.slot] != len(preds) || slotLocs[predSlot.slot] != predSlot.loc { + if state.liveCount[predSlot.slot] != len(preds) || + slotLocs[predSlot.slot].Registers != predSlot.Registers || + slotLocs[predSlot.slot].StackOffset != predSlot.StackOffset { unchanged = false break } @@ -563,7 +579,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) continue } regs := last.Registers &^ (1 << uint8(reg)) - setSlot(slot, VarLoc{regs, last.OnStack, last.StackOffset}) + setSlot(slot, VarLoc{regs, last.StackOffset}) } locs.registers[reg] = locs.registers[reg][:0] @@ -572,7 +588,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) switch { case v.Op == OpArg: home := state.f.getHome(v.ID).(LocalSlot) - stackOffset := state.stackOffset(home) + stackOffset := state.stackOffset(home)<<1 | 1 for _, slot := range vSlots { if state.loggingEnabled { state.logf("at %v: arg %v now on stack in location %v\n", v.ID, state.slots[slot], home) @@ -581,12 +597,12 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) } } - setSlot(slot, VarLoc{0, true, stackOffset}) + setSlot(slot, VarLoc{0, StackOffset(stackOffset)}) } case v.Op == OpStoreReg: home := state.f.getHome(v.ID).(LocalSlot) - stackOffset := state.stackOffset(home) + stackOffset := state.stackOffset(home)<<1 | 1 for _, slot := range vSlots { last := locs.slots[slot] if last.absent() { @@ -594,7 +610,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) break } - setSlot(slot, VarLoc{last.Registers, true, stackOffset}) + setSlot(slot, VarLoc{last.Registers, StackOffset(stackOffset)}) if state.loggingEnabled { state.logf("at %v: %v spilled to stack location %v\n", v.ID, state.slots[slot], home) } @@ -616,7 +632,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) for _, slot := range locs.registers[vReg.num] { last := locs.slots[slot] - setSlot(slot, VarLoc{last.Registers &^ (1 << uint8(vReg.num)), last.OnStack, last.StackOffset}) + setSlot(slot, VarLoc{last.Registers &^ (1 << uint8(vReg.num)), last.StackOffset}) } locs.registers[vReg.num] = locs.registers[vReg.num][:0] locs.registers[vReg.num] = append(locs.registers[vReg.num], vSlots...) @@ -627,7 +643,6 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) var loc VarLoc loc.Registers |= 1 << uint8(vReg.num) if last := locs.slots[slot]; !last.absent() { - loc.OnStack = last.OnStack loc.StackOffset = last.StackOffset loc.Registers |= last.Registers } @@ -686,8 +701,8 @@ func canMerge(pending, new VarLoc) bool { if pending.absent() || new.absent() { return false } - if pending.OnStack { - return new.OnStack && pending.StackOffset == new.StackOffset + if pending.onStack() { + return pending.StackOffset == new.StackOffset } if pending.Registers != 0 && new.Registers != 0 { return firstReg(pending.Registers) == firstReg(new.Registers) @@ -752,12 +767,12 @@ func (state *debugState) buildLocationLists(Ctxt *obj.Link, blockLocs []*BlockDe slot := state.slots[slotID] if !loc.absent() { - if loc.OnStack { - if loc.StackOffset == 0 { + if loc.onStack() { + if loc.stackOffsetValue() == 0 { list = append(list, dwarf.DW_OP_call_frame_cfa) } else { list = append(list, dwarf.DW_OP_fbreg) - list = dwarf.AppendSleb128(list, int64(loc.StackOffset)) + list = dwarf.AppendSleb128(list, int64(loc.stackOffsetValue())) } } else { regnum := Ctxt.Arch.DWARFRegisters[state.registers[firstReg(loc.Registers)].ObjNum()] @@ -933,8 +948,8 @@ func decodeValue(ctxt *obj.Link, word uint64) (ID, ID) { // Append a pointer-sized uint to buf. func appendPtr(ctxt *obj.Link, buf []byte, word uint64) []byte { - if cap(buf) < len(buf)+100 { - b := make([]byte, len(buf), 100+cap(buf)*2) + if cap(buf) < len(buf)+20 { + b := make([]byte, len(buf), 20+cap(buf)*2) copy(b, buf) buf = b }