bool CallAnalyzer::visitICmp(ICmpInst &I) { Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); // First try to handle simplified comparisons. if (!isa<Constant>(LHS)) if (Constant *SimpleLHS = SimplifiedValues.lookup(LHS)) LHS = SimpleLHS; if (!isa<Constant>(RHS)) if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS)) RHS = SimpleRHS; if (Constant *CLHS = dyn_cast<Constant>(LHS)) if (Constant *CRHS = dyn_cast<Constant>(RHS)) if (Constant *C = ConstantExpr::getICmp(I.getPredicate(), CLHS, CRHS)) { SimplifiedValues[&I] = C; return true; } // Otherwise look for a comparison between constant offset pointers with // a common base. Value *LHSBase, *RHSBase; APInt LHSOffset, RHSOffset; llvm::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS); if (LHSBase) { llvm::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS); if (RHSBase && LHSBase == RHSBase) { // We have common bases, fold the icmp to a constant based on the // offsets. Constant *CLHS = ConstantInt::get(LHS->getContext(), LHSOffset); Constant *CRHS = ConstantInt::get(RHS->getContext(), RHSOffset); if (Constant *C = ConstantExpr::getICmp(I.getPredicate(), CLHS, CRHS)) { SimplifiedValues[&I] = C; ++NumConstantPtrCmps; return true; } } } // If the comparison is an equality comparison with null, we can simplify it // for any alloca-derived argument. if (I.isEquality() && isa<ConstantPointerNull>(I.getOperand(1))) if (isAllocaDerivedArg(I.getOperand(0))) { // We can actually predict the result of comparisons between an // alloca-derived value and null. Note that this fires regardless of // SROA firing. bool IsNotEqual = I.getPredicate() == CmpInst::ICMP_NE; SimplifiedValues[&I] = IsNotEqual ? ConstantInt::getTrue(I.getType()) : ConstantInt::getFalse(I.getType()); return true; } // Finally check for SROA candidates in comparisons. Value *SROAArg; DenseMap<Value *, int>::iterator CostIt; if (lookupSROAArgAndCost(I.getOperand(0), SROAArg, CostIt)) { if (isa<ConstantPointerNull>(I.getOperand(1))) { accumulateSROACost(CostIt, InlineConstants::InstrCost); return true; } disableSROA(CostIt); } return false; }
bool GambasPass::runOnFunction(Function &F){ IRBuilder<> Builder(F.getContext()); bool changed = false; for(Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { for(BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ){ ICmpInst* ICI = dyn_cast<ICmpInst>(I); CallInst* CI = dyn_cast<CallInst>(I++); if (ICI && ICI->hasMetadata() && ICI->getMetadata("unref_slt") && dyn_cast<LoadInst>(ICI->getOperand(0))){ ICI->replaceAllUsesWith(ConstantInt::get(ICI->getType(), false)); ICI->eraseFromParent(); changed = true; continue; } if (!CI) continue; Function* callee = CI->getCalledFunction(); if (callee == NULL || !callee->isDeclaration()) continue; StringRef name = callee->getName(); if (name == "JR_release_variant" || name == "JR_borrow_variant"){ ConstantInt* vtype_int = dyn_cast<ConstantInt>(CI->getArgOperand(0)); if (!vtype_int) continue; uint64_t vtype = vtype_int->getZExtValue(); if (TYPE_is_string(vtype) || TYPE_is_object(vtype)) continue; CI->eraseFromParent(); changed = true; } else if (name == FUNCTION_NAME(__finite)){ ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0)); if (!op) continue; int val = __finite(op->getValueAPF().convertToDouble()); Constant* res = ConstantInt::get(CI->getType(), val); CI->replaceAllUsesWith(res); CI->eraseFromParent(); changed = true; } else if (name == FUNCTION_NAME(__isnan)){ ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0)); if (!op) continue; int val = __isnan(op->getValueAPF().convertToDouble()); Constant* res = ConstantInt::get(CI->getType(), val); CI->replaceAllUsesWith(res); CI->eraseFromParent(); changed = true; } else if (name == FUNCTION_NAME(__isinf)){ ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0)); if (!op) continue; int val = __isinf(op->getValueAPF().convertToDouble()); Constant* res = ConstantInt::get(CI->getType(), val); CI->replaceAllUsesWith(res); CI->eraseFromParent(); changed = true; } } } return changed; }