[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