Skip to content

Commit

Permalink
InstCombine: Fold logic of fp_classes together
Browse files Browse the repository at this point in the history
Move logical operators on pairs of llvm.is.fpclass on the same value
into the test mask of a single is_fpclass.

or (class x, mask0), (class x, mask1) -> class x, (mask0 | mask1)
and (class x, mask0), (class x, mask1) -> class x, (mask0 & mask1)
xor (class x, mask0), (class x, mask1) -> class x, (mask0 ^ mask1)

The and/or cases should appear frequently in the builtin math
libraries; haven't seen the xor case but handle it for completeness.
  • Loading branch information
arsenm committed Dec 13, 2022
1 parent e9d298d commit 8fc25ca
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 141 deletions.
49 changes: 49 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Expand Up @@ -1268,6 +1268,46 @@ Value *InstCombinerImpl::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS,
return nullptr;
}

/// or (is_fpclass x, mask0), (is_fpclass x, mask1)
/// -> is_fpclass x, (mask0 | mask1)
/// and (is_fpclass x, mask0), (is_fpclass x, mask1)
/// -> is_fpclass x, (mask0 & mask1)
/// xor (is_fpclass x, mask0), (is_fpclass x, mask1)
/// -> is_fpclass x, (mask0 ^ mask1)
Instruction *InstCombinerImpl::foldLogicOfIsFPClass(BinaryOperator &BO,
Value *Op0, Value *Op1) {
Value *ClassVal;
uint64_t ClassMask0, ClassMask1;

if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::is_fpclass>(
m_Value(ClassVal), m_ConstantInt(ClassMask0)))) &&
match(Op1, m_OneUse(m_Intrinsic<Intrinsic::is_fpclass>(
m_Specific(ClassVal), m_ConstantInt(ClassMask1))))) {
unsigned NewClassMask;
switch (BO.getOpcode()) {
case Instruction::And:
NewClassMask = ClassMask0 & ClassMask1;
break;
case Instruction::Or:
NewClassMask = ClassMask0 | ClassMask1;
break;
case Instruction::Xor:
NewClassMask = ClassMask0 ^ ClassMask1;
break;
default:
llvm_unreachable("not a binary logic operator");
}

// TODO: Also check for special fcmps
auto *II = cast<IntrinsicInst>(Op0);
II->setArgOperand(
1, ConstantInt::get(II->getArgOperand(1)->getType(), NewClassMask));
return replaceInstUsesWith(BO, II);
}

return nullptr;
}

/// This a limited reassociation for a special case (see above) where we are
/// checking if two values are either both NAN (unordered) or not-NAN (ordered).
/// This could be handled more generally in '-reassociation', but it seems like
Expand Down Expand Up @@ -2285,6 +2325,9 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
if (Instruction *Canonicalized = canonicalizeLogicFirst(I, Builder))
return Canonicalized;

if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))
return Folded;

return nullptr;
}

Expand Down Expand Up @@ -3265,6 +3308,9 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
if (Instruction *Canonicalized = canonicalizeLogicFirst(I, Builder))
return Canonicalized;

if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))
return Folded;

return nullptr;
}

Expand Down Expand Up @@ -4060,5 +4106,8 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
if (Instruction *Canonicalized = canonicalizeLogicFirst(I, Builder))
return Canonicalized;

if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))
return Folded;

return nullptr;
}
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineInternal.h
Expand Up @@ -362,6 +362,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
Value *foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd,
bool IsLogicalSelect = false);

Instruction *foldLogicOfIsFPClass(BinaryOperator &Operator, Value *LHS,
Value *RHS);

Value *foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS, ICmpInst *RHS,
Instruction *CxtI, bool IsAnd,
bool IsLogical = false);
Expand Down

0 comments on commit 8fc25ca

Please sign in to comment.