115 lines
4.5 KiB
C++
115 lines
4.5 KiB
C++
/*
|
|
Copyright (c) 2022-2023, Intel Corporation
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of Intel Corporation nor the names of its
|
|
contributors may be used to endorse or promote products derived from
|
|
this software without specific prior written permission.
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "IsCompileTimeConstant.h"
|
|
|
|
namespace ispc {
|
|
|
|
char IsCompileTimeConstantPass::ID = 0;
|
|
|
|
bool IsCompileTimeConstantPass::lowerCompileTimeConstant(llvm::BasicBlock &bb) {
|
|
DEBUG_START_BB("IsCompileTimeConstantPass");
|
|
|
|
llvm::Function *funcs[] = {m->module->getFunction("__is_compile_time_constant_mask"),
|
|
m->module->getFunction("__is_compile_time_constant_uniform_int32"),
|
|
m->module->getFunction("__is_compile_time_constant_varying_int32")};
|
|
|
|
bool modifiedAny = false;
|
|
restart:
|
|
for (llvm::BasicBlock::iterator i = bb.begin(), e = bb.end(); i != e; ++i) {
|
|
// Iterate through the instructions looking for calls to the
|
|
// __is_compile_time_constant_*() functions
|
|
llvm::CallInst *callInst = llvm::dyn_cast<llvm::CallInst>(&*i);
|
|
if (callInst == NULL)
|
|
continue;
|
|
|
|
int j;
|
|
int nFuncs = sizeof(funcs) / sizeof(funcs[0]);
|
|
for (j = 0; j < nFuncs; ++j) {
|
|
if (funcs[j] != NULL && callInst->getCalledFunction() == funcs[j])
|
|
break;
|
|
}
|
|
if (j == nFuncs)
|
|
// not a __is_compile_time_constant_* function
|
|
continue;
|
|
|
|
// This optimization pass can be disabled with both the (poorly
|
|
// named) disableGatherScatterFlattening option and
|
|
// disableMaskAllOnOptimizations.
|
|
if (g->opt.disableGatherScatterFlattening || g->opt.disableMaskAllOnOptimizations) {
|
|
ReplaceInstWithValueWrapper(i, LLVMFalse);
|
|
modifiedAny = true;
|
|
goto restart;
|
|
}
|
|
|
|
// Is it a constant? Bingo, turn the call's value into a constant
|
|
// true value.
|
|
llvm::Value *operand = callInst->getArgOperand(0);
|
|
if (llvm::isa<llvm::Constant>(operand)) {
|
|
ReplaceInstWithValueWrapper(i, LLVMTrue);
|
|
modifiedAny = true;
|
|
goto restart;
|
|
}
|
|
|
|
// This pass runs multiple times during optimization. Up until the
|
|
// very last time, it only replaces the call with a 'true' if the
|
|
// value is known to be constant and otherwise leaves the call
|
|
// alone, in case further optimization passes can help resolve its
|
|
// value. The last time through, it eventually has to give up, and
|
|
// replaces any remaining ones with 'false' constants.
|
|
if (isLastTry) {
|
|
ReplaceInstWithValueWrapper(i, LLVMFalse);
|
|
modifiedAny = true;
|
|
goto restart;
|
|
}
|
|
}
|
|
|
|
DEBUG_END_BB("IsCompileTimeConstantPass");
|
|
|
|
return modifiedAny;
|
|
}
|
|
|
|
bool IsCompileTimeConstantPass::runOnFunction(llvm::Function &F) {
|
|
|
|
llvm::TimeTraceScope FuncScope("IsCompileTimeConstantPass::runOnFunction", F.getName());
|
|
bool modifiedAny = false;
|
|
for (llvm::BasicBlock &BB : F) {
|
|
modifiedAny |= lowerCompileTimeConstant(BB);
|
|
}
|
|
return modifiedAny;
|
|
}
|
|
|
|
llvm::Pass *CreateIsCompileTimeConstantPass(bool isLastTry) { return new IsCompileTimeConstantPass(isLastTry); }
|
|
|
|
} // namespace ispc
|