[llvm-commits] [vector_llvm] CVS: llvm/include/VectorLLVM/Utils.h VectorIntrinsics.h VectorSignificantFunctions.h

Robert Bocchino bocchino at cs.uiuc.edu
Tue Oct 18 12:35:36 PDT 2005



Changes in directory llvm/include/VectorLLVM:

Utils.h added (r1.1.2.1)
VectorIntrinsics.h added (r1.1.2.1)
VectorSignificantFunctions.h added (r1.1.2.1)
---
Log message:

Initial commit of Vector LLVM.


---
Diffs of the changes:  (+642 -0)

 Utils.h                      |  315 +++++++++++++++++++++++++++++++++++++++++++
 VectorIntrinsics.h           |   34 ++++
 VectorSignificantFunctions.h |  293 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 642 insertions(+)


Index: llvm/include/VectorLLVM/Utils.h
diff -c /dev/null llvm/include/VectorLLVM/Utils.h:1.1.2.1
*** /dev/null	Tue Oct 18 14:35:34 2005
--- llvm/include/VectorLLVM/Utils.h	Tue Oct 18 14:35:24 2005
***************
*** 0 ****
--- 1,315 ----
+ //===- Utils.h - Utilities for vector code generation -----------*- C++ -*-===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ // 
+ //===----------------------------------------------------------------------===//
+ //
+ //
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #ifndef PROJECTS_VECTOR_INCLUDE_UTILS_H
+ #define PROJECTS_VECTOR_INCLUDE_UTILS_H
+ 
+ #include "llvm/Constants.h"
+ #include "llvm/DerivedTypes.h"
+ #include "llvm/Function.h"
+ #include "llvm/Instructions.h"
+ #include "llvm/Module.h"
+ #include "llvm/Type.h"
+ #include "llvm/Transforms/Utils/BasicBlockUtils.h"
+ #include "llvm/ADT/hash_set"
+ #include <sstream>
+ #include <iostream>
+ 
+ using namespace llvm;
+ 
+ namespace VectorUtils {
+ 
+ 
+ 
+   //===----------------------------------------------------------------------===//
+   //          Helper functions for managing register and label names
+   //===----------------------------------------------------------------------===//
+ 
+   /// Counter for temporary variable names
+   ///
+   static unsigned tmpCount = 0;
+ 
+   /// Counter for loop labels
+   ///
+   static unsigned loopCount = 0;
+ 
+   /// Counter for conditionals
+   ///
+   static unsigned condCount = 0;
+ 
+   static std::string next(std::string prefix, unsigned suffix) {
+     std::ostringstream os;
+     os << prefix << "." << suffix;
+     return os.str();
+   }
+ 
+   static std::string nextTmp() {
+     return next("tmp", tmpCount++);
+   }
+ 
+   static std::string nextHeader() {
+     return next("loop_header", loopCount++);
+   }
+ 
+   static std::string nextBody() {
+     return next("loop_body", loopCount-1);
+   }
+ 
+   static std::string nextExit() {
+     return next("loop_exit", loopCount-1);
+   }
+ 
+   static std::string nextIfTrue() {
+     return next("if_true", condCount++);
+   }
+ 
+   static std::string nextIfFalse() {
+     return next("if_false", condCount);
+   }
+ 
+ 
+   //===----------------------------------------------------------------------===//
+   //          Helper functions for identifying vector stuff
+   //===----------------------------------------------------------------------===//
+ 
+   static bool recursiveContainsVector(const Type* Ty,
+ 					      hash_set<const Type*> &seenTys) {
+     if (seenTys.count(Ty))
+       return false;
+     seenTys.insert(Ty);
+     if (isa<VectorType>(Ty)) 
+       return true;
+     else if (const SequentialType *SequentialTy = dyn_cast<SequentialType>(Ty)) {
+       return recursiveContainsVector(SequentialTy->getElementType(),
+ 					     seenTys);
+     } else if (const StructType *StructTy = dyn_cast<StructType>(Ty)) {
+       for (StructType::element_iterator I = StructTy->element_begin(),
+ 	     E = StructTy->element_end(); I != E; ++I) {
+ 	if (recursiveContainsVector(*I, seenTys)) return true;
+       }
+       return false;
+     } else if (const FunctionType *FunctionTy = dyn_cast<FunctionType>(Ty)) {
+       if (recursiveContainsVector(FunctionTy->getReturnType(),
+ 					  seenTys))
+ 	return true;
+       for (FunctionType::param_iterator I = FunctionTy->param_begin(),
+ 	   E = FunctionTy->param_end(); I != E; ++I)
+ 	if (recursiveContainsVector(*I, seenTys)) return true;
+       return false;
+     }
+     return false;
+   }
+ 
+   static bool containsVector(const Type *Ty) {
+     hash_set<const Type*> seenTys;
+     return recursiveContainsVector(Ty, seenTys);
+   }
+ 
+   static bool containsVector(Instruction *inst) {
+     if (containsVector(inst->getType())) return true;
+     for (User::op_iterator I = inst->op_begin(), E = inst->op_end();
+ 	 I != E; ++I)
+       if (containsVector((*I)->getType()))
+ 	return true;
+     return false;
+   }
+ 
+ 
+   //===----------------------------------------------------------------------===//
+   //          Very useful for identifying intrinsics
+   //===----------------------------------------------------------------------===//
+ 
+   static bool isFunctionContaining(Value *Val, const std::string &s) {
+     if (CallInst *CI = dyn_cast<CallInst>(Val)) {
+       if (Function *F = CI->getCalledFunction()) {
+ 	if (F->getName().find(s) != std::string::npos) {
+ 	  return true;
+ 	}
+       }
+     }
+     return false;
+   }
+ 
+   //===----------------------------------------------------------------------===//
+   //          Helper functions for array computations
+   //===----------------------------------------------------------------------===//
+ 
+   /// Compute an index into a flattened (one-dimensional) array
+   /// corresponding to the given indices for a possibly
+   /// multidimensional array.
+   ///
+   static Instruction *computeFlattenedPointer(VMemoryInst *VI, std::vector<Value*> indices,
+ 					      Instruction *before) {
+     unsigned numLevels = VI->getNumIndices() >> 2;
+     Value *indexValue = 
+       BinaryOperator::create(Instruction::Mul, indices[0],
+ 			     VI->getMultiplier(0), nextTmp(), before);
+     for (unsigned i = 1; i < numLevels; ++i) {
+       Instruction *mul = 
+ 	BinaryOperator::create(Instruction::Mul, indices[i], 
+ 			       VI->getMultiplier(i), nextTmp(), before);
+       indexValue =
+ 	BinaryOperator::create(Instruction::Add, indexValue, mul,
+ 			       nextTmp(), before);
+     }
+ 
+     std::vector<Value*> indexVector;
+     indexVector.push_back(indexValue);
+     return new GetElementPtrInst(VI->getPointerOperand(), indexVector, 
+ 				 "ptr", before);
+   }
+ 
+   /// Compute the length of an array in a single dimension, given the
+   /// lower bound, upper bound, and stride.  Type is LongTy.
+   ///
+   static Value *computeSingleDimensionLength(Value *lowerBound, Value *upperBound,
+ 					     Value *stride, Instruction *before) {
+     ConstantSInt *longZero = ConstantSInt::get(Type::LongTy, 0);
+     ConstantSInt *longOne = ConstantSInt::get(Type::LongTy, 1);
+     ConstantSInt *longNegOne = ConstantSInt::get(Type::LongTy, -1);
+     Value *length;
+     length = (lowerBound == longZero) ? upperBound :
+       BinaryOperator::create(Instruction::Sub, upperBound, lowerBound, 
+ 			     nextTmp(), before);
+     length = BinaryOperator::create(Instruction::Add, length, stride, 
+ 				    nextTmp(), before);
+     if (stride != longOne)
+       length = BinaryOperator::create(Instruction::Div, length, stride,
+ 				      nextTmp(), before);
+     return length;
+   }
+ 
+   /// Given a vector instruction (vload or vstore), generate code to
+   /// compute the length of the (flattened) array slice defined by the
+   /// indices.  Type is UIntTy.
+   ///
+   static Value *computeIndexedLength(VMemoryInst *VI, 
+ 				     Instruction *before = 0,
+ 				     std::string name = "tmp") {
+     if (!before)
+       before = VI;
+ 
+     unsigned numTriples = VI->getNumIndices() >> 2;
+     Value *oldVal = 0, *newVal = 0, *length = 0;
+ 
+     for (unsigned i = 0; i < numTriples; ++i) {
+       Value *start = VI->getLowerBound(i);
+       Value *end = VI->getUpperBound(i);
+       Value *stride = VI->getStride(i);
+       if (start != end) {
+ 	newVal = computeSingleDimensionLength(start, end, stride, before);
+ 	if (oldVal)
+ 	  newVal = BinaryOperator::create(Instruction::Mul, oldVal, newVal,
+ 					  nextTmp(), before);
+ 	oldVal = newVal;
+       }
+     }
+     if (newVal)
+       length = new CastInst(newVal, Type::UIntTy, name, before);
+     else 
+       length = ConstantUInt::get(Type::UIntTy, 1);
+ 
+     return length;
+   }
+ 
+   /// Given two lengths, generate code to ensure that they are equal;
+   /// abort if not
+   ///
+   static void ensureEquality(Instruction *before, Value *V1, Value *V2) {
+     // Set up the basic blocks
+     //
+     BasicBlock *initial = before->getParent();
+     BasicBlock *ifFalse = initial->splitBasicBlock(before, nextIfFalse());
+     BasicBlock *ifTrue = ifFalse->splitBasicBlock(before, nextIfTrue());
+     Instruction *cond = 
+       BinaryOperator::create(Instruction::SetEQ, V1, V2,
+ 			     nextTmp(), initial->getTerminator());
+     BasicBlock::iterator oldInst(initial->getTerminator());
+     Instruction *newInst = new BranchInst(ifTrue, ifFalse, cond);
+     ReplaceInstWithInst(initial->getInstList(), oldInst, newInst);
+ 
+     // Generate code to abort
+     //
+     std::vector<const Type*> formalArgs;
+     std::vector<Value*> args;
+ 
+     FunctionType *FType = FunctionType::get(Type::VoidTy, formalArgs, false);
+     Function *F = initial->getParent();
+     Module *M = F->getParent();
+     Function *abort = M->getOrInsertFunction("abort", FType);
+     Instruction *call = new CallInst(abort, args, "", ifFalse->getTerminator());
+ 
+     // Generate code to print the error message
+     //
+     formalArgs.push_back(PointerType::get(Type::SByteTy));
+     FType = FunctionType::get(Type::IntTy, formalArgs, true);
+     Function *printf = M->getOrInsertFunction("printf", FType);
+     
+     std::string msg = "unequal vector lengths " + V1->getName() + " and "
+       + V2->getName() + " in function " + F->getName() + "\n";
+     Constant *arr = ConstantArray::get(msg);
+     GlobalVariable *GV = new GlobalVariable(arr->getType(), true,
+ 					    GlobalValue::InternalLinkage, 
+ 					    arr, "error_str", M);
+     std::vector<Constant*> idx;
+     idx.push_back(ConstantUInt::get(Type::ULongTy, 0));
+     idx.push_back(ConstantUInt::get(Type::ULongTy, 0));
+     Constant *gep = ConstantExpr::getGetElementPtr(GV, idx);
+ 
+     args.push_back(gep);
+     new CallInst(printf, args, "", call);
+   }
+ 
+   //===----------------------------------------------------------------------===//
+   //          Nicer CallInst constructor interface
+   //===----------------------------------------------------------------------===//
+ 
+   static CallInst *getCallInst(const Type* RetTy, const std::string& FName, std::vector<Value*>& args,
+ 			       const std::string& Name, Instruction *before) {
+     std::vector<const Type*> formalArgs;
+     for (std::vector<Value*>::iterator I = args.begin(), E = args.end(); I != E; ++I) {
+       formalArgs.push_back((*I)->getType());
+     }
+     FunctionType *FType = FunctionType::get(RetTy, formalArgs, false);
+     Module *M = before->getParent()->getParent()->getParent();
+     Function *F = M->getOrInsertFunction(FName, FType);
+     return new CallInst(F, args, Name, before);
+   }
+ 
+   static CallInst *getCallInst(const Type* RetTy, const std::string& FName, Value *arg1,
+ 			       const std::string& Name, Instruction *before) {
+     std::vector<Value*> args;
+     args.push_back(arg1);
+     return getCallInst(RetTy, FName, args, Name, before);
+   }
+ 
+   static CallInst *getCallInst(const Type* RetTy, const std::string& FName, Value *arg1, Value *arg2,
+ 			       const std::string& Name, Instruction *before) {
+     std::vector<Value*> args;
+     args.push_back(arg1);
+     args.push_back(arg2);
+     return getCallInst(RetTy, FName, args, Name, before);
+   }
+ 
+   static CallInst *getCallInst(const Type* RetTy, const std::string& FName, Value *arg1, Value *arg2, Value *arg3,
+ 			       const std::string& Name, Instruction *before) {
+     std::vector<Value*> args;
+     args.push_back(arg1);
+     args.push_back(arg2);
+     args.push_back(arg3);
+     return getCallInst(RetTy, FName, args, Name, before);
+   }
+ 
+ }
+ 
+ #endif


