bool llvm::isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, SDValue &Chain, const TargetLowering &TLI) { const Function *F = DAG.getMachineFunction().getFunction(); // Conservatively require the attributes of the call to match those of // the return. Ignore noalias because it doesn't affect the call sequence. Attributes CallerRetAttr = F->getAttributes().getRetAttributes(); if (CallerRetAttr & ~Attribute::NoAlias) return false; // It's not safe to eliminate the sign / zero extension of the return value. if (CallerRetAttr.hasZExtAttr() || CallerRetAttr.hasSExtAttr()) return false; // Check if the only use is a function return node. return TLI.isUsedByReturnOnly(Node, Chain); }
/// Test if the given instruction is in a position to be optimized /// with a tail-call. This roughly means that it's in a block with /// a return and there's nothing that needs to be scheduled /// between it and the return. /// /// This function only tests target-independent requirements. bool llvm::isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, const TargetLowering &TLI) { const Instruction *I = CS.getInstruction(); const BasicBlock *ExitBB = I->getParent(); const TerminatorInst *Term = ExitBB->getTerminator(); const ReturnInst *Ret = dyn_cast<ReturnInst>(Term); // The block must end in a return statement or unreachable. // // FIXME: Decline tailcall if it's not guaranteed and if the block ends in // an unreachable, for now. The way tailcall optimization is currently // implemented means it will add an epilogue followed by a jump. That is // not profitable. Also, if the callee is a special function (e.g. // longjmp on x86), it can end up causing miscompilation that has not // been fully understood. if (!Ret && (!TLI.getTargetMachine().Options.GuaranteedTailCallOpt || !isa<UnreachableInst>(Term))) return false; // If I will have a chain, make sure no other instruction that will have a // chain interposes between I and the return. if (I->mayHaveSideEffects() || I->mayReadFromMemory() || !isSafeToSpeculativelyExecute(I)) for (BasicBlock::const_iterator BBI = prior(prior(ExitBB->end())); ; --BBI) { if (&*BBI == I) break; // Debug info intrinsics do not get in the way of tail call optimization. if (isa<DbgInfoIntrinsic>(BBI)) continue; if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() || !isSafeToSpeculativelyExecute(BBI)) return false; } // If the block ends with a void return or unreachable, it doesn't matter // what the call's return type is. if (!Ret || Ret->getNumOperands() == 0) return true; // If the return value is undef, it doesn't matter what the call's // return type is. if (isa<UndefValue>(Ret->getOperand(0))) return true; // Conservatively require the attributes of the call to match those of // the return. Ignore noalias because it doesn't affect the call sequence. const Function *F = ExitBB->getParent(); Attributes CallerRetAttr = F->getAttributes().getRetAttributes(); if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) return false; // It's not safe to eliminate the sign / zero extension of the return value. if (CallerRetAttr.hasZExtAttr() || CallerRetAttr.hasSExtAttr()) return false; // Otherwise, make sure the unmodified return value of I is the return value. // We handle two cases: multiple return values + scalars. Value *RetVal = Ret->getOperand(0); if (!isa<InsertValueInst>(RetVal) || !isa<StructType>(RetVal->getType())) // Handle scalars first. return getNoopInput(Ret->getOperand(0), TLI) == I; // If this is an aggregate return, look through the insert/extract values and // see if each is transparent. for (unsigned i = 0, e =cast<StructType>(RetVal->getType())->getNumElements(); i != e; ++i) { const Value *InScalar = FindInsertedValue(RetVal, i); if (InScalar == 0) return false; InScalar = getNoopInput(InScalar, TLI); // If the scalar value being inserted is an extractvalue of the right index // from the call, then everything is good. const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(InScalar); if (EVI == 0 || EVI->getOperand(0) != I || EVI->getNumIndices() != 1 || EVI->getIndices()[0] != i) return false; } return true; }