Changes in cbackend.cpp to match broadcast generation changes
This commit is contained in:
142
cbackend.cpp
142
cbackend.cpp
@@ -4395,16 +4395,21 @@ public:
|
|||||||
|
|
||||||
static char ID;
|
static char ID;
|
||||||
llvm::Module *module;
|
llvm::Module *module;
|
||||||
int vectorWidth;
|
unsigned int vectorWidth;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int ChainLength(llvm::InsertElementInst *inst) const;
|
||||||
|
llvm::Value *getInsertChainSmearValue(llvm::Instruction* inst) const;
|
||||||
|
llvm::Value *getShuffleSmearValue(llvm::Instruction* inst) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
char SmearCleanupPass::ID = 0;
|
char SmearCleanupPass::ID = 0;
|
||||||
|
|
||||||
|
|
||||||
static int
|
unsigned int
|
||||||
lChainLength(llvm::InsertElementInst *inst) {
|
SmearCleanupPass::ChainLength(llvm::InsertElementInst *inst) const {
|
||||||
int length = 0;
|
unsigned int length = 0;
|
||||||
while (inst != NULL) {
|
while (inst != NULL) {
|
||||||
++length;
|
++length;
|
||||||
inst = llvm::dyn_cast<llvm::InsertElementInst>(inst->getOperand(0));
|
inst = llvm::dyn_cast<llvm::InsertElementInst>(inst->getOperand(0));
|
||||||
@@ -4413,45 +4418,105 @@ lChainLength(llvm::InsertElementInst *inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
llvm::Value *
|
||||||
|
SmearCleanupPass::getInsertChainSmearValue(llvm::Instruction* inst) const {
|
||||||
|
// TODO: we don't check indexes where we do insertion, so we may trigger
|
||||||
|
// transformation for a wrong chain.
|
||||||
|
// This way of doing broadcast is obsolete and should be probably removed
|
||||||
|
// some day.
|
||||||
|
|
||||||
|
llvm::InsertElementInst *insertInst =
|
||||||
|
llvm::dyn_cast<llvm::InsertElementInst>(inst);
|
||||||
|
if (!insertInst) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We consider only chians of vectorWidth length.
|
||||||
|
if (ChainLength(insertInst) != vectorWidth) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: we only want to do this to vectors with width equal to
|
||||||
|
// the target vector width. But we can't easily get that here, so
|
||||||
|
// for now we at least avoid one case where we definitely don't
|
||||||
|
// want to do this.
|
||||||
|
llvm::VectorType *vt = llvm::dyn_cast<llvm::VectorType>(insertInst->getType());
|
||||||
|
if (vt->getNumElements() == 1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value *smearValue = NULL;
|
||||||
|
while (insertInst != NULL) {
|
||||||
|
// operand 1 is inserted value
|
||||||
|
llvm::Value *insertValue = insertInst->getOperand(1);
|
||||||
|
if (smearValue == NULL) {
|
||||||
|
smearValue = insertValue;
|
||||||
|
}
|
||||||
|
else if (smearValue != insertValue) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// operand 0 is a vector to insert into.
|
||||||
|
insertInst =
|
||||||
|
llvm::dyn_cast<llvm::InsertElementInst>(insertInst->getOperand(0));
|
||||||
|
}
|
||||||
|
assert(smearValue != NULL);
|
||||||
|
|
||||||
|
return smearValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
llvm::Value *
|
||||||
|
SmearCleanupPass::getShuffleSmearValue(llvm::Instruction* inst) const {
|
||||||
|
llvm::ShuffleVectorInst *shuffleInst =
|
||||||
|
llvm::dyn_cast<llvm::ShuffleVectorInst>(inst);
|
||||||
|
if (!shuffleInst) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Constant* mask =
|
||||||
|
llvm::dyn_cast<llvm::Constant>(shuffleInst->getOperand(2));
|
||||||
|
|
||||||
|
// Check that the shuffle is a broadcast of the first element of the first vector,
|
||||||
|
// i.e. mask vector is all-zeros vector of expected size.
|
||||||
|
if (!(mask &&
|
||||||
|
mask->isNullValue() &&
|
||||||
|
llvm::dyn_cast<llvm::VectorType>(mask->getType())->getNumElements() == vectorWidth)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
llvm::InsertElementInst *insertInst =
|
||||||
|
llvm::dyn_cast<llvm::InsertElementInst>(shuffleInst->getOperand(0));
|
||||||
|
|
||||||
|
// Check that it's an InsertElementInst that inserts a value to first element.
|
||||||
|
if (!(insertInst &&
|
||||||
|
llvm::isa<llvm::Constant>(insertInst->getOperand(2)) &&
|
||||||
|
llvm::dyn_cast<llvm::Constant>(insertInst->getOperand(2))->isNullValue())) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value *result = insertInst->getOperand(1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SmearCleanupPass::runOnBasicBlock(llvm::BasicBlock &bb) {
|
SmearCleanupPass::runOnBasicBlock(llvm::BasicBlock &bb) {
|
||||||
bool modifiedAny = false;
|
bool modifiedAny = false;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
for (llvm::BasicBlock::iterator iter = bb.begin(), e = bb.end(); iter != e; ++iter) {
|
for (llvm::BasicBlock::iterator iter = bb.begin(), e = bb.end(); iter != e; ++iter) {
|
||||||
llvm::InsertElementInst *insertInst =
|
llvm::Value *smearValue = NULL;
|
||||||
llvm::dyn_cast<llvm::InsertElementInst>(&*iter);
|
|
||||||
if (insertInst == NULL)
|
if (!(smearValue = getInsertChainSmearValue(iter)) &&
|
||||||
|
!(smearValue = getShuffleSmearValue(iter))) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Only do this on the last insert in a chain...
|
|
||||||
if (lChainLength(insertInst) != vectorWidth)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// FIXME: we only want to do this to vectors with width equal to
|
|
||||||
// the target vector width. But we can't easily get that here, so
|
|
||||||
// for now we at least avoid one case where we definitely don't
|
|
||||||
// want to do this.
|
|
||||||
llvm::VectorType *vt = llvm::dyn_cast<llvm::VectorType>(insertInst->getType());
|
|
||||||
if (vt->getNumElements() == 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
llvm::Value *toMatch = NULL;
|
|
||||||
while (insertInst != NULL) {
|
|
||||||
llvm::Value *insertValue = insertInst->getOperand(1);
|
|
||||||
if (toMatch == NULL)
|
|
||||||
toMatch = insertValue;
|
|
||||||
else if (toMatch != insertValue)
|
|
||||||
goto not_equal;
|
|
||||||
|
|
||||||
insertInst =
|
|
||||||
llvm::dyn_cast<llvm::InsertElementInst>(insertInst->getOperand(0));
|
|
||||||
}
|
}
|
||||||
assert(toMatch != NULL);
|
|
||||||
|
|
||||||
{
|
llvm::Type *smearType = smearValue->getType();
|
||||||
llvm::Type *matchType = toMatch->getType();
|
const char *smearFuncName = lGetTypedFunc("smear", smearType, vectorWidth);
|
||||||
const char *smearFuncName = lGetTypedFunc("smear", matchType, vectorWidth);
|
|
||||||
if (smearFuncName != NULL) {
|
if (smearFuncName != NULL) {
|
||||||
llvm::Function *smearFunc = module->getFunction(smearFuncName);
|
llvm::Function *smearFunc = module->getFunction(smearFuncName);
|
||||||
if (smearFunc == NULL) {
|
if (smearFunc == NULL) {
|
||||||
@@ -4460,7 +4525,7 @@ SmearCleanupPass::runOnBasicBlock(llvm::BasicBlock &bb) {
|
|||||||
// parameter type.
|
// parameter type.
|
||||||
llvm::Constant *sf =
|
llvm::Constant *sf =
|
||||||
module->getOrInsertFunction(smearFuncName, iter->getType(),
|
module->getOrInsertFunction(smearFuncName, iter->getType(),
|
||||||
matchType, NULL);
|
smearType, NULL);
|
||||||
smearFunc = llvm::dyn_cast<llvm::Function>(sf);
|
smearFunc = llvm::dyn_cast<llvm::Function>(sf);
|
||||||
assert(smearFunc != NULL);
|
assert(smearFunc != NULL);
|
||||||
#if defined(LLVM_3_1)
|
#if defined(LLVM_3_1)
|
||||||
@@ -4473,10 +4538,10 @@ SmearCleanupPass::runOnBasicBlock(llvm::BasicBlock &bb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(smearFunc != NULL);
|
assert(smearFunc != NULL);
|
||||||
llvm::Value *args[1] = { toMatch };
|
llvm::Value *args[1] = { smearValue };
|
||||||
llvm::ArrayRef<llvm::Value *> argArray(&args[0], &args[1]);
|
llvm::ArrayRef<llvm::Value *> argArray(&args[0], &args[1]);
|
||||||
llvm::Instruction *smearCall =
|
llvm::Instruction *smearCall =
|
||||||
llvm::CallInst::Create(smearFunc, argArray, LLVMGetName(toMatch, "_smear"),
|
llvm::CallInst::Create(smearFunc, argArray, LLVMGetName(smearValue, "_smear"),
|
||||||
(llvm::Instruction *)NULL);
|
(llvm::Instruction *)NULL);
|
||||||
|
|
||||||
ReplaceInstWithInst(iter, smearCall);
|
ReplaceInstWithInst(iter, smearCall);
|
||||||
@@ -4484,9 +4549,6 @@ SmearCleanupPass::runOnBasicBlock(llvm::BasicBlock &bb) {
|
|||||||
modifiedAny = true;
|
modifiedAny = true;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
not_equal:
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifiedAny;
|
return modifiedAny;
|
||||||
|
|||||||
Reference in New Issue
Block a user