InstCombineAndOrXor.cpp [plain text]
#include "InstCombineInternal.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Transforms/Utils/CmpInstAnalysis.h"
using namespace llvm;
using namespace PatternMatch;
#define DEBUG_TYPE "instcombine"
static inline bool isFreeToInvert(Value *V) {
if (BinaryOperator::isNot(V))
return true;
if (isa<ConstantInt>(V))
return true;
if (CmpInst *CI = dyn_cast<CmpInst>(V))
return CI->hasOneUse();
return false;
}
static inline Value *dyn_castNotVal(Value *V) {
if (BinaryOperator::isNot(V)) {
Value *Operand = BinaryOperator::getNotArgument(V);
if (!isFreeToInvert(Operand))
return Operand;
}
if (ConstantInt *C = dyn_cast<ConstantInt>(V))
return ConstantInt::get(C->getType(), ~C->getValue());
return nullptr;
}
static unsigned getFCmpCode(FCmpInst::Predicate CC, bool &isOrdered) {
isOrdered = false;
switch (CC) {
case FCmpInst::FCMP_ORD: isOrdered = true; return 0; case FCmpInst::FCMP_UNO: return 0; case FCmpInst::FCMP_OGT: isOrdered = true; return 1; case FCmpInst::FCMP_UGT: return 1; case FCmpInst::FCMP_OEQ: isOrdered = true; return 2; case FCmpInst::FCMP_UEQ: return 2; case FCmpInst::FCMP_OGE: isOrdered = true; return 3; case FCmpInst::FCMP_UGE: return 3; case FCmpInst::FCMP_OLT: isOrdered = true; return 4; case FCmpInst::FCMP_ULT: return 4; case FCmpInst::FCMP_ONE: isOrdered = true; return 5; case FCmpInst::FCMP_UNE: return 5; case FCmpInst::FCMP_OLE: isOrdered = true; return 6; case FCmpInst::FCMP_ULE: return 6; default:
llvm_unreachable("Unexpected FCmp predicate!");
}
}
static Value *getNewICmpValue(bool Sign, unsigned Code, Value *LHS, Value *RHS,
InstCombiner::BuilderTy *Builder) {
ICmpInst::Predicate NewPred;
if (Value *NewConstant = getICmpValue(Sign, Code, LHS, RHS, NewPred))
return NewConstant;
return Builder->CreateICmp(NewPred, LHS, RHS);
}
static Value *getFCmpValue(bool isordered, unsigned code,
Value *LHS, Value *RHS,
InstCombiner::BuilderTy *Builder) {
CmpInst::Predicate Pred;
switch (code) {
default: llvm_unreachable("Illegal FCmp code!");
case 0: Pred = isordered ? FCmpInst::FCMP_ORD : FCmpInst::FCMP_UNO; break;
case 1: Pred = isordered ? FCmpInst::FCMP_OGT : FCmpInst::FCMP_UGT; break;
case 2: Pred = isordered ? FCmpInst::FCMP_OEQ : FCmpInst::FCMP_UEQ; break;
case 3: Pred = isordered ? FCmpInst::FCMP_OGE : FCmpInst::FCMP_UGE; break;
case 4: Pred = isordered ? FCmpInst::FCMP_OLT : FCmpInst::FCMP_ULT; break;
case 5: Pred = isordered ? FCmpInst::FCMP_ONE : FCmpInst::FCMP_UNE; break;
case 6: Pred = isordered ? FCmpInst::FCMP_OLE : FCmpInst::FCMP_ULE; break;
case 7:
if (!isordered) return ConstantInt::getTrue(LHS->getContext());
Pred = FCmpInst::FCMP_ORD; break;
}
return Builder->CreateFCmp(Pred, LHS, RHS);
}
Value *InstCombiner::SimplifyBSwap(BinaryOperator &I) {
IntegerType *ITy = dyn_cast<IntegerType>(I.getType());
if (I.getType()->isVectorTy()) return nullptr;
unsigned Op = I.getOpcode();
if (Op != Instruction::And && Op != Instruction::Or &&
Op != Instruction::Xor)
return nullptr;
Value *OldLHS = I.getOperand(0);
Value *OldRHS = I.getOperand(1);
ConstantInt *ConstLHS = dyn_cast<ConstantInt>(OldLHS);
ConstantInt *ConstRHS = dyn_cast<ConstantInt>(OldRHS);
IntrinsicInst *IntrLHS = dyn_cast<IntrinsicInst>(OldLHS);
IntrinsicInst *IntrRHS = dyn_cast<IntrinsicInst>(OldRHS);
bool IsBswapLHS = (IntrLHS && IntrLHS->getIntrinsicID() == Intrinsic::bswap);
bool IsBswapRHS = (IntrRHS && IntrRHS->getIntrinsicID() == Intrinsic::bswap);
if (!IsBswapLHS && !IsBswapRHS)
return nullptr;
if (!IsBswapLHS && !ConstLHS)
return nullptr;
if (!IsBswapRHS && !ConstRHS)
return nullptr;
Value *NewLHS = IsBswapLHS ? IntrLHS->getOperand(0) :
Builder->getInt(ConstLHS->getValue().byteSwap());
Value *NewRHS = IsBswapRHS ? IntrRHS->getOperand(0) :
Builder->getInt(ConstRHS->getValue().byteSwap());
Value *BinOp = nullptr;
if (Op == Instruction::And)
BinOp = Builder->CreateAnd(NewLHS, NewRHS);
else if (Op == Instruction::Or)
BinOp = Builder->CreateOr(NewLHS, NewRHS);
else BinOp = Builder->CreateXor(NewLHS, NewRHS);
Module *M = I.getParent()->getParent()->getParent();
Function *F = Intrinsic::getDeclaration(M, Intrinsic::bswap, ITy);
return Builder->CreateCall(F, BinOp);
}
Instruction *InstCombiner::OptAndOp(Instruction *Op,
ConstantInt *OpRHS,
ConstantInt *AndRHS,
BinaryOperator &TheAnd) {
Value *X = Op->getOperand(0);
Constant *Together = nullptr;
if (!Op->isShift())
Together = ConstantExpr::getAnd(AndRHS, OpRHS);
switch (Op->getOpcode()) {
case Instruction::Xor:
if (Op->hasOneUse()) {
Value *And = Builder->CreateAnd(X, AndRHS);
And->takeName(Op);
return BinaryOperator::CreateXor(And, Together);
}
break;
case Instruction::Or:
if (Op->hasOneUse()){
if (Together != OpRHS) {
Value *Or = Builder->CreateOr(X, Together);
Or->takeName(Op);
return BinaryOperator::CreateAnd(Or, AndRHS);
}
ConstantInt *TogetherCI = dyn_cast<ConstantInt>(Together);
if (TogetherCI && !TogetherCI->isZero()){
Together = ConstantExpr::getXor(AndRHS, Together);
Value *And = Builder->CreateAnd(X, Together);
And->takeName(Op);
return BinaryOperator::CreateOr(And, OpRHS);
}
}
break;
case Instruction::Add:
if (Op->hasOneUse()) {
const APInt &AndRHSV = AndRHS->getValue();
if (AndRHSV.isPowerOf2()) {
const APInt& AddRHS = OpRHS->getValue();
if ((AddRHS & (AndRHSV-1)) == 0) {
if ((AddRHS & AndRHSV) == 0) { TheAnd.setOperand(0, X);
return &TheAnd;
} else {
Value *NewAnd = Builder->CreateAnd(X, AndRHS);
NewAnd->takeName(Op);
return BinaryOperator::CreateXor(NewAnd, AndRHS);
}
}
}
}
break;
case Instruction::Shl: {
uint32_t BitWidth = AndRHS->getType()->getBitWidth();
uint32_t OpRHSVal = OpRHS->getLimitedValue(BitWidth);
APInt ShlMask(APInt::getHighBitsSet(BitWidth, BitWidth-OpRHSVal));
ConstantInt *CI = Builder->getInt(AndRHS->getValue() & ShlMask);
if (CI->getValue() == ShlMask)
return ReplaceInstUsesWith(TheAnd, Op);
if (CI != AndRHS) { TheAnd.setOperand(1, CI);
return &TheAnd;
}
break;
}
case Instruction::LShr: {
uint32_t BitWidth = AndRHS->getType()->getBitWidth();
uint32_t OpRHSVal = OpRHS->getLimitedValue(BitWidth);
APInt ShrMask(APInt::getLowBitsSet(BitWidth, BitWidth - OpRHSVal));
ConstantInt *CI = Builder->getInt(AndRHS->getValue() & ShrMask);
if (CI->getValue() == ShrMask)
return ReplaceInstUsesWith(TheAnd, Op);
if (CI != AndRHS) {
TheAnd.setOperand(1, CI); return &TheAnd;
}
break;
}
case Instruction::AShr:
if (Op->hasOneUse()) {
uint32_t BitWidth = AndRHS->getType()->getBitWidth();
uint32_t OpRHSVal = OpRHS->getLimitedValue(BitWidth);
APInt ShrMask(APInt::getLowBitsSet(BitWidth, BitWidth - OpRHSVal));
Constant *C = Builder->getInt(AndRHS->getValue() & ShrMask);
if (C == AndRHS) { Value *ShVal = Op->getOperand(0);
ShVal = Builder->CreateLShr(ShVal, OpRHS, Op->getName());
return BinaryOperator::CreateAnd(ShVal, AndRHS, TheAnd.getName());
}
}
break;
}
return nullptr;
}
Value *InstCombiner::InsertRangeTest(Value *V, Constant *Lo, Constant *Hi,
bool isSigned, bool Inside) {
assert(cast<ConstantInt>(ConstantExpr::getICmp((isSigned ?
ICmpInst::ICMP_SLE:ICmpInst::ICMP_ULE), Lo, Hi))->getZExtValue() &&
"Lo is not <= Hi in range emission code!");
if (Inside) {
if (Lo == Hi) return Builder->getFalse();
if (cast<ConstantInt>(Lo)->isMinValue(isSigned)) {
ICmpInst::Predicate pred = (isSigned ?
ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT);
return Builder->CreateICmp(pred, V, Hi);
}
Constant *NegLo = ConstantExpr::getNeg(Lo);
Value *Add = Builder->CreateAdd(V, NegLo, V->getName()+".off");
Constant *UpperBound = ConstantExpr::getAdd(NegLo, Hi);
return Builder->CreateICmpULT(Add, UpperBound);
}
if (Lo == Hi) return Builder->getTrue();
Hi = SubOne(cast<ConstantInt>(Hi));
if (cast<ConstantInt>(Lo)->isMinValue(isSigned)) {
ICmpInst::Predicate pred = (isSigned ?
ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT);
return Builder->CreateICmp(pred, V, Hi);
}
ConstantInt *NegLo = cast<ConstantInt>(ConstantExpr::getNeg(Lo));
Value *Add = Builder->CreateAdd(V, NegLo, V->getName()+".off");
Constant *LowerBound = ConstantExpr::getAdd(NegLo, Hi);
return Builder->CreateICmpUGT(Add, LowerBound);
}
static bool isRunOfOnes(ConstantInt *Val, uint32_t &MB, uint32_t &ME) {
const APInt& V = Val->getValue();
uint32_t BitWidth = Val->getType()->getBitWidth();
if (!APIntOps::isShiftedMask(BitWidth, V)) return false;
MB = BitWidth - ((V - 1) ^ V).countLeadingZeros();
ME = V.getActiveBits();
return true;
}
Value *InstCombiner::FoldLogicalPlusAnd(Value *LHS, Value *RHS,
ConstantInt *Mask, bool isSub,
Instruction &I) {
Instruction *LHSI = dyn_cast<Instruction>(LHS);
if (!LHSI || LHSI->getNumOperands() != 2 ||
!isa<ConstantInt>(LHSI->getOperand(1))) return nullptr;
ConstantInt *N = cast<ConstantInt>(LHSI->getOperand(1));
switch (LHSI->getOpcode()) {
default: return nullptr;
case Instruction::And:
if (ConstantExpr::getAnd(N, Mask) == Mask) {
if ((Mask->getValue().countLeadingZeros() +
Mask->getValue().countPopulation()) ==
Mask->getValue().getBitWidth())
break;
uint32_t MB = 0, ME = 0;
if (isRunOfOnes(Mask, MB, ME)) { uint32_t BitWidth = cast<IntegerType>(RHS->getType())->getBitWidth();
APInt Mask(APInt::getLowBitsSet(BitWidth, MB-1));
if (MaskedValueIsZero(RHS, Mask, 0, &I))
break;
}
}
return nullptr;
case Instruction::Or:
case Instruction::Xor:
if ((Mask->getValue().countLeadingZeros() +
Mask->getValue().countPopulation()) == Mask->getValue().getBitWidth()
&& ConstantExpr::getAnd(N, Mask)->isNullValue())
break;
return nullptr;
}
if (isSub)
return Builder->CreateSub(LHSI->getOperand(0), RHS, "fold");
return Builder->CreateAdd(LHSI->getOperand(0), RHS, "fold");
}
enum MaskedICmpType {
FoldMskICmp_AMask_AllOnes = 1,
FoldMskICmp_AMask_NotAllOnes = 2,
FoldMskICmp_BMask_AllOnes = 4,
FoldMskICmp_BMask_NotAllOnes = 8,
FoldMskICmp_Mask_AllZeroes = 16,
FoldMskICmp_Mask_NotAllZeroes = 32,
FoldMskICmp_AMask_Mixed = 64,
FoldMskICmp_AMask_NotMixed = 128,
FoldMskICmp_BMask_Mixed = 256,
FoldMskICmp_BMask_NotMixed = 512
};
static unsigned getTypeOfMaskedICmp(Value* A, Value* B, Value* C,
ICmpInst::Predicate SCC)
{
ConstantInt *ACst = dyn_cast<ConstantInt>(A);
ConstantInt *BCst = dyn_cast<ConstantInt>(B);
ConstantInt *CCst = dyn_cast<ConstantInt>(C);
bool icmp_eq = (SCC == ICmpInst::ICMP_EQ);
bool icmp_abit = (ACst && !ACst->isZero() &&
ACst->getValue().isPowerOf2());
bool icmp_bbit = (BCst && !BCst->isZero() &&
BCst->getValue().isPowerOf2());
unsigned result = 0;
if (CCst && CCst->isZero()) {
result |= (icmp_eq ? (FoldMskICmp_Mask_AllZeroes |
FoldMskICmp_Mask_AllZeroes |
FoldMskICmp_AMask_Mixed |
FoldMskICmp_BMask_Mixed)
: (FoldMskICmp_Mask_NotAllZeroes |
FoldMskICmp_Mask_NotAllZeroes |
FoldMskICmp_AMask_NotMixed |
FoldMskICmp_BMask_NotMixed));
if (icmp_abit)
result |= (icmp_eq ? (FoldMskICmp_AMask_NotAllOnes |
FoldMskICmp_AMask_NotMixed)
: (FoldMskICmp_AMask_AllOnes |
FoldMskICmp_AMask_Mixed));
if (icmp_bbit)
result |= (icmp_eq ? (FoldMskICmp_BMask_NotAllOnes |
FoldMskICmp_BMask_NotMixed)
: (FoldMskICmp_BMask_AllOnes |
FoldMskICmp_BMask_Mixed));
return result;
}
if (A == C) {
result |= (icmp_eq ? (FoldMskICmp_AMask_AllOnes |
FoldMskICmp_AMask_Mixed)
: (FoldMskICmp_AMask_NotAllOnes |
FoldMskICmp_AMask_NotMixed));
if (icmp_abit)
result |= (icmp_eq ? (FoldMskICmp_Mask_NotAllZeroes |
FoldMskICmp_AMask_NotMixed)
: (FoldMskICmp_Mask_AllZeroes |
FoldMskICmp_AMask_Mixed));
} else if (ACst && CCst &&
ConstantExpr::getAnd(ACst, CCst) == CCst) {
result |= (icmp_eq ? FoldMskICmp_AMask_Mixed
: FoldMskICmp_AMask_NotMixed);
}
if (B == C) {
result |= (icmp_eq ? (FoldMskICmp_BMask_AllOnes |
FoldMskICmp_BMask_Mixed)
: (FoldMskICmp_BMask_NotAllOnes |
FoldMskICmp_BMask_NotMixed));
if (icmp_bbit)
result |= (icmp_eq ? (FoldMskICmp_Mask_NotAllZeroes |
FoldMskICmp_BMask_NotMixed)
: (FoldMskICmp_Mask_AllZeroes |
FoldMskICmp_BMask_Mixed));
} else if (BCst && CCst &&
ConstantExpr::getAnd(BCst, CCst) == CCst) {
result |= (icmp_eq ? FoldMskICmp_BMask_Mixed
: FoldMskICmp_BMask_NotMixed);
}
return result;
}
static unsigned conjugateICmpMask(unsigned Mask) {
unsigned NewMask;
NewMask = (Mask & (FoldMskICmp_AMask_AllOnes | FoldMskICmp_BMask_AllOnes |
FoldMskICmp_Mask_AllZeroes | FoldMskICmp_AMask_Mixed |
FoldMskICmp_BMask_Mixed))
<< 1;
NewMask |=
(Mask & (FoldMskICmp_AMask_NotAllOnes | FoldMskICmp_BMask_NotAllOnes |
FoldMskICmp_Mask_NotAllZeroes | FoldMskICmp_AMask_NotMixed |
FoldMskICmp_BMask_NotMixed))
>> 1;
return NewMask;
}
static bool decomposeBitTestICmp(const ICmpInst *I, ICmpInst::Predicate &Pred,
Value *&X, Value *&Y, Value *&Z) {
ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1));
if (!C)
return false;
switch (I->getPredicate()) {
default:
return false;
case ICmpInst::ICMP_SLT:
if (!C->isZero())
return false;
Y = ConstantInt::get(I->getContext(), APInt::getSignBit(C->getBitWidth()));
Pred = ICmpInst::ICMP_NE;
break;
case ICmpInst::ICMP_SGT:
if (!C->isAllOnesValue())
return false;
Y = ConstantInt::get(I->getContext(), APInt::getSignBit(C->getBitWidth()));
Pred = ICmpInst::ICMP_EQ;
break;
case ICmpInst::ICMP_ULT:
if (!C->getValue().isPowerOf2())
return false;
Y = ConstantInt::get(I->getContext(), -C->getValue());
Pred = ICmpInst::ICMP_EQ;
break;
case ICmpInst::ICMP_UGT:
if (!(C->getValue() + 1).isPowerOf2())
return false;
Y = ConstantInt::get(I->getContext(), ~C->getValue());
Pred = ICmpInst::ICMP_NE;
break;
}
X = I->getOperand(0);
Z = ConstantInt::getNullValue(C->getType());
return true;
}
static unsigned foldLogOpOfMaskedICmpsHelper(Value*& A,
Value*& B, Value*& C,
Value*& D, Value*& E,
ICmpInst *LHS, ICmpInst *RHS,
ICmpInst::Predicate &LHSCC,
ICmpInst::Predicate &RHSCC) {
if (LHS->getOperand(0)->getType() != RHS->getOperand(0)->getType()) return 0;
if (LHS->getOperand(0)->getType()->isVectorTy()) return 0;
Value *L1 = LHS->getOperand(0);
Value *L2 = LHS->getOperand(1);
Value *L11,*L12,*L21,*L22;
if (decomposeBitTestICmp(LHS, LHSCC, L11, L12, L2)) {
L21 = L22 = L1 = nullptr;
} else {
if (!L1->getType()->isIntegerTy()) {
L11 = L12 = nullptr;
} else if (!match(L1, m_And(m_Value(L11), m_Value(L12)))) {
L11 = L1;
L12 = Constant::getAllOnesValue(L1->getType());
}
if (!L2->getType()->isIntegerTy()) {
L21 = L22 = nullptr;
} else if (!match(L2, m_And(m_Value(L21), m_Value(L22)))) {
L21 = L2;
L22 = Constant::getAllOnesValue(L2->getType());
}
}
if (!ICmpInst::isEquality(LHSCC))
return 0;
Value *R1 = RHS->getOperand(0);
Value *R2 = RHS->getOperand(1);
Value *R11,*R12;
bool ok = false;
if (decomposeBitTestICmp(RHS, RHSCC, R11, R12, R2)) {
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11; D = R12;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12; D = R11;
} else {
return 0;
}
E = R2; R1 = nullptr; ok = true;
} else if (R1->getType()->isIntegerTy()) {
if (!match(R1, m_And(m_Value(R11), m_Value(R12)))) {
R11 = R1;
R12 = Constant::getAllOnesValue(R1->getType());
}
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11; D = R12; E = R2; ok = true;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12; D = R11; E = R2; ok = true;
}
}
if (!ICmpInst::isEquality(RHSCC))
return 0;
if (!ok && R2->getType()->isIntegerTy()) {
if (!match(R2, m_And(m_Value(R11), m_Value(R12)))) {
R11 = R2;
R12 = Constant::getAllOnesValue(R2->getType());
}
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11; D = R12; E = R1; ok = true;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12; D = R11; E = R1; ok = true;
} else {
return 0;
}
}
if (!ok)
return 0;
if (L11 == A) {
B = L12; C = L2;
} else if (L12 == A) {
B = L11; C = L2;
} else if (L21 == A) {
B = L22; C = L1;
} else if (L22 == A) {
B = L21; C = L1;
}
unsigned left_type = getTypeOfMaskedICmp(A, B, C, LHSCC);
unsigned right_type = getTypeOfMaskedICmp(A, D, E, RHSCC);
return left_type & right_type;
}
static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
llvm::InstCombiner::BuilderTy *Builder) {
Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr, *E = nullptr;
ICmpInst::Predicate LHSCC = LHS->getPredicate(), RHSCC = RHS->getPredicate();
unsigned mask = foldLogOpOfMaskedICmpsHelper(A, B, C, D, E, LHS, RHS,
LHSCC, RHSCC);
if (mask == 0) return nullptr;
assert(ICmpInst::isEquality(LHSCC) && ICmpInst::isEquality(RHSCC) &&
"foldLogOpOfMaskedICmpsHelper must return an equality predicate.");
ICmpInst::Predicate NEWCC = IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
if (!IsAnd) {
mask = conjugateICmpMask(mask);
}
if (mask & FoldMskICmp_Mask_AllZeroes) {
Value *newOr = Builder->CreateOr(B, D);
Value *newAnd = Builder->CreateAnd(A, newOr);
Value *zero = Constant::getNullValue(A->getType());
return Builder->CreateICmp(NEWCC, newAnd, zero);
}
if (mask & FoldMskICmp_BMask_AllOnes) {
Value *newOr = Builder->CreateOr(B, D);
Value *newAnd = Builder->CreateAnd(A, newOr);
return Builder->CreateICmp(NEWCC, newAnd, newOr);
}
if (mask & FoldMskICmp_AMask_AllOnes) {
Value *newAnd1 = Builder->CreateAnd(B, D);
Value *newAnd = Builder->CreateAnd(A, newAnd1);
return Builder->CreateICmp(NEWCC, newAnd, A);
}
ConstantInt *BCst = dyn_cast<ConstantInt>(B);
if (!BCst) return nullptr;
ConstantInt *DCst = dyn_cast<ConstantInt>(D);
if (!DCst) return nullptr;
if (mask & (FoldMskICmp_Mask_NotAllZeroes | FoldMskICmp_BMask_NotAllOnes)) {
APInt NewMask = BCst->getValue() & DCst->getValue();
if (NewMask == BCst->getValue())
return LHS;
else if (NewMask == DCst->getValue())
return RHS;
}
if (mask & FoldMskICmp_AMask_NotAllOnes) {
APInt NewMask = BCst->getValue() | DCst->getValue();
if (NewMask == BCst->getValue())
return LHS;
else if (NewMask == DCst->getValue())
return RHS;
}
if (mask & FoldMskICmp_BMask_Mixed) {
ConstantInt *CCst = dyn_cast<ConstantInt>(C);
if (!CCst) return nullptr;
ConstantInt *ECst = dyn_cast<ConstantInt>(E);
if (!ECst) return nullptr;
if (LHSCC != NEWCC)
CCst = cast<ConstantInt>(ConstantExpr::getXor(BCst, CCst));
if (RHSCC != NEWCC)
ECst = cast<ConstantInt>(ConstantExpr::getXor(DCst, ECst));
if (((BCst->getValue() & DCst->getValue()) &
(CCst->getValue() ^ ECst->getValue())) != 0)
return ConstantInt::get(LHS->getType(), !IsAnd);
Value *newOr1 = Builder->CreateOr(B, D);
Value *newOr2 = ConstantExpr::getOr(CCst, ECst);
Value *newAnd = Builder->CreateAnd(A, newOr1);
return Builder->CreateICmp(NEWCC, newAnd, newOr2);
}
return nullptr;
}
Value *InstCombiner::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
bool Inverted) {
ConstantInt *RangeStart = dyn_cast<ConstantInt>(Cmp0->getOperand(1));
if (!RangeStart)
return nullptr;
ICmpInst::Predicate Pred0 = (Inverted ? Cmp0->getInversePredicate() :
Cmp0->getPredicate());
if (!((Pred0 == ICmpInst::ICMP_SGT && RangeStart->isMinusOne()) ||
(Pred0 == ICmpInst::ICMP_SGE && RangeStart->isZero())))
return nullptr;
ICmpInst::Predicate Pred1 = (Inverted ? Cmp1->getInversePredicate() :
Cmp1->getPredicate());
Value *Input = Cmp0->getOperand(0);
Value *RangeEnd;
if (Cmp1->getOperand(0) == Input) {
RangeEnd = Cmp1->getOperand(1);
} else if (Cmp1->getOperand(1) == Input) {
RangeEnd = Cmp1->getOperand(0);
Pred1 = ICmpInst::getSwappedPredicate(Pred1);
} else {
return nullptr;
}
ICmpInst::Predicate NewPred;
switch (Pred1) {
case ICmpInst::ICMP_SLT: NewPred = ICmpInst::ICMP_ULT; break;
case ICmpInst::ICMP_SLE: NewPred = ICmpInst::ICMP_ULE; break;
default: return nullptr;
}
bool IsNegative, IsNotNegative;
ComputeSignBit(RangeEnd, IsNotNegative, IsNegative, 0, Cmp1);
if (!IsNotNegative)
return nullptr;
if (Inverted)
NewPred = ICmpInst::getInversePredicate(NewPred);
return Builder->CreateICmp(NewPred, Input, RangeEnd);
}
Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
ICmpInst::Predicate LHSCC = LHS->getPredicate(), RHSCC = RHS->getPredicate();
if (PredicatesFoldable(LHSCC, RHSCC)) {
if (LHS->getOperand(0) == RHS->getOperand(1) &&
LHS->getOperand(1) == RHS->getOperand(0))
LHS->swapOperands();
if (LHS->getOperand(0) == RHS->getOperand(0) &&
LHS->getOperand(1) == RHS->getOperand(1)) {
Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1);
unsigned Code = getICmpCode(LHS) & getICmpCode(RHS);
bool isSigned = LHS->isSigned() || RHS->isSigned();
return getNewICmpValue(isSigned, Code, Op0, Op1, Builder);
}
}
if (Value *V = foldLogOpOfMaskedICmps(LHS, RHS, true, Builder))
return V;
if (Value *V = simplifyRangeCheck(LHS, RHS, false))
return V;
if (Value *V = simplifyRangeCheck(RHS, LHS, false))
return V;
Value *Val = LHS->getOperand(0), *Val2 = RHS->getOperand(0);
ConstantInt *LHSCst = dyn_cast<ConstantInt>(LHS->getOperand(1));
ConstantInt *RHSCst = dyn_cast<ConstantInt>(RHS->getOperand(1));
if (!LHSCst || !RHSCst) return nullptr;
if (LHSCst == RHSCst && LHSCC == RHSCC) {
if (LHSCC == ICmpInst::ICMP_ULT &&
LHSCst->getValue().isPowerOf2()) {
Value *NewOr = Builder->CreateOr(Val, Val2);
return Builder->CreateICmp(LHSCC, NewOr, LHSCst);
}
if (LHSCC == ICmpInst::ICMP_EQ && LHSCst->isZero()) {
Value *NewOr = Builder->CreateOr(Val, Val2);
return Builder->CreateICmp(LHSCC, NewOr, LHSCst);
}
}
if (LHSCC == ICmpInst::ICMP_EQ && LHSCC == RHSCC &&
LHS->hasOneUse() && RHS->hasOneUse()) {
Value *V;
ConstantInt *AndCst, *SmallCst = nullptr, *BigCst = nullptr;
if (match(Val2, m_Trunc(m_Value(V))) &&
match(Val, m_And(m_Specific(V), m_ConstantInt(AndCst)))) {
SmallCst = RHSCst;
BigCst = LHSCst;
} else if (match(Val, m_Trunc(m_Value(V))) &&
match(Val2, m_And(m_Specific(V), m_ConstantInt(AndCst)))) {
SmallCst = LHSCst;
BigCst = RHSCst;
}
if (SmallCst && BigCst) {
unsigned BigBitSize = BigCst->getType()->getBitWidth();
unsigned SmallBitSize = SmallCst->getType()->getBitWidth();
APInt Low = APInt::getLowBitsSet(BigBitSize, SmallBitSize);
if ((Low & AndCst->getValue()) == 0 && (Low & BigCst->getValue()) == 0) {
Value *NewAnd = Builder->CreateAnd(V, Low | AndCst->getValue());
APInt N = SmallCst->getValue().zext(BigBitSize) | BigCst->getValue();
Value *NewVal = ConstantInt::get(AndCst->getType()->getContext(), N);
return Builder->CreateICmp(LHSCC, NewAnd, NewVal);
}
}
}
if (Val != Val2) return nullptr;
if (LHSCC == ICmpInst::ICMP_UGE || LHSCC == ICmpInst::ICMP_ULE ||
RHSCC == ICmpInst::ICMP_UGE || RHSCC == ICmpInst::ICMP_ULE ||
LHSCC == ICmpInst::ICMP_SGE || LHSCC == ICmpInst::ICMP_SLE ||
RHSCC == ICmpInst::ICMP_SGE || RHSCC == ICmpInst::ICMP_SLE)
return nullptr;
ConstantRange LHSRange =
ConstantRange::makeICmpRegion(LHSCC, LHSCst->getValue());
ConstantRange RHSRange =
ConstantRange::makeICmpRegion(RHSCC, RHSCst->getValue());
if (LHSRange.intersectWith(RHSRange).isEmptySet())
return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0);
if (!PredicatesFoldable(LHSCC, RHSCC))
return nullptr;
bool ShouldSwap;
if (CmpInst::isSigned(LHSCC) ||
(ICmpInst::isEquality(LHSCC) &&
CmpInst::isSigned(RHSCC)))
ShouldSwap = LHSCst->getValue().sgt(RHSCst->getValue());
else
ShouldSwap = LHSCst->getValue().ugt(RHSCst->getValue());
if (ShouldSwap) {
std::swap(LHS, RHS);
std::swap(LHSCst, RHSCst);
std::swap(LHSCC, RHSCC);
}
assert(LHSCst != RHSCst && "Compares not folded above?");
switch (LHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_SLT: return LHS;
}
case ICmpInst::ICMP_NE:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_ULT:
if (LHSCst == SubOne(RHSCst)) return Builder->CreateICmpULT(Val, LHSCst);
if (LHSCst->isNullValue()) return InsertRangeTest(Val, AddOne(LHSCst), RHSCst, false, true);
break; case ICmpInst::ICMP_SLT:
if (LHSCst == SubOne(RHSCst)) return Builder->CreateICmpSLT(Val, LHSCst);
break; case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_UGT: case ICmpInst::ICMP_SGT: return RHS;
case ICmpInst::ICMP_NE:
if (LHSCst->getValue() == 0 && RHSCst->getValue().isAllOnesValue())
std::swap(LHSCst, RHSCst);
if (LHSCst == SubOne(RHSCst)){ Constant *AddCST = ConstantExpr::getNeg(LHSCst);
Value *Add = Builder->CreateAdd(Val, AddCST, Val->getName()+".off");
return Builder->CreateICmpUGT(Add, ConstantInt::get(Add->getType(), 1),
Val->getName()+".cmp");
}
break; }
break;
case ICmpInst::ICMP_ULT:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_UGT: return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0);
case ICmpInst::ICMP_SGT: break;
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_ULT: return LHS;
case ICmpInst::ICMP_SLT: break;
}
break;
case ICmpInst::ICMP_SLT:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_UGT: break;
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_SLT: return LHS;
case ICmpInst::ICMP_ULT: break;
}
break;
case ICmpInst::ICMP_UGT:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_UGT: return RHS;
case ICmpInst::ICMP_SGT: break;
case ICmpInst::ICMP_NE:
if (RHSCst == AddOne(LHSCst)) return Builder->CreateICmp(LHSCC, Val, RHSCst);
break; case ICmpInst::ICMP_ULT: return InsertRangeTest(Val, AddOne(LHSCst), RHSCst, false, true);
case ICmpInst::ICMP_SLT: break;
}
break;
case ICmpInst::ICMP_SGT:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_SGT: return RHS;
case ICmpInst::ICMP_UGT: break;
case ICmpInst::ICMP_NE:
if (RHSCst == AddOne(LHSCst)) return Builder->CreateICmp(LHSCC, Val, RHSCst);
break; case ICmpInst::ICMP_SLT: return InsertRangeTest(Val, AddOne(LHSCst), RHSCst, true, true);
case ICmpInst::ICMP_ULT: break;
}
break;
}
return nullptr;
}
Value *InstCombiner::FoldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS) {
if (LHS->getPredicate() == FCmpInst::FCMP_ORD &&
RHS->getPredicate() == FCmpInst::FCMP_ORD) {
if (LHS->getOperand(0)->getType() != RHS->getOperand(0)->getType())
return nullptr;
if (ConstantFP *LHSC = dyn_cast<ConstantFP>(LHS->getOperand(1)))
if (ConstantFP *RHSC = dyn_cast<ConstantFP>(RHS->getOperand(1))) {
if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN())
return Builder->getFalse();
return Builder->CreateFCmpORD(LHS->getOperand(0), RHS->getOperand(0));
}
if (isa<ConstantAggregateZero>(LHS->getOperand(1)) &&
isa<ConstantAggregateZero>(RHS->getOperand(1)))
return Builder->CreateFCmpORD(LHS->getOperand(0), RHS->getOperand(0));
return nullptr;
}
Value *Op0LHS = LHS->getOperand(0), *Op0RHS = LHS->getOperand(1);
Value *Op1LHS = RHS->getOperand(0), *Op1RHS = RHS->getOperand(1);
FCmpInst::Predicate Op0CC = LHS->getPredicate(), Op1CC = RHS->getPredicate();
if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) {
Op1CC = FCmpInst::getSwappedPredicate(Op1CC);
std::swap(Op1LHS, Op1RHS);
}
if (Op0LHS == Op1LHS && Op0RHS == Op1RHS) {
if (Op0CC == Op1CC)
return Builder->CreateFCmp((FCmpInst::Predicate)Op0CC, Op0LHS, Op0RHS);
if (Op0CC == FCmpInst::FCMP_FALSE || Op1CC == FCmpInst::FCMP_FALSE)
return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0);
if (Op0CC == FCmpInst::FCMP_TRUE)
return RHS;
if (Op1CC == FCmpInst::FCMP_TRUE)
return LHS;
bool Op0Ordered;
bool Op1Ordered;
unsigned Op0Pred = getFCmpCode(Op0CC, Op0Ordered);
unsigned Op1Pred = getFCmpCode(Op1CC, Op1Ordered);
if (Op0Pred == 0 && Op1Pred == 0 && Op0Ordered != Op1Ordered)
return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0);
if (Op1Pred == 0) {
std::swap(LHS, RHS);
std::swap(Op0Pred, Op1Pred);
std::swap(Op0Ordered, Op1Ordered);
}
if (Op0Pred == 0) {
if (!Op0Ordered && (Op0Ordered == Op1Ordered))
return LHS;
if (Op0Ordered && (Op0Ordered == Op1Ordered))
return RHS;
if (!Op0Ordered)
return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0);
return getFCmpValue(true, Op1Pred, Op0LHS, Op0RHS, Builder);
}
}
return nullptr;
}
Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
bool Changed = SimplifyAssociativeOrCommutative(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (Value *V = SimplifyVectorOp(I))
return ReplaceInstUsesWith(I, V);
if (Value *V = SimplifyAndInst(Op0, Op1, DL, TLI, DT, AC))
return ReplaceInstUsesWith(I, V);
if (Value *V = SimplifyUsingDistributiveLaws(I))
return ReplaceInstUsesWith(I, V);
if (SimplifyDemandedInstructionBits(I))
return &I;
if (Value *V = SimplifyBSwap(I))
return ReplaceInstUsesWith(I, V);
if (ConstantInt *AndRHS = dyn_cast<ConstantInt>(Op1)) {
const APInt &AndRHSMask = AndRHS->getValue();
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
Value *Op0LHS = Op0I->getOperand(0);
Value *Op0RHS = Op0I->getOperand(1);
switch (Op0I->getOpcode()) {
default: break;
case Instruction::Xor:
case Instruction::Or: {
if (!Op0I->hasOneUse()) break;
APInt NotAndRHS(~AndRHSMask);
if (MaskedValueIsZero(Op0LHS, NotAndRHS, 0, &I)) {
Value *NewRHS = Builder->CreateAnd(Op0RHS, AndRHS,
Op0RHS->getName()+".masked");
return BinaryOperator::Create(Op0I->getOpcode(), Op0LHS, NewRHS);
}
if (!isa<Constant>(Op0RHS) &&
MaskedValueIsZero(Op0RHS, NotAndRHS, 0, &I)) {
Value *NewLHS = Builder->CreateAnd(Op0LHS, AndRHS,
Op0LHS->getName()+".masked");
return BinaryOperator::Create(Op0I->getOpcode(), NewLHS, Op0RHS);
}
break;
}
case Instruction::Add:
if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, false, I))
return BinaryOperator::CreateAnd(V, AndRHS);
if (Value *V = FoldLogicalPlusAnd(Op0RHS, Op0LHS, AndRHS, false, I))
return BinaryOperator::CreateAnd(V, AndRHS); break;
case Instruction::Sub:
if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I))
return BinaryOperator::CreateAnd(V, AndRHS);
if (Op0I->hasOneUse() && !match(Op0LHS, m_Zero())) {
uint32_t BitWidth = AndRHSMask.getBitWidth();
uint32_t Zeros = AndRHSMask.countLeadingZeros();
APInt Mask = APInt::getLowBitsSet(BitWidth, BitWidth - Zeros);
if (MaskedValueIsZero(Op0LHS, Mask, 0, &I)) {
Value *NewNeg = Builder->CreateNeg(Op0RHS);
return BinaryOperator::CreateAnd(NewNeg, AndRHS);
}
}
break;
case Instruction::Shl:
case Instruction::LShr:
if (AndRHSMask == 1 && Op0LHS == AndRHS) {
Value *NewICmp =
Builder->CreateICmpEQ(Op0RHS, Constant::getNullValue(I.getType()));
return new ZExtInst(NewICmp, I.getType());
}
break;
}
if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
if (Instruction *Res = OptAndOp(Op0I, Op0CI, AndRHS, I))
return Res;
}
{
Value *X = nullptr; ConstantInt *YC = nullptr;
if (match(Op0, m_Trunc(m_And(m_Value(X), m_ConstantInt(YC))))) {
Value *NewCast = Builder->CreateTrunc(X, I.getType(), "and.shrunk");
Constant *C3 = ConstantExpr::getTrunc(YC, I.getType());
C3 = ConstantExpr::getAnd(C3, AndRHS);
return BinaryOperator::CreateAnd(NewCast, C3);
}
}
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
if (Instruction *R = FoldOpIntoSelect(I, SI))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
}
if (Value *Op0NotVal = dyn_castNotVal(Op0))
if (Value *Op1NotVal = dyn_castNotVal(Op1))
if (Op0->hasOneUse() && Op1->hasOneUse()) {
Value *Or = Builder->CreateOr(Op0NotVal, Op1NotVal,
I.getName()+".demorgan");
return BinaryOperator::CreateNot(Or);
}
{
Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr;
if (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
match(Op1, m_Not(m_And(m_Value(C), m_Value(D)))) &&
((A == C && B == D) || (A == D && B == C)))
return BinaryOperator::CreateXor(A, B);
if (match(Op1, m_Or(m_Value(A), m_Value(B))) &&
match(Op0, m_Not(m_And(m_Value(C), m_Value(D)))) &&
((A == C && B == D) || (A == D && B == C)))
return BinaryOperator::CreateXor(A, B);
{
Value *tmpOp0 = Op0;
Value *tmpOp1 = Op1;
if (Op0->hasOneUse() &&
match(Op0, m_Xor(m_Value(A), m_Value(B)))) {
if (A == Op1 || B == Op1 ) {
tmpOp1 = Op0;
tmpOp0 = Op1;
}
}
if (tmpOp1->hasOneUse() &&
match(tmpOp1, m_Xor(m_Value(A), m_Value(B)))) {
if (B == tmpOp0) {
std::swap(A, B);
}
if (A == tmpOp0 && !isa<Constant>(A)) return BinaryOperator::CreateAnd(A, Builder->CreateNot(B));
}
}
if (match(Op0, m_Or(m_Not(m_Specific(Op1)), m_Value(A))) ||
match(Op0, m_Or(m_Value(A), m_Not(m_Specific(Op1)))))
return BinaryOperator::CreateAnd(A, Op1);
if (match(Op1, m_Or(m_Not(m_Specific(Op0)), m_Value(A))) ||
match(Op1, m_Or(m_Value(A), m_Not(m_Specific(Op0)))))
return BinaryOperator::CreateAnd(A, Op0);
if (match(Op0, m_Xor(m_Value(A), m_Value(B))))
if (match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A))))
if (Op1->hasOneUse() || cast<BinaryOperator>(Op1)->hasOneUse())
return BinaryOperator::CreateAnd(Op0, Builder->CreateNot(C));
if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B))))
if (match(Op1, m_Xor(m_Specific(B), m_Specific(A))))
if (Op0->hasOneUse() || cast<BinaryOperator>(Op0)->hasOneUse())
return BinaryOperator::CreateAnd(Op1, Builder->CreateNot(C));
if (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
match(Op1, m_Xor(m_Not(m_Specific(A)), m_Specific(B))))
return BinaryOperator::CreateAnd(A, B);
if (match(Op0, m_Xor(m_Not(m_Value(A)), m_Value(B))) &&
match(Op1, m_Or(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateAnd(A, B);
}
{
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
if (LHS && RHS)
if (Value *Res = FoldAndOfICmps(LHS, RHS))
return ReplaceInstUsesWith(I, Res);
Value *X, *Y;
if (LHS && match(Op1, m_OneUse(m_And(m_Value(X), m_Value(Y))))) {
if (auto *Cmp = dyn_cast<ICmpInst>(X))
if (Value *Res = FoldAndOfICmps(LHS, Cmp))
return ReplaceInstUsesWith(I, Builder->CreateAnd(Res, Y));
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
if (Value *Res = FoldAndOfICmps(LHS, Cmp))
return ReplaceInstUsesWith(I, Builder->CreateAnd(Res, X));
}
if (RHS && match(Op0, m_OneUse(m_And(m_Value(X), m_Value(Y))))) {
if (auto *Cmp = dyn_cast<ICmpInst>(X))
if (Value *Res = FoldAndOfICmps(Cmp, RHS))
return ReplaceInstUsesWith(I, Builder->CreateAnd(Res, Y));
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
if (Value *Res = FoldAndOfICmps(Cmp, RHS))
return ReplaceInstUsesWith(I, Builder->CreateAnd(Res, X));
}
}
if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
if (Value *Res = FoldAndOfFCmps(LHS, RHS))
return ReplaceInstUsesWith(I, Res);
if (CastInst *Op0C = dyn_cast<CastInst>(Op0))
if (CastInst *Op1C = dyn_cast<CastInst>(Op1)) {
Type *SrcTy = Op0C->getOperand(0)->getType();
if (Op0C->getOpcode() == Op1C->getOpcode() && SrcTy == Op1C->getOperand(0)->getType() &&
SrcTy->isIntOrIntVectorTy()) {
Value *Op0COp = Op0C->getOperand(0), *Op1COp = Op1C->getOperand(0);
if (ShouldOptimizeCast(Op0C->getOpcode(), Op0COp, I.getType()) &&
ShouldOptimizeCast(Op1C->getOpcode(), Op1COp, I.getType())) {
Value *NewOp = Builder->CreateAnd(Op0COp, Op1COp, I.getName());
return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType());
}
if (ICmpInst *RHS = dyn_cast<ICmpInst>(Op1COp))
if (ICmpInst *LHS = dyn_cast<ICmpInst>(Op0COp))
if (Value *Res = FoldAndOfICmps(LHS, RHS))
return CastInst::Create(Op0C->getOpcode(), Res, I.getType());
if (FCmpInst *RHS = dyn_cast<FCmpInst>(Op1COp))
if (FCmpInst *LHS = dyn_cast<FCmpInst>(Op0COp))
if (Value *Res = FoldAndOfFCmps(LHS, RHS))
return CastInst::Create(Op0C->getOpcode(), Res, I.getType());
}
}
{
Value *X = nullptr;
bool OpsSwapped = false;
if (match(Op1, m_SExt(m_Value())) ||
match(Op1, m_Not(m_Value()))) {
std::swap(Op0, Op1);
OpsSwapped = true;
}
if (match(Op0, m_SExt(m_Value(X))) &&
X->getType()->getScalarType()->isIntegerTy(1)) {
Value *Zero = Constant::getNullValue(Op1->getType());
return SelectInst::Create(X, Op1, Zero);
}
if (match(Op0, m_Not(m_SExt(m_Value(X)))) &&
X->getType()->getScalarType()->isIntegerTy(1)) {
Value *Zero = Constant::getNullValue(Op0->getType());
return SelectInst::Create(X, Zero, Op1);
}
if (OpsSwapped)
std::swap(Op0, Op1);
}
return Changed ? &I : nullptr;
}
static bool CollectBSwapParts(Value *V, int OverallLeftShift, uint32_t ByteMask,
SmallVectorImpl<Value *> &ByteValues) {
if (Instruction *I = dyn_cast<Instruction>(V)) {
if (I->getOpcode() == Instruction::Or) {
return CollectBSwapParts(I->getOperand(0), OverallLeftShift, ByteMask,
ByteValues) ||
CollectBSwapParts(I->getOperand(1), OverallLeftShift, ByteMask,
ByteValues);
}
if (I->isLogicalShift() && isa<ConstantInt>(I->getOperand(1))) {
unsigned ShAmt =
cast<ConstantInt>(I->getOperand(1))->getLimitedValue(~0U);
if ((ShAmt & 7) || (ShAmt > 8*ByteValues.size()))
return true;
unsigned ByteShift = ShAmt >> 3;
if (I->getOpcode() == Instruction::Shl) {
OverallLeftShift += ByteShift;
ByteMask >>= ByteShift;
} else {
OverallLeftShift -= ByteShift;
ByteMask <<= ByteShift;
ByteMask &= (~0U >> (32-ByteValues.size()));
}
if (OverallLeftShift >= (int)ByteValues.size()) return true;
if (OverallLeftShift <= -(int)ByteValues.size()) return true;
return CollectBSwapParts(I->getOperand(0), OverallLeftShift, ByteMask,
ByteValues);
}
if (I->getOpcode() == Instruction::And &&
isa<ConstantInt>(I->getOperand(1))) {
unsigned NumBytes = ByteValues.size();
APInt Byte(I->getType()->getPrimitiveSizeInBits(), 255);
const APInt &AndMask = cast<ConstantInt>(I->getOperand(1))->getValue();
for (unsigned i = 0; i != NumBytes; ++i, Byte <<= 8) {
if ((ByteMask & (1 << i)) == 0)
continue;
APInt MaskB = AndMask & Byte;
if (MaskB == 0) {
ByteMask &= ~(1U << i);
continue;
}
if (MaskB != Byte)
return true;
}
return CollectBSwapParts(I->getOperand(0), OverallLeftShift, ByteMask,
ByteValues);
}
}
if (!isPowerOf2_32(ByteMask)) return true;
unsigned InputByteNo = countTrailingZeros(ByteMask);
unsigned DestByteNo = InputByteNo + OverallLeftShift;
if (ByteValues.size()-1-DestByteNo != InputByteNo)
return true;
if (ByteValues[DestByteNo] && ByteValues[DestByteNo] != V)
return true;
ByteValues[DestByteNo] = V;
return false;
}
Instruction *InstCombiner::MatchBSwap(BinaryOperator &I) {
IntegerType *ITy = dyn_cast<IntegerType>(I.getType());
if (!ITy || ITy->getBitWidth() % 16 ||
ITy->getBitWidth() > 32*8)
return nullptr;
SmallVector<Value*, 8> ByteValues;
ByteValues.resize(ITy->getBitWidth()/8);
uint32_t ByteMask = ~0U >> (32-ByteValues.size());
if (CollectBSwapParts(&I, 0, ByteMask, ByteValues))
return nullptr;
Value *V = ByteValues[0];
if (!V) return nullptr;
for (unsigned i = 1, e = ByteValues.size(); i != e; ++i)
if (ByteValues[i] != V)
return nullptr;
Module *M = I.getParent()->getParent()->getParent();
Function *F = Intrinsic::getDeclaration(M, Intrinsic::bswap, ITy);
return CallInst::Create(F, V);
}
static Instruction *MatchSelectFromAndOr(Value *A, Value *B,
Value *C, Value *D) {
Value *Cond = nullptr;
if (!match(A, m_SExt(m_Value(Cond))) ||
!Cond->getType()->isIntegerTy(1))
return nullptr;
if (match(D, m_Not(m_SExt(m_Specific(Cond)))))
return SelectInst::Create(Cond, C, B);
if (match(D, m_SExt(m_Not(m_Specific(Cond)))))
return SelectInst::Create(Cond, C, B);
if (match(B, m_Not(m_SExt(m_Specific(Cond)))))
return SelectInst::Create(Cond, C, D);
if (match(B, m_SExt(m_Not(m_Specific(Cond)))))
return SelectInst::Create(Cond, C, D);
return nullptr;
}
Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
Instruction *CxtI) {
ICmpInst::Predicate LHSCC = LHS->getPredicate(), RHSCC = RHS->getPredicate();
ConstantInt *LHSCst = dyn_cast<ConstantInt>(LHS->getOperand(1));
ConstantInt *RHSCst = dyn_cast<ConstantInt>(RHS->getOperand(1));
if (LHS->getPredicate() == ICmpInst::ICMP_EQ && LHSCst && LHSCst->isZero() &&
RHS->getPredicate() == ICmpInst::ICMP_EQ && RHSCst && RHSCst->isZero()) {
BinaryOperator *LAnd = dyn_cast<BinaryOperator>(LHS->getOperand(0));
BinaryOperator *RAnd = dyn_cast<BinaryOperator>(RHS->getOperand(0));
if (LAnd && RAnd && LAnd->hasOneUse() && RHS->hasOneUse() &&
LAnd->getOpcode() == Instruction::And &&
RAnd->getOpcode() == Instruction::And) {
Value *Mask = nullptr;
Value *Masked = nullptr;
if (LAnd->getOperand(0) == RAnd->getOperand(0) &&
isKnownToBeAPowerOfTwo(LAnd->getOperand(1), DL, false, 0, AC, CxtI,
DT) &&
isKnownToBeAPowerOfTwo(RAnd->getOperand(1), DL, false, 0, AC, CxtI,
DT)) {
Mask = Builder->CreateOr(LAnd->getOperand(1), RAnd->getOperand(1));
Masked = Builder->CreateAnd(LAnd->getOperand(0), Mask);
} else if (LAnd->getOperand(1) == RAnd->getOperand(1) &&
isKnownToBeAPowerOfTwo(LAnd->getOperand(0), DL, false, 0, AC,
CxtI, DT) &&
isKnownToBeAPowerOfTwo(RAnd->getOperand(0), DL, false, 0, AC,
CxtI, DT)) {
Mask = Builder->CreateOr(LAnd->getOperand(0), RAnd->getOperand(0));
Masked = Builder->CreateAnd(LAnd->getOperand(1), Mask);
}
if (Masked)
return Builder->CreateICmp(ICmpInst::ICMP_NE, Masked, Mask);
}
}
if ((LHSCC == ICmpInst::ICMP_ULT || LHSCC == ICmpInst::ICMP_ULE) &&
LHSCC == RHSCC && LHSCst && RHSCst && LHS->hasOneUse() &&
RHS->hasOneUse() && LHSCst->getType() == RHSCst->getType() &&
LHSCst->getValue() == (RHSCst->getValue())) {
Value *LAdd = LHS->getOperand(0);
Value *RAdd = RHS->getOperand(0);
Value *LAddOpnd, *RAddOpnd;
ConstantInt *LAddCst, *RAddCst;
if (match(LAdd, m_Add(m_Value(LAddOpnd), m_ConstantInt(LAddCst))) &&
match(RAdd, m_Add(m_Value(RAddOpnd), m_ConstantInt(RAddCst))) &&
LAddCst->getValue().ugt(LHSCst->getValue()) &&
RAddCst->getValue().ugt(LHSCst->getValue())) {
APInt DiffCst = LAddCst->getValue() ^ RAddCst->getValue();
if (LAddOpnd == RAddOpnd && DiffCst.isPowerOf2()) {
ConstantInt *MaxAddCst = nullptr;
if (LAddCst->getValue().ult(RAddCst->getValue()))
MaxAddCst = RAddCst;
else
MaxAddCst = LAddCst;
APInt RRangeLow = -RAddCst->getValue();
APInt RRangeHigh = RRangeLow + LHSCst->getValue();
APInt LRangeLow = -LAddCst->getValue();
APInt LRangeHigh = LRangeLow + LHSCst->getValue();
APInt LowRangeDiff = RRangeLow ^ LRangeLow;
APInt HighRangeDiff = RRangeHigh ^ LRangeHigh;
APInt RangeDiff = LRangeLow.sgt(RRangeLow) ? LRangeLow - RRangeLow
: RRangeLow - LRangeLow;
if (LowRangeDiff.isPowerOf2() && LowRangeDiff == HighRangeDiff &&
RangeDiff.ugt(LHSCst->getValue())) {
Value *MaskCst = ConstantInt::get(LAddCst->getType(), ~DiffCst);
Value *NewAnd = Builder->CreateAnd(LAddOpnd, MaskCst);
Value *NewAdd = Builder->CreateAdd(NewAnd, MaxAddCst);
return (Builder->CreateICmp(LHS->getPredicate(), NewAdd, LHSCst));
}
}
}
}
if (PredicatesFoldable(LHSCC, RHSCC)) {
if (LHS->getOperand(0) == RHS->getOperand(1) &&
LHS->getOperand(1) == RHS->getOperand(0))
LHS->swapOperands();
if (LHS->getOperand(0) == RHS->getOperand(0) &&
LHS->getOperand(1) == RHS->getOperand(1)) {
Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1);
unsigned Code = getICmpCode(LHS) | getICmpCode(RHS);
bool isSigned = LHS->isSigned() || RHS->isSigned();
return getNewICmpValue(isSigned, Code, Op0, Op1, Builder);
}
}
if (Value *V = foldLogOpOfMaskedICmps(LHS, RHS, false, Builder))
return V;
Value *Val = LHS->getOperand(0), *Val2 = RHS->getOperand(0);
if (LHS->hasOneUse() || RHS->hasOneUse()) {
Value *A = nullptr, *B = nullptr;
if (LHSCC == ICmpInst::ICMP_EQ && LHSCst && LHSCst->isZero()) {
B = Val;
if (RHSCC == ICmpInst::ICMP_ULT && Val == RHS->getOperand(1))
A = Val2;
else if (RHSCC == ICmpInst::ICMP_UGT && Val == Val2)
A = RHS->getOperand(1);
}
else if (RHSCC == ICmpInst::ICMP_EQ && RHSCst && RHSCst->isZero()) {
B = Val2;
if (LHSCC == ICmpInst::ICMP_ULT && Val2 == LHS->getOperand(1))
A = Val;
else if (LHSCC == ICmpInst::ICMP_UGT && Val2 == Val)
A = LHS->getOperand(1);
}
if (A && B)
return Builder->CreateICmp(
ICmpInst::ICMP_UGE,
Builder->CreateAdd(B, ConstantInt::getSigned(B->getType(), -1)), A);
}
if (Value *V = simplifyRangeCheck(LHS, RHS, true))
return V;
if (Value *V = simplifyRangeCheck(RHS, LHS, true))
return V;
if (!LHSCst || !RHSCst) return nullptr;
if (LHSCst == RHSCst && LHSCC == RHSCC) {
if (LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero()) {
Value *NewOr = Builder->CreateOr(Val, Val2);
return Builder->CreateICmp(LHSCC, NewOr, LHSCst);
}
}
if (LHSCC == ICmpInst::ICMP_ULT && RHSCC == ICmpInst::ICMP_EQ) {
ConstantInt *AddCst;
if (match(Val, m_Add(m_Specific(Val2), m_ConstantInt(AddCst))))
if (RHSCst->getValue() + AddCst->getValue() == LHSCst->getValue())
return Builder->CreateICmpULE(Val, LHSCst);
}
if (Val != Val2) return nullptr;
if (LHSCC == ICmpInst::ICMP_UGE || LHSCC == ICmpInst::ICMP_ULE ||
RHSCC == ICmpInst::ICMP_UGE || RHSCC == ICmpInst::ICMP_ULE ||
LHSCC == ICmpInst::ICMP_SGE || LHSCC == ICmpInst::ICMP_SLE ||
RHSCC == ICmpInst::ICMP_SGE || RHSCC == ICmpInst::ICMP_SLE)
return nullptr;
if (!PredicatesFoldable(LHSCC, RHSCC))
return nullptr;
bool ShouldSwap;
if (CmpInst::isSigned(LHSCC) ||
(ICmpInst::isEquality(LHSCC) &&
CmpInst::isSigned(RHSCC)))
ShouldSwap = LHSCst->getValue().sgt(RHSCst->getValue());
else
ShouldSwap = LHSCst->getValue().ugt(RHSCst->getValue());
if (ShouldSwap) {
std::swap(LHS, RHS);
std::swap(LHSCst, RHSCst);
std::swap(LHSCC, RHSCC);
}
assert(LHSCst != RHSCst && "Compares not folded above?");
switch (LHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ:
if (LHS->getOperand(0) == RHS->getOperand(0)) {
assert(LHSCst->getValue().ule(LHSCst->getValue()));
APInt Xor = LHSCst->getValue() ^ RHSCst->getValue();
if (Xor.isPowerOf2()) {
Value *NegCst = Builder->getInt(~Xor);
Value *And = Builder->CreateAnd(LHS->getOperand(0), NegCst);
return Builder->CreateICmp(ICmpInst::ICMP_EQ, And, LHSCst);
}
}
if (LHSCst == SubOne(RHSCst)) {
Constant *AddCST = ConstantExpr::getNeg(LHSCst);
Value *Add = Builder->CreateAdd(Val, AddCST, Val->getName()+".off");
AddCST = ConstantExpr::getSub(AddOne(RHSCst), LHSCst);
return Builder->CreateICmpULT(Add, AddCST);
}
break; case ICmpInst::ICMP_UGT: case ICmpInst::ICMP_SGT: break;
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_SLT: return RHS;
}
break;
case ICmpInst::ICMP_NE:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_UGT: case ICmpInst::ICMP_SGT: return LHS;
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_SLT: return Builder->getTrue();
}
case ICmpInst::ICMP_ULT:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ: break;
case ICmpInst::ICMP_UGT: if (RHSCst->isMaxValue(false))
return LHS;
return InsertRangeTest(Val, LHSCst, AddOne(RHSCst), false, false);
case ICmpInst::ICMP_SGT: break;
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_ULT: return RHS;
case ICmpInst::ICMP_SLT: break;
}
break;
case ICmpInst::ICMP_SLT:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ: break;
case ICmpInst::ICMP_SGT: if (RHSCst->isMaxValue(true))
return LHS;
return InsertRangeTest(Val, LHSCst, AddOne(RHSCst), true, false);
case ICmpInst::ICMP_UGT: break;
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_SLT: return RHS;
case ICmpInst::ICMP_ULT: break;
}
break;
case ICmpInst::ICMP_UGT:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_UGT: return LHS;
case ICmpInst::ICMP_SGT: break;
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_ULT: return Builder->getTrue();
case ICmpInst::ICMP_SLT: break;
}
break;
case ICmpInst::ICMP_SGT:
switch (RHSCC) {
default: llvm_unreachable("Unknown integer condition code!");
case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_SGT: return LHS;
case ICmpInst::ICMP_UGT: break;
case ICmpInst::ICMP_NE: case ICmpInst::ICMP_SLT: return Builder->getTrue();
case ICmpInst::ICMP_ULT: break;
}
break;
}
return nullptr;
}
Value *InstCombiner::FoldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS) {
if (LHS->getPredicate() == FCmpInst::FCMP_UNO &&
RHS->getPredicate() == FCmpInst::FCMP_UNO &&
LHS->getOperand(0)->getType() == RHS->getOperand(0)->getType()) {
if (ConstantFP *LHSC = dyn_cast<ConstantFP>(LHS->getOperand(1)))
if (ConstantFP *RHSC = dyn_cast<ConstantFP>(RHS->getOperand(1))) {
if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN())
return Builder->getTrue();
return Builder->CreateFCmpUNO(LHS->getOperand(0), RHS->getOperand(0));
}
if (isa<ConstantAggregateZero>(LHS->getOperand(1)) &&
isa<ConstantAggregateZero>(RHS->getOperand(1)))
return Builder->CreateFCmpUNO(LHS->getOperand(0), RHS->getOperand(0));
return nullptr;
}
Value *Op0LHS = LHS->getOperand(0), *Op0RHS = LHS->getOperand(1);
Value *Op1LHS = RHS->getOperand(0), *Op1RHS = RHS->getOperand(1);
FCmpInst::Predicate Op0CC = LHS->getPredicate(), Op1CC = RHS->getPredicate();
if (Op0LHS == Op1RHS && Op0RHS == Op1LHS) {
Op1CC = FCmpInst::getSwappedPredicate(Op1CC);
std::swap(Op1LHS, Op1RHS);
}
if (Op0LHS == Op1LHS && Op0RHS == Op1RHS) {
if (Op0CC == Op1CC)
return Builder->CreateFCmp((FCmpInst::Predicate)Op0CC, Op0LHS, Op0RHS);
if (Op0CC == FCmpInst::FCMP_TRUE || Op1CC == FCmpInst::FCMP_TRUE)
return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 1);
if (Op0CC == FCmpInst::FCMP_FALSE)
return RHS;
if (Op1CC == FCmpInst::FCMP_FALSE)
return LHS;
bool Op0Ordered;
bool Op1Ordered;
unsigned Op0Pred = getFCmpCode(Op0CC, Op0Ordered);
unsigned Op1Pred = getFCmpCode(Op1CC, Op1Ordered);
if (Op0Ordered == Op1Ordered) {
return getFCmpValue(Op0Ordered, Op0Pred|Op1Pred, Op0LHS, Op0RHS, Builder);
}
}
return nullptr;
}
Instruction *InstCombiner::FoldOrWithConstants(BinaryOperator &I, Value *Op,
Value *A, Value *B, Value *C) {
ConstantInt *CI1 = dyn_cast<ConstantInt>(C);
if (!CI1) return nullptr;
Value *V1 = nullptr;
ConstantInt *CI2 = nullptr;
if (!match(Op, m_And(m_Value(V1), m_ConstantInt(CI2)))) return nullptr;
APInt Xor = CI1->getValue() ^ CI2->getValue();
if (!Xor.isAllOnesValue()) return nullptr;
if (V1 == A || V1 == B) {
Value *NewOp = Builder->CreateAnd((V1 == A) ? B : A, CI1);
return BinaryOperator::CreateOr(NewOp, V1);
}
return nullptr;
}
Instruction *InstCombiner::FoldXorWithConstants(BinaryOperator &I, Value *Op,
Value *A, Value *B, Value *C) {
ConstantInt *CI1 = dyn_cast<ConstantInt>(C);
if (!CI1)
return nullptr;
Value *V1 = nullptr;
ConstantInt *CI2 = nullptr;
if (!match(Op, m_And(m_Value(V1), m_ConstantInt(CI2))))
return nullptr;
APInt Xor = CI1->getValue() ^ CI2->getValue();
if (!Xor.isAllOnesValue())
return nullptr;
if (V1 == A || V1 == B) {
Value *NewOp = Builder->CreateAnd(V1 == A ? B : A, CI1);
return BinaryOperator::CreateXor(NewOp, V1);
}
return nullptr;
}
Instruction *InstCombiner::visitOr(BinaryOperator &I) {
bool Changed = SimplifyAssociativeOrCommutative(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (Value *V = SimplifyVectorOp(I))
return ReplaceInstUsesWith(I, V);
if (Value *V = SimplifyOrInst(Op0, Op1, DL, TLI, DT, AC))
return ReplaceInstUsesWith(I, V);
if (Value *V = SimplifyUsingDistributiveLaws(I))
return ReplaceInstUsesWith(I, V);
if (SimplifyDemandedInstructionBits(I))
return &I;
if (Value *V = SimplifyBSwap(I))
return ReplaceInstUsesWith(I, V);
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
ConstantInt *C1 = nullptr; Value *X = nullptr;
if (match(Op0, m_And(m_Value(X), m_ConstantInt(C1))) &&
(RHS->getValue() & C1->getValue()) != 0 &&
Op0->hasOneUse()) {
Value *Or = Builder->CreateOr(X, RHS);
Or->takeName(Op0);
return BinaryOperator::CreateAnd(Or,
Builder->getInt(RHS->getValue() | C1->getValue()));
}
if (match(Op0, m_Xor(m_Value(X), m_ConstantInt(C1))) &&
Op0->hasOneUse()) {
Value *Or = Builder->CreateOr(X, RHS);
Or->takeName(Op0);
return BinaryOperator::CreateXor(Or,
Builder->getInt(C1->getValue() & ~RHS->getValue()));
}
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
if (Instruction *R = FoldOpIntoSelect(I, SI))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
}
Value *A = nullptr, *B = nullptr;
ConstantInt *C1 = nullptr, *C2 = nullptr;
if (match(Op0, m_Or(m_Value(), m_Value())) ||
match(Op1, m_Or(m_Value(), m_Value())) ||
(match(Op0, m_LogicalShift(m_Value(), m_Value())) &&
match(Op1, m_LogicalShift(m_Value(), m_Value())))) {
if (Instruction *BSwap = MatchBSwap(I))
return BSwap;
}
if (Op0->hasOneUse() &&
match(Op0, m_Xor(m_Value(A), m_ConstantInt(C1))) &&
MaskedValueIsZero(Op1, C1->getValue(), 0, &I)) {
Value *NOr = Builder->CreateOr(A, Op1);
NOr->takeName(Op0);
return BinaryOperator::CreateXor(NOr, C1);
}
if (Op1->hasOneUse() &&
match(Op1, m_Xor(m_Value(A), m_ConstantInt(C1))) &&
MaskedValueIsZero(Op0, C1->getValue(), 0, &I)) {
Value *NOr = Builder->CreateOr(A, Op0);
NOr->takeName(Op0);
return BinaryOperator::CreateXor(NOr, C1);
}
if (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) &&
match(Op1, m_Specific(A)))
return BinaryOperator::CreateOr(A, B);
if (match(Op0, m_And(m_Value(A), m_Value(B))) &&
match(Op1, m_Not(m_Specific(A))))
return BinaryOperator::CreateOr(Builder->CreateNot(A), B);
if (match(Op0, m_And(m_Value(A), m_Not(m_Value(B)))) &&
match(Op1, m_Xor(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateXor(A, B);
if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
match(Op1, m_And(m_Specific(A), m_Not(m_Specific(B)))))
return BinaryOperator::CreateXor(A, B);
Value *C = nullptr, *D = nullptr;
if (match(Op0, m_And(m_Value(A), m_Value(C))) &&
match(Op1, m_And(m_Value(B), m_Value(D)))) {
Value *V1 = nullptr, *V2 = nullptr;
C1 = dyn_cast<ConstantInt>(C);
C2 = dyn_cast<ConstantInt>(D);
if (C1 && C2) { if ((C1->getValue() & C2->getValue()) == 0) {
if (match(A, m_Or(m_Value(V1), m_Value(V2))) &&
((V1 == B &&
MaskedValueIsZero(V2, ~C1->getValue(), 0, &I)) || (V2 == B &&
MaskedValueIsZero(V1, ~C1->getValue(), 0, &I)))) return BinaryOperator::CreateAnd(A,
Builder->getInt(C1->getValue()|C2->getValue()));
if (match(B, m_Or(m_Value(V1), m_Value(V2))) &&
((V1 == A &&
MaskedValueIsZero(V2, ~C2->getValue(), 0, &I)) || (V2 == A &&
MaskedValueIsZero(V1, ~C2->getValue(), 0, &I)))) return BinaryOperator::CreateAnd(B,
Builder->getInt(C1->getValue()|C2->getValue()));
ConstantInt *C3 = nullptr, *C4 = nullptr;
if (match(A, m_Or(m_Value(V1), m_ConstantInt(C3))) &&
(C3->getValue() & ~C1->getValue()) == 0 &&
match(B, m_Or(m_Specific(V1), m_ConstantInt(C4))) &&
(C4->getValue() & ~C2->getValue()) == 0) {
V2 = Builder->CreateOr(V1, ConstantExpr::getOr(C3, C4), "bitfield");
return BinaryOperator::CreateAnd(V2,
Builder->getInt(C1->getValue()|C2->getValue()));
}
}
}
if (!I.getType()->isVectorTy()) {
if (Instruction *Match = MatchSelectFromAndOr(A, B, C, D))
return Match;
if (Instruction *Match = MatchSelectFromAndOr(B, A, D, C))
return Match;
if (Instruction *Match = MatchSelectFromAndOr(C, B, A, D))
return Match;
if (Instruction *Match = MatchSelectFromAndOr(D, A, B, C))
return Match;
}
if ((match(C, m_Not(m_Specific(D))) &&
match(B, m_Not(m_Specific(A)))))
return BinaryOperator::CreateXor(A, D);
if ((match(A, m_Not(m_Specific(D))) &&
match(B, m_Not(m_Specific(C)))))
return BinaryOperator::CreateXor(C, D);
if ((match(C, m_Not(m_Specific(B))) &&
match(D, m_Not(m_Specific(A)))))
return BinaryOperator::CreateXor(A, B);
if ((match(A, m_Not(m_Specific(B))) &&
match(D, m_Not(m_Specific(C)))))
return BinaryOperator::CreateXor(C, B);
if (match(A, m_Or(m_Value(V1), m_Specific(B))) ||
match(A, m_Or(m_Specific(B), m_Value(V1)))) {
Instruction *Ret = FoldOrWithConstants(I, Op1, V1, B, C);
if (Ret) return Ret;
}
if (match(B, m_Or(m_Specific(A), m_Value(V1))) ||
match(B, m_Or(m_Value(V1), m_Specific(A)))) {
Instruction *Ret = FoldOrWithConstants(I, Op0, A, V1, D);
if (Ret) return Ret;
}
if (match(A, m_Xor(m_Value(V1), m_Specific(B))) ||
match(A, m_Xor(m_Specific(B), m_Value(V1)))) {
Instruction *Ret = FoldXorWithConstants(I, Op1, V1, B, C);
if (Ret) return Ret;
}
if (match(B, m_Xor(m_Specific(A), m_Value(V1))) ||
match(B, m_Xor(m_Value(V1), m_Specific(A)))) {
Instruction *Ret = FoldXorWithConstants(I, Op0, A, V1, D);
if (Ret) return Ret;
}
}
if (match(Op0, m_Xor(m_Value(A), m_Value(B))))
if (match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A))))
if (Op1->hasOneUse() || cast<BinaryOperator>(Op1)->hasOneUse())
return BinaryOperator::CreateOr(Op0, C);
if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B))))
if (match(Op1, m_Xor(m_Specific(B), m_Specific(A))))
if (Op0->hasOneUse() || cast<BinaryOperator>(Op0)->hasOneUse())
return BinaryOperator::CreateOr(Op1, C);
if (match(Op0, m_And(m_Or(m_Specific(Op1), m_Value(C)), m_Value(A))))
return BinaryOperator::CreateOr(Op1, Builder->CreateAnd(A, C));
if (Value *Op0NotVal = dyn_castNotVal(Op0))
if (Value *Op1NotVal = dyn_castNotVal(Op1))
if (Op0->hasOneUse() && Op1->hasOneUse()) {
Value *And = Builder->CreateAnd(Op0NotVal, Op1NotVal,
I.getName()+".demorgan");
return BinaryOperator::CreateNot(And);
}
bool SwappedForXor = false;
if (match(Op0, m_Xor(m_Value(), m_Value()))) {
std::swap(Op0, Op1);
SwappedForXor = true;
}
if (match(Op1, m_Xor(m_Value(A), m_Value(B)))) {
if (Op0 == A || Op0 == B)
return BinaryOperator::CreateOr(A, B);
if (match(Op0, m_And(m_Specific(A), m_Specific(B))) ||
match(Op0, m_And(m_Specific(B), m_Specific(A))))
return BinaryOperator::CreateOr(A, B);
if (Op1->hasOneUse() && match(A, m_Not(m_Specific(Op0)))) {
Value *Not = Builder->CreateNot(B, B->getName()+".not");
return BinaryOperator::CreateOr(Not, Op0);
}
if (Op1->hasOneUse() && match(B, m_Not(m_Specific(Op0)))) {
Value *Not = Builder->CreateNot(A, A->getName()+".not");
return BinaryOperator::CreateOr(Not, Op0);
}
}
if (match(Op1, m_Not(m_Value(A))))
if (BinaryOperator *B = dyn_cast<BinaryOperator>(A))
if ((Op0 == B->getOperand(0) || Op0 == B->getOperand(1)) &&
Op1->hasOneUse() && (B->getOpcode() == Instruction::Or ||
B->getOpcode() == Instruction::Xor)) {
Value *NotOp = Op0 == B->getOperand(0) ? B->getOperand(1) :
B->getOperand(0);
Value *Not = Builder->CreateNot(NotOp, NotOp->getName()+".not");
return BinaryOperator::CreateOr(Not, Op0);
}
if (match(Op0, m_And(m_Value(A), m_Value(B))) &&
match(Op1, m_Xor(m_Not(m_Specific(A)), m_Specific(B))))
return BinaryOperator::CreateXor(Builder->CreateNot(A), B);
if (match(Op0, m_Xor(m_Not(m_Value(A)), m_Value(B))) &&
match(Op1, m_And(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateXor(Builder->CreateNot(A), B);
if (SwappedForXor)
std::swap(Op0, Op1);
{
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
if (LHS && RHS)
if (Value *Res = FoldOrOfICmps(LHS, RHS, &I))
return ReplaceInstUsesWith(I, Res);
Value *X, *Y;
if (LHS && match(Op1, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
if (auto *Cmp = dyn_cast<ICmpInst>(X))
if (Value *Res = FoldOrOfICmps(LHS, Cmp, &I))
return ReplaceInstUsesWith(I, Builder->CreateOr(Res, Y));
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
if (Value *Res = FoldOrOfICmps(LHS, Cmp, &I))
return ReplaceInstUsesWith(I, Builder->CreateOr(Res, X));
}
if (RHS && match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
if (auto *Cmp = dyn_cast<ICmpInst>(X))
if (Value *Res = FoldOrOfICmps(Cmp, RHS, &I))
return ReplaceInstUsesWith(I, Builder->CreateOr(Res, Y));
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
if (Value *Res = FoldOrOfICmps(Cmp, RHS, &I))
return ReplaceInstUsesWith(I, Builder->CreateOr(Res, X));
}
}
if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
if (Value *Res = FoldOrOfFCmps(LHS, RHS))
return ReplaceInstUsesWith(I, Res);
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
CastInst *Op1C = dyn_cast<CastInst>(Op1);
if (Op1C && Op0C->getOpcode() == Op1C->getOpcode()) { Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() &&
SrcTy->isIntOrIntVectorTy()) {
Value *Op0COp = Op0C->getOperand(0), *Op1COp = Op1C->getOperand(0);
if ((!isa<ICmpInst>(Op0COp) || !isa<ICmpInst>(Op1COp)) &&
ShouldOptimizeCast(Op0C->getOpcode(), Op0COp, I.getType()) &&
ShouldOptimizeCast(Op1C->getOpcode(), Op1COp, I.getType())) {
Value *NewOp = Builder->CreateOr(Op0COp, Op1COp, I.getName());
return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType());
}
if (ICmpInst *RHS = dyn_cast<ICmpInst>(Op1COp))
if (ICmpInst *LHS = dyn_cast<ICmpInst>(Op0COp))
if (Value *Res = FoldOrOfICmps(LHS, RHS, &I))
return CastInst::Create(Op0C->getOpcode(), Res, I.getType());
if (FCmpInst *RHS = dyn_cast<FCmpInst>(Op1COp))
if (FCmpInst *LHS = dyn_cast<FCmpInst>(Op0COp))
if (Value *Res = FoldOrOfFCmps(LHS, RHS))
return CastInst::Create(Op0C->getOpcode(), Res, I.getType());
}
}
}
if (match(Op0, m_SExt(m_Value(A))) && A->getType()->isIntegerTy(1))
return SelectInst::Create(A, ConstantInt::getSigned(I.getType(), -1), Op1);
if (match(Op1, m_SExt(m_Value(A))) && A->getType()->isIntegerTy(1))
return SelectInst::Create(A, ConstantInt::getSigned(I.getType(), -1), Op0);
if (Op0->hasOneUse() && !isa<ConstantInt>(Op1) &&
match(Op0, m_Or(m_Value(A), m_ConstantInt(C1)))) {
Value *Inner = Builder->CreateOr(A, Op1);
Inner->takeName(Op0);
return BinaryOperator::CreateOr(Inner, C1);
}
{
Value *X = nullptr, *Y = nullptr;
if (Op0->hasOneUse() && Op1->hasOneUse() &&
match(Op0, m_Select(m_Value(X), m_Value(A), m_Value(B))) &&
match(Op1, m_Select(m_Value(Y), m_Value(C), m_Value(D))) && X == Y) {
Value *orTrue = Builder->CreateOr(A, C);
Value *orFalse = Builder->CreateOr(B, D);
return SelectInst::Create(X, orTrue, orFalse);
}
}
return Changed ? &I : nullptr;
}
Instruction *InstCombiner::visitXor(BinaryOperator &I) {
bool Changed = SimplifyAssociativeOrCommutative(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (Value *V = SimplifyVectorOp(I))
return ReplaceInstUsesWith(I, V);
if (Value *V = SimplifyXorInst(Op0, Op1, DL, TLI, DT, AC))
return ReplaceInstUsesWith(I, V);
if (Value *V = SimplifyUsingDistributiveLaws(I))
return ReplaceInstUsesWith(I, V);
if (SimplifyDemandedInstructionBits(I))
return &I;
if (Value *V = SimplifyBSwap(I))
return ReplaceInstUsesWith(I, V);
if (Value *NotOp = dyn_castNotVal(&I)) {
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(NotOp)) {
if (Op0I->getOpcode() == Instruction::And ||
Op0I->getOpcode() == Instruction::Or) {
if (dyn_castNotVal(Op0I->getOperand(1)))
Op0I->swapOperands();
if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) {
Value *NotY =
Builder->CreateNot(Op0I->getOperand(1),
Op0I->getOperand(1)->getName()+".not");
if (Op0I->getOpcode() == Instruction::And)
return BinaryOperator::CreateOr(Op0NotVal, NotY);
return BinaryOperator::CreateAnd(Op0NotVal, NotY);
}
if (isFreeToInvert(Op0I->getOperand(0)) &&
isFreeToInvert(Op0I->getOperand(1))) {
Value *NotX =
Builder->CreateNot(Op0I->getOperand(0), "notlhs");
Value *NotY =
Builder->CreateNot(Op0I->getOperand(1), "notrhs");
if (Op0I->getOpcode() == Instruction::And)
return BinaryOperator::CreateOr(NotX, NotY);
return BinaryOperator::CreateAnd(NotX, NotY);
}
} else if (Op0I->getOpcode() == Instruction::AShr) {
if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0)))
return BinaryOperator::CreateAShr(Op0NotVal, Op0I->getOperand(1));
}
}
}
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
if (RHS->isOne() && Op0->hasOneUse())
if (CmpInst *CI = dyn_cast<CmpInst>(Op0))
return CmpInst::Create(CI->getOpcode(),
CI->getInversePredicate(),
CI->getOperand(0), CI->getOperand(1));
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
if (CmpInst *CI = dyn_cast<CmpInst>(Op0C->getOperand(0))) {
if (CI->hasOneUse() && Op0C->hasOneUse()) {
Instruction::CastOps Opcode = Op0C->getOpcode();
if ((Opcode == Instruction::ZExt || Opcode == Instruction::SExt) &&
(RHS == ConstantExpr::getCast(Opcode, Builder->getTrue(),
Op0C->getDestTy()))) {
CI->setPredicate(CI->getInversePredicate());
return CastInst::Create(Opcode, CI, Op0C->getType());
}
}
}
}
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
if (Op0I->getOpcode() == Instruction::Sub && RHS->isAllOnesValue())
if (Constant *Op0I0C = dyn_cast<Constant>(Op0I->getOperand(0))) {
Constant *NegOp0I0C = ConstantExpr::getNeg(Op0I0C);
Constant *ConstantRHS = ConstantExpr::getSub(NegOp0I0C,
ConstantInt::get(I.getType(), 1));
return BinaryOperator::CreateAdd(Op0I->getOperand(1), ConstantRHS);
}
if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
if (Op0I->getOpcode() == Instruction::Add) {
if (RHS->isAllOnesValue()) {
Constant *NegOp0CI = ConstantExpr::getNeg(Op0CI);
return BinaryOperator::CreateSub(
ConstantExpr::getSub(NegOp0CI,
ConstantInt::get(I.getType(), 1)),
Op0I->getOperand(0));
} else if (RHS->getValue().isSignBit()) {
Constant *C = Builder->getInt(RHS->getValue() + Op0CI->getValue());
return BinaryOperator::CreateAdd(Op0I->getOperand(0), C);
}
} else if (Op0I->getOpcode() == Instruction::Or) {
if (MaskedValueIsZero(Op0I->getOperand(0), Op0CI->getValue(),
0, &I)) {
Constant *NewRHS = ConstantExpr::getOr(Op0CI, RHS);
Constant *CommonBits = ConstantExpr::getAnd(Op0CI, RHS);
NewRHS = ConstantExpr::getAnd(NewRHS,
ConstantExpr::getNot(CommonBits));
Worklist.Add(Op0I);
I.setOperand(0, Op0I->getOperand(0));
I.setOperand(1, NewRHS);
return &I;
}
} else if (Op0I->getOpcode() == Instruction::LShr) {
BinaryOperator *E1;
ConstantInt *C1;
if (Op0I->hasOneUse() &&
(E1 = dyn_cast<BinaryOperator>(Op0I->getOperand(0))) &&
E1->getOpcode() == Instruction::Xor &&
(C1 = dyn_cast<ConstantInt>(E1->getOperand(1)))) {
ConstantInt *C2 = Op0CI, *C3 = RHS;
APInt FoldConst = C1->getValue().lshr(C2->getValue());
FoldConst ^= C3->getValue();
Value *Opnd0 = Builder->CreateLShr(E1->getOperand(0), C2);
Opnd0->takeName(Op0I);
cast<Instruction>(Opnd0)->setDebugLoc(I.getDebugLoc());
Value *FoldVal = ConstantInt::get(Opnd0->getType(), FoldConst);
return BinaryOperator::CreateXor(Opnd0, FoldVal);
}
}
}
}
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
if (Instruction *R = FoldOpIntoSelect(I, SI))
return R;
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
}
BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1);
if (Op1I) {
Value *A, *B;
if (match(Op1I, m_Or(m_Value(A), m_Value(B)))) {
if (A == Op0) { Op1I->swapOperands();
I.swapOperands();
std::swap(Op0, Op1);
} else if (B == Op0) { I.swapOperands(); std::swap(Op0, Op1);
}
} else if (match(Op1I, m_And(m_Value(A), m_Value(B))) &&
Op1I->hasOneUse()){
if (A == Op0) { Op1I->swapOperands();
std::swap(A, B);
}
if (B == Op0) { I.swapOperands(); std::swap(Op0, Op1);
}
}
}
BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0);
if (Op0I) {
Value *A, *B;
if (match(Op0I, m_Or(m_Value(A), m_Value(B))) &&
Op0I->hasOneUse()) {
if (A == Op1) std::swap(A, B);
if (B == Op1) return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1));
} else if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
Op0I->hasOneUse()){
if (A == Op1) std::swap(A, B);
if (B == Op1 && !isa<ConstantInt>(Op1)) { return BinaryOperator::CreateAnd(Builder->CreateNot(A), Op1);
}
}
}
if (Op0I && Op1I) {
Value *A, *B, *C, *D;
if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
match(Op1I, m_Or(m_Value(C), m_Value(D)))) {
if ((A == C && B == D) || (A == D && B == C))
return BinaryOperator::CreateXor(A, B);
}
if (match(Op0I, m_Or(m_Value(A), m_Value(B))) &&
match(Op1I, m_And(m_Value(C), m_Value(D)))) {
if ((A == C && B == D) || (A == D && B == C))
return BinaryOperator::CreateXor(A, B);
}
if (match(Op0I, m_Or(m_Value(A), m_Not(m_Value(B)))) &&
match(Op1I, m_Or(m_Not(m_Specific(A)), m_Specific(B)))) {
return BinaryOperator::CreateXor(A, B);
}
if (match(Op0I, m_Or(m_Not(m_Value(A)), m_Value(B))) &&
match(Op1I, m_Or(m_Specific(A), m_Not(m_Specific(B))))) {
return BinaryOperator::CreateXor(A, B);
}
if (match(Op0I, m_And(m_Value(A), m_Not(m_Value(B)))) &&
match(Op1I, m_And(m_Not(m_Specific(A)), m_Specific(B)))) {
return BinaryOperator::CreateXor(A, B);
}
if (match(Op0I, m_And(m_Not(m_Value(A)), m_Value(B))) &&
match(Op1I, m_And(m_Specific(A), m_Not(m_Specific(B))))) {
return BinaryOperator::CreateXor(A, B);
}
if (match(Op0I, m_Xor(m_Value(D), m_Value(C))) &&
match(Op1I, m_Or(m_Value(A), m_Value(B)))) {
if (D == A)
return BinaryOperator::CreateXor(
Builder->CreateAnd(Builder->CreateNot(A), B), C);
if (D == B)
return BinaryOperator::CreateXor(
Builder->CreateAnd(Builder->CreateNot(B), A), C);
}
if (match(Op0I, m_Or(m_Value(A), m_Value(B))) &&
match(Op1I, m_Xor(m_Value(D), m_Value(C)))) {
if (D == A)
return BinaryOperator::CreateXor(
Builder->CreateAnd(Builder->CreateNot(A), B), C);
if (D == B)
return BinaryOperator::CreateXor(
Builder->CreateAnd(Builder->CreateNot(B), A), C);
}
if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
match(Op1I, m_Xor(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateOr(A, B);
if (match(Op0I, m_Xor(m_Value(A), m_Value(B))) &&
match(Op1I, m_And(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateOr(A, B);
}
Value *A = nullptr, *B = nullptr;
if (match(Op0, m_And(m_Value(A), m_Not(m_Value(B)))) &&
match(Op1, m_Not(m_Specific(A))))
return BinaryOperator::CreateNot(Builder->CreateAnd(A, B));
if (ICmpInst *RHS = dyn_cast<ICmpInst>(I.getOperand(1)))
if (ICmpInst *LHS = dyn_cast<ICmpInst>(I.getOperand(0)))
if (PredicatesFoldable(LHS->getPredicate(), RHS->getPredicate())) {
if (LHS->getOperand(0) == RHS->getOperand(1) &&
LHS->getOperand(1) == RHS->getOperand(0))
LHS->swapOperands();
if (LHS->getOperand(0) == RHS->getOperand(0) &&
LHS->getOperand(1) == RHS->getOperand(1)) {
Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1);
unsigned Code = getICmpCode(LHS) ^ getICmpCode(RHS);
bool isSigned = LHS->isSigned() || RHS->isSigned();
return ReplaceInstUsesWith(I,
getNewICmpValue(isSigned, Code, Op0, Op1,
Builder));
}
}
if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {
if (CastInst *Op1C = dyn_cast<CastInst>(Op1))
if (Op0C->getOpcode() == Op1C->getOpcode()) { Type *SrcTy = Op0C->getOperand(0)->getType();
if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegerTy() &&
ShouldOptimizeCast(Op0C->getOpcode(), Op0C->getOperand(0),
I.getType()) &&
ShouldOptimizeCast(Op1C->getOpcode(), Op1C->getOperand(0),
I.getType())) {
Value *NewOp = Builder->CreateXor(Op0C->getOperand(0),
Op1C->getOperand(0), I.getName());
return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType());
}
}
}
return Changed ? &I : nullptr;
}