Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // TODO: move this as a proper LLVM pass into the optimization pipeline
- // so we'll be able to re-use the precomputed bits analysis results
- // and get the optimizations for free
- llvm::legacy::PassManager PassRunner;
- llvm::legacy::FunctionPassManager FunctionPassRunner(finalFn->getParent());
- FunctionPassRunner.add(llvm::createDemandedBitsWrapperPass());
- FunctionPassRunner.run(*finalFn);
- const llvm::DataLayout &DL = finalFn->getParent()->getDataLayout();
- for (auto &BB : *finalFn) {
- for (auto &I : BB) {
- // Check if we found a 'load' instruction
- if (auto *Load = llvm::dyn_cast<llvm::LoadInst>(&I)) {
- if (auto *BitCast = llvm::dyn_cast<llvm::BitCastInst>(Load->getPointerOperand())) {
- if (auto *GEP = llvm::dyn_cast<llvm::GetElementPtrInst>(BitCast->getOperand(0))) {
- // Check if it has a single index
- if (GEP->getNumIndices() == 1) {
- // Determine if the index is an 'add' instruction
- if (auto *BO = llvm::dyn_cast<llvm::BinaryOperator>(GEP->getOperand(1))) {
- if (BO->getOpcode() == llvm::Instruction::BinaryOps::Add) {
- // Check if one of the operands may be folded to 2 known values
- auto *Op1 = BO->getOperand(0);
- auto *Op2 = BO->getOperand(1);
- auto *Op1Ty = Op1->getType();
- auto *Op2Ty = Op2->getType();
- // Compute the known bits (zeros and ones)
- llvm::KnownBits Op1KnownBits(Op1Ty->getIntegerBitWidth());
- llvm::KnownBits Op2KnownBits(Op2Ty->getIntegerBitWidth());
- llvm::computeKnownBits(Op1, Op1KnownBits, DL);
- llvm::computeKnownBits(Op2, Op2KnownBits, DL);
- // Determine the unknown bits mask
- auto Op1UnknownBits = ~(Op1KnownBits.Zero | Op1KnownBits.One);
- auto Op2UnknownBits = ~(Op2KnownBits.Zero | Op2KnownBits.One);
- // Determine if we have a value with 1 unknown bit
- if (Op1UnknownBits.isPowerOf2() && !Op2UnknownBits.isPowerOf2()) {
- // Fine, we'll handle the case
- } else if (Op1UnknownBits.isPowerOf2() && !Op2UnknownBits.isPowerOf2()) {
- // Switch the values
- auto *Tmp = Op1;
- Op1 = Op2;
- Op2 = Tmp;
- } else {
- // Stop the optimization
- continue;
- }
- // Get the 2 possible constant values
- auto *Const1 = llvm::ConstantInt::get(Op1Ty, Op1KnownBits.getMinValue());
- auto *Const2 = llvm::ConstantInt::get(Op1Ty, Op1KnownBits.getMaxValue());
- // Generate the 2 possible indexes
- auto *Index1 = llvm::BinaryOperator::Create(
- llvm::Instruction::BinaryOps::Add, Op2, Const1, "", Load);
- auto *Index2 = llvm::BinaryOperator::Create(
- llvm::Instruction::BinaryOps::Add, Op2, Const2, "", Load);
- // Generate the 2 possible 'getelementptr' instructions
- llvm::ArrayRef<llvm::Value *> Indexes1{Index1};
- auto *GEP1 = llvm::GetElementPtrInst::CreateInBounds(
- GEP->getPointerOperand(), Indexes1, "", Load);
- llvm::ArrayRef<llvm::Value *> Indexes2{Index2};
- auto *GEP2 = llvm::GetElementPtrInst::CreateInBounds(
- GEP->getPointerOperand(), Indexes2, "", Load);
- // Generate the 2 possible 'bitcast' instructions
- auto *BC1 = new llvm::BitCastInst(GEP1, BitCast->getType(), "", Load);
- auto *BC2 = new llvm::BitCastInst(GEP2, BitCast->getType(), "", Load);
- // Generate the 2 possible 'load' instructions
- auto *L1 = new llvm::LoadInst(BC1, "", Load);
- auto *L2 = new llvm::LoadInst(BC2, "", Load);
- // Generate a new 'icmp' instruction
- auto *ICmp =
- llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::ICmpInst::ICMP_EQ,
- Op1, Const1, "", Load);
- // Generate a new 'select' instruction
- auto *Select = llvm::SelectInst::Create(ICmp, L1, L2, "", Load);
- // Replace the original 'getelementptr'
- Load->replaceAllUsesWith(Select);
- }
- }
- }
- }
- }
- }
- }
- }
- // Optimize again to guarantee the propagation
- lifter.OptimizeFunction(finalFn, g);
Add Comment
Please, Sign In to add comment