Merge pull request #321 from mmp/setzero

More varied support for constant vectors from C++ backend.
This commit is contained in:
Jean-Luc Duprat
2012-07-09 08:57:05 -07:00
7 changed files with 330 additions and 104 deletions

View File

@@ -1098,22 +1098,31 @@ bool CWriter::printCast(unsigned opc, llvm::Type *SrcTy, llvm::Type *DstTy) {
}
// FIXME: generalize this/make it not so hard-coded?
static const char *lGetSmearFunc(llvm::Type *matchType) {
/** Construct the name of a function with the given base and returning a
vector of a given type. For example, if base is "foo" and matchType is
i16, this will return the string "__foo_i16".
*/
static const char *
lGetTypedFunc(const char *base, llvm::Type *matchType) {
char buf[64];
sprintf(buf, "__%s_", base);
switch (matchType->getTypeID()) {
case llvm::Type::FloatTyID: return "__smear_float";
case llvm::Type::DoubleTyID: return "__smear_double";
case llvm::Type::FloatTyID: strcat(buf, "float"); break;
case llvm::Type::DoubleTyID: strcat(buf, "double"); break;
case llvm::Type::IntegerTyID: {
switch (llvm::cast<llvm::IntegerType>(matchType)->getBitWidth()) {
case 1: return "__smear_i1";
case 8: return "__smear_i8";
case 16: return "__smear_i16";
case 32: return "__smear_i32";
case 64: return "__smear_i64";
case 1: strcat(buf, "i1"); break;
case 8: strcat(buf, "i8"); break;
case 16: strcat(buf, "i16"); break;
case 32: strcat(buf, "i32"); break;
case 64: strcat(buf, "i64"); break;
default: return NULL;
}
break;
}
default: return NULL;
}
return strdup(buf);
}
@@ -1458,64 +1467,63 @@ void CWriter::printConstant(llvm::Constant *CPV, bool Static) {
}
case llvm::Type::VectorTyID: {
llvm::VectorType *VT = llvm::dyn_cast<llvm::VectorType>(CPV->getType());
const char *smearFunc = lGetSmearFunc(VT->getElementType());
if (llvm::isa<llvm::ConstantAggregateZero>(CPV)) {
assert(smearFunc != NULL);
llvm::Constant *CZ = llvm::Constant::getNullValue(VT->getElementType());
Out << smearFunc << "(";
printType(Out, VT);
Out << "(), ";
printConstant(CZ, Static);
Out << ")";
// All zeros; call the __setzero_* function.
const char *setZeroFunc = lGetTypedFunc("setzero", VT->getElementType());
assert(setZeroFunc != NULL);
Out << setZeroFunc << "()";
}
else if (llvm::ConstantVector *CV = llvm::dyn_cast<llvm::ConstantVector>(CPV)) {
llvm::Constant *splatValue = CV->getSplatValue();
if (splatValue != NULL && smearFunc != NULL) {
Out << smearFunc << "(";
printType(Out, VT);
Out << "(), ";
printConstant(splatValue, Static);
Out << ")";
}
else {
printType(Out, CPV->getType());
Out << "(";
printConstantVector(CV, Static);
Out << ")";
}
else if (llvm::isa<llvm::UndefValue>(CPV)) {
// Undefined value; call __undef_* so that we can potentially pass
// this information along..
const char *undefFunc = lGetTypedFunc("undef", VT->getElementType());
assert(undefFunc != NULL);
Out << undefFunc << "()";
}
#ifndef LLVM_3_0
else if (llvm::ConstantDataVector *CDV = llvm::dyn_cast<llvm::ConstantDataVector>(CPV)) {
llvm::Constant *splatValue = CDV->getSplatValue();
if (splatValue != NULL && smearFunc != NULL) {
Out << smearFunc << "(";
printType(Out, VT);
Out << "(), ";
printConstant(splatValue, Static);
Out << ")";
}
else {
printType(Out, CPV->getType());
Out << "(";
printConstantDataSequential(CDV, Static);
Out << ")";
}
}
#endif // !LLVM_3_0
else {
assert(llvm::isa<llvm::UndefValue>(CPV));
llvm::Constant *CZ = llvm::Constant::getNullValue(VT->getElementType());
printType(Out, CPV->getType());
Out << "(";
printConstant(CZ, Static);
for (unsigned i = 1, e = VT->getNumElements(); i != e; ++i) {
Out << ", ";
printConstant(CZ, Static);
}
Out << ")";
const char *smearFunc = lGetTypedFunc("smear", VT->getElementType());
if (llvm::ConstantVector *CV = llvm::dyn_cast<llvm::ConstantVector>(CPV)) {
llvm::Constant *splatValue = CV->getSplatValue();
if (splatValue != NULL && smearFunc != NULL) {
// If it's a basic type and has a __smear_* function, then
// call that.
Out << smearFunc << "(";
printConstant(splatValue, Static);
Out << ")";
}
else {
// Otherwise call the constructor for the type
printType(Out, CPV->getType());
Out << "(";
printConstantVector(CV, Static);
Out << ")";
}
}
#ifndef LLVM_3_0
// LLVM 3.1 and beyond have a different representation of constant vectors..
else if (llvm::ConstantDataVector *CDV =
llvm::dyn_cast<llvm::ConstantDataVector>(CPV)) {
llvm::Constant *splatValue = CDV->getSplatValue();
if (splatValue != NULL && smearFunc != NULL) {
Out << smearFunc << "(";
printConstant(splatValue, Static);
Out << ")";
}
else {
printType(Out, CPV->getType());
Out << "(";
printConstantDataSequential(CDV, Static);
Out << ")";
}
}
#endif // !LLVM_3_0
else {
llvm::report_fatal_error("Unexpected vector type");
}
}
break;
}
case llvm::Type::StructTyID:
@@ -4233,7 +4241,7 @@ char SmearCleanupPass::ID = 0;
static int
lChainLength(llvm::InsertElementInst *inst) {
lChainLength(llvm::InsertElementInst *inst) {
int length = 0;
while (inst != NULL) {
++length;
@@ -4281,24 +4289,26 @@ SmearCleanupPass::runOnBasicBlock(llvm::BasicBlock &bb) {
{
llvm::Type *matchType = toMatch->getType();
const char *smearFuncName = lGetSmearFunc(matchType);
const char *smearFuncName = lGetTypedFunc("smear", matchType);
if (smearFuncName != NULL) {
llvm::Function *smearFunc = module->getFunction(smearFuncName);
if (smearFunc == NULL) {
// Declare the smar function if needed; it takes a single
// scalar parameter and returns a vector of the same
// parameter type.
llvm::Constant *sf =
module->getOrInsertFunction(smearFuncName, iter->getType(),
iter->getType(), matchType, NULL);
matchType, NULL);
smearFunc = llvm::dyn_cast<llvm::Function>(sf);
assert(smearFunc != NULL);
smearFunc->setDoesNotThrow(true);
smearFunc->setDoesNotAccessMemory(true);
}
llvm::Value *undefResult = llvm::UndefValue::get(vt);
assert(smearFunc != NULL);
llvm::Value *args[2] = { undefResult, toMatch };
llvm::ArrayRef<llvm::Value *> argArray(&args[0], &args[2]);
llvm::Value *args[1] = { toMatch };
llvm::ArrayRef<llvm::Value *> argArray(&args[0], &args[1]);
llvm::Instruction *smearCall =
llvm::CallInst::Create(smearFunc, argArray, LLVMGetName(toMatch, "_smear"),
(llvm::Instruction *)NULL);