Add VSelMovMsk optimization pass.
Various peephole improvements to vector select instructions.
This commit is contained in:
91
opt.cpp
91
opt.cpp
@@ -84,6 +84,7 @@
|
|||||||
#endif // ISPC_IS_WINDOWS
|
#endif // ISPC_IS_WINDOWS
|
||||||
|
|
||||||
static llvm::Pass *CreateIntrinsicsOptPass();
|
static llvm::Pass *CreateIntrinsicsOptPass();
|
||||||
|
static llvm::Pass *CreateVSelMovmskOptPass();
|
||||||
static llvm::Pass *CreateGatherScatterFlattenPass();
|
static llvm::Pass *CreateGatherScatterFlattenPass();
|
||||||
static llvm::Pass *CreateGatherScatterImprovementsPass();
|
static llvm::Pass *CreateGatherScatterImprovementsPass();
|
||||||
static llvm::Pass *CreateLowerGatherScatterPass();
|
static llvm::Pass *CreateLowerGatherScatterPass();
|
||||||
@@ -291,6 +292,7 @@ Optimize(llvm::Module *module, int optLevel) {
|
|||||||
|
|
||||||
if (!g->opt.disableMaskAllOnOptimizations) {
|
if (!g->opt.disableMaskAllOnOptimizations) {
|
||||||
optPM.add(CreateIntrinsicsOptPass());
|
optPM.add(CreateIntrinsicsOptPass());
|
||||||
|
optPM.add(CreateVSelMovmskOptPass());
|
||||||
optPM.add(CreateMaskedStoreOptPass());
|
optPM.add(CreateMaskedStoreOptPass());
|
||||||
optPM.add(CreateMaskedLoadOptPass());
|
optPM.add(CreateMaskedLoadOptPass());
|
||||||
}
|
}
|
||||||
@@ -307,6 +309,7 @@ Optimize(llvm::Module *module, int optLevel) {
|
|||||||
optPM.add(llvm::createFunctionInliningPass());
|
optPM.add(llvm::createFunctionInliningPass());
|
||||||
optPM.add(llvm::createConstantPropagationPass());
|
optPM.add(llvm::createConstantPropagationPass());
|
||||||
optPM.add(CreateIntrinsicsOptPass());
|
optPM.add(CreateIntrinsicsOptPass());
|
||||||
|
optPM.add(CreateVSelMovmskOptPass());
|
||||||
|
|
||||||
#if defined(LLVM_2_9)
|
#if defined(LLVM_2_9)
|
||||||
llvm::createStandardModulePasses(&optPM, 3,
|
llvm::createStandardModulePasses(&optPM, 3,
|
||||||
@@ -323,6 +326,7 @@ Optimize(llvm::Module *module, int optLevel) {
|
|||||||
|
|
||||||
optPM.add(CreateIsCompileTimeConstantPass(true));
|
optPM.add(CreateIsCompileTimeConstantPass(true));
|
||||||
optPM.add(CreateIntrinsicsOptPass());
|
optPM.add(CreateIntrinsicsOptPass());
|
||||||
|
optPM.add(CreateVSelMovmskOptPass());
|
||||||
|
|
||||||
llvm::createStandardModulePasses(&optPM, 3,
|
llvm::createStandardModulePasses(&optPM, 3,
|
||||||
false /* opt size */,
|
false /* opt size */,
|
||||||
@@ -343,6 +347,7 @@ Optimize(llvm::Module *module, int optLevel) {
|
|||||||
|
|
||||||
optPM.add(CreateIsCompileTimeConstantPass(false));
|
optPM.add(CreateIsCompileTimeConstantPass(false));
|
||||||
optPM.add(CreateIntrinsicsOptPass());
|
optPM.add(CreateIntrinsicsOptPass());
|
||||||
|
optPM.add(CreateVSelMovmskOptPass());
|
||||||
|
|
||||||
builder.populateLTOPassManager(optPM, true /* internalize */,
|
builder.populateLTOPassManager(optPM, true /* internalize */,
|
||||||
true /* inline once again */);
|
true /* inline once again */);
|
||||||
@@ -729,6 +734,92 @@ CreateIntrinsicsOptPass() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/** This simple optimization pass looks for a vector select instruction
|
||||||
|
with an all-on or all-off constant mask, simplifying it to the
|
||||||
|
appropriate operand if so.
|
||||||
|
|
||||||
|
@todo The better thing to do would be to submit a patch to LLVM to get
|
||||||
|
these; they're presumably pretty simple patterns to match.
|
||||||
|
*/
|
||||||
|
class VSelMovmskOpt : public llvm::BasicBlockPass {
|
||||||
|
public:
|
||||||
|
VSelMovmskOpt()
|
||||||
|
: BasicBlockPass(ID) { }
|
||||||
|
|
||||||
|
const char *getPassName() const { return "Vector Select Optimization"; }
|
||||||
|
bool runOnBasicBlock(llvm::BasicBlock &BB);
|
||||||
|
|
||||||
|
static char ID;
|
||||||
|
};
|
||||||
|
|
||||||
|
char VSelMovmskOpt::ID = 0;
|
||||||
|
llvm::RegisterPass<VSelMovmskOpt> vsel("vector-select", "Vector Select Pass");
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
VSelMovmskOpt::runOnBasicBlock(llvm::BasicBlock &bb) {
|
||||||
|
bool modifiedAny = false;
|
||||||
|
|
||||||
|
restart:
|
||||||
|
for (llvm::BasicBlock::iterator iter = bb.begin(), e = bb.end(); iter != e; ++iter) {
|
||||||
|
// vector select wasn't available before 3.1...
|
||||||
|
#if defined(LLVM_3_1svn)
|
||||||
|
llvm::SelectInst *selectInst = llvm::dyn_cast<llvm::SelectInst>(&*iter);
|
||||||
|
if (selectInst != NULL && selectInst->getType()->isVectorTy()) {
|
||||||
|
llvm::Value *factor = selectInst->getOperand(0);
|
||||||
|
int mask = lGetMask(factor);
|
||||||
|
int allOnMask = (1 << g->target.vectorWidth) - 1;
|
||||||
|
llvm::Value *value = NULL;
|
||||||
|
if (mask == allOnMask)
|
||||||
|
// Mask all on -> replace with the first select value
|
||||||
|
value = selectInst->getOperand(1);
|
||||||
|
else if (mask == 0)
|
||||||
|
// Mask all off -> replace with the second select blend value
|
||||||
|
value = selectInst->getOperand(1);
|
||||||
|
|
||||||
|
if (value != NULL) {
|
||||||
|
llvm::ReplaceInstWithValue(iter->getParent()->getInstList(),
|
||||||
|
iter, value);
|
||||||
|
modifiedAny = true;
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // LLVM_3_1svn
|
||||||
|
|
||||||
|
llvm::CallInst *callInst = llvm::dyn_cast<llvm::CallInst>(&*iter);
|
||||||
|
if (callInst == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
llvm::Function *calledFunc = callInst->getCalledFunction();
|
||||||
|
if (calledFunc != m->module->getFunction("__movmsk"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int mask = lGetMask(callInst->getArgOperand(0));
|
||||||
|
if (mask != -1) {
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "mask %d\n", mask);
|
||||||
|
callInst->getArgOperand(0)->dump();
|
||||||
|
fprintf(stderr, "-----------\n");
|
||||||
|
#endif
|
||||||
|
llvm::ReplaceInstWithValue(iter->getParent()->getInstList(),
|
||||||
|
iter, LLVMInt32(mask));
|
||||||
|
modifiedAny = true;
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifiedAny;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static llvm::Pass *
|
||||||
|
CreateVSelMovmskOptPass() {
|
||||||
|
return new VSelMovmskOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// GatherScatterFlattenOpt
|
// GatherScatterFlattenOpt
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user