Add LLVMShuffleVectors() and LLVMConcatVectors() functions.

These were local functions in opt.cpp that are now public via the
llvmutil.* files.
This commit is contained in:
Matt Pharr
2012-03-19 11:34:52 -07:00
parent 74a031a759
commit 1067a2e4be
3 changed files with 81 additions and 67 deletions

View File

@@ -782,3 +782,53 @@ LLVMDumpValue(llvm::Value *v) {
lDumpValue(v, done); lDumpValue(v, done);
fprintf(stderr, "----\n"); fprintf(stderr, "----\n");
} }
/** Given two vectors of the same type, concatenate them into a vector that
has twice as many elements, where the first half has the elements from
the first vector and the second half has the elements from the second
vector.
*/
llvm::Value *
LLVMConcatVectors(llvm::Value *v1, llvm::Value *v2,
llvm::Instruction *insertBefore) {
Assert(v1->getType() == v2->getType());
LLVM_TYPE_CONST llvm::VectorType *vt =
llvm::dyn_cast<LLVM_TYPE_CONST llvm::VectorType>(v1->getType());
Assert(vt != NULL);
int32_t identity[ISPC_MAX_NVEC];
int resultSize = 2*vt->getNumElements();
Assert(resultSize <= ISPC_MAX_NVEC);
for (int i = 0; i < resultSize; ++i)
identity[i] = i;
return LLVMShuffleVectors(v1, v2, identity, resultSize, insertBefore);
}
/** Shuffle two vectors together with a ShuffleVectorInst, returning a
vector with shufSize elements, where the shuf[] array offsets are used
to determine which element from the two given vectors is used for each
result element. */
llvm::Value *
LLVMShuffleVectors(llvm::Value *v1, llvm::Value *v2, int32_t shuf[],
int shufSize, llvm::Instruction *insertBefore) {
std::vector<llvm::Constant *> shufVec;
for (int i = 0; i < shufSize; ++i) {
if (shuf[i] == -1)
shufVec.push_back(llvm::UndefValue::get(LLVMTypes::Int32Type));
else
shufVec.push_back(LLVMInt32(shuf[i]));
}
#ifndef LLVM_2_9
llvm::ArrayRef<llvm::Constant *> aref(&shufVec[0], &shufVec[shufSize]);
llvm::Value *vec = llvm::ConstantVector::get(aref);
#else // LLVM_2_9
llvm::Value *vec = llvm::ConstantVector::get(shufVec);
#endif
return new llvm::ShuffleVectorInst(v1, v2, vec, "shuffle", insertBefore);
}

View File

@@ -239,4 +239,18 @@ void LLVMFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
on. */ on. */
extern void LLVMDumpValue(llvm::Value *v); extern void LLVMDumpValue(llvm::Value *v);
/** This function takes two vectors, expected to be the same length, and
returns a new vector of twice the length that represents concatenating
the two of them. */
extern llvm::Value *LLVMConcatVectors(llvm::Value *v1, llvm::Value *v2,
llvm::Instruction *insertBefore);
/** This is a utility function for vector shuffling; it takes two vectors
v1 and v2, and a compile-time constant set of integer permutations in
shuf[] and returns a new vector of length shufSize that represents the
corresponding shufflevector operation. */
extern llvm::Value *LLVMShuffleVectors(llvm::Value *v1, llvm::Value *v2,
int32_t shuf[], int shufSize,
llvm::Instruction *insertBefore);
#endif // ISPC_LLVMUTIL_H #endif // ISPC_LLVMUTIL_H

84
opt.cpp
View File

@@ -3156,32 +3156,6 @@ lEmitLoads(llvm::Value *basePtr, std::vector<CoalescedLoadOp> &loadOps,
} }
/** Shuffle two vectors together with a ShuffleVectorInst, returning a
vector with shufSize elements, where the shuf[] array offsets are used
to determine which element from the two given vectors is used for each
result element. */
static llvm::Value *
lShuffleVectors(llvm::Value *v1, llvm::Value *v2, int32_t shuf[],
int shufSize, llvm::Instruction *insertBefore) {
std::vector<llvm::Constant *> shufVec;
for (int i = 0; i < shufSize; ++i) {
if (shuf[i] == -1)
shufVec.push_back(llvm::UndefValue::get(LLVMTypes::Int32Type));
else
shufVec.push_back(LLVMInt32(shuf[i]));
}
#ifndef LLVM_2_9
llvm::ArrayRef<llvm::Constant *> aref(&shufVec[0], &shufVec[shufSize]);
llvm::Value *vec = llvm::ConstantVector::get(aref);
#else // LLVM_2_9
llvm::Value *vec = llvm::ConstantVector::get(shufVec);
#endif
return new llvm::ShuffleVectorInst(v1, v2, vec, "shuffle", insertBefore);
}
/** Convert any loads of 8-wide vectors into two 4-wide vectors /** Convert any loads of 8-wide vectors into two 4-wide vectors
(logically). This allows the assembly code below to always operate on (logically). This allows the assembly code below to always operate on
4-wide vectors, which leads to better code. Returns a new vector of 4-wide vectors, which leads to better code. Returns a new vector of
@@ -3199,12 +3173,12 @@ lSplit8WideLoads(const std::vector<CoalescedLoadOp> &loadOps,
int32_t shuf[2][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 } }; int32_t shuf[2][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 } };
ret.push_back(CoalescedLoadOp(loadOps[i].start, 4)); ret.push_back(CoalescedLoadOp(loadOps[i].start, 4));
ret.back().load = lShuffleVectors(loadOps[i].load, loadOps[i].load, ret.back().load = LLVMShuffleVectors(loadOps[i].load, loadOps[i].load,
shuf[0], 4, insertBefore); shuf[0], 4, insertBefore);
ret.push_back(CoalescedLoadOp(loadOps[i].start+4, 4)); ret.push_back(CoalescedLoadOp(loadOps[i].start+4, 4));
ret.back().load = lShuffleVectors(loadOps[i].load, loadOps[i].load, ret.back().load = LLVMShuffleVectors(loadOps[i].load, loadOps[i].load,
shuf[1], 4, insertBefore); shuf[1], 4, insertBefore);
} }
else else
ret.push_back(loadOps[i]); ret.push_back(loadOps[i]);
@@ -3338,7 +3312,7 @@ lApplyLoad4(llvm::Value *result, const CoalescedLoadOp &load,
// Now, issue a shufflevector instruction if any of the values from the // Now, issue a shufflevector instruction if any of the values from the
// load we just considered were applicable. // load we just considered were applicable.
if (shuf[0] != 4 || shuf[1] != 5 || shuf[2] != 6 || shuf[3] != 7) if (shuf[0] != 4 || shuf[1] != 5 || shuf[2] != 6 || shuf[3] != 7)
result = lShuffleVectors(load.load, result, shuf, 4, insertBefore); result = LLVMShuffleVectors(load.load, result, shuf, 4, insertBefore);
return result; return result;
} }
@@ -3438,8 +3412,8 @@ lApplyLoad4s(llvm::Value *result, const std::vector<CoalescedLoadOp> &loadOps,
else else
shuffle[i] = 4 + matchElements[i]; shuffle[i] = 4 + matchElements[i];
} }
result = lShuffleVectors(firstMatch->load, loadop.load, shuffle, result = LLVMShuffleVectors(firstMatch->load, loadop.load, shuffle,
4, insertBefore); 4, insertBefore);
firstMatch = NULL; firstMatch = NULL;
} }
} }
@@ -3451,15 +3425,15 @@ lApplyLoad4s(llvm::Value *result, const std::vector<CoalescedLoadOp> &loadOps,
else else
shuffle[i] = i; shuffle[i] = i;
} }
result = lShuffleVectors(result, loadop.load, shuffle, 4, result = LLVMShuffleVectors(result, loadop.load, shuffle, 4,
insertBefore); insertBefore);
} }
} }
} }
if (firstMatch != NULL && llvm::isa<llvm::UndefValue>(result)) if (firstMatch != NULL && llvm::isa<llvm::UndefValue>(result))
return lShuffleVectors(firstMatch->load, result, firstMatchElements, return LLVMShuffleVectors(firstMatch->load, result, firstMatchElements,
4, insertBefore); 4, insertBefore);
else else
return result; return result;
} }
@@ -3518,30 +3492,6 @@ lAssemble4Vector(const std::vector<CoalescedLoadOp> &loadOps,
#endif #endif
/** Given two vectors of the same type, concatenate them into a vector that
has twice as many elements, where the first half has the elements from
the first vector and the second half has the elements from the second
vector.
*/
static llvm::Value *
lConcatVectors(llvm::Value *v1, llvm::Value *v2,
llvm::Instruction *insertBefore) {
Assert(v1->getType() == v2->getType());
LLVM_TYPE_CONST llvm::VectorType *vt =
llvm::dyn_cast<LLVM_TYPE_CONST llvm::VectorType>(v1->getType());
Assert(vt != NULL);
int32_t identity[ISPC_MAX_NVEC];
int resultSize = 2*vt->getNumElements();
Assert(resultSize <= ISPC_MAX_NVEC);
for (int i = 0; i < resultSize; ++i)
identity[i] = i;
return lShuffleVectors(v1, v2, identity, resultSize, insertBefore);
}
/** Given the set of loads that we've done and the set of result values to /** Given the set of loads that we've done and the set of result values to
be computed, this function computes the final llvm::Value *s for each be computed, this function computes the final llvm::Value *s for each
result vector. result vector.
@@ -3570,14 +3520,14 @@ lAssembleResultVectors(const std::vector<CoalescedLoadOp> &loadOps,
result = vec4s[i]; result = vec4s[i];
break; break;
case 8: case 8:
result = lConcatVectors(vec4s[2*i], vec4s[2*i+1], insertBefore); result = LLVMConcatVectors(vec4s[2*i], vec4s[2*i+1], insertBefore);
break; break;
case 16: { case 16: {
llvm::Value *v1 = lConcatVectors(vec4s[4*i], vec4s[4*i+1], llvm::Value *v1 = LLVMConcatVectors(vec4s[4*i], vec4s[4*i+1],
insertBefore); insertBefore);
llvm::Value *v2 = lConcatVectors(vec4s[4*i+2], vec4s[4*i+3], llvm::Value *v2 = LLVMConcatVectors(vec4s[4*i+2], vec4s[4*i+3],
insertBefore); insertBefore);
result = lConcatVectors(v1, v2, insertBefore); result = LLVMConcatVectors(v1, v2, insertBefore);
break; break;
} }
default: default: