mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
[InstCombine] Add new rule for MIN(MAX(~A, ~B), ~C) et. al.
Summary: Optimizing these well are especially interesting for IRCE since it "clamps" values by generating this sort of pattern through SCEV expressions. Depends on D9352. Reviewers: majnemer Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D9353 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236203 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c0730628a4
commit
a34038226e
@ -20,6 +20,46 @@ using namespace PatternMatch;
|
||||
|
||||
#define DEBUG_TYPE "instcombine"
|
||||
|
||||
static SelectPatternFlavor
|
||||
getInverseMinMaxSelectPattern(SelectPatternFlavor SPF) {
|
||||
switch (SPF) {
|
||||
default:
|
||||
llvm_unreachable("unhandled!");
|
||||
|
||||
case SPF_SMIN:
|
||||
return SPF_SMAX;
|
||||
case SPF_UMIN:
|
||||
return SPF_UMAX;
|
||||
case SPF_SMAX:
|
||||
return SPF_SMIN;
|
||||
case SPF_UMAX:
|
||||
return SPF_UMIN;
|
||||
}
|
||||
}
|
||||
|
||||
static CmpInst::Predicate getICmpPredicateForMinMax(SelectPatternFlavor SPF) {
|
||||
switch (SPF) {
|
||||
default:
|
||||
llvm_unreachable("unhandled!");
|
||||
|
||||
case SPF_SMIN:
|
||||
return ICmpInst::ICMP_SLT;
|
||||
case SPF_UMIN:
|
||||
return ICmpInst::ICMP_ULT;
|
||||
case SPF_SMAX:
|
||||
return ICmpInst::ICMP_SGT;
|
||||
case SPF_UMAX:
|
||||
return ICmpInst::ICMP_UGT;
|
||||
}
|
||||
}
|
||||
|
||||
static Value *generateMinMaxSelectPattern(InstCombiner::BuilderTy *Builder,
|
||||
SelectPatternFlavor SPF, Value *A,
|
||||
Value *B) {
|
||||
CmpInst::Predicate Pred = getICmpPredicateForMinMax(SPF);
|
||||
return Builder->CreateSelect(Builder->CreateICmp(Pred, A, B), A, B);
|
||||
}
|
||||
|
||||
/// MatchSelectPattern - Pattern match integer [SU]MIN, [SU]MAX, and ABS idioms,
|
||||
/// returning the kind and providing the out parameter results if we
|
||||
/// successfully match.
|
||||
@ -840,6 +880,52 @@ Instruction *InstCombiner::FoldSPFofSPF(Instruction *Inner,
|
||||
SI->getCondition(), SI->getFalseValue(), SI->getTrueValue());
|
||||
return ReplaceInstUsesWith(Outer, NewSI);
|
||||
}
|
||||
|
||||
auto IsFreeOrProfitableToInvert =
|
||||
[&](Value *V, Value *&NotV, bool &ElidesXor) {
|
||||
if (match(V, m_Not(m_Value(NotV)))) {
|
||||
// If V has at most 2 uses then we can get rid of the xor operation
|
||||
// entirely.
|
||||
ElidesXor |= !V->hasNUsesOrMore(3);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsFreeToInvert(V, !V->hasNUsesOrMore(3))) {
|
||||
NotV = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Value *NotA, *NotB, *NotC;
|
||||
bool ElidesXor = false;
|
||||
|
||||
// MIN(MIN(~A, ~B), ~C) == ~MAX(MAX(A, B), C)
|
||||
// MIN(MAX(~A, ~B), ~C) == ~MAX(MIN(A, B), C)
|
||||
// MAX(MIN(~A, ~B), ~C) == ~MIN(MAX(A, B), C)
|
||||
// MAX(MAX(~A, ~B), ~C) == ~MIN(MIN(A, B), C)
|
||||
//
|
||||
// This transform is performance neutral if we can elide at least one xor from
|
||||
// the set of three operands, since we'll be tacking on an xor at the very
|
||||
// end.
|
||||
if (IsFreeOrProfitableToInvert(A, NotA, ElidesXor) &&
|
||||
IsFreeOrProfitableToInvert(B, NotB, ElidesXor) &&
|
||||
IsFreeOrProfitableToInvert(C, NotC, ElidesXor) && ElidesXor) {
|
||||
if (!NotA)
|
||||
NotA = Builder->CreateNot(A);
|
||||
if (!NotB)
|
||||
NotB = Builder->CreateNot(B);
|
||||
if (!NotC)
|
||||
NotC = Builder->CreateNot(C);
|
||||
|
||||
Value *NewInner = generateMinMaxSelectPattern(
|
||||
Builder, getInverseMinMaxSelectPattern(SPF1), NotA, NotB);
|
||||
Value *NewOuter = Builder->CreateNot(generateMinMaxSelectPattern(
|
||||
Builder, getInverseMinMaxSelectPattern(SPF2), NewInner, NotC));
|
||||
return ReplaceInstUsesWith(Outer, NewOuter);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -66,3 +66,20 @@ define i32 @compute_min_pessimization(i32 %x, i32 %y) {
|
||||
%min = sub i32 -1, %not_min
|
||||
ret i32 %min
|
||||
}
|
||||
|
||||
define i32 @max_of_nots(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: @max_of_nots(
|
||||
; CHECK-NEXT: icmp
|
||||
; CHECK-NEXT: select
|
||||
; CHECK-NEXT: icmp
|
||||
; CHECK-NEXT: select
|
||||
; CHECK-NEXT: xor
|
||||
; CHECK-NEXT: ret
|
||||
%c0 = icmp sgt i32 %y, 0
|
||||
%xor_y = xor i32 %y, -1
|
||||
%s0 = select i1 %c0, i32 %xor_y, i32 -1
|
||||
%xor_x = xor i32 %x, -1
|
||||
%c1 = icmp slt i32 %s0, %xor_x
|
||||
%smax96 = select i1 %c1, i32 %xor_x, i32 %s0
|
||||
ret i32 %smax96
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user