// // This file is distributed under the MIT License. See LICENSE.md for details. // #include "llvm/ADT/SmallVector.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/Pass.h" using namespace llvm; namespace { /// `inttoptr` already does an implicit zero-extension when its operand is /// narrower than the target pointer, and `ptrtoint` already truncates when the /// target integer is narrower than the pointer. /// This pass exploits this fact turning: /// /// %w = zext iN %x to iM /// %p = inttoptr iM %w to ptr /// %w = ptrtoint ptr %p to iM /// %t = trunc iM %w to iN /// /// into: /// /// %p = inttoptr iN %x to ptr /// %t = ptrtoint ptr %p to iN /// /// \note instcombine reverts these changes, so you might want to run this // close to the leaves of your pipeline. struct DropRedundantPtrIntCasts : public FunctionPass { static char ID; DropRedundantPtrIntCasts() : FunctionPass(ID) {} void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); } bool runOnFunction(Function &F) override { bool Changed = false; SmallVector ToErase; for (auto &I : llvm::instructions(F)) { if (auto *IntToPtr = dyn_cast(&I)) { if (auto *ZeroExtend = dyn_cast(IntToPtr->getOperand(0))) { IRBuilder<> B(IntToPtr); auto *New = B.CreateIntToPtr(ZeroExtend->getOperand(0), IntToPtr->getType()); if (auto *NewI = dyn_cast(New)) NewI->copyMetadata(*IntToPtr); IntToPtr->replaceAllUsesWith(New); ToErase.push_back(IntToPtr); Changed = true; } } else if (auto *TR = dyn_cast(&I)) { if (auto *PtrToInt = dyn_cast(TR->getOperand(0))) { IRBuilder<> B(TR); auto *New = B.CreatePtrToInt(PtrToInt->getPointerOperand(), TR->getType()); if (auto *NewI = dyn_cast(New)) NewI->copyMetadata(*TR); TR->replaceAllUsesWith(New); ToErase.push_back(TR); Changed = true; } } } for (auto *I : ToErase) I->eraseFromParent(); return Changed; } }; } // namespace char DropRedundantPtrIntCasts::ID = 0; using Register = RegisterPass; static Register X("drop-redundant-ptrint-casts", "", false, false);