Add test for commutative operations in SkVM.

SkVM should be able to optimize away these equivalent expressions:

	(intA & intB)   <->  (intB & intA)
	(intA ^ intB)   <->  (intB ^ intA)
	(intA | intB)   <->  (intB | intA)
	(intA + intB)   <->  (intB + intA)
	(intA * intB)   <->  (intB * intA)
	(intA == intB)  <->  (intB == intA)
	(intA != intB)  <->  (intB != intA)

These should be guaranteed by IEEE754 as well:

	(floatA + floatB)   <->  (floatB + floatA)
	(floatA * floatB)   <->  (floatB * floatA)

I've added a test to demonstrate existing behavior, which leaves these
optimizations on the table.

Change-Id: I01ce1d6f1cfadb3d77db405a83752c9dd52c99bd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/473238
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-11-18 15:26:15 -05:00 committed by SkCQ
parent dd7540fccb
commit 626dbe195a
4 changed files with 145 additions and 0 deletions

View File

@ -610,6 +610,7 @@ sksl_rte_tests = [
"/sksl/runtime/ArrayIndexing.rts",
"/sksl/runtime/ArrayNarrowingConversions.rts",
"/sksl/runtime/Blend.rtb",
"/sksl/runtime/Commutative.rts",
"/sksl/runtime/ConstPreservation.rts",
"/sksl/runtime/ConversionConstructors.rts",
"/sksl/runtime/GLSLTypeNames.rts",

View File

@ -0,0 +1,48 @@
/*#pragma settings NoES2Restrictions*/
// We use bitwise ops below, which SkVM supports but ES2 technically does not.
uniform half4 colorGreen, colorRed;
uniform int a, b;
uniform float c, d;
half4 main(float2 xy) {
bool ok = true;
int a_and_b = a & b;
int b_and_a = b & a;
ok = ok && (a_and_b == b_and_a);
int a_or_b = a | b;
int b_or_a = b | a;
ok = ok && (a_or_b == b_or_a);
int a_xor_b = a ^ b;
int b_xor_a = b ^ a;
ok = ok && (a_xor_b == b_xor_a);
bool a_eq_b = a == b;
bool b_eq_a = b == a;
ok = ok && (a_eq_b == b_eq_a);
bool a_neq_b = a != b;
bool b_neq_a = b != a;
ok = ok && (a_neq_b == b_neq_a);
int a_add_b = a + b;
int b_add_a = b + a;
ok = ok && (a_add_b == b_add_a);
float c_add_d = c + d;
float d_add_c = d + c;
ok = ok && (c_add_d == d_add_c);
int a_mul_b = a * b;
int b_mul_a = b * a;
ok = ok && (a_mul_b == b_mul_a);
float c_mul_d = c * d;
float d_mul_c = d * c;
ok = ok && (c_mul_d == d_mul_c);
return ok ? colorGreen : colorRed;
}

View File

@ -0,0 +1,58 @@
17 registers, 56 instructions:
0 r0 = uniform32 ptr0 4
1 r1 = uniform32 ptr0 8
2 r2 = uniform32 ptr0 C
3 r3 = uniform32 ptr0 10
4 r4 = uniform32 ptr0 14
5 r5 = uniform32 ptr0 18
6 r6 = uniform32 ptr0 1C
7 r7 = uniform32 ptr0 20
8 r8 = uniform32 ptr0 24
9 r9 = uniform32 ptr0 28
10 r10 = uniform32 ptr0 2C
11 r11 = uniform32 ptr0 30
12 r12 = splat FFFFFFFF (nan)
13 r13 = bit_and r8 r9
14 r14 = bit_and r9 r8
15 r14 = eq_i32 r13 r14
16 r13 = bit_or r8 r9
17 r15 = bit_or r9 r8
18 r15 = eq_i32 r13 r15
19 r15 = bit_and r14 r15
20 r14 = bit_xor r8 r9
21 r13 = bit_xor r9 r8
22 r13 = eq_i32 r14 r13
23 r13 = bit_and r15 r13
24 r15 = eq_i32 r8 r9
25 r14 = eq_i32 r9 r8
26 r16 = eq_i32 r15 r14
27 r16 = bit_and r13 r16
28 r15 = bit_xor r12 r15
29 r14 = bit_xor r12 r14
30 r14 = eq_i32 r15 r14
31 r14 = bit_and r16 r14
32 r16 = add_i32 r8 r9
33 r15 = add_i32 r9 r8
34 r15 = eq_i32 r16 r15
35 r15 = bit_and r14 r15
36 r14 = add_f32 r10 r11
37 r16 = add_f32 r11 r10
38 r16 = eq_f32 r14 r16
39 r16 = bit_and r15 r16
40 r15 = mul_i32 r8 r9
41 r8 = mul_i32 r9 r8
42 r8 = eq_i32 r15 r8
43 r8 = bit_and r16 r8
44 r16 = mul_f32 r10 r11
45 r10 = mul_f32 r11 r10
46 r10 = eq_f32 r16 r10
47 r10 = bit_and r8 r10
48 r4 = select r10 r0 r4
49 r5 = select r10 r1 r5
50 r6 = select r10 r2 r6
51 r7 = select r10 r3 r7
loop:
52 store32 ptr1 r4
53 store32 ptr2 r5
54 store32 ptr3 r6
55 store32 ptr4 r7

View File

@ -0,0 +1,38 @@
uniform half4 colorGreen;
uniform half4 colorRed;
uniform int a;
uniform int b;
uniform float c;
uniform float d;
half4 main(float2 xy)
{
bool ok = true;
int a_and_b = a & b;
int b_and_a = b & a;
ok = ok && a_and_b == b_and_a;
int a_or_b = a | b;
int b_or_a = b | a;
ok = ok && a_or_b == b_or_a;
int a_xor_b = a ^ b;
int b_xor_a = b ^ a;
ok = ok && a_xor_b == b_xor_a;
bool a_eq_b = a == b;
bool b_eq_a = b == a;
ok = ok && a_eq_b == b_eq_a;
bool a_neq_b = a != b;
bool b_neq_a = b != a;
ok = ok && a_neq_b == b_neq_a;
int a_add_b = a + b;
int b_add_a = b + a;
ok = ok && a_add_b == b_add_a;
float c_add_d = c + d;
float d_add_c = d + c;
ok = ok && c_add_d == d_add_c;
int a_mul_b = a * b;
int b_mul_a = b * a;
ok = ok && a_mul_b == b_mul_a;
float c_mul_d = c * d;
float d_mul_c = d * c;
ok = ok && c_mul_d == d_mul_c;
return half4(ok ? colorGreen : colorRed);
}