Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: extraneous CMPQ instructions #15509

Closed
josharian opened this issue May 2, 2016 · 8 comments
Closed

cmd/compile: extraneous CMPQ instructions #15509

josharian opened this issue May 2, 2016 · 8 comments

Comments

@josharian
Copy link
Contributor

package x

var i int

func inrange(n, lo, hi int) {
    b0 := n >= lo
    b1 := n < hi
    if b0 && b1 {
        i = 1
    }
}

Result:

"".inrange t=1 size=48 args=0x18 locals=0x0
    0x0000 00000 (x.go:6)   TEXT    "".r0(SB), $0-24
    0x0000 00000 (x.go:6)   NOP
    0x0000 00000 (x.go:6)   NOP
    0x0000 00000 (x.go:6)   FUNCDATA    $0, gclocals·790e5cc5051fc0affc980ade09e929ec(SB)
    0x0000 00000 (x.go:6)   FUNCDATA    $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
    0x0000 00000 (x.go:8)   MOVQ    "".n+8(FP), AX
    0x0005 00005 (x.go:8)   MOVQ    "".hi+24(FP), CX
    0x000a 00010 (x.go:8)   CMPQ    AX, CX
    0x000d 00013 (x.go:7)   MOVQ    "".lo+16(FP), DX
    0x0012 00018 (x.go:7)   CMPQ    AX, DX
    0x0015 00021 (x.go:9)   JLT 39
    0x0017 00023 (x.go:8)   CMPQ    AX, CX
    0x001a 00026 (x.go:9)   JGE 39
    0x001c 00028 (x.go:10)  MOVQ    $1, "".i(SB)
    0x0027 00039 (x.go:12)  RET

Observe that the CMPQ at 00010 is unnecessary. This arose when working on optimizing scanobject.

cc @randall77 @brtzsnr @aclements

@josharian josharian added this to the Go1.8 milestone May 2, 2016
@brtzsnr
Copy link
Contributor

brtzsnr commented May 2, 2016

Can you explain why the comparison is not necessary? It looks perfectly fine, but I'm jet-lagged so my mind is not very sharp right now.

@josharian
Copy link
Contributor Author

The resulting flag doesn't get used, and it gets overwritten by the CMPQ at 00018.

@brtzsnr
Copy link
Contributor

brtzsnr commented May 2, 2016

Ah, I missed that there are three comparisons, not two. It's actually subtle, a copy is introduced during flagalloc pass. The original is dead, but never removed.

  pass flagalloc begin
  pass flagalloc end [3125 ns]
inrange <nil>
  b1:
    v1 = InitMem <mem>
    v7 = Arg <int> {n}
    v8 = Arg <int> {lo}
    v10 = Arg <int> {hi}
    v12 = CMPQ <flags> v7 v10 DEAD
    v15 = CMPQ <flags> v7 v8
    GE v15 -> b4 b6
  b4: <- b1
    v14 = CMPQ <flags> v7 v10
    LT v14 -> b2 b7
  b2: <- b4
    v16 = VarDef <mem> {i} v1
    v3 = SB <uintptr>
    v17 = MOVQstoreconst <mem> {i} [val=1,off=0] v3 v16
    Plain -> b3
  b3: <- b5 b2
    v18 = Phi <mem> v1 v17
    Ret v18
  b7: <- b4
    Plain -> b5
  b5: <- b6 b7
    Plain -> b3
  b6: <- b1
    Plain -> b5

@brtzsnr
Copy link
Contributor

brtzsnr commented May 2, 2016

I wonder if the comparison should have been moved during the tighten pass. v11 has a single use, so it should be defined in b4 instead of b1, right? I'm not suggesting it's bug, just that it's not aggressive enough.

  pass tighten begin
  pass tighten end [11807 ns]
inrange <nil>
  b1:
    v1 = InitMem <mem>
    v7 = Arg <int> {n}
    v8 = Arg <int> {lo}
    v9 = Geq64 <bool> v7 v8
    v10 = Arg <int> {hi}
    v11 = Less64 <bool> v7 v10
    If v9 -> b4 b3
  b2: <- b4
    v16 = VarDef <mem> {i} v1
    v13 = Const64 <int> [1]
    v3 = SB <uintptr>
    v14 = Addr <*int> {i} v3
    v17 = Store <mem> [8] v14 v13 v16
    Plain -> b3
  b3: <- b1 b4 b2
    v18 = Phi <mem> v1 v1 v17
    Ret v18
  b4: <- b1
    If v11 -> b2 b3

@josharian
Copy link
Contributor Author

Yeah. Tighten won't move any values that depend on two values, for fear of increasing the number of live values that must be spilled and loaded. However, v11 depends on args, which never need to get spilled, so at worst this will (in general) introduce extra loads. There are other kinds of args (constants, what else?) that probably also should not get counted when making this decision.

@randall77
Copy link
Contributor

Fixing tighten to ignore args and rematerializeable values sounds good (for 1.8).

@josharian
Copy link
Contributor Author

Ok. Added to my queue. I don't think it'll fix all instances of this problem, but I will find out. :)

@josharian josharian self-assigned this May 3, 2016
@gopherbot
Copy link

CL https://golang.org/cl/28390 mentions this issue.

@golang golang locked and limited conversation to collaborators Sep 1, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants