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:
50
llvmutil.cpp
50
llvmutil.cpp
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
14
llvmutil.h
14
llvmutil.h
@@ -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
84
opt.cpp
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user