mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 05:00:26 +00:00
Rework InstrTypes.h so to reduce the repetition around the NSW/NUW/Exact
versions of creation functions. Eventually, the "insertion point" versions of these should just be removed, we do have IRBuilder afterall. Do a massive rewrite of much of pattern match. It is now shorter and less redundant and has several other widgets I will be using in other patches. Among other changes, m_Div is renamed to m_IDiv (since it only matches integer divides) and m_Shift is gone (it used to match all binops!!) and we now have m_LogicalShift for the one client to use. Enhance IRBuilder to have "isExact" arguments to things like CreateUDiv and reduce redundancy within IRbuilder by having these methods chain to each other more instead of duplicating code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125194 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1aac1864cf
commit
aeaf3d484b
@ -194,175 +194,93 @@ public:
|
|||||||
}
|
}
|
||||||
#include "llvm/Instruction.def"
|
#include "llvm/Instruction.def"
|
||||||
|
|
||||||
|
static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
/// CreateNSWAdd - Create an Add operator with the NSW flag set.
|
|
||||||
///
|
|
||||||
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
|
||||||
const Twine &Name = "") {
|
const Twine &Name = "") {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name);
|
||||||
BO->setHasNoSignedWrap(true);
|
BO->setHasNoSignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
const Twine &Name, BasicBlock *BB) {
|
const Twine &Name, BasicBlock *BB) {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name, BB);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name, BB);
|
||||||
BO->setHasNoSignedWrap(true);
|
BO->setHasNoSignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2,
|
static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
const Twine &Name, Instruction *I) {
|
const Twine &Name, Instruction *I) {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name, I);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name, I);
|
||||||
BO->setHasNoSignedWrap(true);
|
BO->setHasNoSignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CreateNUWAdd - Create an Add operator with the NUW flag set.
|
static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
///
|
|
||||||
static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2,
|
|
||||||
const Twine &Name = "") {
|
const Twine &Name = "") {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name);
|
||||||
BO->setHasNoUnsignedWrap(true);
|
BO->setHasNoUnsignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2,
|
static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
const Twine &Name, BasicBlock *BB) {
|
const Twine &Name, BasicBlock *BB) {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name, BB);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name, BB);
|
||||||
BO->setHasNoUnsignedWrap(true);
|
BO->setHasNoUnsignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2,
|
static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
const Twine &Name, Instruction *I) {
|
const Twine &Name, Instruction *I) {
|
||||||
BinaryOperator *BO = CreateAdd(V1, V2, Name, I);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name, I);
|
||||||
BO->setHasNoUnsignedWrap(true);
|
BO->setHasNoUnsignedWrap(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CreateNSWSub - Create an Sub operator with the NSW flag set.
|
static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
///
|
|
||||||
static BinaryOperator *CreateNSWSub(Value *V1, Value *V2,
|
|
||||||
const Twine &Name = "") {
|
const Twine &Name = "") {
|
||||||
BinaryOperator *BO = CreateSub(V1, V2, Name);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name);
|
||||||
BO->setHasNoSignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateNSWSub(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, BasicBlock *BB) {
|
|
||||||
BinaryOperator *BO = CreateSub(V1, V2, Name, BB);
|
|
||||||
BO->setHasNoSignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateNSWSub(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, Instruction *I) {
|
|
||||||
BinaryOperator *BO = CreateSub(V1, V2, Name, I);
|
|
||||||
BO->setHasNoSignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CreateNUWSub - Create an Sub operator with the NUW flag set.
|
|
||||||
///
|
|
||||||
static BinaryOperator *CreateNUWSub(Value *V1, Value *V2,
|
|
||||||
const Twine &Name = "") {
|
|
||||||
BinaryOperator *BO = CreateSub(V1, V2, Name);
|
|
||||||
BO->setHasNoUnsignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateNUWSub(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, BasicBlock *BB) {
|
|
||||||
BinaryOperator *BO = CreateSub(V1, V2, Name, BB);
|
|
||||||
BO->setHasNoUnsignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateNUWSub(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, Instruction *I) {
|
|
||||||
BinaryOperator *BO = CreateSub(V1, V2, Name, I);
|
|
||||||
BO->setHasNoUnsignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CreateNSWMul - Create a Mul operator with the NSW flag set.
|
|
||||||
///
|
|
||||||
static BinaryOperator *CreateNSWMul(Value *V1, Value *V2,
|
|
||||||
const Twine &Name = "") {
|
|
||||||
BinaryOperator *BO = CreateMul(V1, V2, Name);
|
|
||||||
BO->setHasNoSignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateNSWMul(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, BasicBlock *BB) {
|
|
||||||
BinaryOperator *BO = CreateMul(V1, V2, Name, BB);
|
|
||||||
BO->setHasNoSignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateNSWMul(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, Instruction *I) {
|
|
||||||
BinaryOperator *BO = CreateMul(V1, V2, Name, I);
|
|
||||||
BO->setHasNoSignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CreateNUWMul - Create a Mul operator with the NUW flag set.
|
|
||||||
///
|
|
||||||
static BinaryOperator *CreateNUWMul(Value *V1, Value *V2,
|
|
||||||
const Twine &Name = "") {
|
|
||||||
BinaryOperator *BO = CreateMul(V1, V2, Name);
|
|
||||||
BO->setHasNoUnsignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateNUWMul(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, BasicBlock *BB) {
|
|
||||||
BinaryOperator *BO = CreateMul(V1, V2, Name, BB);
|
|
||||||
BO->setHasNoUnsignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateNUWMul(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, Instruction *I) {
|
|
||||||
BinaryOperator *BO = CreateMul(V1, V2, Name, I);
|
|
||||||
BO->setHasNoUnsignedWrap(true);
|
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CreateExactUDiv - Create a UDiv operator with the exact flag set.
|
|
||||||
///
|
|
||||||
static BinaryOperator *CreateExactUDiv(Value *V1, Value *V2,
|
|
||||||
const Twine &Name = "") {
|
|
||||||
BinaryOperator *BO = CreateUDiv(V1, V2, Name);
|
|
||||||
BO->setIsExact(true);
|
BO->setIsExact(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateExactUDiv(Value *V1, Value *V2,
|
static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
const Twine &Name, BasicBlock *BB) {
|
const Twine &Name, BasicBlock *BB) {
|
||||||
BinaryOperator *BO = CreateUDiv(V1, V2, Name, BB);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name, BB);
|
||||||
BO->setIsExact(true);
|
BO->setIsExact(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
static BinaryOperator *CreateExactUDiv(Value *V1, Value *V2,
|
static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2,
|
||||||
const Twine &Name, Instruction *I) {
|
const Twine &Name, Instruction *I) {
|
||||||
BinaryOperator *BO = CreateUDiv(V1, V2, Name, I);
|
BinaryOperator *BO = Create(Opc, V1, V2, Name, I);
|
||||||
BO->setIsExact(true);
|
BO->setIsExact(true);
|
||||||
return BO;
|
return BO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CreateExactSDiv - Create an SDiv operator with the exact flag set.
|
#define DEFINE_HELPERS(OPC, NUWNSWEXACT) \
|
||||||
///
|
static BinaryOperator *Create ## NUWNSWEXACT ## OPC \
|
||||||
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
(Value *V1, Value *V2, const Twine &Name = "") { \
|
||||||
const Twine &Name = "") {
|
return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name); \
|
||||||
BinaryOperator *BO = CreateSDiv(V1, V2, Name);
|
} \
|
||||||
BO->setIsExact(true);
|
static BinaryOperator *Create ## NUWNSWEXACT ## OPC \
|
||||||
return BO;
|
(Value *V1, Value *V2, const Twine &Name, BasicBlock *BB) { \
|
||||||
}
|
return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, BB); \
|
||||||
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
} \
|
||||||
const Twine &Name, BasicBlock *BB) {
|
static BinaryOperator *Create ## NUWNSWEXACT ## OPC \
|
||||||
BinaryOperator *BO = CreateSDiv(V1, V2, Name, BB);
|
(Value *V1, Value *V2, const Twine &Name, Instruction *I) { \
|
||||||
BO->setIsExact(true);
|
return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, I); \
|
||||||
return BO;
|
|
||||||
}
|
|
||||||
static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2,
|
|
||||||
const Twine &Name, Instruction *I) {
|
|
||||||
BinaryOperator *BO = CreateSDiv(V1, V2, Name, I);
|
|
||||||
BO->setIsExact(true);
|
|
||||||
return BO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_HELPERS(Add, NSW) // CreateNSWAdd
|
||||||
|
DEFINE_HELPERS(Add, NUW) // CreateNUWAdd
|
||||||
|
DEFINE_HELPERS(Sub, NSW) // CreateNSWSub
|
||||||
|
DEFINE_HELPERS(Sub, NUW) // CreateNUWSub
|
||||||
|
DEFINE_HELPERS(Mul, NSW) // CreateNSWMul
|
||||||
|
DEFINE_HELPERS(Mul, NUW) // CreateNUWMul
|
||||||
|
DEFINE_HELPERS(Shl, NSW) // CreateNSWShl
|
||||||
|
DEFINE_HELPERS(Shl, NUW) // CreateNUWShl
|
||||||
|
|
||||||
|
DEFINE_HELPERS(SDiv, Exact) // CreateExactSDiv
|
||||||
|
DEFINE_HELPERS(UDiv, Exact) // CreateExactUDiv
|
||||||
|
DEFINE_HELPERS(AShr, Exact) // CreateExactAShr
|
||||||
|
DEFINE_HELPERS(LShr, Exact) // CreateExactLShr
|
||||||
|
|
||||||
|
#undef DEFINE_HELPERS
|
||||||
|
|
||||||
/// Helper functions to construct and inspect unary operations (NEG and NOT)
|
/// Helper functions to construct and inspect unary operations (NEG and NOT)
|
||||||
/// via binary operators SUB and XOR:
|
/// via binary operators SUB and XOR:
|
||||||
///
|
///
|
||||||
|
@ -521,29 +521,29 @@ public:
|
|||||||
return Insert(Folder.CreateFMul(LC, RC), Name);
|
return Insert(Folder.CreateFMul(LC, RC), Name);
|
||||||
return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||||
|
bool isExact = false) {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||||
return Insert(Folder.CreateUDiv(LC, RC), Name);
|
return Insert(Folder.CreateUDiv(LC, RC, isExact), Name);
|
||||||
|
if (!isExact)
|
||||||
return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name);
|
||||||
}
|
|
||||||
Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
|
||||||
return Insert(Folder.CreateExactUDiv(LC, RC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||||
|
return CreateUDiv(LHS, RHS, Name, true);
|
||||||
|
}
|
||||||
|
Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||||
|
bool isExact = false) {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||||
return Insert(Folder.CreateSDiv(LC, RC), Name);
|
return Insert(Folder.CreateSDiv(LC, RC, isExact), Name);
|
||||||
|
if (!isExact)
|
||||||
return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name);
|
||||||
|
return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
return CreateSDiv(LHS, RHS, Name, true);
|
||||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
|
||||||
return Insert(Folder.CreateExactSDiv(LC, RC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name);
|
|
||||||
}
|
}
|
||||||
Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||||
@ -577,54 +577,46 @@ public:
|
|||||||
return Insert(BinaryOperator::CreateShl(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateShl(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
return Insert(Folder.CreateShl(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
return Insert(Folder.CreateShl(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||||
|
bool isExact = false) {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||||
return Insert(Folder.CreateLShr(LC, RC), Name);
|
return Insert(Folder.CreateLShr(LC, RC, isExact), Name);
|
||||||
|
if (!isExact)
|
||||||
return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name);
|
||||||
|
return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
bool isExact = false) {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
|
||||||
return Insert(Folder.CreateLShr(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
bool isExact = false) {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
|
||||||
return Insert(Folder.CreateLShr(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "",
|
||||||
|
bool isExact = false) {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||||
return Insert(Folder.CreateAShr(LC, RC), Name);
|
return Insert(Folder.CreateAShr(LC, RC, isExact), Name);
|
||||||
|
if (!isExact)
|
||||||
return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name);
|
||||||
|
return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "",
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
bool isExact = false) {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
|
||||||
return Insert(Folder.CreateAShr(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "",
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
bool isExact = false) {
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact);
|
||||||
return Insert(Folder.CreateAShr(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||||
@ -637,16 +629,10 @@ public:
|
|||||||
return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
return Insert(Folder.CreateAnd(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateAnd(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
return Insert(Folder.CreateAnd(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateAnd(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||||
@ -659,16 +645,10 @@ public:
|
|||||||
return Insert(BinaryOperator::CreateOr(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateOr(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
return Insert(Folder.CreateOr(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateOr(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
return Insert(Folder.CreateOr(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateOr(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") {
|
Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||||
@ -678,16 +658,10 @@ public:
|
|||||||
return Insert(BinaryOperator::CreateXor(LHS, RHS), Name);
|
return Insert(BinaryOperator::CreateXor(LHS, RHS), Name);
|
||||||
}
|
}
|
||||||
Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") {
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
return Insert(Folder.CreateXor(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateXor(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
||||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name);
|
||||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
|
||||||
return Insert(Folder.CreateXor(LC, RHSC), Name);
|
|
||||||
return Insert(BinaryOperator::CreateXor(LHS, RHSC), Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *CreateBinOp(Instruction::BinaryOps Opc,
|
Value *CreateBinOp(Instruction::BinaryOps Opc,
|
||||||
|
@ -41,18 +41,61 @@ bool match(Val *V, const Pattern &P) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Class>
|
template<typename Class>
|
||||||
struct leaf_ty {
|
struct class_match {
|
||||||
template<typename ITy>
|
template<typename ITy>
|
||||||
bool match(ITy *V) { return isa<Class>(V); }
|
bool match(ITy *V) { return isa<Class>(V); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// m_Value() - Match an arbitrary value and ignore it.
|
/// m_Value() - Match an arbitrary value and ignore it.
|
||||||
inline leaf_ty<Value> m_Value() { return leaf_ty<Value>(); }
|
inline class_match<Value> m_Value() { return class_match<Value>(); }
|
||||||
/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it.
|
/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it.
|
||||||
inline leaf_ty<ConstantInt> m_ConstantInt() { return leaf_ty<ConstantInt>(); }
|
inline class_match<ConstantInt> m_ConstantInt() {
|
||||||
|
return class_match<ConstantInt>();
|
||||||
|
}
|
||||||
|
/// m_Undef() - Match an arbitrary undef constant.
|
||||||
|
inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
|
||||||
|
|
||||||
|
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
|
||||||
|
|
||||||
|
struct match_zero {
|
||||||
|
template<typename ITy>
|
||||||
|
bool match(ITy *V) {
|
||||||
|
if (const Constant *C = dyn_cast<Constant>(V))
|
||||||
|
return C->isNullValue();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// m_Zero() - Match an arbitrary zero/null constant. This includes
|
||||||
|
/// zero_initializer for vectors and ConstantPointerNull for pointers.
|
||||||
|
inline match_zero m_Zero() { return match_zero(); }
|
||||||
|
|
||||||
|
|
||||||
|
struct apint_match {
|
||||||
|
const APInt *&Res;
|
||||||
|
apint_match(const APInt *&R) : Res(R) {}
|
||||||
|
template<typename ITy>
|
||||||
|
bool match(ITy *V) {
|
||||||
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||||
|
Res = &CI->getValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (ConstantVector *CV = dyn_cast<ConstantVector>(V))
|
||||||
|
if (ConstantInt *CI = cast_or_null<ConstantInt>(CV->getSplatValue())) {
|
||||||
|
Res = &CI->getValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the
|
||||||
|
/// specified pointer to the contained APInt.
|
||||||
|
inline apint_match m_APInt(const APInt *&Res) { return Res; }
|
||||||
|
|
||||||
|
|
||||||
template<int64_t Val>
|
template<int64_t Val>
|
||||||
struct constantint_ty {
|
struct constantint_match {
|
||||||
template<typename ITy>
|
template<typename ITy>
|
||||||
bool match(ITy *V) {
|
bool match(ITy *V) {
|
||||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||||
@ -68,79 +111,82 @@ struct constantint_ty {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// m_ConstantInt(int64_t) - Match a ConstantInt with a specific value
|
/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value.
|
||||||
/// and ignore it.
|
|
||||||
template<int64_t Val>
|
template<int64_t Val>
|
||||||
inline constantint_ty<Val> m_ConstantInt() {
|
inline constantint_match<Val> m_ConstantInt() {
|
||||||
return constantint_ty<Val>();
|
return constantint_match<Val>();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct undef_ty {
|
/// cst_pred_ty - This helper class is used to match scalar and vector constants
|
||||||
template<typename ITy>
|
/// that satisfy a specified predicate.
|
||||||
bool match(ITy *V) {
|
template<typename Predicate>
|
||||||
return isa<UndefValue>(V);
|
struct cst_pred_ty : public Predicate {
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// m_Undef() - Match an arbitrary undef constant.
|
|
||||||
inline undef_ty m_Undef() { return undef_ty(); }
|
|
||||||
|
|
||||||
struct zero_ty {
|
|
||||||
template<typename ITy>
|
|
||||||
bool match(ITy *V) {
|
|
||||||
if (const Constant *C = dyn_cast<Constant>(V))
|
|
||||||
return C->isNullValue();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// m_Zero() - Match an arbitrary zero/null constant.
|
|
||||||
inline zero_ty m_Zero() { return zero_ty(); }
|
|
||||||
|
|
||||||
struct one_ty {
|
|
||||||
template<typename ITy>
|
template<typename ITy>
|
||||||
bool match(ITy *V) {
|
bool match(ITy *V) {
|
||||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
|
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
|
||||||
return CI->isOne();
|
return this->isValue(CI->getValue());
|
||||||
if (const ConstantVector *CV = dyn_cast<ConstantVector>(V))
|
if (const ConstantVector *CV = dyn_cast<ConstantVector>(V))
|
||||||
if (ConstantInt *CI = cast_or_null<ConstantInt>(CV->getSplatValue()))
|
if (ConstantInt *CI = cast_or_null<ConstantInt>(CV->getSplatValue()))
|
||||||
return CI->isOne();
|
return this->isValue(CI->getValue());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// api_pred_ty - This helper class is used to match scalar and vector constants
|
||||||
|
/// that satisfy a specified predicate, and bind them to an APInt.
|
||||||
|
template<typename Predicate>
|
||||||
|
struct api_pred_ty : public Predicate {
|
||||||
|
const APInt *&Res;
|
||||||
|
api_pred_ty(const APInt *&R) : Res(R) {}
|
||||||
|
template<typename ITy>
|
||||||
|
bool match(ITy *V) {
|
||||||
|
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
|
||||||
|
if (this->isValue(CI->getValue())) {
|
||||||
|
Res = &CI->getValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (const ConstantVector *CV = dyn_cast<ConstantVector>(V))
|
||||||
|
if (ConstantInt *CI = cast_or_null<ConstantInt>(CV->getSplatValue()))
|
||||||
|
if (this->isValue(CI->getValue())) {
|
||||||
|
Res = &CI->getValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct is_one {
|
||||||
|
bool isValue(const APInt &C) { return C == 1; }
|
||||||
|
};
|
||||||
|
|
||||||
/// m_One() - Match an integer 1 or a vector with all elements equal to 1.
|
/// m_One() - Match an integer 1 or a vector with all elements equal to 1.
|
||||||
inline one_ty m_One() { return one_ty(); }
|
inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); }
|
||||||
|
inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; }
|
||||||
|
|
||||||
struct all_ones_ty {
|
struct is_all_ones {
|
||||||
template<typename ITy>
|
bool isValue(const APInt &C) { return C.isAllOnesValue(); }
|
||||||
bool match(ITy *V) {
|
|
||||||
if (const ConstantInt *C = dyn_cast<ConstantInt>(V))
|
|
||||||
return C->isAllOnesValue();
|
|
||||||
if (const ConstantVector *C = dyn_cast<ConstantVector>(V))
|
|
||||||
return C->isAllOnesValue();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// m_AllOnes() - Match an integer or vector with all bits set to true.
|
/// m_AllOnes() - Match an integer or vector with all bits set to true.
|
||||||
inline all_ones_ty m_AllOnes() { return all_ones_ty(); }
|
inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();}
|
||||||
|
inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; }
|
||||||
|
|
||||||
struct signbit_ty {
|
struct is_sign_bit {
|
||||||
template<typename ITy>
|
bool isValue(const APInt &C) { return C.isSignBit(); }
|
||||||
bool match(ITy *V) {
|
|
||||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
|
|
||||||
return CI->getValue().isSignBit();
|
|
||||||
if (const ConstantVector *CV = dyn_cast<ConstantVector>(V))
|
|
||||||
if (ConstantInt *CI = cast_or_null<ConstantInt>(CV->getSplatValue()))
|
|
||||||
return CI->getValue().isSignBit();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// m_SignBit() - Match an integer or vector with only the sign bit(s) set.
|
/// m_SignBit() - Match an integer or vector with only the sign bit(s) set.
|
||||||
inline signbit_ty m_SignBit() { return signbit_ty(); }
|
inline cst_pred_ty<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();}
|
||||||
|
inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; }
|
||||||
|
|
||||||
|
struct is_power2 {
|
||||||
|
bool isValue(const APInt &C) { return C.isPowerOf2(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// m_Power2() - Match an integer or vector power of 2.
|
||||||
|
inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); }
|
||||||
|
inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; }
|
||||||
|
|
||||||
template<typename Class>
|
template<typename Class>
|
||||||
struct bind_ty {
|
struct bind_ty {
|
||||||
@ -163,6 +209,9 @@ inline bind_ty<Value> m_Value(Value *&V) { return V; }
|
|||||||
/// m_ConstantInt - Match a ConstantInt, capturing the value if we match.
|
/// m_ConstantInt - Match a ConstantInt, capturing the value if we match.
|
||||||
inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; }
|
inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; }
|
||||||
|
|
||||||
|
/// m_Constant - Match a Constant, capturing the value if we match.
|
||||||
|
inline bind_ty<Constant> m_Constant(Constant *&C) { return C; }
|
||||||
|
|
||||||
/// specificval_ty - Match a specified Value*.
|
/// specificval_ty - Match a specified Value*.
|
||||||
struct specificval_ty {
|
struct specificval_ty {
|
||||||
const Value *Val;
|
const Value *Val;
|
||||||
@ -182,8 +231,7 @@ inline specificval_ty m_Specific(const Value *V) { return V; }
|
|||||||
// Matchers for specific binary operators.
|
// Matchers for specific binary operators.
|
||||||
//
|
//
|
||||||
|
|
||||||
template<typename LHS_t, typename RHS_t,
|
template<typename LHS_t, typename RHS_t, unsigned Opcode>
|
||||||
unsigned Opcode, typename ConcreteTy = BinaryOperator>
|
|
||||||
struct BinaryOp_match {
|
struct BinaryOp_match {
|
||||||
LHS_t L;
|
LHS_t L;
|
||||||
RHS_t R;
|
RHS_t R;
|
||||||
@ -193,9 +241,8 @@ struct BinaryOp_match {
|
|||||||
template<typename OpTy>
|
template<typename OpTy>
|
||||||
bool match(OpTy *V) {
|
bool match(OpTy *V) {
|
||||||
if (V->getValueID() == Value::InstructionVal + Opcode) {
|
if (V->getValueID() == Value::InstructionVal + Opcode) {
|
||||||
ConcreteTy *I = cast<ConcreteTy>(V);
|
BinaryOperator *I = cast<BinaryOperator>(V);
|
||||||
return I->getOpcode() == Opcode && L.match(I->getOperand(0)) &&
|
return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
|
||||||
R.match(I->getOperand(1));
|
|
||||||
}
|
}
|
||||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
||||||
return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) &&
|
return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) &&
|
||||||
@ -205,227 +252,156 @@ struct BinaryOp_match {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::Add>
|
||||||
const RHS &R) {
|
m_Add(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::FAdd>
|
||||||
const RHS &R) {
|
m_FAdd(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::Sub>
|
||||||
const RHS &R) {
|
m_Sub(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::FSub>
|
||||||
const RHS &R) {
|
m_FSub(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::Mul>
|
||||||
const RHS &R) {
|
m_Mul(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::FMul>
|
||||||
const RHS &R) {
|
m_FMul(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::UDiv>
|
||||||
const RHS &R) {
|
m_UDiv(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::SDiv>
|
||||||
const RHS &R) {
|
m_SDiv(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::FDiv>
|
||||||
const RHS &R) {
|
m_FDiv(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::URem>
|
||||||
const RHS &R) {
|
m_URem(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::SRem>
|
||||||
const RHS &R) {
|
m_SRem(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::FRem>
|
||||||
const RHS &R) {
|
m_FRem(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::And>
|
||||||
const RHS &R) {
|
m_And(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::And>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::And>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::Or>
|
||||||
const RHS &R) {
|
m_Or(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::Xor>
|
||||||
const RHS &R) {
|
m_Xor(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::Shl>
|
||||||
const RHS &R) {
|
m_Shl(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::LShr>
|
||||||
const RHS &R) {
|
m_LShr(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L,
|
inline BinaryOp_match<LHS, RHS, Instruction::AShr>
|
||||||
const RHS &R) {
|
m_AShr(const LHS &L, const RHS &R) {
|
||||||
return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R);
|
return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Matchers for either AShr or LShr .. for convenience
|
// Class that matches two different binary ops.
|
||||||
//
|
//
|
||||||
template<typename LHS_t, typename RHS_t, typename ConcreteTy = BinaryOperator>
|
template<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2>
|
||||||
struct Shr_match {
|
struct BinOp2_match {
|
||||||
LHS_t L;
|
LHS_t L;
|
||||||
RHS_t R;
|
RHS_t R;
|
||||||
|
|
||||||
Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
|
BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
|
||||||
|
|
||||||
template<typename OpTy>
|
template<typename OpTy>
|
||||||
bool match(OpTy *V) {
|
bool match(OpTy *V) {
|
||||||
if (V->getValueID() == Value::InstructionVal + Instruction::LShr ||
|
if (V->getValueID() == Value::InstructionVal + Opc1 ||
|
||||||
V->getValueID() == Value::InstructionVal + Instruction::AShr) {
|
V->getValueID() == Value::InstructionVal + Opc2) {
|
||||||
ConcreteTy *I = cast<ConcreteTy>(V);
|
BinaryOperator *I = cast<BinaryOperator>(V);
|
||||||
return (I->getOpcode() == Instruction::AShr ||
|
return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
|
||||||
I->getOpcode() == Instruction::LShr) &&
|
|
||||||
L.match(I->getOperand(0)) &&
|
|
||||||
R.match(I->getOperand(1));
|
|
||||||
}
|
}
|
||||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
||||||
return (CE->getOpcode() == Instruction::LShr ||
|
return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) &&
|
||||||
CE->getOpcode() == Instruction::AShr) &&
|
L.match(CE->getOperand(0)) && R.match(CE->getOperand(1));
|
||||||
L.match(CE->getOperand(0)) &&
|
|
||||||
R.match(CE->getOperand(1));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// m_Shr - Matches LShr or AShr.
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline Shr_match<LHS, RHS> m_Shr(const LHS &L, const RHS &R) {
|
inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>
|
||||||
return Shr_match<LHS, RHS>(L, R);
|
m_Shr(const LHS &L, const RHS &R) {
|
||||||
|
return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
/// m_LogicalShift - Matches LShr or Shl.
|
||||||
// Matchers for either SDiv or UDiv .. for convenience
|
|
||||||
//
|
|
||||||
template<typename LHS_t, typename RHS_t, typename ConcreteTy = BinaryOperator>
|
|
||||||
struct Div_match {
|
|
||||||
LHS_t L;
|
|
||||||
RHS_t R;
|
|
||||||
|
|
||||||
Div_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
|
|
||||||
|
|
||||||
template<typename OpTy>
|
|
||||||
bool match(OpTy *V) {
|
|
||||||
if (V->getValueID() == Value::InstructionVal + Instruction::SDiv ||
|
|
||||||
V->getValueID() == Value::InstructionVal + Instruction::UDiv) {
|
|
||||||
ConcreteTy *I = cast<ConcreteTy>(V);
|
|
||||||
return (I->getOpcode() == Instruction::UDiv ||
|
|
||||||
I->getOpcode() == Instruction::SDiv) &&
|
|
||||||
L.match(I->getOperand(0)) &&
|
|
||||||
R.match(I->getOperand(1));
|
|
||||||
}
|
|
||||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
|
||||||
return (CE->getOpcode() == Instruction::SDiv ||
|
|
||||||
CE->getOpcode() == Instruction::UDiv) &&
|
|
||||||
L.match(CE->getOperand(0)) &&
|
|
||||||
R.match(CE->getOperand(1));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline Div_match<LHS, RHS> m_Div(const LHS &L, const RHS &R) {
|
inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>
|
||||||
return Div_match<LHS, RHS>(L, R);
|
m_LogicalShift(const LHS &L, const RHS &R) {
|
||||||
|
return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
/// m_IDiv - Matches UDiv and SDiv.
|
||||||
// Matchers for binary classes
|
|
||||||
//
|
|
||||||
|
|
||||||
template<typename LHS_t, typename RHS_t, typename Class, typename OpcType>
|
|
||||||
struct BinaryOpClass_match {
|
|
||||||
OpcType *Opcode;
|
|
||||||
LHS_t L;
|
|
||||||
RHS_t R;
|
|
||||||
|
|
||||||
BinaryOpClass_match(OpcType &Op, const LHS_t &LHS,
|
|
||||||
const RHS_t &RHS)
|
|
||||||
: Opcode(&Op), L(LHS), R(RHS) {}
|
|
||||||
BinaryOpClass_match(const LHS_t &LHS, const RHS_t &RHS)
|
|
||||||
: Opcode(0), L(LHS), R(RHS) {}
|
|
||||||
|
|
||||||
template<typename OpTy>
|
|
||||||
bool match(OpTy *V) {
|
|
||||||
if (Class *I = dyn_cast<Class>(V))
|
|
||||||
if (L.match(I->getOperand(0)) &&
|
|
||||||
R.match(I->getOperand(1))) {
|
|
||||||
if (Opcode)
|
|
||||||
*Opcode = I->getOpcode();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#if 0 // Doesn't handle constantexprs yet!
|
|
||||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
|
||||||
return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) &&
|
|
||||||
R.match(CE->getOperand(1));
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps>
|
inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>
|
||||||
m_Shift(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) {
|
m_IDiv(const LHS &L, const RHS &R) {
|
||||||
return BinaryOpClass_match<LHS, RHS,
|
return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R);
|
||||||
BinaryOperator, Instruction::BinaryOps>(Op, L, R);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
|
||||||
inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps>
|
|
||||||
m_Shift(const LHS &L, const RHS &R) {
|
|
||||||
return BinaryOpClass_match<LHS, RHS,
|
|
||||||
BinaryOperator, Instruction::BinaryOps>(L, R);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -438,15 +414,13 @@ struct CmpClass_match {
|
|||||||
LHS_t L;
|
LHS_t L;
|
||||||
RHS_t R;
|
RHS_t R;
|
||||||
|
|
||||||
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS,
|
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
|
||||||
const RHS_t &RHS)
|
|
||||||
: Predicate(Pred), L(LHS), R(RHS) {}
|
: Predicate(Pred), L(LHS), R(RHS) {}
|
||||||
|
|
||||||
template<typename OpTy>
|
template<typename OpTy>
|
||||||
bool match(OpTy *V) {
|
bool match(OpTy *V) {
|
||||||
if (Class *I = dyn_cast<Class>(V))
|
if (Class *I = dyn_cast<Class>(V))
|
||||||
if (L.match(I->getOperand(0)) &&
|
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
|
||||||
R.match(I->getOperand(1))) {
|
|
||||||
Predicate = I->getPredicate();
|
Predicate = I->getPredicate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -501,11 +475,9 @@ m_Select(const Cond &C, const LHS &L, const RHS &R) {
|
|||||||
/// m_SelectCst - This matches a select of two constants, e.g.:
|
/// m_SelectCst - This matches a select of two constants, e.g.:
|
||||||
/// m_SelectCst<-1, 0>(m_Value(V))
|
/// m_SelectCst<-1, 0>(m_Value(V))
|
||||||
template<int64_t L, int64_t R, typename Cond>
|
template<int64_t L, int64_t R, typename Cond>
|
||||||
inline SelectClass_match<Cond, constantint_ty<L>, constantint_ty<R> >
|
inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> >
|
||||||
m_SelectCst(const Cond &C) {
|
m_SelectCst(const Cond &C) {
|
||||||
return SelectClass_match<Cond, constantint_ty<L>,
|
return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>());
|
||||||
constantint_ty<R> >(C, m_ConstantInt<L>(),
|
|
||||||
m_ConstantInt<R>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -589,12 +561,8 @@ private:
|
|||||||
bool matchIfNot(Value *LHS, Value *RHS) {
|
bool matchIfNot(Value *LHS, Value *RHS) {
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS))
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS))
|
||||||
return CI->isAllOnesValue() && L.match(LHS);
|
return CI->isAllOnesValue() && L.match(LHS);
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(LHS))
|
|
||||||
return CI->isAllOnesValue() && L.match(RHS);
|
|
||||||
if (ConstantVector *CV = dyn_cast<ConstantVector>(RHS))
|
if (ConstantVector *CV = dyn_cast<ConstantVector>(RHS))
|
||||||
return CV->isAllOnesValue() && L.match(LHS);
|
return CV->isAllOnesValue() && L.match(LHS);
|
||||||
if (ConstantVector *CV = dyn_cast<ConstantVector>(LHS))
|
|
||||||
return CV->isAllOnesValue() && L.match(RHS);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -621,11 +589,13 @@ struct neg_match {
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
bool matchIfNeg(Value *LHS, Value *RHS) {
|
bool matchIfNeg(Value *LHS, Value *RHS) {
|
||||||
return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) &&
|
if (ConstantInt *C = dyn_cast<ConstantInt>(LHS))
|
||||||
L.match(RHS);
|
return C->isZero() && L.match(RHS);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// m_Neg - Match an integer negate.
|
||||||
template<typename LHS>
|
template<typename LHS>
|
||||||
inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
|
inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
|
||||||
|
|
||||||
@ -644,23 +614,23 @@ struct fneg_match {
|
|||||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
||||||
if (CE->getOpcode() == Instruction::FSub)
|
if (CE->getOpcode() == Instruction::FSub)
|
||||||
return matchIfFNeg(CE->getOperand(0), CE->getOperand(1));
|
return matchIfFNeg(CE->getOperand(0), CE->getOperand(1));
|
||||||
if (ConstantFP *CF = dyn_cast<ConstantFP>(V))
|
|
||||||
return L.match(ConstantExpr::getFNeg(CF));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
bool matchIfFNeg(Value *LHS, Value *RHS) {
|
bool matchIfFNeg(Value *LHS, Value *RHS) {
|
||||||
return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) &&
|
if (ConstantFP *C = dyn_cast<ConstantFP>(LHS))
|
||||||
L.match(RHS);
|
return C->isNegativeZeroValue() && L.match(RHS);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// m_FNeg - Match a floating point negate.
|
||||||
template<typename LHS>
|
template<typename LHS>
|
||||||
inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
|
inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Matchers for control flow
|
// Matchers for control flow.
|
||||||
//
|
//
|
||||||
|
|
||||||
template<typename Cond_t>
|
template<typename Cond_t>
|
||||||
@ -674,13 +644,11 @@ struct brc_match {
|
|||||||
template<typename OpTy>
|
template<typename OpTy>
|
||||||
bool match(OpTy *V) {
|
bool match(OpTy *V) {
|
||||||
if (BranchInst *BI = dyn_cast<BranchInst>(V))
|
if (BranchInst *BI = dyn_cast<BranchInst>(V))
|
||||||
if (BI->isConditional()) {
|
if (BI->isConditional() && Cond.match(BI->getCondition())) {
|
||||||
if (Cond.match(BI->getCondition())) {
|
|
||||||
T = BI->getSuccessor(0);
|
T = BI->getSuccessor(0);
|
||||||
F = BI->getSuccessor(1);
|
F = BI->getSuccessor(1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -734,8 +734,8 @@ static Value *SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD,
|
|||||||
|
|
||||||
// (X / Y) * Y -> X if the division is exact.
|
// (X / Y) * Y -> X if the division is exact.
|
||||||
Value *X = 0, *Y = 0;
|
Value *X = 0, *Y = 0;
|
||||||
if ((match(Op0, m_Div(m_Value(X), m_Value(Y))) && Y == Op1) || // (X / Y) * Y
|
if ((match(Op0, m_IDiv(m_Value(X), m_Value(Y))) && Y == Op1) || // (X / Y) * Y
|
||||||
(match(Op1, m_Div(m_Value(X), m_Value(Y))) && Y == Op0)) { // Y * (X / Y)
|
(match(Op1, m_IDiv(m_Value(X), m_Value(Y))) && Y == Op0)) { // Y * (X / Y)
|
||||||
BinaryOperator *Div = cast<BinaryOperator>(Y == Op1 ? Op0 : Op1);
|
BinaryOperator *Div = cast<BinaryOperator>(Y == Op1 ? Op0 : Op1);
|
||||||
if (Div->isExact())
|
if (Div->isExact())
|
||||||
return X;
|
return X;
|
||||||
|
@ -1755,8 +1755,8 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
|||||||
// (A >> B) | (C << D) and (A << B) | (B >> C) -> bswap if possible.
|
// (A >> B) | (C << D) and (A << B) | (B >> C) -> bswap if possible.
|
||||||
if (match(Op0, m_Or(m_Value(), m_Value())) ||
|
if (match(Op0, m_Or(m_Value(), m_Value())) ||
|
||||||
match(Op1, m_Or(m_Value(), m_Value())) ||
|
match(Op1, m_Or(m_Value(), m_Value())) ||
|
||||||
(match(Op0, m_Shift(m_Value(), m_Value())) &&
|
(match(Op0, m_LogicalShift(m_Value(), m_Value())) &&
|
||||||
match(Op1, m_Shift(m_Value(), m_Value())))) {
|
match(Op1, m_LogicalShift(m_Value(), m_Value())))) {
|
||||||
if (Instruction *BSwap = MatchBSwap(I))
|
if (Instruction *BSwap = MatchBSwap(I))
|
||||||
return BSwap;
|
return BSwap;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user