Index: llvm/include/VectorLLVM/VectorIntrinsics.h
diff -c /dev/null llvm/include/VectorLLVM/VectorIntrinsics.h:1.1.2.1
*** /dev/null	Tue Oct 18 14:35:35 2005
--- llvm/include/VectorLLVM/VectorIntrinsics.h	Tue Oct 18 14:35:24 2005
***************
*** 0 ****
--- 1,34 ----
+ //===-- llvm/VectorLLVM/VectorInstrinsics.h - LLVM Vector Intrinsic Function Handling ---*- C++ -*-===//
+ //
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file defines a set of enums which allow processing of
+ // intrinsic functions for Vector-LLVM.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #ifndef LLVM_VECTOR_INTRINSICS_H
+ #define LLVM_VECTOR_INTRINSICS_H
+ 
+ namespace llvm {
+ 
+ /// Intrinsic Namespace - This namespace contains an enum with a value for
+ /// every vector intrinsic/builtin function known by LLVM.
+ ///
+ namespace VectorIntrinsic {
+   enum ID {
+     not_intrinsic = 0,   // Must be zero
+ 
+ 
+   };
+ 
+ } // End VectorIntrinsic namespace
+ 
+ } // End llvm namespace
+ 
+ #endif


Index: llvm/include/VectorLLVM/VectorSignificantFunctions.h
diff -c /dev/null llvm/include/VectorLLVM/VectorSignificantFunctions.h:1.1.2.1
*** /dev/null	Tue Oct 18 14:35:35 2005
--- llvm/include/VectorLLVM/VectorSignificantFunctions.h	Tue Oct 18 14:35:24 2005
***************
*** 0 ****
--- 1,293 ----
+ //===-- llvm/VectorLLVM/Instrinsics.h - LLVM Vector Significant Function Handling ---*- C++ -*-===//
+ //
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file defines a set of enums which allow processing of
+ // significant functions for Vector-LLVM.
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #ifndef LLVM_VECTOR_SIGNIFICANT_FUNCTIONS_H
+ #define LLVM_VECTOR_SIGNIFICANT_FUNCTIONS_H
+ 
+ #include <string.h>
+ 
+ namespace llvm {
+ 
+ /// VectorSignificantFunctions Namespace - This namespace contains an
+ /// enum with a value for every vector significant function known by
+ /// LLVM.
+ ///
+ namespace VectorSignificantFunctions {
+ 
+ #define NUM_NAMES 17
+ 
+   std::string names[NUM_NAMES] = {
+     "vimm",
+     "fixed_vimm",
+     "vgather",
+     "vscatter",
+     "load",
+     "store",
+     "vselect", 
+     "extract", 
+     "combine", 
+     "fixed_combine",
+     "extractelement", 
+     "combineelement",
+     "constant",
+     "fixed_permute",
+     // Older forms
+     "vload", 
+     "vloadi", 
+     "vstore"
+   };
+ 
+   enum ID {
+     not_significant = 0,   // Must be zero
+     vimm,
+     fixed_vimm,
+     vgather,
+     vscatter,
+     load,
+     store,
+     vselect,
+     extract, 
+     combine, 
+     fixed_combine,
+     extractelement, 
+     combineelement,
+     constant,
+     fixed_permute,
+     // Older forms
+     vload, 
+     vloadi, 
+     vstore
+   };
+ 
+   ID getID(std::string name) {
+     for (unsigned i = 0; i < NUM_NAMES; ++i) {
+       if (name.substr(0, 5) == "vllvm") {
+ 	if (name.substr(6, names[i].length()+1) == names[i] + '_')
+ 	  return ID(i+1);
+       }
+       if (name.substr(0, names[i].length()+2) == '_'+names[i]+'_')
+ 	return ID(i+1);
+     }
+     return not_significant;
+   }
+ 
+   /// Return true if the specified call represents a properly declared
+   /// vector significant function
+   ///
+   bool isProperlyDeclared(Function *F) {
+     std::string name = F->getName();
+     const FunctionType *FTy = F->getFunctionType();
+     const Type *RetTy = FTy->getReturnType();
+     unsigned numParams = FTy->getNumParams();
+     bool isVarArg = FTy->isVarArg();
+     switch(getID(name)) {
+     case not_significant:
+       return true;
+     case vgather:
+     case vload: {
+       // A vload function must be a varargs function with 1 argument:
+       // the place to load from
+       //
+       if (numParams != 1 || !isVarArg)
+ 	return false;
+       const PointerType *PointerTy = 
+ 	dyn_cast<PointerType>(FTy->getParamType(0));
+       if (!PointerTy || RetTy != PointerTy->getElementType())
+ 	return false;
+       break;
+     }
+     case load: {
+       // A fixed_vload function must have precisely 3 arguments: a
+       // pointer, a vector length, and an index.  The pointer must
+       // point to the return value type.
+       //
+       if (numParams != 3 || isVarArg)
+ 	return false;
+       const PointerType *PointerTy = 
+ 	dyn_cast<PointerType>(FTy->getParamType(0));
+       if (!PointerTy || RetTy != PointerTy->getElementType())
+ 	return false;
+       if (!FTy->getParamType(1)->isIntegral())
+ 	return false;
+       if (!FTy->getParamType(2)->isIntegral())
+ 	return false;
+       break;
+     }
+     case vloadi:
+       // A vloadi function must have precisely 2 arguments: a scalar
+       // and a length.  It must return the type of its first argument.
+       //
+       if (numParams != 2 || isVarArg)
+ 	return false;
+       if (RetTy != FTy->getParamType(0))
+ 	return false;
+       if (!FTy->getParamType(0)->isIntegral())
+ 	return false;
+       break;
+     case vimm:
+     case fixed_vimm:{
+       // A fixed_vimm must have precisely 2 arguments: a scalar and a
+       // vector length.  It must return the type of its first
+       // argument.
+       //
+       if (numParams != 2 || isVarArg)
+ 	return false;
+       if (RetTy != FTy->getParamType(0))
+ 	return false;
+       if (!FTy->getParamType(0)->isIntegral())
+ 	return false;
+       break;
+     }
+     case vscatter:
+     case vstore:
+       // A vstore function must be a varargs function with 2
+       // arguments: the value to store and the place to store it
+       //
+       if (numParams != 2 || !isVarArg)
+ 	return false;
+       if (!isa<PointerType>(FTy->getParamType(1)))
+ 	return false;
+       if (FTy->getParamType(0) != cast<PointerType>(FTy->getParamType(1))->getElementType())
+ 	return false;
+       break;
+     case store: {
+       // A store function must have precisely 3 arguments: a value to
+       // store, the place to store it, and an index.  The pointer must
+       // point to the value type.
+       //
+       if (numParams != 3 || isVarArg)
+ 	return false;
+       const PointerType *PointerTy = 
+ 	dyn_cast<PointerType>(FTy->getParamType(1));
+       if (!PointerTy || FTy->getParamType(0) != PointerTy->getElementType())
+ 	return false;
+       if (!FTy->getParamType(2)->isIntegral())
+ 	return false;
+       break;
+     }
+     case vselect:
+       // A vselect function must have precisely 3 arguments: an int
+       // (really a boolean) and two values of the same type
+       //
+       if (numParams != 3 || isVarArg)
+ 	return false;
+       if (FTy->getParamType(0) != Type::IntTy)
+ 	return false;
+       if (FTy->getParamType(1) != FTy->getParamType(2))
+ 	return false;
+       break;
+     case extract:
+       // An extract function must have precisely 4 arguments: a value
+       // and 3 unsigned ints
+       //
+       if (numParams != 4 || isVarArg)
+ 	return false;
+       if (FTy->getParamType(1) != Type::UIntTy)
+ 	return false;
+       if (FTy->getParamType(2) != Type::UIntTy)
+ 	return false;
+       if (FTy->getParamType(3) != Type::UIntTy)
+ 	return false;
+       break;
+     case combine:
+       // A combine function must have precisely 4 arguments: two
+       // values of the same type and two unsigned ints
+       //
+       if (numParams != 4 || isVarArg)
+ 	return false;
+       if (RetTy != FTy->getParamType(0))
+ 	return false;
+       if (FTy->getParamType(0) != FTy->getParamType(1))
+ 	return false;
+       if (FTy->getParamType(2) != Type::UIntTy)
+ 	return false;
+       if (FTy->getParamType(3) != Type::UIntTy)
+ 	return false;
+       break;
+     case fixed_combine:
+       // A fixed_combine must have precisely 6 arguments: a value, a
+       // vector length, another value of the same type as the first,
+       // another vector length, and two unsigned ints.
+       //
+       if (numParams != 6 || isVarArg)
+ 	return false;
+       if (RetTy != FTy->getParamType(0))
+ 	return false;
+       if (FTy->getParamType(0) != FTy->getParamType(2))
+ 	return false;
+       if (FTy->getParamType(1) != Type::UIntTy)
+ 	return false;
+       if (FTy->getParamType(3) != Type::UIntTy)
+ 	return false;
+       if (FTy->getParamType(4) != Type::UIntTy)
+ 	return false;
+       if (FTy->getParamType(5) != Type::UIntTy)
+ 	return false;
+       break;
+     case extractelement:
+       // An extractelement function must have precisely 2 arguments: a
+       // value and an unsigned int
+       //
+       if (numParams != 2 || isVarArg)
+ 	return false;
+       if (FTy->getParamType(1) != Type::UIntTy)
+ 	return false;
+       break;
+     case combineelement:
+       // A combineelement function must have precisely 3 arguments:
+       // two values of the same type and two unsigned ints
+       //
+       if (numParams != 3 || isVarArg)
+ 	return false;
+       if (FTy->getParamType(0) != FTy->getParamType(1))
+ 	return false;
+       if (FTy->getParamType(2) != Type::UIntTy)
+ 	return false;
+       break;
+     case constant:
+       // A constant function must be a varargs function with one
+       // argument.  The return type must be the same as the type of
+       // that argument
+       //
+       if (numParams != 1 || !isVarArg)
+ 	return false;
+       if (RetTy != FTy->getParamType(0))
+ 	return false;
+       break;
+     case fixed_permute:
+       // A fixed permute function must have four arguments: a vector,
+       // a length, and index vector, and a length
+       if (numParams != 4 || isVarArg)
+ 	return false;
+       if (FTy->getParamType(0) != FTy->getParamType(2))
+ 	return false;
+       if (FTy->getParamType(1) != Type::UIntTy ||
+ 	  FTy->getParamType(3) != Type::UIntTy)
+ 	return false;
+       break;
+       //
+       // Newer Forms
+       //
+     default:
+       std::cerr << "Unknown vector significant function " << name << "!\n";
+       exit(1);
+     }
+     return true;
+   }
+ 
+ } // End VectorSignificantFunctions namespace
+ 
+ } // End llvm namespace
+ 
+ #endif






More information about the llvm-commits mailing list