Skip to content

Commit

Permalink
[InstCombine] add helper function for folding {and,or,xor} (cast X), …
Browse files Browse the repository at this point in the history
…C ; NFCI

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281187 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
rotateright committed Sep 12, 2016
1 parent 278eb07 commit 52fed49
Showing 1 changed file with 41 additions and 28 deletions.
69 changes: 41 additions & 28 deletions lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,45 @@ bool InstCombiner::shouldOptimizeCast(CastInst *CI) {
return true;
}

/// Fold {and,or,xor} (cast X), C.
static Instruction *foldLogicCastConstant(BinaryOperator &Logic, CastInst *Cast,
InstCombiner::BuilderTy *Builder) {
Constant *C;
if (!match(Logic.getOperand(1), m_Constant(C)))
return nullptr;

auto LogicOpc = Logic.getOpcode();
Type *DestTy = Logic.getType();
Type *SrcTy = Cast->getSrcTy();

// If the first operand is bitcast, move the logic operation ahead of the
// bitcast (do the logic operation in the original type). This can eliminate
// bitcasts and allow combines that would otherwise be impeded by the bitcast.
Value *X;
if (match(Cast, m_BitCast(m_Value(X)))) {
Value *NewConstant = ConstantExpr::getBitCast(C, SrcTy);
Value *NewOp = Builder->CreateBinOp(LogicOpc, X, NewConstant);
return CastInst::CreateBitOrPointerCast(NewOp, DestTy);
}

// Similarly, move the logic operation ahead of a zext if the constant is
// unchanged in the smaller source type. Performing the logic in a smaller
// type may provide more information to later folds, and the smaller logic
// instruction may be cheaper (particularly in the case of vectors).
if (match(Cast, m_OneUse(m_ZExt(m_Value(X))))) {
Constant *TruncC = ConstantExpr::getTrunc(C, SrcTy);
Constant *ZextTruncC = ConstantExpr::getZExt(TruncC, DestTy);
if (ZextTruncC == C) {
// LogicOpc (zext X), C --> zext (LogicOpc X, C)
Value *NewOp = Builder->CreateBinOp(LogicOpc, X, TruncC);
return new ZExtInst(NewOp, DestTy);
}
}

return nullptr;
}

/// Fold {and,or,xor} (cast X), Y.
Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) {
auto LogicOpc = I.getOpcode();
assert((LogicOpc == Instruction::And || LogicOpc == Instruction::Or ||
Expand All @@ -1149,34 +1188,8 @@ Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) {
if (!SrcTy->isIntOrIntVectorTy())
return nullptr;

// If one operand is a bitcast and the other is a constant, move the logic
// operation ahead of the bitcast. That is, do the logic operation in the
// original type. This can eliminate useless bitcasts and allow normal
// combines that would otherwise be impeded by the bitcast. Canonicalization
// ensures that if there is a constant operand, it will be the second operand.
Value *BC = nullptr;
Constant *C = nullptr;
if ((match(Op0, m_BitCast(m_Value(BC))) && match(Op1, m_Constant(C)))) {
Value *NewConstant = ConstantExpr::getBitCast(C, SrcTy);
Value *NewOp = Builder->CreateBinOp(LogicOpc, BC, NewConstant, I.getName());
return CastInst::CreateBitOrPointerCast(NewOp, DestTy);
}

// Similarly, if one operand is zexted and the other is a constant, move the
// logic operation ahead of the zext if the constant is unchanged in the
// smaller source type. Performing the logic in a smaller type may provide
// more information to later folds, and the smaller logic instruction may be
// cheaper (particularly in the case of vectors).
Value *X;
if (match(Op0, m_OneUse(m_ZExt(m_Value(X)))) && match(Op1, m_Constant(C))) {
Constant *TruncC = ConstantExpr::getTrunc(C, SrcTy);
Constant *ZextTruncC = ConstantExpr::getZExt(TruncC, DestTy);
if (ZextTruncC == C) {
// LogicOpc (zext X), C --> zext (LogicOpc X, C)
Value *NewOp = Builder->CreateBinOp(LogicOpc, X, TruncC);
return new ZExtInst(NewOp, DestTy);
}
}
if (Instruction *Ret = foldLogicCastConstant(I, Cast0, Builder))
return Ret;

CastInst *Cast1 = dyn_cast<CastInst>(Op1);
if (!Cast1)
Expand Down

0 comments on commit 52fed49

Please sign in to comment.