From: Keith Randall Date: Mon, 12 Sep 2016 20:47:55 +0000 (-0700) Subject: cmd/compile: fix tuple-generating flag ops as clobbering flags X-Git-Tag: go1.8beta1~1359 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=6ca7c2055bd114c08426d3dbdee444b280b569b6;p=gostls13.git cmd/compile: fix tuple-generating flag ops as clobbering flags If an op generates a tuple, and part of that tuple is of flags type, then treat the op as clobbering flags. Normally this doesn't matter because we do: v1 = ADDS v2 = Select0 v1 v3 = Select1 v1 And v3 will do the right clobbering of flags. But in the rare cases where we issue a tuple-with-flag op and the flag portion is dead, then we never issue a Select1. But v1 still clobbers flags, so we need to respect that. Fixes builder failure in CL 28950. Change-Id: I589089fd81aaeaaa9750bb8d85e7b10199aaa002 Reviewed-on: https://go-review.googlesource.com/29083 Reviewed-by: Cherry Zhang --- diff --git a/src/cmd/compile/internal/ssa/flagalloc.go b/src/cmd/compile/internal/ssa/flagalloc.go index aefa81b5b3..5d1ced42b4 100644 --- a/src/cmd/compile/internal/ssa/flagalloc.go +++ b/src/cmd/compile/internal/ssa/flagalloc.go @@ -31,7 +31,7 @@ func flagalloc(f *Func) { if v == flag { flag = nil } - if opcodeTable[v.Op].clobberFlags { + if v.clobbersFlags() { flag = nil } for _, a := range v.Args { @@ -103,7 +103,7 @@ func flagalloc(f *Func) { } // Issue v. b.Values = append(b.Values, v) - if opcodeTable[v.Op].clobberFlags { + if v.clobbersFlags() { flag = nil } if v.Type.IsFlags() { @@ -134,6 +134,19 @@ func flagalloc(f *Func) { } } +func (v *Value) clobbersFlags() bool { + if opcodeTable[v.Op].clobberFlags { + return true + } + if v.Type.IsTuple() && (v.Type.FieldType(0).IsFlags() || v.Type.FieldType(1).IsFlags()) { + // This case handles the possibility where a flag value is generated but never used. + // In that case, there's no corresponding Select to overwrite the flags value, + // so we must consider flags clobbered by the tuple-generating instruction. + return true + } + return false +} + // copyFlags copies v (flag generator) into b, returns the copy. // If v's arg is also flags, copy recursively. func copyFlags(v *Value, b *Block) *Value {