From 71b570774da4c42139a9e16735a353209f0f8def Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 24 Jul 2015 12:47:00 -0700 Subject: [PATCH] [dev.ssa] cmd/compile: finish implementing comparisons Change-Id: I4e496c7c7239111133631f76ca25e14be64800c6 Reviewed-on: https://go-review.googlesource.com/12656 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 105 +++++----------- src/cmd/compile/internal/ssa/gen/AMD64.rules | 6 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 3 + src/cmd/compile/internal/ssa/opGen.go | 39 ++++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 120 +++++++++++++++++++ 5 files changed, 197 insertions(+), 76 deletions(-) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 2b6962a979..b8831793fc 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1702,7 +1702,8 @@ func genValue(v *ssa.Value) { case ssa.OpAMD64SETEQ, ssa.OpAMD64SETNE, ssa.OpAMD64SETL, ssa.OpAMD64SETLE, ssa.OpAMD64SETG, ssa.OpAMD64SETGE, - ssa.OpAMD64SETB: + ssa.OpAMD64SETB, ssa.OpAMD64SETBE, + ssa.OpAMD64SETA, ssa.OpAMD64SETAE: p := Prog(v.Op.Asm()) p.To.Type = obj.TYPE_REG p.To.Reg = regnum(v) @@ -1725,6 +1726,19 @@ func movZero(as int, width int64, nbytes int64, offset int64, regnum int16) (nle return nleft, offset } +var blockJump = [...]struct{ asm, invasm int }{ + ssa.BlockAMD64EQ: {x86.AJEQ, x86.AJNE}, + ssa.BlockAMD64NE: {x86.AJNE, x86.AJEQ}, + ssa.BlockAMD64LT: {x86.AJLT, x86.AJGE}, + ssa.BlockAMD64GE: {x86.AJGE, x86.AJLT}, + ssa.BlockAMD64LE: {x86.AJLE, x86.AJGT}, + ssa.BlockAMD64GT: {x86.AJGT, x86.AJLE}, + ssa.BlockAMD64ULT: {x86.AJCS, x86.AJCC}, + ssa.BlockAMD64UGE: {x86.AJCC, x86.AJCS}, + ssa.BlockAMD64UGT: {x86.AJHI, x86.AJLS}, + ssa.BlockAMD64ULE: {x86.AJLS, x86.AJHI}, +} + func genBlock(b, next *ssa.Block, branches []branch) []branch { lineno = b.Line switch b.Kind { @@ -1742,85 +1756,24 @@ func genBlock(b, next *ssa.Block, branches []branch) []branch { p.To.Type = obj.TYPE_BRANCH branches = append(branches, branch{p, b.Succs[0]}) } - case ssa.BlockAMD64EQ: - if b.Succs[0] == next { - p := Prog(x86.AJNE) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[1]}) - } else if b.Succs[1] == next { - p := Prog(x86.AJEQ) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[0]}) - } else { - p := Prog(x86.AJEQ) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[0]}) - q := Prog(obj.AJMP) - q.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{q, b.Succs[1]}) - } - case ssa.BlockAMD64NE: - if b.Succs[0] == next { - p := Prog(x86.AJEQ) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[1]}) - } else if b.Succs[1] == next { - p := Prog(x86.AJNE) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[0]}) - } else { - p := Prog(x86.AJNE) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[0]}) - q := Prog(obj.AJMP) - q.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{q, b.Succs[1]}) - } - case ssa.BlockAMD64LT: - if b.Succs[0] == next { - p := Prog(x86.AJGE) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[1]}) - } else if b.Succs[1] == next { - p := Prog(x86.AJLT) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[0]}) - } else { - p := Prog(x86.AJLT) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[0]}) - q := Prog(obj.AJMP) - q.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{q, b.Succs[1]}) - } - case ssa.BlockAMD64ULT: - if b.Succs[0] == next { - p := Prog(x86.AJCC) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[1]}) - } else if b.Succs[1] == next { - p := Prog(x86.AJCS) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[0]}) - } else { - p := Prog(x86.AJCS) - p.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{p, b.Succs[0]}) - q := Prog(obj.AJMP) - q.To.Type = obj.TYPE_BRANCH - branches = append(branches, branch{q, b.Succs[1]}) - } - case ssa.BlockAMD64UGT: - if b.Succs[0] == next { - p := Prog(x86.AJLS) + case ssa.BlockAMD64EQ, ssa.BlockAMD64NE, + ssa.BlockAMD64LT, ssa.BlockAMD64GE, + ssa.BlockAMD64LE, ssa.BlockAMD64GT, + ssa.BlockAMD64ULT, ssa.BlockAMD64UGT, + ssa.BlockAMD64ULE, ssa.BlockAMD64UGE: + + jmp := blockJump[b.Kind] + switch next { + case b.Succs[0]: + p := Prog(jmp.invasm) p.To.Type = obj.TYPE_BRANCH branches = append(branches, branch{p, b.Succs[1]}) - } else if b.Succs[1] == next { - p := Prog(x86.AJHI) + case b.Succs[1]: + p := Prog(jmp.asm) p.To.Type = obj.TYPE_BRANCH branches = append(branches, branch{p, b.Succs[0]}) - } else { - p := Prog(x86.AJHI) + default: + p := Prog(jmp.asm) p.To.Type = obj.TYPE_BRANCH branches = append(branches, branch{p, b.Succs[0]}) q := Prog(obj.AJMP) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 59f5564080..f1ae4f6a82 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -118,9 +118,15 @@ // block rewrites (If (SETL cmp) yes no) -> (LT cmp yes no) +(If (SETLE cmp) yes no) -> (LE cmp yes no) +(If (SETG cmp) yes no) -> (GT cmp yes no) +(If (SETGE cmp) yes no) -> (GE cmp yes no) (If (SETEQ cmp) yes no) -> (EQ cmp yes no) (If (SETNE cmp) yes no) -> (NE cmp yes no) (If (SETB cmp) yes no) -> (ULT cmp yes no) +(If (SETBE cmp) yes no) -> (ULE cmp yes no) +(If (SETA cmp) yes no) -> (UGT cmp yes no) +(If (SETAE cmp) yes no) -> (UGE cmp yes no) (If cond yes no) && cond.Op == OpAMD64MOVBload -> (NE (TESTB cond cond) yes no) (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 382d666ae6..382d64c9de 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -123,6 +123,9 @@ func init() { {name: "SETG", reg: flagsgp, asm: "SETGT"}, // extract signed > condition from arg0 {name: "SETGE", reg: flagsgp, asm: "SETGE"}, // extract signed >= condition from arg0 {name: "SETB", reg: flagsgp, asm: "SETCS"}, // extract unsigned < condition from arg0 + {name: "SETBE", reg: flagsgp, asm: "SETLS"}, // extract unsigned <= condition from arg0 + {name: "SETA", reg: flagsgp, asm: "SETHI"}, // extract unsigned > condition from arg0 + {name: "SETAE", reg: flagsgp, asm: "SETCC"}, // extract unsigned >= condition from arg0 {name: "CMOVQCC", reg: cmov}, // carry clear diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 0b15801ced..8c1ef0b9d9 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -74,6 +74,9 @@ const ( OpAMD64SETG OpAMD64SETGE OpAMD64SETB + OpAMD64SETBE + OpAMD64SETA + OpAMD64SETAE OpAMD64CMOVQCC OpAMD64MOVBQSX OpAMD64MOVBQZX @@ -532,6 +535,42 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "SETBE", + asm: x86.ASETLS, + reg: regInfo{ + inputs: []regMask{ + 8589934592, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETA", + asm: x86.ASETHI, + reg: regInfo{ + inputs: []regMask{ + 8589934592, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETAE", + asm: x86.ASETCC, + reg: regInfo{ + inputs: []regMask{ + 8589934592, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, { name: "CMOVQCC", reg: regInfo{ diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 4b63c97ebb..f8642a7bb5 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2589,6 +2589,66 @@ func rewriteBlockAMD64(b *Block) bool { } goto ende4d36879bb8e1bd8facaa8c91ba99dcc ende4d36879bb8e1bd8facaa8c91ba99dcc: + ; + // match: (If (SETLE cmp) yes no) + // cond: + // result: (LE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETLE { + goto end40df18679690e8f9005d8642fab44654 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64LE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end40df18679690e8f9005d8642fab44654 + end40df18679690e8f9005d8642fab44654: + ; + // match: (If (SETG cmp) yes no) + // cond: + // result: (GT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETG { + goto endb1faff07a84ae08a4b05a4a7e71eb740 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64GT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endb1faff07a84ae08a4b05a4a7e71eb740 + endb1faff07a84ae08a4b05a4a7e71eb740: + ; + // match: (If (SETGE cmp) yes no) + // cond: + // result: (GE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETGE { + goto enda9211ccfa5b0ab8eafc0017630c542b6 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64GE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto enda9211ccfa5b0ab8eafc0017630c542b6 + enda9211ccfa5b0ab8eafc0017630c542b6: ; // match: (If (SETEQ cmp) yes no) // cond: @@ -2649,6 +2709,66 @@ func rewriteBlockAMD64(b *Block) bool { } goto end04935012db9defeafceef8175f803ea2 end04935012db9defeafceef8175f803ea2: + ; + // match: (If (SETBE cmp) yes no) + // cond: + // result: (ULE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETBE { + goto endfe0178f6f4406945ca8966817d04be60 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64ULE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endfe0178f6f4406945ca8966817d04be60 + endfe0178f6f4406945ca8966817d04be60: + ; + // match: (If (SETA cmp) yes no) + // cond: + // result: (UGT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETA { + goto endbd22a7d56a98d85e4e132ff952dae262 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64UGT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endbd22a7d56a98d85e4e132ff952dae262 + endbd22a7d56a98d85e4e132ff952dae262: + ; + // match: (If (SETAE cmp) yes no) + // cond: + // result: (UGE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETAE { + goto end9bea9963c3c5dfb97249a5feb8287f94 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64UGE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end9bea9963c3c5dfb97249a5feb8287f94 + end9bea9963c3c5dfb97249a5feb8287f94: ; // match: (If cond yes no) // cond: cond.Op == OpAMD64MOVBload -- 2.48.1