blob: 7242f12b4b3bad85597a63a10d7202018430310a [file] [log] [blame]
//===-- Int2PtrCmp.cpp - Merge inttoptr/ptrtoint --------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Remove unnecessary inttoptr casts
// Specially ones used in just compares
// Most cases derived from InstCombine
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "int2ptr-cmp"
#include "assistDS/Int2PtrCmp.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Debug.h"
#include "llvm/IR/PatternMatch.h"
#include <set>
#include <map>
#include <vector>
using namespace llvm;
using namespace PatternMatch;
//
// Method: runOnModule()
//
// Description:
// Entry point for this LLVM pass.
// Remove unnecessary inttoptr instructions.
//
// Inputs:
// M - A reference to the LLVM module to transform
//
// Outputs:
// M - The transformed LLVM module.
//
// Return value:
// true - The module was modified.
// false - The module was not modified.
//
bool Int2PtrCmp::runOnModule(Module& M) {
TD = &getAnalysis<DataLayoutPass>().getDataLayout();
for (Module::iterator F = M.begin(); F != M.end(); ++F) {
for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) {
// ptrtoint(inttoptr ty Y) to ty -> Y
if(PtrToIntInst *P2I = dyn_cast<PtrToIntInst>(I++)) {
if(IntToPtrInst *I2P = dyn_cast<IntToPtrInst>(P2I->getOperand(0))) {
if(I2P->getSrcTy() == P2I->getDestTy()){
P2I->replaceAllUsesWith(I2P->getOperand(0));
P2I->eraseFromParent();
if(I2P->use_empty()) {
// If this is the only use of the cast delete it.
I2P->eraseFromParent();
}
}
}
}
}
for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) {
//icmp pred inttoptr(X), null -> icmp pred X 0
if(ICmpInst *CI = dyn_cast<ICmpInst>(I++)) {
Value *Op0 = CI->getOperand(0);
Value *Op1 = CI->getOperand(1);
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
if (Instruction *LHSI = dyn_cast<Instruction>(Op0)){
if(LHSI->getOpcode() == Instruction::IntToPtr) {
if (RHSC->isNullValue() && TD &&
TD->getIntPtrType(RHSC->getContext(), 0) ==
LHSI->getOperand(0)->getType()){
ICmpInst *CI_new = new ICmpInst(CI, CI->getPredicate(), LHSI->getOperand(0),
Constant::getNullValue(LHSI->getOperand(0)->getType()));
CI->replaceAllUsesWith(CI_new);
CI->eraseFromParent();
if(LHSI->use_empty()) {
// If this is the only use of the cast delete it.
LHSI->eraseFromParent();
}
}
}
}
}
}
}
}
}
for (Module::iterator F = M.begin(); F != M.end(); ++F) {
for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) {
if(ICmpInst *ICI = dyn_cast<ICmpInst>(I++)) {
Value *Op0 = ICI->getOperand(0);
Value *Op1 = ICI->getOperand(1);
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
// Since the RHS is a ConstantInt (CI), if the left hand side is an
// instruction, see if that instruction also has constants so that the
// instruction can be folded into the icmp
if (Instruction *LHSI = dyn_cast<Instruction>(Op0)){
if(LHSI->getOpcode() == Instruction::Or) {
if (!ICI->isEquality() || !CI->isNullValue() || !LHSI->hasOneUse())
break;
Value *P, *Q, *R;
if (match(LHSI, m_Or(m_PtrToInt(m_Value(P)), m_PtrToInt(m_Value(Q))))) {
// Simplify icmp eq (or (ptrtoint P), (ptrtoint Q)), 0
// -> and (icmp eq P, null), (icmp eq Q, null).
Value *ICIP = new ICmpInst(ICI, ICI->getPredicate(), P,
Constant::getNullValue(P->getType()));
Value *ICIQ = new ICmpInst(ICI, ICI->getPredicate(), Q,
Constant::getNullValue(Q->getType()));
Instruction *Op;
if (ICI->getPredicate() == ICmpInst::ICMP_EQ)
Op = BinaryOperator::CreateAnd(ICIP, ICIQ,"",ICI);
else
Op = BinaryOperator::CreateOr(ICIP, ICIQ, "", ICI);
ICI->replaceAllUsesWith(Op);
} else if(match(LHSI, m_Or(m_Or(m_PtrToInt(m_Value(P)),
m_PtrToInt(m_Value(Q))),
m_PtrToInt(m_Value(R))))) {
// Simplify icmp eq (or (or (ptrtoint P), (ptrtoint Q)), ptrtoint(R)), 0
// -> and (and (icmp eq P, null), (icmp eq Q, null)), (icmp eq R, null).
Value *ICIP = new ICmpInst(ICI, ICI->getPredicate(), P,
Constant::getNullValue(P->getType()));
Value *ICIQ = new ICmpInst(ICI, ICI->getPredicate(), Q,
Constant::getNullValue(Q->getType()));
Value *ICIR = new ICmpInst(ICI, ICI->getPredicate(), R,
Constant::getNullValue(R->getType()));
Instruction *Op;
if (ICI->getPredicate() == ICmpInst::ICMP_EQ)
Op = BinaryOperator::CreateAnd(ICIP, ICIQ,"",ICI);
else
Op = BinaryOperator::CreateOr(ICIP, ICIQ, "", ICI);
if (ICI->getPredicate() == ICmpInst::ICMP_EQ)
Op = BinaryOperator::CreateAnd(Op, ICIR,"",ICI);
else
Op = BinaryOperator::CreateOr(Op, ICIR, "", ICI);
ICI->replaceAllUsesWith(Op);
} else if(match(LHSI, m_Or(m_PtrToInt(m_Value(Q)), m_Or(
m_PtrToInt(m_Value(P)), m_PtrToInt(m_Value(R)))))) {
// Simplify icmp eq (or (ptrtoint P), or((ptrtoint Q), ptrtoint(R))), 0
// -> and (icmp eq P, null), (and (icmp eq Q, null), (icmp eq R, null)).
Value *ICIP = new ICmpInst(ICI, ICI->getPredicate(), P,
Constant::getNullValue(P->getType()));
Value *ICIQ = new ICmpInst(ICI, ICI->getPredicate(), Q,
Constant::getNullValue(Q->getType()));
Value *ICIR = new ICmpInst(ICI, ICI->getPredicate(), R,
Constant::getNullValue(R->getType()));
Instruction *Op;
if (ICI->getPredicate() == ICmpInst::ICMP_EQ)
Op = BinaryOperator::CreateAnd(ICIP, ICIQ,"",ICI);
else
Op = BinaryOperator::CreateOr(ICIP, ICIQ, "", ICI);
if (ICI->getPredicate() == ICmpInst::ICMP_EQ)
Op = BinaryOperator::CreateAnd(Op, ICIR,"",ICI);
else
Op = BinaryOperator::CreateOr(Op, ICIR, "", ICI);
ICI->replaceAllUsesWith(Op);
}
}
}
}
}
}
}
}
return true;
}
// Pass ID variable
char Int2PtrCmp::ID = 0;
// Register the pass
static RegisterPass<Int2PtrCmp>
X("int2ptrcmp", "Simplify inttoptr/ptrtoint insts");