diff options
author | Ed Schouten <ed@FreeBSD.org> | 2009-06-07 09:21:09 +0000 |
---|---|---|
committer | Ed Schouten <ed@FreeBSD.org> | 2009-06-07 09:21:09 +0000 |
commit | d2a7037439ec5d4f4d2b7a813a3f1a83e10756b1 (patch) | |
tree | 7faa7e6887831d68515763b37bd680e3d4a886ea | |
parent | f4fe016fa15f703fe9c1b932d1e81e2c718521db (diff) |
Notes
31 files changed, 613 insertions, 366 deletions
diff --git a/docs/GoldPlugin.html b/docs/GoldPlugin.html index 17a50aca6e99..b5148ab3312e 100644 --- a/docs/GoldPlugin.html +++ b/docs/GoldPlugin.html @@ -157,7 +157,7 @@ export AR="$PREFIX/bin/ar" export NM="$PREFIX/bin/nm" export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a export CFLAGS="-O4" - </pre> +</pre> </li> <li>Or you can just set your path: <pre class="doc_code"> @@ -166,7 +166,7 @@ export CC="llvm-gcc -use-gold-plugin" export CXX="llvm-g++ -use-gold-plugin" export RANLIB=/bin/true export CFLAGS="-O4" - </pre> +</pre> </li> <li>Configure & build the project as usual: <tt>./configure && make && make check</tt> </li> </ul> diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 88002cb77530..e3d429934cc7 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -227,9 +227,9 @@ namespace llvm { /// TargetData *TD; - /// UnknownValue - This SCEV is used to represent unknown trip counts and - /// things. - SCEVHandle UnknownValue; + /// CouldNotCompute - This SCEV is used to represent unknown trip + /// counts and things. + SCEVHandle CouldNotCompute; /// Scalars - This is a cache of the scalars we have analyzed so far. /// @@ -322,23 +322,23 @@ namespace llvm { /// a constant number of times (the condition evolves only from constants), /// try to evaluate a few iterations of the loop until we get the exit /// condition gets a value of ExitWhen (true or false). If we cannot - /// evaluate the trip count of the loop, return UnknownValue. + /// evaluate the trip count of the loop, return CouldNotCompute. SCEVHandle ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, bool ExitWhen); /// HowFarToZero - Return the number of times a backedge comparing the /// specified value to zero will execute. If not computable, return - /// UnknownValue. + /// CouldNotCompute. SCEVHandle HowFarToZero(const SCEV *V, const Loop *L); /// HowFarToNonZero - Return the number of times a backedge checking the /// specified value for nonzero will execute. If not computable, return - /// UnknownValue. + /// CouldNotCompute. SCEVHandle HowFarToNonZero(const SCEV *V, const Loop *L); /// HowManyLessThans - Return the number of times a backedge containing the /// specified less-than comparison will execute. If not computable, return - /// UnknownValue. isSigned specifies whether the less-than is signed. + /// CouldNotCompute. isSigned specifies whether the less-than is signed. BackedgeTakenInfo HowManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L, bool isSigned); diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h index dd6d908df410..fa951bf70d05 100644 --- a/include/llvm/DerivedTypes.h +++ b/include/llvm/DerivedTypes.h @@ -159,6 +159,10 @@ public: /// type. static bool isValidReturnType(const Type *RetTy); + /// isValidArgumentType - Return true if the specified type is valid as an + /// argument type. + static bool isValidArgumentType(const Type *ArgTy); + inline bool isVarArg() const { return isVarArgs; } inline const Type *getReturnType() const { return ContainedTys[0]; } @@ -232,6 +236,10 @@ public: /// an empty struct, pass NULL, NULL. static StructType *get(const Type *type, ...) END_WITH_NULL; + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + // Iterator access to the elements typedef Type::subtype_iterator element_iterator; element_iterator element_begin() const { return ContainedTys; } @@ -331,6 +339,10 @@ public: /// static ArrayType *get(const Type *ElementType, uint64_t NumElements); + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + inline uint64_t getNumElements() const { return NumElements; } // Implement the AbstractTypeUser interface. @@ -391,6 +403,10 @@ public: return VectorType::get(EltTy, VTy->getNumElements()); } + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + /// @brief Return the number of elements in the Vector type. inline unsigned getNumElements() const { return NumElements; } @@ -431,6 +447,10 @@ public: return PointerType::get(ElementType, 0); } + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + /// @brief Return the address space of the Pointer type. inline unsigned getAddressSpace() const { return AddressSpace; } diff --git a/include/llvm/Type.h b/include/llvm/Type.h index 5ce23ef4e4b7..c1732af09bdd 100644 --- a/include/llvm/Type.h +++ b/include/llvm/Type.h @@ -205,7 +205,7 @@ public: inline bool isAbstract() const { return Abstract; } /// canLosslesslyBitCastTo - Return true if this type could be converted - /// with a lossless BitCast to type 'Ty'. For example, uint to int. BitCasts + /// with a lossless BitCast to type 'Ty'. For example, i8* to i32*. BitCasts /// are valid for types of the same size only where no re-interpretation of /// the bits is done. /// @brief Determine if this type could be losslessly bitcast to Ty diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 03c5005989e7..fd97db8a9dc2 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -1771,7 +1771,7 @@ const Type *ScalarEvolution::getEffectiveSCEVType(const Type *Ty) const { } SCEVHandle ScalarEvolution::getCouldNotCompute() { - return UnknownValue; + return CouldNotCompute; } /// hasSCEV - Return true if the SCEV for this value has already been @@ -2395,7 +2395,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { BackedgeTakenCounts.insert(std::make_pair(L, getCouldNotCompute())); if (Pair.second) { BackedgeTakenInfo ItCount = ComputeBackedgeTakenCount(L); - if (ItCount.Exact != UnknownValue) { + if (ItCount.Exact != CouldNotCompute) { assert(ItCount.Exact->isLoopInvariant(L) && ItCount.Max->isLoopInvariant(L) && "Computed trip count isn't loop invariant for loop!"); @@ -2464,20 +2464,20 @@ ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) { // If the loop has a non-one exit block count, we can't analyze it. BasicBlock *ExitBlock = L->getExitBlock(); if (!ExitBlock) - return UnknownValue; + return CouldNotCompute; // Okay, there is one exit block. Try to find the condition that causes the // loop to be exited. BasicBlock *ExitingBlock = L->getExitingBlock(); if (!ExitingBlock) - return UnknownValue; // More than one block exiting! + return CouldNotCompute; // More than one block exiting! // Okay, we've computed the exiting block. See what condition causes us to // exit. // // FIXME: we should be able to handle switch instructions (with a single exit) BranchInst *ExitBr = dyn_cast<BranchInst>(ExitingBlock->getTerminator()); - if (ExitBr == 0) return UnknownValue; + if (ExitBr == 0) return CouldNotCompute; assert(ExitBr->isConditional() && "If unconditional, it can't be in loop!"); // At this point, we know we have a conditional branch that determines whether @@ -2493,7 +2493,7 @@ ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) { if (ExitBr->getSuccessor(0) != L->getHeader() && ExitBr->getSuccessor(1) != L->getHeader() && ExitBr->getParent() != L->getHeader()) - return UnknownValue; + return CouldNotCompute; ICmpInst *ExitCond = dyn_cast<ICmpInst>(ExitBr->getCondition()); @@ -2647,11 +2647,11 @@ SCEVHandle ScalarEvolution:: ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, Constant *RHS, const Loop *L, ICmpInst::Predicate predicate) { - if (LI->isVolatile()) return UnknownValue; + if (LI->isVolatile()) return CouldNotCompute; // Check to see if the loaded pointer is a getelementptr of a global. GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(LI->getOperand(0)); - if (!GEP) return UnknownValue; + if (!GEP) return CouldNotCompute; // Make sure that it is really a constant global we are gepping, with an // initializer, and make sure the first IDX is really 0. @@ -2659,7 +2659,7 @@ ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, Constant *RHS, if (!GV || !GV->isConstant() || !GV->hasInitializer() || GEP->getNumOperands() < 3 || !isa<Constant>(GEP->getOperand(1)) || !cast<Constant>(GEP->getOperand(1))->isNullValue()) - return UnknownValue; + return CouldNotCompute; // Okay, we allow one non-constant index into the GEP instruction. Value *VarIdx = 0; @@ -2669,7 +2669,7 @@ ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, Constant *RHS, if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(i))) { Indexes.push_back(CI); } else if (!isa<ConstantInt>(GEP->getOperand(i))) { - if (VarIdx) return UnknownValue; // Multiple non-constant idx's. + if (VarIdx) return CouldNotCompute; // Multiple non-constant idx's. VarIdx = GEP->getOperand(i); VarIdxNum = i-2; Indexes.push_back(0); @@ -2686,7 +2686,7 @@ ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, Constant *RHS, if (!IdxExpr || !IdxExpr->isAffine() || IdxExpr->isLoopInvariant(L) || !isa<SCEVConstant>(IdxExpr->getOperand(0)) || !isa<SCEVConstant>(IdxExpr->getOperand(1))) - return UnknownValue; + return CouldNotCompute; unsigned MaxSteps = MaxBruteForceIterations; for (unsigned IterationNum = 0; IterationNum != MaxSteps; ++IterationNum) { @@ -2713,7 +2713,7 @@ ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, Constant *RHS, return getConstant(ItCst); // Found terminating iteration! } } - return UnknownValue; + return CouldNotCompute; } @@ -2852,11 +2852,11 @@ getConstantEvolutionLoopExitValue(PHINode *PN, const APInt& BEs, const Loop *L){ /// constant number of times (the condition evolves only from constants), /// try to evaluate a few iterations of the loop until we get the exit /// condition gets a value of ExitWhen (true or false). If we cannot -/// evaluate the trip count of the loop, return UnknownValue. +/// evaluate the trip count of the loop, return CouldNotCompute. SCEVHandle ScalarEvolution:: ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, bool ExitWhen) { PHINode *PN = getConstantEvolvingPHI(Cond, L); - if (PN == 0) return UnknownValue; + if (PN == 0) return CouldNotCompute; // Since the loop is canonicalized, the PHI node must have two entries. One // entry must be a constant (coming in from outside of the loop), and the @@ -2864,11 +2864,11 @@ ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, bool ExitWhen) bool SecondIsBackedge = L->contains(PN->getIncomingBlock(1)); Constant *StartCST = dyn_cast<Constant>(PN->getIncomingValue(!SecondIsBackedge)); - if (StartCST == 0) return UnknownValue; // Must be a constant. + if (StartCST == 0) return CouldNotCompute; // Must be a constant. Value *BEValue = PN->getIncomingValue(SecondIsBackedge); PHINode *PN2 = getConstantEvolvingPHI(BEValue, L); - if (PN2 != PN) return UnknownValue; // Not derived from same PHI. + if (PN2 != PN) return CouldNotCompute; // Not derived from same PHI. // Okay, we find a PHI node that defines the trip count of this loop. Execute // the loop symbolically to determine when the condition gets a value of @@ -2881,7 +2881,7 @@ ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, bool ExitWhen) dyn_cast_or_null<ConstantInt>(EvaluateExpression(Cond, PHIVal)); // Couldn't symbolically evaluate. - if (!CondVal) return UnknownValue; + if (!CondVal) return CouldNotCompute; if (CondVal->getValue() == uint64_t(ExitWhen)) { ConstantEvolutionLoopExitValue[PN] = PHIVal; @@ -2892,12 +2892,12 @@ ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, bool ExitWhen) // Compute the value of the PHI node for the next iteration. Constant *NextPHI = EvaluateExpression(BEValue, PHIVal); if (NextPHI == 0 || NextPHI == PHIVal) - return UnknownValue; // Couldn't evaluate or not making progress... + return CouldNotCompute; // Couldn't evaluate or not making progress... PHIVal = NextPHI; } // Too many iterations were needed to evaluate. - return UnknownValue; + return CouldNotCompute; } /// getSCEVAtScope - Return a SCEV expression handle for the specified value @@ -3052,7 +3052,7 @@ SCEVHandle ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) { // To evaluate this recurrence, we need to know how many times the AddRec // loop iterates. Compute this now. SCEVHandle BackedgeTakenCount = getBackedgeTakenCount(AddRec->getLoop()); - if (BackedgeTakenCount == UnknownValue) return AddRec; + if (BackedgeTakenCount == CouldNotCompute) return AddRec; // Then, evaluate the AddRec. return AddRec->evaluateAtIteration(BackedgeTakenCount, *this); @@ -3201,18 +3201,18 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) { } /// HowFarToZero - Return the number of times a backedge comparing the specified -/// value to zero will execute. If not computable, return UnknownValue. +/// value to zero will execute. If not computable, return CouldNotCompute. SCEVHandle ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { // If the value is a constant if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) { // If the value is already zero, the branch will execute zero times. if (C->getValue()->isZero()) return C; - return UnknownValue; // Otherwise it will loop infinitely. + return CouldNotCompute; // Otherwise it will loop infinitely. } const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(V); if (!AddRec || AddRec->getLoop() != L) - return UnknownValue; + return CouldNotCompute; if (AddRec->isAffine()) { // If this is an affine expression, the execution count of this branch is @@ -3274,12 +3274,12 @@ SCEVHandle ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { } } - return UnknownValue; + return CouldNotCompute; } /// HowFarToNonZero - Return the number of times a backedge checking the /// specified value for nonzero will execute. If not computable, return -/// UnknownValue +/// CouldNotCompute SCEVHandle ScalarEvolution::HowFarToNonZero(const SCEV *V, const Loop *L) { // Loops that look like: while (X == 0) are very strange indeed. We don't // handle them yet except for the trivial case. This could be expanded in the @@ -3290,12 +3290,12 @@ SCEVHandle ScalarEvolution::HowFarToNonZero(const SCEV *V, const Loop *L) { if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) { if (!C->getValue()->isNullValue()) return getIntegerSCEV(0, C->getType()); - return UnknownValue; // Otherwise it will loop infinitely. + return CouldNotCompute; // Otherwise it will loop infinitely. } // We could implement others, but I really doubt anyone writes loops like // this, and if they did, they would already be constant folded. - return UnknownValue; + return CouldNotCompute; } /// getLoopPredecessor - If the given loop's header has exactly one unique @@ -3446,16 +3446,16 @@ bool ScalarEvolution::isLoopGuardedByCond(const Loop *L, /// HowManyLessThans - Return the number of times a backedge containing the /// specified less-than comparison will execute. If not computable, return -/// UnknownValue. +/// CouldNotCompute. ScalarEvolution::BackedgeTakenInfo ScalarEvolution:: HowManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L, bool isSigned) { // Only handle: "ADDREC < LoopInvariant". - if (!RHS->isLoopInvariant(L)) return UnknownValue; + if (!RHS->isLoopInvariant(L)) return CouldNotCompute; const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(LHS); if (!AddRec || AddRec->getLoop() != L) - return UnknownValue; + return CouldNotCompute; if (AddRec->isAffine()) { // FORNOW: We only support unit strides. @@ -3466,7 +3466,7 @@ HowManyLessThans(const SCEV *LHS, const SCEV *RHS, // TODO: handle non-constant strides. const SCEVConstant *CStep = dyn_cast<SCEVConstant>(Step); if (!CStep || CStep->isZero()) - return UnknownValue; + return CouldNotCompute; if (CStep->isOne()) { // With unit stride, the iteration never steps past the limit value. } else if (CStep->getValue()->getValue().isStrictlyPositive()) { @@ -3477,19 +3477,19 @@ HowManyLessThans(const SCEV *LHS, const SCEV *RHS, APInt Max = APInt::getSignedMaxValue(BitWidth); if ((Max - CStep->getValue()->getValue()) .slt(CLimit->getValue()->getValue())) - return UnknownValue; + return CouldNotCompute; } else { APInt Max = APInt::getMaxValue(BitWidth); if ((Max - CStep->getValue()->getValue()) .ult(CLimit->getValue()->getValue())) - return UnknownValue; + return CouldNotCompute; } } else // TODO: handle non-constant limit values below. - return UnknownValue; + return CouldNotCompute; } else // TODO: handle negative strides below. - return UnknownValue; + return CouldNotCompute; // We know the LHS is of the form {n,+,s} and the RHS is some loop-invariant // m. So, we count the number of iterations in which {n,+,s} < m is true. @@ -3536,7 +3536,7 @@ HowManyLessThans(const SCEV *LHS, const SCEV *RHS, return BackedgeTakenInfo(BECount, MaxBECount); } - return UnknownValue; + return CouldNotCompute; } /// getNumIterationsInRange - Return the number of iterations of this loop that @@ -3724,7 +3724,7 @@ ScalarEvolution::SCEVCallbackVH::SCEVCallbackVH(Value *V, ScalarEvolution *se) //===----------------------------------------------------------------------===// ScalarEvolution::ScalarEvolution() - : FunctionPass(&ID), UnknownValue(new SCEVCouldNotCompute()) { + : FunctionPass(&ID), CouldNotCompute(new SCEVCouldNotCompute()) { } bool ScalarEvolution::runOnFunction(Function &F) { diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 5c4450244c18..4863f3c5116a 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -1043,6 +1043,8 @@ bool LLParser::ParseTypeRec(PATypeHolder &Result) { return TokError("basic block pointers are invalid"); if (Result.get() == Type::VoidTy) return TokError("pointers to void are invalid; use i8* instead"); + if (!PointerType::isValidElementType(Result.get())) + return TokError("pointer to this type is invalid"); Result = HandleUpRefs(PointerType::getUnqual(Result.get())); Lex.Lex(); break; @@ -1053,6 +1055,8 @@ bool LLParser::ParseTypeRec(PATypeHolder &Result) { return TokError("basic block pointers are invalid"); if (Result.get() == Type::VoidTy) return TokError("pointers to void are invalid; use i8* instead"); + if (!PointerType::isValidElementType(Result.get())) + return TokError("pointer to this type is invalid"); unsigned AddrSpace; if (ParseOptionalAddrSpace(AddrSpace) || ParseToken(lltok::star, "expected '*' in address space")) @@ -1149,7 +1153,7 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList, Lex.Lex(); } - if (!ArgTy->isFirstClassType() && !isa<OpaqueType>(ArgTy)) + if (!FunctionType::isValidArgumentType(ArgTy)) return Error(TypeLoc, "invalid type for function argument"); ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name)); @@ -1245,6 +1249,8 @@ bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) { if (Result == Type::VoidTy) return Error(EltTyLoc, "struct element can not have void type"); + if (!StructType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for struct"); while (EatIfPresent(lltok::comma)) { EltTyLoc = Lex.getLoc(); @@ -1252,6 +1258,8 @@ bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) { if (Result == Type::VoidTy) return Error(EltTyLoc, "struct element can not have void type"); + if (!StructType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for struct"); ParamsList.push_back(Result); } @@ -1299,11 +1307,11 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) { return Error(SizeLoc, "zero element vector is illegal"); if ((unsigned)Size != Size) return Error(SizeLoc, "size too large for vector"); - if (!EltTy->isFloatingPoint() && !EltTy->isInteger()) + if (!VectorType::isValidElementType(EltTy)) return Error(TypeLoc, "vector element type must be fp or integer"); Result = VectorType::get(EltTy, unsigned(Size)); } else { - if (!EltTy->isFirstClassType() && !isa<OpaqueType>(EltTy)) + if (!ArrayType::isValidElementType(EltTy)) return Error(TypeLoc, "invalid array element type"); Result = HandleUpRefs(ArrayType::get(EltTy, Size)); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 5ae183e2fa09..f3c2833e0fe3 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1785,48 +1785,41 @@ SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) { /// support the operation, but do support the resultant vector type. SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { unsigned NumElems = Node->getNumOperands(); - SDValue SplatValue = Node->getOperand(0); + SDValue Value1, Value2; DebugLoc dl = Node->getDebugLoc(); MVT VT = Node->getValueType(0); - MVT OpVT = SplatValue.getValueType(); + MVT OpVT = Node->getOperand(0).getValueType(); MVT EltVT = VT.getVectorElementType(); // If the only non-undef value is the low element, turn this into a // SCALAR_TO_VECTOR node. If this is { X, X, X, X }, determine X. bool isOnlyLowElement = true; - - // FIXME: it would be far nicer to change this into map<SDValue,uint64_t> - // and use a bitmask instead of a list of elements. - // FIXME: this doesn't treat <0, u, 0, u> for example, as a splat. - std::map<SDValue, std::vector<unsigned> > Values; - Values[SplatValue].push_back(0); + bool MoreThanTwoValues = false; bool isConstant = true; - if (!isa<ConstantFPSDNode>(SplatValue) && !isa<ConstantSDNode>(SplatValue) && - SplatValue.getOpcode() != ISD::UNDEF) - isConstant = false; - - for (unsigned i = 1; i < NumElems; ++i) { + for (unsigned i = 0; i < NumElems; ++i) { SDValue V = Node->getOperand(i); - Values[V].push_back(i); - if (V.getOpcode() != ISD::UNDEF) + if (V.getOpcode() == ISD::UNDEF) + continue; + if (i > 0) isOnlyLowElement = false; - if (SplatValue != V) - SplatValue = SDValue(0, 0); - - // If this isn't a constant element or an undef, we can't use a constant - // pool load. - if (!isa<ConstantFPSDNode>(V) && !isa<ConstantSDNode>(V) && - V.getOpcode() != ISD::UNDEF) + if (!isa<ConstantFPSDNode>(V) && !isa<ConstantSDNode>(V)) isConstant = false; + + if (!Value1.getNode()) { + Value1 = V; + } else if (!Value2.getNode()) { + if (V != Value1) + Value2 = V; + } else if (V != Value1 && V != Value2) { + MoreThanTwoValues = true; + } } - if (isOnlyLowElement) { - // If the low element is an undef too, then this whole things is an undef. - if (Node->getOperand(0).getOpcode() == ISD::UNDEF) - return DAG.getUNDEF(VT); - // Otherwise, turn this into a scalar_to_vector node. + if (!Value1.getNode()) + return DAG.getUNDEF(VT); + + if (isOnlyLowElement) return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Node->getOperand(0)); - } // If all elements are constants, create a load from the constant pool. if (isConstant) { @@ -1852,59 +1845,25 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { false, Alignment); } - if (SplatValue.getNode()) { // Splat of one value? - // Build the shuffle constant vector: <0, 0, 0, 0> - SmallVector<int, 8> ZeroVec(NumElems, 0); - - // If the target supports VECTOR_SHUFFLE and this shuffle mask, use it. - if (TLI.isShuffleMaskLegal(ZeroVec, Node->getValueType(0))) { + if (!MoreThanTwoValues) { + SmallVector<int, 8> ShuffleVec(NumElems, -1); + for (unsigned i = 0; i < NumElems; ++i) { + SDValue V = Node->getOperand(i); + if (V.getOpcode() == ISD::UNDEF) + continue; + ShuffleVec[i] = V == Value1 ? 0 : NumElems; + } + if (TLI.isShuffleMaskLegal(ShuffleVec, Node->getValueType(0))) { // Get the splatted value into the low element of a vector register. - SDValue LowValVec = - DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, SplatValue); + SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Value1); + SDValue Vec2; + if (Value2.getNode()) + Vec2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Value2); + else + Vec2 = DAG.getUNDEF(VT); // Return shuffle(LowValVec, undef, <0,0,0,0>) - return DAG.getVectorShuffle(VT, dl, LowValVec, DAG.getUNDEF(VT), - &ZeroVec[0]); - } - } - - // If there are only two unique elements, we may be able to turn this into a - // vector shuffle. - if (Values.size() == 2) { - // Get the two values in deterministic order. - SDValue Val1 = Node->getOperand(1); - SDValue Val2; - std::map<SDValue, std::vector<unsigned> >::iterator MI = Values.begin(); - if (MI->first != Val1) - Val2 = MI->first; - else - Val2 = (++MI)->first; - - // If Val1 is an undef, make sure it ends up as Val2, to ensure that our - // vector shuffle has the undef vector on the RHS. - if (Val1.getOpcode() == ISD::UNDEF) - std::swap(Val1, Val2); - - // Build the shuffle constant vector: e.g. <0, 4, 0, 4> - SmallVector<int, 8> ShuffleMask(NumElems, -1); - - // Set elements of the shuffle mask for Val1. - std::vector<unsigned> &Val1Elts = Values[Val1]; - for (unsigned i = 0, e = Val1Elts.size(); i != e; ++i) - ShuffleMask[Val1Elts[i]] = 0; - - // Set elements of the shuffle mask for Val2. - std::vector<unsigned> &Val2Elts = Values[Val2]; - for (unsigned i = 0, e = Val2Elts.size(); i != e; ++i) - if (Val2.getOpcode() != ISD::UNDEF) - ShuffleMask[Val2Elts[i]] = NumElems; - - // If the target supports SCALAR_TO_VECTOR and this shuffle mask, use it. - if (TLI.isOperationLegalOrCustom(ISD::SCALAR_TO_VECTOR, VT) && - TLI.isShuffleMaskLegal(ShuffleMask, VT)) { - Val1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Val1); - Val2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Val2); - return DAG.getVectorShuffle(VT, dl, Val1, Val2, &ShuffleMask[0]); + return DAG.getVectorShuffle(VT, dl, Vec1, Vec2, ShuffleVec.data()); } } diff --git a/lib/Target/PowerPC/PPCInstrAltivec.td b/lib/Target/PowerPC/PPCInstrAltivec.td index 9a5be79e816f..3f4d3296bdd0 100644 --- a/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/lib/Target/PowerPC/PPCInstrAltivec.td @@ -666,3 +666,25 @@ def : Pat<(int_ppc_altivec_vnmsubfp VRRC:$A, VRRC:$B, VRRC:$C), def : Pat<(PPCvperm (v16i8 VRRC:$vA), VRRC:$vB, VRRC:$vC), (VPERM VRRC:$vA, VRRC:$vB, VRRC:$vC)>; + +// Vector shifts +def : Pat<(v16i8 (shl (v16i8 VRRC:$vA), (v16i8 VRRC:$vB))), + (v16i8 (VSLB VRRC:$vA, VRRC:$vB))>; +def : Pat<(v8i16 (shl (v8i16 VRRC:$vA), (v8i16 VRRC:$vB))), + (v8i16 (VSLH VRRC:$vA, VRRC:$vB))>; +def : Pat<(v4i32 (shl (v4i32 VRRC:$vA), (v4i32 VRRC:$vB))), + (v4i32 (VSLW VRRC:$vA, VRRC:$vB))>; + +def : Pat<(v16i8 (srl (v16i8 VRRC:$vA), (v16i8 VRRC:$vB))), + (v16i8 (VSRB VRRC:$vA, VRRC:$vB))>; +def : Pat<(v8i16 (srl (v8i16 VRRC:$vA), (v8i16 VRRC:$vB))), + (v8i16 (VSRH VRRC:$vA, VRRC:$vB))>; +def : Pat<(v4i32 (srl (v4i32 VRRC:$vA), (v4i32 VRRC:$vB))), + (v4i32 (VSRW VRRC:$vA, VRRC:$vB))>; + +def : Pat<(v16i8 (sra (v16i8 VRRC:$vA), (v16i8 VRRC:$vB))), + (v16i8 (VSRAB VRRC:$vA, VRRC:$vB))>; +def : Pat<(v8i16 (sra (v8i16 VRRC:$vA), (v8i16 VRRC:$vB))), + (v8i16 (VSRAH VRRC:$vA, VRRC:$vB))>; +def : Pat<(v4i32 (sra (v4i32 VRRC:$vA), (v4i32 VRRC:$vB))), + (v4i32 (VSRAW VRRC:$vA, VRRC:$vB))>; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index ef60ff5e0927..9e15a543bced 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -7691,13 +7691,15 @@ static bool isBaseAlignmentOfN(unsigned N, SDNode *Base, } static bool EltsFromConsecutiveLoads(ShuffleVectorSDNode *N, unsigned NumElems, - MVT EVT, SDNode *&Base, + MVT EVT, LoadSDNode *&LDBase, + unsigned &LastLoadedElt, SelectionDAG &DAG, MachineFrameInfo *MFI, const TargetLowering &TLI) { - Base = NULL; + LDBase = NULL; + LastLoadedElt = -1; for (unsigned i = 0; i < NumElems; ++i) { if (N->getMaskElt(i) < 0) { - if (!Base) + if (!LDBase) return false; continue; } @@ -7706,19 +7708,20 @@ static bool EltsFromConsecutiveLoads(ShuffleVectorSDNode *N, unsigned NumElems, if (!Elt.getNode() || (Elt.getOpcode() != ISD::UNDEF && !ISD::isNON_EXTLoad(Elt.getNode()))) return false; - if (!Base) { - Base = Elt.getNode(); - if (Base->getOpcode() == ISD::UNDEF) + if (!LDBase) { + if (Elt.getNode()->getOpcode() == ISD::UNDEF) return false; + LDBase = cast<LoadSDNode>(Elt.getNode()); + LastLoadedElt = i; continue; } if (Elt.getOpcode() == ISD::UNDEF) continue; LoadSDNode *LD = cast<LoadSDNode>(Elt); - LoadSDNode *LDBase = cast<LoadSDNode>(Base); if (!TLI.isConsecutiveLoad(LD, LDBase, EVT.getSizeInBits()/8, i, MFI)) return false; + LastLoadedElt = i; } return true; } @@ -7737,134 +7740,29 @@ static SDValue PerformShuffleCombine(SDNode *N, SelectionDAG &DAG, ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(N); unsigned NumElems = VT.getVectorNumElements(); - // For x86-32 machines, if we see an insert and then a shuffle in a v2i64 - // where the upper half is 0, it is advantageous to rewrite it as a build - // vector of (0, val) so it can use movq. - if (VT == MVT::v2i64) { - SDValue In[2]; - In[0] = N->getOperand(0); - In[1] = N->getOperand(1); - int Idx0 = SVN->getMaskElt(0); - int Idx1 = SVN->getMaskElt(1); - // FIXME: can we take advantage of undef index? - if (Idx0 >= 0 && Idx1 >= 0 && - In[Idx0/2].getOpcode() == ISD::INSERT_VECTOR_ELT && - In[Idx1/2].getOpcode() == ISD::BUILD_VECTOR) { - ConstantSDNode* InsertVecIdx = - dyn_cast<ConstantSDNode>(In[Idx0/2].getOperand(2)); - if (InsertVecIdx && - InsertVecIdx->getZExtValue() == (unsigned)(Idx0 % 2) && - isZeroNode(In[Idx1/2].getOperand(Idx1 % 2))) { - return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, - In[Idx0/2].getOperand(1), - In[Idx1/2].getOperand(Idx1 % 2)); - } - } - } + if (VT.getSizeInBits() != 128) + return SDValue(); // Try to combine a vector_shuffle into a 128-bit load. MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); - SDNode *Base = NULL; - if (!EltsFromConsecutiveLoads(SVN, NumElems, EVT, Base, DAG, MFI, TLI)) + LoadSDNode *LD = NULL; + unsigned LastLoadedElt; + if (!EltsFromConsecutiveLoads(SVN, NumElems, EVT, LD, LastLoadedElt, DAG, + MFI, TLI)) return SDValue(); - LoadSDNode *LD = cast<LoadSDNode>(Base); - if (isBaseAlignmentOfN(16, Base->getOperand(1).getNode(), TLI)) + if (LastLoadedElt == NumElems - 1) { + if (isBaseAlignmentOfN(16, LD->getBasePtr().getNode(), TLI)) + return DAG.getLoad(VT, dl, LD->getChain(), LD->getBasePtr(), + LD->getSrcValue(), LD->getSrcValueOffset(), + LD->isVolatile()); return DAG.getLoad(VT, dl, LD->getChain(), LD->getBasePtr(), LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile()); - return DAG.getLoad(VT, dl, LD->getChain(), LD->getBasePtr(), - LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), LD->getAlignment()); -} - -/// PerformBuildVectorCombine - build_vector 0,(load i64 / f64) -> movq / movsd. -static SDValue PerformBuildVectorCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const X86Subtarget *Subtarget, - const TargetLowering &TLI) { - unsigned NumOps = N->getNumOperands(); - DebugLoc dl = N->getDebugLoc(); - - // Ignore single operand BUILD_VECTOR. - if (NumOps == 1) - return SDValue(); - - MVT VT = N->getValueType(0); - MVT EVT = VT.getVectorElementType(); - - // Before or during type legalization, we want to try and convert a - // build_vector of an i64 load and a zero value into vzext_movl before the - // legalizer can break it up. - // FIXME: does the case below remove the need to do this? - if (DCI.isBeforeLegalize() || DCI.isCalledByLegalizer()) { - if ((EVT != MVT::i64 && EVT != MVT::f64) || Subtarget->is64Bit()) - return SDValue(); - - // This must be an insertion into a zero vector. - SDValue HighElt = N->getOperand(1); - if (!isZeroNode(HighElt)) - return SDValue(); - - // Value must be a load. - SDNode *Base = N->getOperand(0).getNode(); - if (!isa<LoadSDNode>(Base)) { - if (Base->getOpcode() != ISD::BIT_CONVERT) - return SDValue(); - Base = Base->getOperand(0).getNode(); - if (!isa<LoadSDNode>(Base)) - return SDValue(); - } - - // Transform it into VZEXT_LOAD addr. - LoadSDNode *LD = cast<LoadSDNode>(Base); - - // Load must not be an extload. - if (LD->getExtensionType() != ISD::NON_EXTLOAD) - return SDValue(); - - // Load type should legal type so we don't have to legalize it. - if (!TLI.isTypeLegal(VT)) - return SDValue(); - - SDVTList Tys = DAG.getVTList(VT, MVT::Other); - SDValue Ops[] = { LD->getChain(), LD->getBasePtr() }; - SDValue ResNode = DAG.getNode(X86ISD::VZEXT_LOAD, dl, Tys, Ops, 2); - TargetLowering::TargetLoweringOpt TLO(DAG); - TLO.CombineTo(SDValue(Base, 1), ResNode.getValue(1)); - DCI.CommitTargetLoweringOpt(TLO); - return ResNode; - } - - // The type legalizer will have broken apart v2i64 build_vector created during - // widening before the code which handles that case is run. Look for build - // vector (load, load + 4, 0/undef, 0/undef) - if (VT == MVT::v4i32 || VT == MVT::v4f32) { - LoadSDNode *LD0 = dyn_cast<LoadSDNode>(N->getOperand(0)); - LoadSDNode *LD1 = dyn_cast<LoadSDNode>(N->getOperand(1)); - if (!LD0 || !LD1) - return SDValue(); - if (LD0->getExtensionType() != ISD::NON_EXTLOAD || - LD1->getExtensionType() != ISD::NON_EXTLOAD) - return SDValue(); - // Make sure the second elt is a consecutive load. - if (!TLI.isConsecutiveLoad(LD1, LD0, EVT.getSizeInBits()/8, 1, - DAG.getMachineFunction().getFrameInfo())) - return SDValue(); - - SDValue N2 = N->getOperand(2); - SDValue N3 = N->getOperand(3); - if (!isZeroNode(N2) && N2.getOpcode() != ISD::UNDEF) - return SDValue(); - if (!isZeroNode(N3) && N3.getOpcode() != ISD::UNDEF) - return SDValue(); - + LD->isVolatile(), LD->getAlignment()); + } else if (NumElems == 4 && LastLoadedElt == 1) { SDVTList Tys = DAG.getVTList(MVT::v2i64, MVT::Other); - SDValue Ops[] = { LD0->getChain(), LD0->getBasePtr() }; + SDValue Ops[] = { LD->getChain(), LD->getBasePtr() }; SDValue ResNode = DAG.getNode(X86ISD::VZEXT_LOAD, dl, Tys, Ops, 2); - TargetLowering::TargetLoweringOpt TLO(DAG); - TLO.CombineTo(SDValue(LD0, 1), ResNode.getValue(1)); - DCI.CommitTargetLoweringOpt(TLO); return DAG.getNode(ISD::BIT_CONVERT, dl, VT, ResNode); } return SDValue(); @@ -8466,14 +8364,25 @@ static SDValue PerformBTCombine(SDNode *N, return SDValue(); } +static SDValue PerformVZEXT_MOVLCombine(SDNode *N, SelectionDAG &DAG) { + SDValue Op = N->getOperand(0); + if (Op.getOpcode() == ISD::BIT_CONVERT) + Op = Op.getOperand(0); + MVT VT = N->getValueType(0), OpVT = Op.getValueType(); + if (Op.getOpcode() == X86ISD::VZEXT_LOAD && + VT.getVectorElementType().getSizeInBits() == + OpVT.getVectorElementType().getSizeInBits()) { + return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), VT, Op); + } + return SDValue(); +} + SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; switch (N->getOpcode()) { default: break; case ISD::VECTOR_SHUFFLE: return PerformShuffleCombine(N, DAG, *this); - case ISD::BUILD_VECTOR: - return PerformBuildVectorCombine(N, DAG, DCI, Subtarget, *this); case ISD::SELECT: return PerformSELECTCombine(N, DAG, Subtarget); case X86ISD::CMOV: return PerformCMOVCombine(N, DAG, DCI); case ISD::MUL: return PerformMulCombine(N, DAG, DCI); @@ -8485,6 +8394,7 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, case X86ISD::FOR: return PerformFORCombine(N, DAG); case X86ISD::FAND: return PerformFANDCombine(N, DAG); case X86ISD::BT: return PerformBTCombine(N, DAG, DCI); + case X86ISD::VZEXT_MOVL: return PerformVZEXT_MOVLCombine(N, DAG); } return SDValue(); diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 2c01cc30bd69..5f12825f043a 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -932,8 +932,7 @@ static bool ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Instruction *V, GlobalVariable *GV, SmallPtrSet<PHINode*, 8> &PHIs) { for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ - Instruction *Inst = dyn_cast<Instruction>(*UI); - if (Inst == 0) return false; + Instruction *Inst = cast<Instruction>(*UI); if (isa<LoadInst>(Inst) || isa<CmpInst>(Inst)) { continue; // Fine, ignore. diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp index 2dc855824691..e4a9deadd971 100644 --- a/lib/Transforms/IPO/IPConstantPropagation.cpp +++ b/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -241,15 +241,11 @@ bool IPCP::PropagateConstantReturn(Function &F) { for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); I != E;) { - Instruction *Ins = dyn_cast<Instruction>(*I); + Instruction *Ins = cast<Instruction>(*I); // Increment now, so we can remove the use ++I; - // Not an instruction? Ignore - if (!Ins) - continue; - // Find the index of the retval to replace with int index = -1; if (ExtractValueInst *EV = dyn_cast<ExtractValueInst>(Ins)) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 97bd34c771c2..6d2ff0e3e53c 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -12579,6 +12579,12 @@ Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) { } } + unsigned VWidth = cast<VectorType>(VecOp->getType())->getNumElements(); + APInt UndefElts(VWidth, 0); + APInt AllOnesEltMask(APInt::getAllOnesValue(VWidth)); + if (SimplifyDemandedVectorElts(&IE, AllOnesEltMask, UndefElts)) + return &IE; + return 0; } diff --git a/lib/Transforms/Scalar/PredicateSimplifier.cpp b/lib/Transforms/Scalar/PredicateSimplifier.cpp index a7e4d6eec443..b9b5688dfdf2 100644 --- a/lib/Transforms/Scalar/PredicateSimplifier.cpp +++ b/lib/Transforms/Scalar/PredicateSimplifier.cpp @@ -1525,12 +1525,12 @@ namespace { Instruction *I2 = dyn_cast<Instruction>(R); if (I2 && below(I2)) { std::vector<Instruction *> ToNotify; - for (Value::use_iterator UI = R->use_begin(), UE = R->use_end(); + for (Value::use_iterator UI = I2->use_begin(), UE = I2->use_end(); UI != UE;) { Use &TheUse = UI.getUse(); ++UI; - if (Instruction *I = dyn_cast<Instruction>(TheUse.getUser())) - ToNotify.push_back(I); + Instruction *I = cast<Instruction>(TheUse.getUser()); + ToNotify.push_back(I); } DOUT << "Simply removing " << *I2 @@ -1658,10 +1658,9 @@ namespace { ++UI; Value *V = TheUse.getUser(); if (!V->use_empty()) { - if (Instruction *Inst = dyn_cast<Instruction>(V)) { - if (aboveOrBelow(Inst)) - opsToDef(Inst); - } + Instruction *Inst = cast<Instruction>(V); + if (aboveOrBelow(Inst)) + opsToDef(Inst); } } } @@ -2262,10 +2261,9 @@ namespace { UE = O.LHS->use_end(); UI != UE;) { Use &TheUse = UI.getUse(); ++UI; - if (Instruction *I = dyn_cast<Instruction>(TheUse.getUser())) { - if (aboveOrBelow(I)) - opsToDef(I); - } + Instruction *I = cast<Instruction>(TheUse.getUser()); + if (aboveOrBelow(I)) + opsToDef(I); } } if (Instruction *I2 = dyn_cast<Instruction>(O.RHS)) { @@ -2277,10 +2275,9 @@ namespace { UE = O.RHS->use_end(); UI != UE;) { Use &TheUse = UI.getUse(); ++UI; - if (Instruction *I = dyn_cast<Instruction>(TheUse.getUser())) { - if (aboveOrBelow(I)) - opsToDef(I); - } + Instruction *I = cast<Instruction>(TheUse.getUser()); + if (aboveOrBelow(I)) + opsToDef(I); } } } diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index d73519c04e35..3deee5477291 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -639,8 +639,8 @@ void SCCPSolver::visitReturnInst(ReturnInst &I) { DenseMap<std::pair<Function*, unsigned>, LatticeVal>::iterator It = TrackedMultipleRetVals.find(std::make_pair(F, i)); if (It == TrackedMultipleRetVals.end()) break; - Value *Val = FindInsertedValue(I.getOperand(0), i); - mergeInValue(It->second, F, getValueState(Val)); + if (Value *Val = FindInsertedValue(I.getOperand(0), i)) + mergeInValue(It->second, F, getValueState(Val)); } } } diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 9935f12f893b..7143c7be485e 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -1228,7 +1228,8 @@ void SROA::CleanupAllocaUsers(AllocationInst *AI) { User *U = *UI++; if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) CleanupGEP(GEPI); - else if (Instruction *I = dyn_cast<Instruction>(U)) { + else { + Instruction *I = cast<Instruction>(U); SmallVector<DbgInfoIntrinsic *, 2> DbgInUses; if (!isa<StoreInst>(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) { // Safe to remove debug info uses. diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 11b93ffda49f..a1e6c42f86fa 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -135,8 +135,8 @@ bool Type::isFPOrFPVector() const { return cast<VectorType>(this)->getElementType()->isFloatingPoint(); } -// canLosslesllyBitCastTo - Return true if this type can be converted to -// 'Ty' without any reinterpretation of bits. For example, uint to int. +// canLosslesslyBitCastTo - Return true if this type can be converted to +// 'Ty' without any reinterpretation of bits. For example, i8* to i32*. // bool Type::canLosslesslyBitCastTo(const Type *Ty) const { // Identity cast means no change so return true @@ -318,6 +318,17 @@ bool FunctionType::isValidReturnType(const Type *RetTy) { return true; } +/// isValidArgumentType - Return true if the specified type is valid as an +/// argument type. +bool FunctionType::isValidArgumentType(const Type *ArgTy) { + if ((!ArgTy->isFirstClassType() && !isa<OpaqueType>(ArgTy)) || + (isa<PointerType>(ArgTy) && + cast<PointerType>(ArgTy)->getElementType() == Type::MetadataTy)) + return false; + + return true; +} + FunctionType::FunctionType(const Type *Result, const std::vector<const Type*> &Params, bool IsVarArgs) @@ -331,11 +342,8 @@ FunctionType::FunctionType(const Type *Result, new (&ContainedTys[0]) PATypeHandle(Result, this); for (unsigned i = 0; i != Params.size(); ++i) { - assert((Params[i]->isFirstClassType() || isa<OpaqueType>(Params[i])) && - "Function arguments must be value types!"); - assert((!isa<PointerType>(Params[i]) || - cast<PointerType>(Params[i])->getElementType() != Type::MetadataTy) - && "Attempt to use metadata* as function argument type!"); + assert(isValidArgumentType(Params[i]) && + "Not a valid type for function argument!"); new (&ContainedTys[i+1]) PATypeHandle(Params[i], this); isAbstract |= Params[i]->isAbstract(); } @@ -352,12 +360,8 @@ StructType::StructType(const std::vector<const Type*> &Types, bool isPacked) bool isAbstract = false; for (unsigned i = 0; i < Types.size(); ++i) { assert(Types[i] && "<null> type for structure field!"); - assert(Types[i] != Type::VoidTy && "Void type for structure field!"); - assert(Types[i] != Type::LabelTy && "Label type for structure field!"); - assert(Types[i] != Type::MetadataTy && "Metadata type for structure field"); - assert((!isa<PointerType>(Types[i]) || - cast<PointerType>(Types[i])->getElementType() != Type::MetadataTy) - && "Type 'metadata*' is invalid for structure field."); + assert(isValidElementType(Types[i]) && + "Invalid type for structure element!"); new (&ContainedTys[i]) PATypeHandle(Types[i], this); isAbstract |= Types[i]->isAbstract(); } @@ -379,8 +383,7 @@ VectorType::VectorType(const Type *ElType, unsigned NumEl) NumElements = NumEl; setAbstract(ElType->isAbstract()); assert(NumEl > 0 && "NumEl of a VectorType must be greater than 0"); - assert((ElType->isInteger() || ElType->isFloatingPoint() || - isa<OpaqueType>(ElType)) && + assert(isValidElementType(ElType) && "Elements of a VectorType must be a primitive type"); } @@ -1051,12 +1054,7 @@ static ManagedStatic<TypeMap<ArrayValType, ArrayType> > ArrayTypes; ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { assert(ElementType && "Can't get array of <null> types!"); - assert(ElementType != Type::VoidTy && "Array of void is not valid!"); - assert(ElementType != Type::LabelTy && "Array of labels is not valid!"); - assert(ElementType != Type::MetadataTy && "Array of metadata is not valid!"); - assert((!isa<PointerType>(ElementType) || - cast<PointerType>(ElementType)->getElementType() != Type::MetadataTy) - && "Array of metadata* is not valid!"); + assert(isValidElementType(ElementType) && "Invalid type for array element!"); ArrayValType AVT(ElementType, NumElements); ArrayType *AT = ArrayTypes->get(AVT); @@ -1071,6 +1069,18 @@ ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { return AT; } +bool ArrayType::isValidElementType(const Type *ElemTy) { + if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy || + ElemTy == Type::MetadataTy) + return false; + + if (const PointerType *PTy = dyn_cast<PointerType>(ElemTy)) + if (PTy->getElementType() == Type::MetadataTy) + return false; + + return true; +} + //===----------------------------------------------------------------------===// // Vector Type Factory... @@ -1115,6 +1125,14 @@ VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { return PT; } +bool VectorType::isValidElementType(const Type *ElemTy) { + if (ElemTy->isInteger() || ElemTy->isFloatingPoint() || + isa<OpaqueType>(ElemTy)) + return true; + + return false; +} + //===----------------------------------------------------------------------===// // Struct Type Factory... // @@ -1181,6 +1199,17 @@ StructType *StructType::get(const Type *type, ...) { return llvm::StructType::get(StructFields); } +bool StructType::isValidElementType(const Type *ElemTy) { + if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy || + ElemTy == Type::MetadataTy) + return false; + + if (const PointerType *PTy = dyn_cast<PointerType>(ElemTy)) + if (PTy->getElementType() == Type::MetadataTy) + return false; + + return true; +} //===----------------------------------------------------------------------===// @@ -1217,10 +1246,7 @@ PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) { assert(ValueType && "Can't get a pointer to <null> type!"); assert(ValueType != Type::VoidTy && "Pointer to void is not valid, use i8* instead!"); - assert(ValueType != Type::LabelTy && "Pointer to label is not valid!"); - assert((!isa<PointerType>(ValueType) || - cast<PointerType>(ValueType)->getElementType() != Type::MetadataTy) - && "Pointer to metadata* is not valid!"); + assert(isValidElementType(ValueType) && "Invalid type for pointer element!"); PointerValType PVT(ValueType, AddressSpace); PointerType *PT = PointerTypes->get(PVT); @@ -1239,6 +1265,18 @@ PointerType *Type::getPointerTo(unsigned addrs) const { return PointerType::get(this, addrs); } +bool PointerType::isValidElementType(const Type *ElemTy) { + if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy) + return false; + + if (const PointerType *PTy = dyn_cast<PointerType>(ElemTy)) + if (PTy->getElementType() == Type::MetadataTy) + return false; + + return true; +} + + //===----------------------------------------------------------------------===// // Derived Type Refinement Functions //===----------------------------------------------------------------------===// diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index b047d0c9fb6d..b1297ff22562 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -280,7 +280,6 @@ namespace { bool isReturnValue, const Value *V); void VerifyFunctionAttrs(const FunctionType *FT, const AttrListPtr &Attrs, const Value *V); - bool VerifyMDNode(const MDNode *N); void WriteValue(const Value *V) { if (!V) return; @@ -380,24 +379,22 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { // Verify that any metadata used in a global initializer points only to // other globals. if (MDNode *FirstNode = dyn_cast<MDNode>(GV.getInitializer())) { - if (VerifyMDNode(FirstNode)) { - SmallVector<const MDNode *, 4> NodesToAnalyze; - NodesToAnalyze.push_back(FirstNode); - while (!NodesToAnalyze.empty()) { - const MDNode *N = NodesToAnalyze.back(); - NodesToAnalyze.pop_back(); - - for (MDNode::const_elem_iterator I = N->elem_begin(), - E = N->elem_end(); I != E; ++I) - if (const Value *V = *I) { - if (const MDNode *Next = dyn_cast<MDNode>(V)) - NodesToAnalyze.push_back(Next); - else - Assert3(isa<Constant>(V), - "reference to instruction from global metadata node", - &GV, N, V); - } - } + SmallVector<const MDNode *, 4> NodesToAnalyze; + NodesToAnalyze.push_back(FirstNode); + while (!NodesToAnalyze.empty()) { + const MDNode *N = NodesToAnalyze.back(); + NodesToAnalyze.pop_back(); + + for (MDNode::const_elem_iterator I = N->elem_begin(), + E = N->elem_end(); I != E; ++I) + if (const Value *V = *I) { + if (const MDNode *Next = dyn_cast<MDNode>(V)) + NodesToAnalyze.push_back(Next); + else + Assert3(isa<Constant>(V), + "reference to instruction from global metadata node", + &GV, N, V); + } } } } else { @@ -1708,44 +1705,6 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, "Intrinsic has wrong parameter attributes!", F); } -/// Verify that an MDNode is not cyclic. -bool Verifier::VerifyMDNode(const MDNode *N) { - if (N->elem_empty()) return true; - - // The current DFS path through the nodes. Node and element number. - typedef std::pair<const MDNode *, MDNode::const_elem_iterator> Edge; - SmallVector<Edge, 8> Path; - - Path.push_back(std::make_pair(N, N->elem_begin())); - while (!Path.empty()) { - Edge &e = Path.back(); - const MDNode *&e_N = e.first; - MDNode::const_elem_iterator &e_I = e.second; - - if (e_N->elem_end() == e_I) { - Path.pop_back(); - continue; - } - - for (MDNode::const_elem_iterator e_E = e_N->elem_end(); e_I != e_E; ++e_I) { - if (const MDNode *C = dyn_cast_or_null<MDNode>(e_I->operator Value*())) { - // Is child MDNode C already in the Path? - for (SmallVectorImpl<Edge>::iterator I = Path.begin(), E = Path.end(); - I != E; ++I) { - if (I->first != C) { - CheckFailed("MDNode is cyclic.", C); - return false; - } - } - - Path.push_back(std::make_pair(C, C->elem_begin())); - break; - } - } - } - return true; -} - //===----------------------------------------------------------------------===// // Implement the public interfaces to this file... diff --git a/test/CodeGen/PowerPC/vec_shift.ll b/test/CodeGen/PowerPC/vec_shift.ll new file mode 100644 index 000000000000..0cc699cee42c --- /dev/null +++ b/test/CodeGen/PowerPC/vec_shift.ll @@ -0,0 +1,10 @@ +; RUN: llvm-as < %s | llc -march=ppc32 -mcpu=g5 +; PR3628 + +define void @update(<4 x i32> %val, <4 x i32>* %dst) nounwind { +entry: + %shl = shl <4 x i32> %val, < i32 4, i32 3, i32 2, i32 1 > + %shr = ashr <4 x i32> %shl, < i32 1, i32 2, i32 3, i32 4 > + store <4 x i32> %shr, <4 x i32>* %dst + ret void +} diff --git a/test/CodeGen/X86/vec_loadsingles.ll b/test/CodeGen/X86/vec_loadsingles.ll new file mode 100644 index 000000000000..67122763ec9b --- /dev/null +++ b/test/CodeGen/X86/vec_loadsingles.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | grep movq + +define <4 x float> @a(<4 x float> %a, float* nocapture %p) nounwind readonly { +entry: + %tmp1 = load float* %p + %vecins = insertelement <4 x float> undef, float %tmp1, i32 0 + %add.ptr = getelementptr float* %p, i32 1 + %tmp5 = load float* %add.ptr + %vecins7 = insertelement <4 x float> %vecins, float %tmp5, i32 1 + ret <4 x float> %vecins7 +} + diff --git a/test/CodeGen/X86/vec_set-5.ll b/test/CodeGen/X86/vec_set-5.ll index 4fc652c022ae..d3329701119b 100644 --- a/test/CodeGen/X86/vec_set-5.ll +++ b/test/CodeGen/X86/vec_set-5.ll @@ -1,7 +1,6 @@ ; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -o %t -f ; RUN: grep movlhps %t | count 1 -; RUN: grep movq %t | count 1 -; RUN: grep movsd %t | count 1 +; RUN: grep movq %t | count 2 define <4 x float> @test1(float %a, float %b) nounwind { %tmp = insertelement <4 x float> zeroinitializer, float %a, i32 0 ; <<4 x float>> [#uses=1] diff --git a/test/CodeGen/X86/vec_set-6.ll b/test/CodeGen/X86/vec_set-6.ll index 02df526cee81..c7b6747a86f7 100644 --- a/test/CodeGen/X86/vec_set-6.ll +++ b/test/CodeGen/X86/vec_set-6.ll @@ -1,6 +1,6 @@ ; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -o %t -f ; RUN: grep movss %t | count 1 -; RUN: grep movups %t | count 1 +; RUN: grep movq %t | count 1 ; RUN: grep shufps %t | count 1 define <4 x float> @test(float %a, float %b, float %c) nounwind { diff --git a/test/Transforms/InstCombine/vec_demanded_elts-3.ll b/test/Transforms/InstCombine/vec_demanded_elts-3.ll new file mode 100644 index 000000000000..eba3629eb9e7 --- /dev/null +++ b/test/Transforms/InstCombine/vec_demanded_elts-3.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep load +; PR4340 + +define void @vac(<4 x float>* nocapture %a) nounwind { +entry: + %tmp1 = load <4 x float>* %a ; <<4 x float>> [#uses=1] + %vecins = insertelement <4 x float> %tmp1, float 0.000000e+00, i32 0 ; <<4 x float>> [#uses=1] + %vecins4 = insertelement <4 x float> %vecins, float 0.000000e+00, i32 1; <<4 x float>> [#uses=1] + %vecins6 = insertelement <4 x float> %vecins4, float 0.000000e+00, i32 2; <<4 x float>> [#uses=1] + %vecins8 = insertelement <4 x float> %vecins6, float 0.000000e+00, i32 3; <<4 x float>> [#uses=1] + store <4 x float> %vecins8, <4 x float>* %a + ret void +} + diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 86d3fd3b92c1..46b1717fca69 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -45,6 +45,7 @@ namespace { bool generate_api_file = false; const char *gcc_path = NULL; + const char *as_path = NULL; struct claimed_file { lto_module_t M; @@ -109,6 +110,13 @@ ld_plugin_status onload(ld_plugin_tv *tv) { } else { gcc_path = strdup(tv->tv_u.tv_string + 4); } + } else if (strncmp("as=", tv->tv_u.tv_string, 3) == 0) { + if (as_path) { + (*message)(LDPL_WARNING, "Path to as specified twice. " + "Discarding %s", tv->tv_u.tv_string); + } else { + as_path = strdup(tv->tv_u.tv_string + 3); + } } else { (*message)(LDPL_WARNING, "Ignoring flag %s", tv->tv_u.tv_string); } @@ -346,6 +354,8 @@ ld_plugin_status all_symbols_read_hook(void) { lto_codegen_set_debug_model(cg, LTO_DEBUG_MODEL_DWARF); if (gcc_path) lto_codegen_set_gcc_path(cg, gcc_path); + if (as_path) + lto_codegen_set_assembler_path(cg, as_path); size_t bufsize = 0; const char *buffer = static_cast<const char *>(lto_codegen_compile(cg, diff --git a/tools/llvmc/example/mcc16/Makefile b/tools/llvmc/example/mcc16/Makefile new file mode 100644 index 000000000000..efc9d2dc7ba1 --- /dev/null +++ b/tools/llvmc/example/mcc16/Makefile @@ -0,0 +1,24 @@ +##===- llvmc/example/mcc16/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open +# Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +# Change this so that $(BASE_LEVEL)/Makefile.common refers to +# $LLVM_DIR/Makefile.common. +export LLVMC_BASE_LEVEL = ../../../.. + +# Change this to the name of your LLVMC-based driver. +export LLVMC_BASED_DRIVER_NAME = mcc16 + +# List your plugin names here +export LLVMC_BUILTIN_PLUGINS = PIC16Base + +LEVEL = $(LLVMC_BASE_LEVEL) + +DIRS = plugins driver + +include $(LEVEL)/Makefile.common diff --git a/tools/llvmc/example/mcc16/README b/tools/llvmc/example/mcc16/README new file mode 100644 index 000000000000..eeef6a4f8f1b --- /dev/null +++ b/tools/llvmc/example/mcc16/README @@ -0,0 +1,75 @@ +This is a basic compiler driver for the PIC16 toolchain that shows how to create +your own llvmc-based drivers. It is based on the example/Skeleton template. + +The PIC16 toolchain looks like this: + +clang-cc (FE) -> llvm-ld (optimizer) -> llc (codegen) -> native-as -> native-ld + +Following features were requested by Sanjiv: + +From: Sanjiv Gupta <sanjiv.gupta <at> microchip.com> +Subject: Re: llvmc for PIC16 +Newsgroups: gmane.comp.compilers.llvm.devel +Date: 2009-06-05 06:51:14 GMT + +The salient features that we want to have in the driver are: +1. llvm-ld will be used as "The Optimizer". +2. If the user has specified to generate the final executable, then +llvm-ld should run on all the .bc files generated by clang and create a +single optimized .bc file for further tools. +3. -Wo <options> - pass optimizations to the llvm-ld +4. mcc16 -Wl <options> - pass options to native linker. +5. mcc16 -Wa <options> - pass options to native assembler. + +Here are some example command lines and sample command invocations as to +what should be done. + +$ mcc16 -S foo.c +// [clang-cc foo.c] -> foo.bc +// [llvm-ld foo.bc] -> foo.opt.bc +// [llc foo.opt.bc] -> foo.s + +$ mcc16 -S foo.c bar.c +// [clang-cc foo.c] -> foo.bc +// [llvm-ld foo.bc] -> foo.opt.bc +// [llc foo.opt.bc] -> foo.s +// [clang-cc bar.c] -> bar.bc +// [llvm-ld bar.bc] -> bar.opt.bc +// [llc bar.opt.bc] -> bar.s + +** Use of -g causes llvm-ld to run with -disable-opt +$ mcc16 -S -g foo.c +// [clang-cc foo.c] -> foo.bc +// [llvm-ld -disable-opt foo.bc] -> foo.opt.bc +// [llc foo.opt.bc] -> foo.s + +** -I is passed to clang-cc, -pre-RA-sched=list-burr to llc. +$ mcc16 -S -g -I ../include -pre-RA-sched=list-burr foo.c +// [clang-cc -I ../include foo.c] -> foo.bc +// [llvm-ld -disable-opt foo.bc] -> foo.opt.bc +// [llc -pre-RA-sched=list-burr foo.opt.bc] -> foo.s + +** -Wo passes options to llvm-ld +$ mcc16 -Wo=opt1,opt2 -S -I ../include -pre-RA-sched=list-burr foo.c +// [clang-cc -I ../include foo.c] -> foo.bc +// [llvm-ld -opt1 -opt2 foo.bc] -> foo.opt.bc +// [llc -pre-RA-sched=list-burr foo.opt.bc] -> foo.s + +** -Wa passes options to native as. +$ mcc16 -c foo.c -Wa=opt1 +// [clang-cc foo.c] -> foo.bc +// [llvm-ld foo.bc] -> foo.opt.bc +// [llc foo.opt.bc] -> foo.s +// [native-as -opt1 foo.s] -> foo.o + +$ mcc16 -Wo=opt1 -Wl=opt2 -Wa=opt3 foo.c bar.c +// [clang-cc foo.c] -> foo.bc +// [clang-cc bar.c] -> bar.bc +// [llvm-ld -opt1 foo.bc bar.bc] -> a.out.bc +// [llc a.out.bc] -> a.out.s +// [native-as -opt3 a.out.s] -> a.out.o +// [native-ld -opt2 a.out.o] -> a.out + +Is this achievable by a tablegen based driver ? + +- Sanjiv diff --git a/tools/llvmc/example/mcc16/driver/Main.cpp b/tools/llvmc/example/mcc16/driver/Main.cpp new file mode 100644 index 000000000000..b1f5b6798ae6 --- /dev/null +++ b/tools/llvmc/example/mcc16/driver/Main.cpp @@ -0,0 +1,14 @@ +//===--- Main.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Just include CompilerDriver/Main.inc. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/Main.inc" diff --git a/tools/llvmc/example/mcc16/driver/Makefile b/tools/llvmc/example/mcc16/driver/Makefile new file mode 100644 index 000000000000..ed9ebfdca922 --- /dev/null +++ b/tools/llvmc/example/mcc16/driver/Makefile @@ -0,0 +1,22 @@ +##===- llvmc/example/mcc16/driver/Makefile -----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open +# Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = $(LLVMC_BASE_LEVEL)/.. + +TOOLNAME = $(LLVMC_BASED_DRIVER_NAME) +LLVMLIBS = CompilerDriver + +ifneq ($(LLVMC_BUILTIN_PLUGINS),) +USEDLIBS += $(patsubst %,plugin_llvmc_%,$(LLVMC_BUILTIN_PLUGINS)) +endif + +LINK_COMPONENTS = support system +REQUIRES_EH := 1 + +include $(LEVEL)/Makefile.common diff --git a/tools/llvmc/example/mcc16/plugins/Makefile b/tools/llvmc/example/mcc16/plugins/Makefile new file mode 100644 index 000000000000..fb07f23d58e5 --- /dev/null +++ b/tools/llvmc/example/mcc16/plugins/Makefile @@ -0,0 +1,18 @@ +##===- llvmc/example/Skeleton/plugins/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open +# Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = $(LLVMC_BASE_LEVEL)/.. + +ifneq ($(LLVMC_BUILTIN_PLUGINS),) +DIRS = $(LLVMC_BUILTIN_PLUGINS) +endif + +export LLVMC_BUILTIN_PLUGIN=1 + +include $(LEVEL)/Makefile.common diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/Makefile b/tools/llvmc/example/mcc16/plugins/PIC16Base/Makefile new file mode 100644 index 000000000000..5d785fd4821f --- /dev/null +++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/Makefile @@ -0,0 +1,17 @@ +##===- llvmc/example/Skeleton/plugins/Plugin/Makefile ------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = $(LLVMC_BASE_LEVEL)/../.. + +# Change this to the name of your plugin. +LLVMC_PLUGIN = PIC16Base + +BUILT_SOURCES = AutoGenerated.inc + +include $(LEVEL)/Makefile.common diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td b/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td new file mode 100644 index 000000000000..0b8a22b80702 --- /dev/null +++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/PIC16Base.td @@ -0,0 +1,116 @@ +//===- PIC16Base.td - PIC16 toolchain driver ---------------*- tablegen -*-===// +// +// A basic driver for the PIC16 toolchain. +// +//===----------------------------------------------------------------------===// + +include "llvm/CompilerDriver/Common.td" + +// Options + +def OptionList : OptionList<[ + (switch_option "g", + (help "Disable optimizations")), + (switch_option "S", + (help "Stop after compilation, do not assemble")), + (parameter_option "I", + (help "Add a directory to include path")), + (parameter_option "pre-RA-sched", + (help "Example of an option that is passed to llc")), + (prefix_list_option "Wa,", + (help "Pass options to native assembler")), + (prefix_list_option "Wl,", + (help "Pass options to native linker")), + (prefix_list_option "Wllc,", + (help "Pass options to llc")), + (prefix_list_option "Wo,", + (help "Pass options to llvm-ld")) +]>; + +// Tools + +def clang_cc : Tool<[ + (in_language "c"), + (out_language "llvm-bitcode"), + (output_suffix "bc"), + (cmd_line "clang-cc $INFILE -o $OUTFILE"), + (actions (case + (not_empty "I"), (forward "I"))), + (sink) +]>; + +def llvm_ld : Tool<[ + (in_language "llvm-bitcode"), + (out_language "llvm-bitcode"), + (output_suffix "bc"), + (cmd_line "llvm-ld $INFILE -o $OUTFILE"), + (actions (case + (switch_on "g"), (append_cmd "-disable-opt"), + (not_empty "Wo,"), (unpack_values "Wo,"))) +]>; + +def llvm_ld_lto : Tool<[ + (in_language "llvm-bitcode"), + (out_language "llvm-bitcode"), + (output_suffix "bc"), + (cmd_line "llvm-ld $INFILE -o $OUTFILE"), + (actions (case + (switch_on "g"), (append_cmd "-disable-opt"), + (not_empty "Wo,"), (unpack_values "Wo,"))), + (join) +]>; + +def llc : Tool<[ + (in_language "llvm-bitcode"), + (out_language "assembler"), + (output_suffix "s"), + (cmd_line "llc -f $INFILE -o $OUTFILE"), + (actions (case + (switch_on "S"), (stop_compilation), + (not_empty "Wllc,"), (unpack_values "Wllc,"), + (not_empty "pre-RA-sched"), (forward "pre-RA-sched"))) +]>; + +def native_as : Tool<[ + (in_language "assembler"), + (out_language "object-code"), + (output_suffix "o"), + (cmd_line "native-as $INFILE -o $OUTFILE"), + (actions (case + (not_empty "Wa,"), (unpack_values "Wa,"))) +]>; + +def native_ld : Tool<[ + (in_language "object-code"), + (out_language "executable"), + (output_suffix "out"), + (cmd_line "native-ld $INFILE -o $OUTFILE"), + (actions (case + (not_empty "Wl,"), (unpack_values "Wl,"))), + (join) +]>; + +// Language map + +def LanguageMap : LanguageMap<[ + LangToSuffixes<"c", ["c"]>, + LangToSuffixes<"c-cpp-output", ["i"]>, + LangToSuffixes<"assembler", ["s"]>, + LangToSuffixes<"assembler-with-cpp", ["S"]>, + LangToSuffixes<"llvm-assembler", ["ll"]>, + LangToSuffixes<"llvm-bitcode", ["bc"]>, + LangToSuffixes<"object-code", ["o"]>, + LangToSuffixes<"executable", ["out"]> +]>; + +// Compilation graph + +def CompilationGraph : CompilationGraph<[ + Edge<"root", "clang_cc">, + Edge<"clang_cc", "llvm_ld_lto">, + Edge<"llvm_ld_lto", "llc">, + OptionalEdge<"clang_cc", "llvm_ld", (case (switch_on "S"), (inc_weight))>, + Edge<"llvm_ld", "llc">, + Edge<"llc", "native_as">, + Edge<"native_as", "native_ld"> +]>; diff --git a/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp b/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp new file mode 100644 index 000000000000..add8acb4a574 --- /dev/null +++ b/tools/llvmc/example/mcc16/plugins/PIC16Base/PluginMain.cpp @@ -0,0 +1 @@ +#include "AutoGenerated.inc" |