]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix tuple-generating flag ops as clobbering flags
authorKeith Randall <khr@golang.org>
Mon, 12 Sep 2016 20:47:55 +0000 (13:47 -0700)
committerKeith Randall <khr@golang.org>
Mon, 12 Sep 2016 22:41:03 +0000 (22:41 +0000)
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        <int32, flags>
v2 = Select0 v1  <int32>
v3 = Select1 v1  <flags>

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 <cherryyz@google.com>
src/cmd/compile/internal/ssa/flagalloc.go

index aefa81b5b3cb7ca78494b1b97e11209e6b7c8ac6..5d1ced42b4dbbb9276c66f042389c1f4e17a592e 100644 (file)
@@ -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 {