mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 09:53:54 +00:00
[InstCombine] add helper function for folding {and,or,xor} (cast X), C ; NFCI
llvm-svn: 281187
This commit is contained in:
parent
2a06320b7c
commit
2306b9373b
@ -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 ||
|
||||
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user