Commit 71b57077 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

[dev.ssa] cmd/compile: finish implementing comparisons

Change-Id: I4e496c7c7239111133631f76ca25e14be64800c6
Reviewed-on: https://go-review.googlesource.com/12656Reviewed-by: 's avatarKeith Randall <khr@golang.org>
parent 5c5f2a73
......@@ -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)
......
......@@ -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 <TypeFlags> cond cond) yes no)
(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
......
......@@ -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
......
......@@ -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{
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment