mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-18 22:44:50 +02:00
Fix cmplt implementation
This commit is contained in:
@@ -386,7 +386,7 @@ func shrn8b_immediate4(a, b Register) uint32 {
|
||||
}
|
||||
|
||||
func encode_cmgt16b(a, b, dest Register) (ans uint32) {
|
||||
return 0x271<<21 | a.ARMId()<<16 | 0xd<<10 | b.ARMId()<<5 | dest.ARMId()
|
||||
return 0x271<<21 | b.ARMId()<<16 | 0xd<<10 | a.ARMId()<<5 | dest.ARMId()
|
||||
}
|
||||
|
||||
func (f *Function) CountBytesToFirstMatchDestructive(vec, ans Register) {
|
||||
@@ -738,19 +738,36 @@ func (f *Function) cmp(a, b, ans Register, op, c_rep string) {
|
||||
f.instr("WORD", fmt.Sprintf("$0x%x", encode_cmgt16b(a, b, ans)))
|
||||
}
|
||||
} else {
|
||||
op := `PCMP` + op + "B"
|
||||
fop := `PCMP` + op + "B"
|
||||
if f.ISA.Bits == 128 {
|
||||
switch ans.Name {
|
||||
case a.Name:
|
||||
f.instr(op, b, ans)
|
||||
case b.Name:
|
||||
f.instr(op, a, ans)
|
||||
default:
|
||||
f.CopyRegister(a, ans)
|
||||
f.instr(op, b, ans)
|
||||
if op == "EQ" {
|
||||
switch ans.Name {
|
||||
case a.Name:
|
||||
f.instr(fop, b, ans)
|
||||
case b.Name:
|
||||
f.instr(fop, a, ans)
|
||||
default:
|
||||
f.CopyRegister(a, ans)
|
||||
f.instr(fop, b, ans)
|
||||
}
|
||||
} else {
|
||||
// order matters, we want destination aka 2nd arg to be both a and ans
|
||||
switch ans.Name {
|
||||
case a.Name:
|
||||
f.instr(fop, b, a)
|
||||
case b.Name:
|
||||
vec := f.Vec(a.Size)
|
||||
f.CopyRegister(a, vec)
|
||||
f.instr(fop, b, vec)
|
||||
f.CopyRegister(vec, b)
|
||||
f.ReleaseReg(vec)
|
||||
default:
|
||||
f.CopyRegister(a, ans)
|
||||
f.instr(fop, b, ans)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
f.instr("V"+op, a, b, ans)
|
||||
f.instr("V"+fop, b, a, ans)
|
||||
}
|
||||
}
|
||||
f.AddTrailingComment(ans, "= 0xff on every byte where", a.Name+"[n]", c_rep, b.Name+"[n] and zero elsewhere")
|
||||
@@ -1201,14 +1218,31 @@ func (s *State) test_cmpeq_epi8() {
|
||||
}
|
||||
|
||||
func (s *State) test_cmplt_epi8() {
|
||||
f := s.NewFunction("test_cmplt_epi8_asm", "Test byte comparison of two vectors", []FunctionParam{{"a", ByteSlice}, {"b", ByteSlice}, {"ans", ByteSlice}}, nil)
|
||||
f := s.NewFunction(
|
||||
"test_cmplt_epi8_asm", "Test byte comparison of two vectors", []FunctionParam{{"a", ByteSlice}, {"b", ByteSlice}, {"which", types.Int}, {"ans", ByteSlice}}, nil)
|
||||
if !s.ISA.HasSIMD {
|
||||
return
|
||||
}
|
||||
which := f.LoadParam("which")
|
||||
a := f.load_vec_from_param("a")
|
||||
b := f.load_vec_from_param("b")
|
||||
r := f.Reg()
|
||||
f.SetRegisterTo(r, 1)
|
||||
f.JumpIfEqual(which, r, "one")
|
||||
f.SetRegisterTo(r, 2)
|
||||
f.JumpIfEqual(which, r, "two")
|
||||
ans := f.Vec()
|
||||
f.CmpLtEpi8(a, b, ans)
|
||||
f.store_vec_in_param(ans, "ans")
|
||||
f.Return()
|
||||
f.Label("one")
|
||||
f.CmpLtEpi8(a, b, a)
|
||||
f.store_vec_in_param(a, "ans")
|
||||
f.Return()
|
||||
f.Label("two")
|
||||
f.CmpLtEpi8(a, b, b)
|
||||
f.store_vec_in_param(b, "ans")
|
||||
f.Return()
|
||||
}
|
||||
|
||||
func (s *State) test_or() {
|
||||
|
||||
@@ -44,12 +44,21 @@ func test_cmpeq_epi8(a, b []byte) []byte {
|
||||
return ans
|
||||
}
|
||||
|
||||
func test_cmplt_epi8(a, b []byte) []byte {
|
||||
func test_cmplt_epi8(t *testing.T, a, b []byte) []byte {
|
||||
ans := make([]byte, len(a))
|
||||
if len(ans) == 16 {
|
||||
test_cmplt_epi8_asm_128(a, b, ans)
|
||||
} else {
|
||||
test_cmplt_epi8_asm_256(a, b, ans)
|
||||
var prev []byte
|
||||
for which := 0; which < 3; which++ {
|
||||
if len(ans) == 16 {
|
||||
test_cmplt_epi8_asm_128(a, b, which, ans)
|
||||
} else {
|
||||
test_cmplt_epi8_asm_256(a, b, which, ans)
|
||||
}
|
||||
if prev != nil {
|
||||
if s := cmp.Diff(prev, ans); s != "" {
|
||||
t.Fatalf("cmplt returned different result for which=%d\n%s", which, s)
|
||||
}
|
||||
}
|
||||
prev = bytes.Clone(ans)
|
||||
}
|
||||
return ans
|
||||
}
|
||||
@@ -251,14 +260,25 @@ func TestIntrinsics(t *testing.T) {
|
||||
b := ordered_bytes(sz)
|
||||
ans := test_cmpeq_epi8(a, b)
|
||||
ae(sz, `cmpeq_epi8_test`, broadcast_byte(0xff, sz), ans)
|
||||
threshold := -1
|
||||
a[1] = byte(threshold)
|
||||
a[2] = byte(threshold - 1)
|
||||
ans = test_cmplt_epi8(a, broadcast_byte(byte(threshold), sz))
|
||||
expected := broadcast_byte(0xff, sz)
|
||||
expected[1] = 0
|
||||
expected[2] = 0
|
||||
ae(sz, `cmplt_epi8_test`, expected, ans)
|
||||
|
||||
lt := func(a, b []byte) []byte {
|
||||
ans := make([]byte, len(a))
|
||||
for i := range ans {
|
||||
if int8(a[i]) < int8(b[i]) {
|
||||
ans[i] = 0xff
|
||||
}
|
||||
}
|
||||
return ans
|
||||
}
|
||||
|
||||
ae(sz, "cmplt_epi8_test with equal vecs of non-negative numbers", lt(a, b), test_cmplt_epi8(t, a, b))
|
||||
a = broadcast_byte(1, sz)
|
||||
b = broadcast_byte(2, sz)
|
||||
ae(sz, "cmplt_epi8_test with 1 and 2", lt(a, b), test_cmplt_epi8(t, a, b))
|
||||
ae(sz, "cmplt_epi8_test with 2 and 1", lt(b, a), test_cmplt_epi8(t, b, a))
|
||||
a = broadcast_byte(0xff, sz)
|
||||
b = broadcast_byte(0, sz)
|
||||
ae(sz, "cmplt_epi8_test with -1 and 0", lt(a, b), test_cmplt_epi8(t, a, b))
|
||||
})
|
||||
tests = append(tests, func(sz int) {
|
||||
a := make([]byte, sz)
|
||||
|
||||
Reference in New Issue
Block a user