From 66fbb80b7280ae39d91af77f43593388923fc10c Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Tue, 22 Sep 2020 15:31:43 +0200 Subject: [PATCH] cmd/compile: more amd64 typed rules Passes gotip build -toolexec 'toolstash -cmp' -a std Change-Id: I2621f9ab48199204cf6116941b19b6df4170d0e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/256497 Trust: Alberto Donizetti Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/gen/AMD64.rules | 89 ++++--- src/cmd/compile/internal/ssa/rewriteAMD64.go | 235 +++++++++---------- 2 files changed, 156 insertions(+), 168 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 8d6fad4393c..6dfe11dcfa2 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -1224,59 +1224,58 @@ (LEAQ [off+int32(scale)*8] {sym} x) // Absorb InvertFlags into branches. -(LT (InvertFlags cmp) yes no) -> (GT cmp yes no) -(GT (InvertFlags cmp) yes no) -> (LT cmp yes no) -(LE (InvertFlags cmp) yes no) -> (GE cmp yes no) -(GE (InvertFlags cmp) yes no) -> (LE cmp yes no) -(ULT (InvertFlags cmp) yes no) -> (UGT cmp yes no) -(UGT (InvertFlags cmp) yes no) -> (ULT cmp yes no) -(ULE (InvertFlags cmp) yes no) -> (UGE cmp yes no) -(UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no) -(EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no) -(NE (InvertFlags cmp) yes no) -> (NE cmp yes no) +(LT (InvertFlags cmp) yes no) => (GT cmp yes no) +(GT (InvertFlags cmp) yes no) => (LT cmp yes no) +(LE (InvertFlags cmp) yes no) => (GE cmp yes no) +(GE (InvertFlags cmp) yes no) => (LE cmp yes no) +(ULT (InvertFlags cmp) yes no) => (UGT cmp yes no) +(UGT (InvertFlags cmp) yes no) => (ULT cmp yes no) +(ULE (InvertFlags cmp) yes no) => (UGE cmp yes no) +(UGE (InvertFlags cmp) yes no) => (ULE cmp yes no) +(EQ (InvertFlags cmp) yes no) => (EQ cmp yes no) +(NE (InvertFlags cmp) yes no) => (NE cmp yes no) // Constant comparisons. -(CMPQconst (MOVQconst [x]) [y]) && x==y -> (FlagEQ) -(CMPQconst (MOVQconst [x]) [y]) && x (FlagLT_ULT) -(CMPQconst (MOVQconst [x]) [y]) && xuint64(y) -> (FlagLT_UGT) -(CMPQconst (MOVQconst [x]) [y]) && x>y && uint64(x) (FlagGT_ULT) -(CMPQconst (MOVQconst [x]) [y]) && x>y && uint64(x)>uint64(y) -> (FlagGT_UGT) -(CMPLconst (MOVLconst [x]) [y]) && int32(x)==int32(y) -> (FlagEQ) -(CMPLconst (MOVLconst [x]) [y]) && int32(x) (FlagLT_ULT) -(CMPLconst (MOVLconst [x]) [y]) && int32(x)uint32(y) -> (FlagLT_UGT) -(CMPLconst (MOVLconst [x]) [y]) && int32(x)>int32(y) && uint32(x) (FlagGT_ULT) -(CMPLconst (MOVLconst [x]) [y]) && int32(x)>int32(y) && uint32(x)>uint32(y) -> (FlagGT_UGT) -(CMPWconst (MOVLconst [x]) [y]) && int16(x)==int16(y) -> (FlagEQ) -(CMPWconst (MOVLconst [x]) [y]) && int16(x) (FlagLT_ULT) -(CMPWconst (MOVLconst [x]) [y]) && int16(x)uint16(y) -> (FlagLT_UGT) -(CMPWconst (MOVLconst [x]) [y]) && int16(x)>int16(y) && uint16(x) (FlagGT_ULT) -(CMPWconst (MOVLconst [x]) [y]) && int16(x)>int16(y) && uint16(x)>uint16(y) -> (FlagGT_UGT) -(CMPBconst (MOVLconst [x]) [y]) && int8(x)==int8(y) -> (FlagEQ) -(CMPBconst (MOVLconst [x]) [y]) && int8(x) (FlagLT_ULT) -(CMPBconst (MOVLconst [x]) [y]) && int8(x)uint8(y) -> (FlagLT_UGT) -(CMPBconst (MOVLconst [x]) [y]) && int8(x)>int8(y) && uint8(x) (FlagGT_ULT) -(CMPBconst (MOVLconst [x]) [y]) && int8(x)>int8(y) && uint8(x)>uint8(y) -> (FlagGT_UGT) +(CMPQconst (MOVQconst [x]) [y]) && x==int64(y) => (FlagEQ) +(CMPQconst (MOVQconst [x]) [y]) && x (FlagLT_ULT) +(CMPQconst (MOVQconst [x]) [y]) && xuint64(int64(y)) => (FlagLT_UGT) +(CMPQconst (MOVQconst [x]) [y]) && x>int64(y) && uint64(x) (FlagGT_ULT) +(CMPQconst (MOVQconst [x]) [y]) && x>int64(y) && uint64(x)>uint64(int64(y)) => (FlagGT_UGT) +(CMPLconst (MOVLconst [x]) [y]) && x==y => (FlagEQ) +(CMPLconst (MOVLconst [x]) [y]) && x (FlagLT_ULT) +(CMPLconst (MOVLconst [x]) [y]) && xuint32(y) => (FlagLT_UGT) +(CMPLconst (MOVLconst [x]) [y]) && x>y && uint32(x) (FlagGT_ULT) +(CMPLconst (MOVLconst [x]) [y]) && x>y && uint32(x)>uint32(y) => (FlagGT_UGT) +(CMPWconst (MOVLconst [x]) [y]) && int16(x)==y => (FlagEQ) +(CMPWconst (MOVLconst [x]) [y]) && int16(x) (FlagLT_ULT) +(CMPWconst (MOVLconst [x]) [y]) && int16(x)uint16(y) => (FlagLT_UGT) +(CMPWconst (MOVLconst [x]) [y]) && int16(x)>y && uint16(x) (FlagGT_ULT) +(CMPWconst (MOVLconst [x]) [y]) && int16(x)>y && uint16(x)>uint16(y) => (FlagGT_UGT) +(CMPBconst (MOVLconst [x]) [y]) && int8(x)==y => (FlagEQ) +(CMPBconst (MOVLconst [x]) [y]) && int8(x) (FlagLT_ULT) +(CMPBconst (MOVLconst [x]) [y]) && int8(x)uint8(y) => (FlagLT_UGT) +(CMPBconst (MOVLconst [x]) [y]) && int8(x)>y && uint8(x) (FlagGT_ULT) +(CMPBconst (MOVLconst [x]) [y]) && int8(x)>y && uint8(x)>uint8(y) => (FlagGT_UGT) // CMPQconst requires a 32 bit const, but we can still constant-fold 64 bit consts. // In theory this applies to any of the simplifications above, // but CMPQ is the only one I've actually seen occur. -(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x==y -> (FlagEQ) -(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x (FlagLT_ULT) -(CMPQ (MOVQconst [x]) (MOVQconst [y])) && xuint64(y) -> (FlagLT_UGT) -(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x>y && uint64(x) (FlagGT_ULT) -(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x>y && uint64(x)>uint64(y) -> (FlagGT_UGT) +(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x==y => (FlagEQ) +(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x (FlagLT_ULT) +(CMPQ (MOVQconst [x]) (MOVQconst [y])) && xuint64(y) => (FlagLT_UGT) +(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x>y && uint64(x) (FlagGT_ULT) +(CMPQ (MOVQconst [x]) (MOVQconst [y])) && x>y && uint64(x)>uint64(y) => (FlagGT_UGT) // Other known comparisons. -(CMPQconst (MOVBQZX _) [c]) && 0xFF < c -> (FlagLT_ULT) -(CMPQconst (MOVWQZX _) [c]) && 0xFFFF < c -> (FlagLT_ULT) -(CMPQconst (MOVLQZX _) [c]) && 0xFFFFFFFF < c -> (FlagLT_ULT) -(CMPLconst (SHRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1< (FlagLT_ULT) -(CMPQconst (SHRQconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 64 && (1< (FlagLT_ULT) -(CMPQconst (ANDQconst _ [m]) [n]) && 0 <= m && m < n -> (FlagLT_ULT) -(CMPQconst (ANDLconst _ [m]) [n]) && 0 <= m && m < n -> (FlagLT_ULT) -(CMPLconst (ANDLconst _ [m]) [n]) && 0 <= int32(m) && int32(m) < int32(n) -> (FlagLT_ULT) -(CMPWconst (ANDLconst _ [m]) [n]) && 0 <= int16(m) && int16(m) < int16(n) -> (FlagLT_ULT) -(CMPBconst (ANDLconst _ [m]) [n]) && 0 <= int8(m) && int8(m) < int8(n) -> (FlagLT_ULT) +(CMPQconst (MOVBQZX _) [c]) && 0xFF < c => (FlagLT_ULT) +(CMPQconst (MOVWQZX _) [c]) && 0xFFFF < c => (FlagLT_ULT) +(CMPLconst (SHRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1< (FlagLT_ULT) +(CMPQconst (SHRQconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 64 && (1< (FlagLT_ULT) +(CMPQconst (ANDQconst _ [m]) [n]) && 0 <= m && m < n => (FlagLT_ULT) +(CMPQconst (ANDLconst _ [m]) [n]) && 0 <= m && m < n => (FlagLT_ULT) +(CMPLconst (ANDLconst _ [m]) [n]) && 0 <= m && m < n => (FlagLT_ULT) +(CMPWconst (ANDLconst _ [m]) [n]) && 0 <= m && int16(m) < n => (FlagLT_ULT) +(CMPBconst (ANDLconst _ [m]) [n]) && 0 <= m && int8(m) < n => (FlagLT_ULT) // TESTQ c c sets flags like CMPQ c 0. (TEST(Q|L)const [c] (MOV(Q|L)const [c])) && c == 0 -> (FlagEQ) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 3f58ad392b2..a7b3635b5ef 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -6811,90 +6811,90 @@ func rewriteValueAMD64_OpAMD64CMPBconst(v *Value) bool { v_0 := v.Args[0] b := v.Block // match: (CMPBconst (MOVLconst [x]) [y]) - // cond: int8(x)==int8(y) + // cond: int8(x)==y // result: (FlagEQ) for { - y := v.AuxInt + y := auxIntToInt8(v.AuxInt) if v_0.Op != OpAMD64MOVLconst { break } - x := v_0.AuxInt - if !(int8(x) == int8(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(int8(x) == y) { break } v.reset(OpAMD64FlagEQ) return true } // match: (CMPBconst (MOVLconst [x]) [y]) - // cond: int8(x)uint8(y) + // cond: int8(x)uint8(y) // result: (FlagLT_UGT) for { - y := v.AuxInt + y := auxIntToInt8(v.AuxInt) if v_0.Op != OpAMD64MOVLconst { break } - x := v_0.AuxInt - if !(int8(x) < int8(y) && uint8(x) > uint8(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(int8(x) < y && uint8(x) > uint8(y)) { break } v.reset(OpAMD64FlagLT_UGT) return true } // match: (CMPBconst (MOVLconst [x]) [y]) - // cond: int8(x)>int8(y) && uint8(x)y && uint8(x) int8(y) && uint8(x) < uint8(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(int8(x) > y && uint8(x) < uint8(y)) { break } v.reset(OpAMD64FlagGT_ULT) return true } // match: (CMPBconst (MOVLconst [x]) [y]) - // cond: int8(x)>int8(y) && uint8(x)>uint8(y) + // cond: int8(x)>y && uint8(x)>uint8(y) // result: (FlagGT_UGT) for { - y := v.AuxInt + y := auxIntToInt8(v.AuxInt) if v_0.Op != OpAMD64MOVLconst { break } - x := v_0.AuxInt - if !(int8(x) > int8(y) && uint8(x) > uint8(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(int8(x) > y && uint8(x) > uint8(y)) { break } v.reset(OpAMD64FlagGT_UGT) return true } // match: (CMPBconst (ANDLconst _ [m]) [n]) - // cond: 0 <= int8(m) && int8(m) < int8(n) + // cond: 0 <= m && int8(m) < n // result: (FlagLT_ULT) for { - n := v.AuxInt + n := auxIntToInt8(v.AuxInt) if v_0.Op != OpAMD64ANDLconst { break } - m := v_0.AuxInt - if !(0 <= int8(m) && int8(m) < int8(n)) { + m := auxIntToInt32(v_0.AuxInt) + if !(0 <= m && int8(m) < n) { break } v.reset(OpAMD64FlagLT_ULT) @@ -7197,75 +7197,75 @@ func rewriteValueAMD64_OpAMD64CMPLconst(v *Value) bool { v_0 := v.Args[0] b := v.Block // match: (CMPLconst (MOVLconst [x]) [y]) - // cond: int32(x)==int32(y) + // cond: x==y // result: (FlagEQ) for { - y := v.AuxInt + y := auxIntToInt32(v.AuxInt) if v_0.Op != OpAMD64MOVLconst { break } - x := v_0.AuxInt - if !(int32(x) == int32(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(x == y) { break } v.reset(OpAMD64FlagEQ) return true } // match: (CMPLconst (MOVLconst [x]) [y]) - // cond: int32(x)uint32(y) + // cond: xuint32(y) // result: (FlagLT_UGT) for { - y := v.AuxInt + y := auxIntToInt32(v.AuxInt) if v_0.Op != OpAMD64MOVLconst { break } - x := v_0.AuxInt - if !(int32(x) < int32(y) && uint32(x) > uint32(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(x < y && uint32(x) > uint32(y)) { break } v.reset(OpAMD64FlagLT_UGT) return true } // match: (CMPLconst (MOVLconst [x]) [y]) - // cond: int32(x)>int32(y) && uint32(x)y && uint32(x) int32(y) && uint32(x) < uint32(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(x > y && uint32(x) < uint32(y)) { break } v.reset(OpAMD64FlagGT_ULT) return true } // match: (CMPLconst (MOVLconst [x]) [y]) - // cond: int32(x)>int32(y) && uint32(x)>uint32(y) + // cond: x>y && uint32(x)>uint32(y) // result: (FlagGT_UGT) for { - y := v.AuxInt + y := auxIntToInt32(v.AuxInt) if v_0.Op != OpAMD64MOVLconst { break } - x := v_0.AuxInt - if !(int32(x) > int32(y) && uint32(x) > uint32(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(x > y && uint32(x) > uint32(y)) { break } v.reset(OpAMD64FlagGT_UGT) @@ -7275,11 +7275,11 @@ func rewriteValueAMD64_OpAMD64CMPLconst(v *Value) bool { // cond: 0 <= n && 0 < c && c <= 32 && (1< uint64(y)) { break } @@ -7615,11 +7615,11 @@ func rewriteValueAMD64_OpAMD64CMPQ(v *Value) bool { if v_0.Op != OpAMD64MOVQconst { break } - x := v_0.AuxInt + x := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpAMD64MOVQconst { break } - y := v_1.AuxInt + y := auxIntToInt64(v_1.AuxInt) if !(x > y && uint64(x) < uint64(y)) { break } @@ -7633,11 +7633,11 @@ func rewriteValueAMD64_OpAMD64CMPQ(v *Value) bool { if v_0.Op != OpAMD64MOVQconst { break } - x := v_0.AuxInt + x := auxIntToInt64(v_0.AuxInt) if v_1.Op != OpAMD64MOVQconst { break } - y := v_1.AuxInt + y := auxIntToInt64(v_1.AuxInt) if !(x > y && uint64(x) > uint64(y)) { break } @@ -7730,75 +7730,75 @@ func rewriteValueAMD64_OpAMD64CMPQconst(v *Value) bool { return true } // match: (CMPQconst (MOVQconst [x]) [y]) - // cond: x==y + // cond: x==int64(y) // result: (FlagEQ) for { - y := v.AuxInt + y := auxIntToInt32(v.AuxInt) if v_0.Op != OpAMD64MOVQconst { break } - x := v_0.AuxInt - if !(x == y) { + x := auxIntToInt64(v_0.AuxInt) + if !(x == int64(y)) { break } v.reset(OpAMD64FlagEQ) return true } // match: (CMPQconst (MOVQconst [x]) [y]) - // cond: xuint64(y) + // cond: xuint64(int64(y)) // result: (FlagLT_UGT) for { - y := v.AuxInt + y := auxIntToInt32(v.AuxInt) if v_0.Op != OpAMD64MOVQconst { break } - x := v_0.AuxInt - if !(x < y && uint64(x) > uint64(y)) { + x := auxIntToInt64(v_0.AuxInt) + if !(x < int64(y) && uint64(x) > uint64(int64(y))) { break } v.reset(OpAMD64FlagLT_UGT) return true } // match: (CMPQconst (MOVQconst [x]) [y]) - // cond: x>y && uint64(x)int64(y) && uint64(x) y && uint64(x) < uint64(y)) { + x := auxIntToInt64(v_0.AuxInt) + if !(x > int64(y) && uint64(x) < uint64(int64(y))) { break } v.reset(OpAMD64FlagGT_ULT) return true } // match: (CMPQconst (MOVQconst [x]) [y]) - // cond: x>y && uint64(x)>uint64(y) + // cond: x>int64(y) && uint64(x)>uint64(int64(y)) // result: (FlagGT_UGT) for { - y := v.AuxInt + y := auxIntToInt32(v.AuxInt) if v_0.Op != OpAMD64MOVQconst { break } - x := v_0.AuxInt - if !(x > y && uint64(x) > uint64(y)) { + x := auxIntToInt64(v_0.AuxInt) + if !(x > int64(y) && uint64(x) > uint64(int64(y))) { break } v.reset(OpAMD64FlagGT_UGT) @@ -7808,7 +7808,7 @@ func rewriteValueAMD64_OpAMD64CMPQconst(v *Value) bool { // cond: 0xFF < c // result: (FlagLT_ULT) for { - c := v.AuxInt + c := auxIntToInt32(v.AuxInt) if v_0.Op != OpAMD64MOVBQZX || !(0xFF < c) { break } @@ -7819,33 +7819,22 @@ func rewriteValueAMD64_OpAMD64CMPQconst(v *Value) bool { // cond: 0xFFFF < c // result: (FlagLT_ULT) for { - c := v.AuxInt + c := auxIntToInt32(v.AuxInt) if v_0.Op != OpAMD64MOVWQZX || !(0xFFFF < c) { break } v.reset(OpAMD64FlagLT_ULT) return true } - // match: (CMPQconst (MOVLQZX _) [c]) - // cond: 0xFFFFFFFF < c - // result: (FlagLT_ULT) - for { - c := v.AuxInt - if v_0.Op != OpAMD64MOVLQZX || !(0xFFFFFFFF < c) { - break - } - v.reset(OpAMD64FlagLT_ULT) - return true - } // match: (CMPQconst (SHRQconst _ [c]) [n]) // cond: 0 <= n && 0 < c && c <= 64 && (1<uint16(y) + // cond: int16(x)uint16(y) // result: (FlagLT_UGT) for { - y := v.AuxInt + y := auxIntToInt16(v.AuxInt) if v_0.Op != OpAMD64MOVLconst { break } - x := v_0.AuxInt - if !(int16(x) < int16(y) && uint16(x) > uint16(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(int16(x) < y && uint16(x) > uint16(y)) { break } v.reset(OpAMD64FlagLT_UGT) return true } // match: (CMPWconst (MOVLconst [x]) [y]) - // cond: int16(x)>int16(y) && uint16(x)y && uint16(x) int16(y) && uint16(x) < uint16(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(int16(x) > y && uint16(x) < uint16(y)) { break } v.reset(OpAMD64FlagGT_ULT) return true } // match: (CMPWconst (MOVLconst [x]) [y]) - // cond: int16(x)>int16(y) && uint16(x)>uint16(y) + // cond: int16(x)>y && uint16(x)>uint16(y) // result: (FlagGT_UGT) for { - y := v.AuxInt + y := auxIntToInt16(v.AuxInt) if v_0.Op != OpAMD64MOVLconst { break } - x := v_0.AuxInt - if !(int16(x) > int16(y) && uint16(x) > uint16(y)) { + x := auxIntToInt32(v_0.AuxInt) + if !(int16(x) > y && uint16(x) > uint16(y)) { break } v.reset(OpAMD64FlagGT_UGT) return true } // match: (CMPWconst (ANDLconst _ [m]) [n]) - // cond: 0 <= int16(m) && int16(m) < int16(n) + // cond: 0 <= m && int16(m) < n // result: (FlagLT_ULT) for { - n := v.AuxInt + n := auxIntToInt16(v.AuxInt) if v_0.Op != OpAMD64ANDLconst { break } - m := v_0.AuxInt - if !(0 <= int16(m) && int16(m) < int16(n)) { + m := auxIntToInt32(v_0.AuxInt) + if !(0 <= m && int16(m) < n) { break } v.reset(OpAMD64FlagLT_ULT)