[InstCombine] Non-canonical clamp-like pattern handling

Authored by lebedev.ri on Aug 13 2019, 5:49 AM.


[InstCombine] Non-canonical clamp-like pattern handling

Given a pattern like:

%old_cmp1 = icmp slt i32 %x, C2
%old_replacement = select i1 %old_cmp1, i32 %target_low, i32 %target_high
%old_x_offseted = add i32 %x, C1
%old_cmp0 = icmp ult i32 %old_x_offseted, C0
%r = select i1 %old_cmp0, i32 %x, i32 %old_replacement

it can be rewritten as more canonical pattern:

%new_cmp1 = icmp slt i32 %x, -C1
%new_cmp2 = icmp sge i32 %x, C0-C1
%new_clamped_low = select i1 %new_cmp1, i32 %target_low, i32 %x
%r = select i1 %new_cmp2, i32 %target_high, i32 %new_clamped_low

Iff -C1 s<= C2 s<= C0-C1
Also, ULT predicate can also be UGE; or UGT iff C0 != -1 (+invert result)
Also, SLT predicate can also be SGE; or SGT iff C2 != INT_MAX (+invert result)

If C1 == 0, then all 3 instructions must be one-use; else at most either %old_cmp1 or %old_x_offseted can have extra uses.

NOTE: if we could reuse %old_cmp1 as one of the comparisons we'll have to build, this could be less limiting.

So there are two icmp's, each one with 3 predicate variants, so there are 9 fold variants:

This fold was brought up in https://reviews.llvm.org/D65148#1603922 by @dmgreen, and is needed to unblock that patch.
This patch requires D65530.

Reviewers: spatel, nikic, xbolva00, dmgreen

Reviewed By: spatel

Subscribers: hiraditya, llvm-commits, dmgreen

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D65765

llvm-svn: 368687