From ae5984082b5e7aa4e7c4c8f9201f83bca067f66e Mon Sep 17 00:00:00 2001 From: John Stiles Date: Thu, 24 Mar 2022 16:35:32 -0400 Subject: [PATCH] Optimize SkVM selects. The expression `!x ? y : z` can be optimized to `x ? z : y`, saving a bit-not. SkVM now supports this optimization. Change-Id: I06a0d2a716947de1021ba66b054b92e25568c641 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/524226 Reviewed-by: Arman Uguray Commit-Queue: John Stiles Auto-Submit: John Stiles --- src/core/SkVM.cpp | 12 ++++--- .../sksl/runtime/ConversionConstructors.skvm | 36 +++++++++---------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/core/SkVM.cpp b/src/core/SkVM.cpp index 7c3e86f3b6..888205b0a2 100644 --- a/src/core/SkVM.cpp +++ b/src/core/SkVM.cpp @@ -1163,10 +1163,14 @@ namespace skvm { I32 Builder::select(I32 x, I32 y, I32 z) { if (y.id == z.id) { return y; } if (int X,Y,Z; this->allImm(x.id,&X, y.id,&Y, z.id,&Z)) { return splat(X?Y:Z); } - if (this->isImm(x.id,~0)) { return y; } // true ? y : z == y - if (this->isImm(x.id, 0)) { return z; } // false ? y : z == z - if (this->isImm(y.id, 0)) { return bit_clear(z,x); } // x ? 0 : z == ~x&z - if (this->isImm(z.id, 0)) { return bit_and (y,x); } // x ? y : 0 == x&y + if (this->isImm(x.id,~0)) { return y; } // (true ? y : z) == y + if (this->isImm(x.id, 0)) { return z; } // (false ? y : z) == z + if (this->isImm(y.id, 0)) { return bit_clear(z,x); } // (x ? 0 : z) == ~x&z + if (this->isImm(z.id, 0)) { return bit_and (y,x); } // (x ? y : 0) == x&y + if (Val notX = this->holdsBitNot(x.id); notX != NA) { // (!x ? y : z) == (x ? z : y) + x.id = notX; + std::swap(y, z); + } return {this, this->push(Op::select, x.id, y.id, z.id)}; } diff --git a/tests/sksl/runtime/ConversionConstructors.skvm b/tests/sksl/runtime/ConversionConstructors.skvm index 3d61ae44f9..fa477085e7 100644 --- a/tests/sksl/runtime/ConversionConstructors.skvm +++ b/tests/sksl/runtime/ConversionConstructors.skvm @@ -1,24 +1,22 @@ -8 registers, 22 instructions: +7 registers, 20 instructions: 0 r0 = uniform32 ptr0 4 1 r1 = uniform32 ptr0 8 2 r2 = uniform32 ptr0 C 3 r3 = splat 0 (0) -4 r4 = splat FFFFFFFF (nan) -5 r5 = neq_f32 r0 r3 -6 r6 = splat 3F800000 (1) -7 r6 = bit_and r2 r6 -8 r7 = to_f32 r1 -9 r7 = select r5 r6 r7 -10 r3 = eq_i32 r1 r3 -11 r4 = bit_xor r3 r4 -12 r3 = splat 1 (1.4012985e-45) -13 r3 = bit_and r2 r3 -14 r0 = trunc r0 -15 r0 = select r4 r3 r0 -16 r0 = to_f32 r0 -17 r0 = mul_f32 r7 r0 +4 r4 = neq_f32 r0 r3 +5 r5 = splat 3F800000 (1) +6 r5 = bit_and r2 r5 +7 r6 = to_f32 r1 +8 r6 = select r4 r5 r6 +9 r3 = eq_i32 r1 r3 +10 r1 = splat 1 (1.4012985e-45) +11 r1 = bit_and r2 r1 +12 r0 = trunc r0 +13 r1 = select r3 r0 r1 +14 r1 = to_f32 r1 +15 r1 = mul_f32 r6 r1 loop: -18 store32 ptr1 r0 -19 store32 ptr2 r0 -20 store32 ptr3 r0 -21 store32 ptr4 r0 +16 store32 ptr1 r1 +17 store32 ptr2 r1 +18 store32 ptr3 r1 +19 store32 ptr4 r1