[PATCH] D33172: [InstCombine] Simpify inverted predicates in 'or'
Sanjay Patel via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon May 15 08:11:12 PDT 2017
spatel added a comment.
I agree that we're missing some kind of more general transform. Eg:
int goo(int x, int y, int r) {
if (x > y) r += 42;
if (x <= y) r += 12;
return r;
}
define i32 @goo(i32, i32, i32) {
%4 = icmp sgt i32 %0, %1
%5 = add nsw i32 %2, 42
%6 = select i1 %4, i32 %5, i32 %2
%7 = add nsw i32 %6, 12
%8 = select i1 %4, i32 %5, i32 %7
ret i32 %8
}
https://godbolt.org/g/tszo72
It's worth noting that one motivation for PR32791 (although I forgot to write it there) is that I think we should canonicalize all:
not (cmp P, X, Y) --> cmp P', X, Y
Ie, invert the predicate to eliminate an explicit 'not' (xor) because then we have eliminated a dependency in the IR. This was discussed in https://reviews.llvm.org/D32725.
So we should look at how the existing InstCombine test ("@poo" is just above the new test here) fails if we implement that canonicalization:
define i32 @poo5(i32 %a, i32 %b, i32 %c, i32 %d) {
%cmp = icmp slt i32 %a, %b
%and1 = select i1 %cmp, i32 %c, i32 0
%cmpnot = xor i1 %cmp, -1 <--- this can be replaced by "icmp sge i32 %a, %b", and we have the first testcase in this patch (the test from PR32791)
%and2 = select i1 %cmpnot, i32 %d, i32 0
%or = or i32 %and1, %and2
ret i32 %or
}
define i32 @poo6(i32 %a, i32 %b, i32 %c, i32 %d) {
%cmp = icmp slt i32 %a, %b
%and1 = select i1 %cmp, i32 %c, i32 0
%and2 = select i1 %cmp, i32 0, i32 %d <--- we fold a 'not' compare by swapping the select operands
%or = or i32 %and1, %and2
ret i32 %or
}
For this pattern, there's a fold in InstCombiner::SimplifyUsingDistributiveLaws():
// (op (select (a, c, b)), (select (a, d, b))) -> (select (a, (op c, d), 0))
// (op (select (a, b, c)), (select (a, b, d))) -> (select (a, 0, (op c, d)))
Note: the implementation for that fold seems bogus. We create a new binop and a new select for *both* of the current selects in this example and then don't use one pair.
So if we want a more general InstCombine solution than what is currently proposed here, I think we should enhance that to account for an inverted predicate as well as matching predicates:
binop (select P, A, B), (select P', C, D) --> binop (select P, A, B), (select P, D, C)
and let the existing fold take it from there.
Swapping select operands to eliminate an inverted compare seems like a generally good fold for some other pass too. Would that be GVN?
https://reviews.llvm.org/D33172
More information about the llvm-commits
mailing list