Commit 6fcbdddb by Karl Schimpf

Disable Subzero IR generation for performance testing.

This CL allows one to time Subzero's bitcode parsing without IR generation (other than types, function declarations, and uninitialized global variables) for performance testing. BUG=None R=jvoung@chromium.org Review URL: https://codereview.chromium.org/696383004
parent 0faec4c9
...@@ -51,10 +51,12 @@ CXX_DEFINES = ...@@ -51,10 +51,12 @@ CXX_DEFINES =
ifdef MINIMAL ifdef MINIMAL
OBJDIR := $(OBJDIR)+Min OBJDIR := $(OBJDIR)+Min
CXX_DEFINES += -DALLOW_TEXT_ASM=0 -DALLOW_DUMP=0 -DALLOW_LLVM_CL=0 \ CXX_DEFINES += -DALLOW_TEXT_ASM=0 -DALLOW_DUMP=0 -DALLOW_LLVM_CL=0 \
-DALLOW_LLVM_IR=0 -DALLOW_LLVM_IR_AS_INPUT=0 -DALLOW_LLVM_IR=0 -DALLOW_LLVM_IR_AS_INPUT=0 \
-DALLOW_DISABLE_IR_GEN=0
else else
CXX_DEFINES += -DALLOW_TEXT_ASM=1 -DALLOW_DUMP=1 -DALLOW_LLVM_CL=1 \ CXX_DEFINES += -DALLOW_TEXT_ASM=1 -DALLOW_DUMP=1 -DALLOW_LLVM_CL=1 \
-DALLOW_LLVM_IR=1 -DALLOW_LLVM_IR_AS_INPUT=1 -DALLOW_LLVM_IR=1 -DALLOW_LLVM_IR_AS_INPUT=1 \
-DALLOW_DISABLE_IR_GEN=1
endif endif
ifdef NOASSERT ifdef NOASSERT
......
...@@ -47,6 +47,7 @@ def main(): ...@@ -47,6 +47,7 @@ def main():
action='store_true', action='store_true',
help='Trace command that generates ICE instructions') help='Trace command that generates ICE instructions')
argparser.add_argument('--args', '-a', nargs=argparse.REMAINDER, argparser.add_argument('--args', '-a', nargs=argparse.REMAINDER,
default=[],
help='Remaining arguments are passed to llvm2ice') help='Remaining arguments are passed to llvm2ice')
args = argparser.parse_args() args = argparser.parse_args()
...@@ -78,7 +79,6 @@ def main(): ...@@ -78,7 +79,6 @@ def main():
cmd += ['--build-on-read=0'] cmd += ['--build-on-read=0']
else: else:
cmd += ['--build-on-read=1'] cmd += ['--build-on-read=1']
if args.args:
cmd += args.args cmd += args.args
if args.llvm_source: if args.llvm_source:
cmd += [llfile] cmd += [llfile]
......
...@@ -31,7 +31,10 @@ Cfg::Cfg(GlobalContext *Ctx) ...@@ -31,7 +31,10 @@ Cfg::Cfg(GlobalContext *Ctx)
VMetadata(new VariablesMetadata(this)), VMetadata(new VariablesMetadata(this)),
TargetAssembler( TargetAssembler(
TargetLowering::createAssembler(Ctx->getTargetArch(), this)), TargetLowering::createAssembler(Ctx->getTargetArch(), this)),
CurrentNode(NULL) {} CurrentNode(NULL) {
assert(!Ctx->isIRGenerationDisabled() &&
"Attempt to build cfg when IR generation disabled");
}
Cfg::~Cfg() {} Cfg::~Cfg() {}
......
...@@ -26,8 +26,9 @@ public: ...@@ -26,8 +26,9 @@ public:
UseIntegratedAssembler(false), UseSandboxing(false), UseIntegratedAssembler(false), UseSandboxing(false),
PhiEdgeSplit(false), DecorateAsm(false), DumpStats(false), PhiEdgeSplit(false), DecorateAsm(false), DumpStats(false),
AllowUninitializedGlobals(false), TimeEachFunction(false), AllowUninitializedGlobals(false), TimeEachFunction(false),
DefaultGlobalPrefix(""), DefaultFunctionPrefix(""), TimingFocusOn(""), DisableIRGeneration(false), DefaultGlobalPrefix(""),
VerboseFocusOn(""), TranslateOnly("") {} DefaultFunctionPrefix(""), TimingFocusOn(""), VerboseFocusOn(""),
TranslateOnly("") {}
bool DisableInternal; bool DisableInternal;
bool SubzeroTimingEnabled; bool SubzeroTimingEnabled;
bool DisableTranslation; bool DisableTranslation;
...@@ -40,6 +41,7 @@ public: ...@@ -40,6 +41,7 @@ public:
bool DumpStats; bool DumpStats;
bool AllowUninitializedGlobals; bool AllowUninitializedGlobals;
bool TimeEachFunction; bool TimeEachFunction;
bool DisableIRGeneration;
IceString DefaultGlobalPrefix; IceString DefaultGlobalPrefix;
IceString DefaultFunctionPrefix; IceString DefaultFunctionPrefix;
IceString TimingFocusOn; IceString TimingFocusOn;
......
...@@ -140,6 +140,10 @@ public: ...@@ -140,6 +140,10 @@ public:
const ClFlags &getFlags() const { return Flags; } const ClFlags &getFlags() const { return Flags; }
bool isIRGenerationDisabled() const {
return ALLOW_DISABLE_IR_GEN ? getFlags().DisableIRGeneration : false;
}
// Allocate data of type T using the global allocator. // Allocate data of type T using the global allocator.
template <typename T> T *allocate() { return Allocator.Allocate<T>(); } template <typename T> T *allocate() { return Allocator.Allocate<T>(); }
......
...@@ -137,6 +137,8 @@ class ConstantPrimitive : public Constant { ...@@ -137,6 +137,8 @@ class ConstantPrimitive : public Constant {
public: public:
static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value, static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value,
uint32_t PoolEntryID) { uint32_t PoolEntryID) {
assert(!Ctx->isIRGenerationDisabled() &&
"Attempt to build primitive constant when IR generation disabled");
return new (Ctx->allocate<ConstantPrimitive>()) return new (Ctx->allocate<ConstantPrimitive>())
ConstantPrimitive(Ty, Value, PoolEntryID); ConstantPrimitive(Ty, Value, PoolEntryID);
} }
...@@ -206,6 +208,8 @@ public: ...@@ -206,6 +208,8 @@ public:
static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
const RelocatableTuple &Tuple, const RelocatableTuple &Tuple,
uint32_t PoolEntryID) { uint32_t PoolEntryID) {
assert(!Ctx->isIRGenerationDisabled() &&
"Attempt to build relocatable constant when IR generation disabled");
return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
} }
...@@ -246,6 +250,8 @@ class ConstantUndef : public Constant { ...@@ -246,6 +250,8 @@ class ConstantUndef : public Constant {
public: public:
static ConstantUndef *create(GlobalContext *Ctx, Type Ty, static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
uint32_t PoolEntryID) { uint32_t PoolEntryID) {
assert(!Ctx->isIRGenerationDisabled() &&
"Attempt to build undefined constant when IR generation disabled");
return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID); return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID);
} }
......
...@@ -201,6 +201,12 @@ public: ...@@ -201,6 +201,12 @@ public:
/// Changes the size of the type list to the given size. /// Changes the size of the type list to the given size.
void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); } void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); }
/// Returns true if generation of Subzero IR is disabled.
bool isIRGenerationDisabled() const {
return ALLOW_DISABLE_IR_GEN ? Translator.getFlags().DisableIRGeneration
: false;
}
/// Returns the undefined type associated with type ID. /// Returns the undefined type associated with type ID.
/// Note: Returns extended type ready to be defined. /// Note: Returns extended type ready to be defined.
ExtendedType *getTypeByIDForDefining(unsigned ID) { ExtendedType *getTypeByIDForDefining(unsigned ID) {
...@@ -284,6 +290,11 @@ public: ...@@ -284,6 +290,11 @@ public:
if (C != nullptr) if (C != nullptr)
return C; return C;
if (isIRGenerationDisabled()) {
ValueIDConstants[ID] = nullptr;
return nullptr;
}
// If reached, no such constant exists, create one. // If reached, no such constant exists, create one.
// TODO(kschimpf) Don't get addresses of intrinsic function declarations. // TODO(kschimpf) Don't get addresses of intrinsic function declarations.
Ice::GlobalDeclaration *Decl = nullptr; Ice::GlobalDeclaration *Decl = nullptr;
...@@ -523,6 +534,11 @@ protected: ...@@ -523,6 +534,11 @@ protected:
const Ice::ClFlags &getFlags() const { return getTranslator().getFlags(); } const Ice::ClFlags &getFlags() const { return getTranslator().getFlags(); }
bool isIRGenerationDisabled() const {
return ALLOW_DISABLE_IR_GEN ? getTranslator().getFlags().DisableIRGeneration
: false;
}
// Generates an error Message with the bit address prefixed to it. // Generates an error Message with the bit address prefixed to it.
bool Error(const std::string &Message) override { bool Error(const std::string &Message) override {
uint64_t Bit = Record.GetStartBit() + Context->getHeaderSize() * 8; uint64_t Bit = Record.GetStartBit() + Context->getHeaderSize() * 8;
...@@ -811,6 +827,8 @@ public: ...@@ -811,6 +827,8 @@ public:
Ice::VariableDeclaration::create(getTranslator().getContext())), Ice::VariableDeclaration::create(getTranslator().getContext())),
CurGlobalVar(DummyGlobalVar) {} CurGlobalVar(DummyGlobalVar) {}
~GlobalsParser() final {}
private: private:
Ice::TimerMarker Timer; Ice::TimerMarker Timer;
// Keeps track of how many initializers are expected for the global variable // Keeps track of how many initializers are expected for the global variable
...@@ -881,10 +899,12 @@ void GlobalsParser::ProcessRecord() { ...@@ -881,10 +899,12 @@ void GlobalsParser::ProcessRecord() {
if (!isValidRecordSize(2, "Globals variable")) if (!isValidRecordSize(2, "Globals variable"))
return; return;
verifyNoMissingInitializers(); verifyNoMissingInitializers();
if (!isIRGenerationDisabled()) {
InitializersNeeded = 1; InitializersNeeded = 1;
CurGlobalVar = Context->getGlobalVariableByID(NextGlobalID); CurGlobalVar = Context->getGlobalVariableByID(NextGlobalID);
CurGlobalVar->setAlignment((1 << Values[0]) >> 1); CurGlobalVar->setAlignment((1 << Values[0]) >> 1);
CurGlobalVar->setIsConstant(Values[1] != 0); CurGlobalVar->setIsConstant(Values[1] != 0);
}
++NextGlobalID; ++NextGlobalID;
return; return;
} }
...@@ -903,12 +923,16 @@ void GlobalsParser::ProcessRecord() { ...@@ -903,12 +923,16 @@ void GlobalsParser::ProcessRecord() {
Error(StrBuf.str()); Error(StrBuf.str());
return; return;
} }
if (isIRGenerationDisabled())
return;
InitializersNeeded = Values[0]; InitializersNeeded = Values[0];
return; return;
case naclbitc::GLOBALVAR_ZEROFILL: { case naclbitc::GLOBALVAR_ZEROFILL: {
// ZEROFILL: [size] // ZEROFILL: [size]
if (!isValidRecordSize(1, "Globals zerofill")) if (!isValidRecordSize(1, "Globals zerofill"))
return; return;
if (isIRGenerationDisabled())
return;
CurGlobalVar->addInitializer( CurGlobalVar->addInitializer(
new Ice::VariableDeclaration::ZeroInitializer(Values[0])); new Ice::VariableDeclaration::ZeroInitializer(Values[0]));
return; return;
...@@ -917,6 +941,8 @@ void GlobalsParser::ProcessRecord() { ...@@ -917,6 +941,8 @@ void GlobalsParser::ProcessRecord() {
// DATA: [b0, b1, ...] // DATA: [b0, b1, ...]
if (!isValidRecordSizeAtLeast(1, "Globals data")) if (!isValidRecordSizeAtLeast(1, "Globals data"))
return; return;
if (isIRGenerationDisabled())
return;
CurGlobalVar->addInitializer( CurGlobalVar->addInitializer(
new Ice::VariableDeclaration::DataInitializer(Values)); new Ice::VariableDeclaration::DataInitializer(Values));
return; return;
...@@ -925,6 +951,8 @@ void GlobalsParser::ProcessRecord() { ...@@ -925,6 +951,8 @@ void GlobalsParser::ProcessRecord() {
// RELOC: [val, [addend]] // RELOC: [val, [addend]]
if (!isValidRecordSizeInRange(1, 2, "Globals reloc")) if (!isValidRecordSizeInRange(1, 2, "Globals reloc"))
return; return;
if (isIRGenerationDisabled())
return;
unsigned Index = Values[0]; unsigned Index = Values[0];
Ice::SizeT Offset = 0; Ice::SizeT Offset = 0;
if (Values.size() == 2) if (Values.size() == 2)
...@@ -1011,21 +1039,30 @@ public: ...@@ -1011,21 +1039,30 @@ public:
FunctionParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser) FunctionParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
: BlockParserBaseClass(BlockID, EnclosingParser), : BlockParserBaseClass(BlockID, EnclosingParser),
Timer(Ice::TimerStack::TT_parseFunctions, getTranslator().getContext()), Timer(Ice::TimerStack::TT_parseFunctions, getTranslator().getContext()),
Func(new Ice::Cfg(getTranslator().getContext())), CurrentBbIndex(0), Func(isIRGenerationDisabled()
FcnId(Context->getNextFunctionBlockValueID()), ? nullptr
: new Ice::Cfg(getTranslator().getContext())),
CurrentBbIndex(0), FcnId(Context->getNextFunctionBlockValueID()),
FuncDecl(Context->getFunctionByID(FcnId)), FuncDecl(Context->getFunctionByID(FcnId)),
CachedNumGlobalValueIDs(Context->getNumGlobalIDs()), CachedNumGlobalValueIDs(Context->getNumGlobalIDs()),
NextLocalInstIndex(Context->getNumGlobalIDs()), NextLocalInstIndex(Context->getNumGlobalIDs()),
InstIsTerminating(false) { InstIsTerminating(false) {
Func->setFunctionName(FuncDecl->getName());
if (getFlags().TimeEachFunction) if (getFlags().TimeEachFunction)
getTranslator().getContext()->pushTimer( getTranslator().getContext()->pushTimer(
getTranslator().getContext()->getTimerID( getTranslator().getContext()->getTimerID(
Ice::GlobalContext::TSK_Funcs, Func->getFunctionName()), Ice::GlobalContext::TSK_Funcs, FuncDecl->getName()),
Ice::GlobalContext::TSK_Funcs); Ice::GlobalContext::TSK_Funcs);
// TODO(kschimpf) Clean up API to add a function signature to // TODO(kschimpf) Clean up API to add a function signature to
// a CFG. // a CFG.
const Ice::FuncSigType &Signature = FuncDecl->getSignature(); const Ice::FuncSigType &Signature = FuncDecl->getSignature();
if (isIRGenerationDisabled()) {
CurrentNode = nullptr;
for (Ice::Type ArgType : Signature.getArgList()) {
(void)ArgType;
setNextLocalInstIndex(nullptr);
}
} else {
Func->setFunctionName(FuncDecl->getName());
Func->setReturnType(Signature.getReturnType()); Func->setReturnType(Signature.getReturnType());
Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage); Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage);
CurrentNode = InstallNextBasicBlock(); CurrentNode = InstallNextBasicBlock();
...@@ -1034,14 +1071,17 @@ public: ...@@ -1034,14 +1071,17 @@ public:
Func->addArg(getNextInstVar(ArgType)); Func->addArg(getNextInstVar(ArgType));
} }
} }
}
~FunctionParser() override {}; ~FunctionParser() final {}
// Set the next constant ID to the given constant C. void setNextLocalInstIndex(Ice::Operand *Op) {
void setNextConstantID(Ice::Constant *C) { setOperand(NextLocalInstIndex++, Op);
setOperand(NextLocalInstIndex++, C);
} }
// Set the next constant ID to the given constant C.
void setNextConstantID(Ice::Constant *C) { setNextLocalInstIndex(C); }
private: private:
Ice::TimerMarker Timer; Ice::TimerMarker Timer;
// The corresponding ICE function defined by the function block. // The corresponding ICE function defined by the function block.
...@@ -1068,6 +1108,15 @@ private: ...@@ -1068,6 +1108,15 @@ private:
// Upper limit of alignment power allowed by LLVM // Upper limit of alignment power allowed by LLVM
static const uint64_t AlignPowerLimit = 29; static const uint64_t AlignPowerLimit = 29;
void popTimerIfTimingEachFunction() const {
if (getFlags().TimeEachFunction) {
getTranslator().getContext()->popTimer(
getTranslator().getContext()->getTimerID(
Ice::GlobalContext::TSK_Funcs, Func->getFunctionName()),
Ice::GlobalContext::TSK_Funcs);
}
}
// Extracts the corresponding Alignment to use, given the AlignPower // Extracts the corresponding Alignment to use, given the AlignPower
// (i.e. 2**AlignPower, or 0 if AlignPower == 0). InstName is the // (i.e. 2**AlignPower, or 0 if AlignPower == 0). InstName is the
// name of the instruction the alignment appears in. // name of the instruction the alignment appears in.
...@@ -1093,10 +1142,14 @@ private: ...@@ -1093,10 +1142,14 @@ private:
void ExitBlock() override; void ExitBlock() override;
// Creates and appends a new basic block to the list of basic blocks. // Creates and appends a new basic block to the list of basic blocks.
Ice::CfgNode *InstallNextBasicBlock() { return Func->makeNode(); } Ice::CfgNode *InstallNextBasicBlock() {
assert(!isIRGenerationDisabled());
return Func->makeNode();
}
// Returns the Index-th basic block in the list of basic blocks. // Returns the Index-th basic block in the list of basic blocks.
Ice::CfgNode *getBasicBlock(uint32_t Index) { Ice::CfgNode *getBasicBlock(uint32_t Index) {
assert(!isIRGenerationDisabled());
const Ice::NodeList &Nodes = Func->getNodes(); const Ice::NodeList &Nodes = Func->getNodes();
if (Index >= Nodes.size()) { if (Index >= Nodes.size()) {
std::string Buffer; std::string Buffer;
...@@ -1115,6 +1168,7 @@ private: ...@@ -1115,6 +1168,7 @@ private:
// the branch references the entry block, it also generates a // the branch references the entry block, it also generates a
// corresponding error. // corresponding error.
Ice::CfgNode *getBranchBasicBlock(uint32_t Index) { Ice::CfgNode *getBranchBasicBlock(uint32_t Index) {
assert(!isIRGenerationDisabled());
if (Index == 0) { if (Index == 0) {
Error("Branch to entry block not allowed"); Error("Branch to entry block not allowed");
// TODO(kschimpf) Remove error recovery once implementation complete. // TODO(kschimpf) Remove error recovery once implementation complete.
...@@ -1124,6 +1178,7 @@ private: ...@@ -1124,6 +1178,7 @@ private:
// Generate an instruction variable with type Ty. // Generate an instruction variable with type Ty.
Ice::Variable *createInstVar(Ice::Type Ty) { Ice::Variable *createInstVar(Ice::Type Ty) {
assert(!isIRGenerationDisabled());
if (Ty == Ice::IceType_void) { if (Ty == Ice::IceType_void) {
Error("Can't define instruction value using type void"); Error("Can't define instruction value using type void");
// Recover since we can't throw an exception. // Recover since we can't throw an exception.
...@@ -1134,6 +1189,7 @@ private: ...@@ -1134,6 +1189,7 @@ private:
// Generates the next available local variable using the given type. // Generates the next available local variable using the given type.
Ice::Variable *getNextInstVar(Ice::Type Ty) { Ice::Variable *getNextInstVar(Ice::Type Ty) {
assert(!isIRGenerationDisabled());
assert(NextLocalInstIndex >= CachedNumGlobalValueIDs); assert(NextLocalInstIndex >= CachedNumGlobalValueIDs);
// Before creating one, see if a forwardtyperef has already defined it. // Before creating one, see if a forwardtyperef has already defined it.
uint32_t LocalIndex = NextLocalInstIndex - CachedNumGlobalValueIDs; uint32_t LocalIndex = NextLocalInstIndex - CachedNumGlobalValueIDs;
...@@ -1191,6 +1247,8 @@ private: ...@@ -1191,6 +1247,8 @@ private:
} }
Ice::Operand *Op = LocalOperands[LocalIndex]; Ice::Operand *Op = LocalOperands[LocalIndex];
if (Op == nullptr) { if (Op == nullptr) {
if (isIRGenerationDisabled())
return nullptr;
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
StrBuf << "Value index " << Index << " not defined!"; StrBuf << "Value index " << Index << " not defined!";
...@@ -1202,7 +1260,7 @@ private: ...@@ -1202,7 +1260,7 @@ private:
// Sets element Index (in the local operands list) to Op. // Sets element Index (in the local operands list) to Op.
void setOperand(uint32_t Index, Ice::Operand *Op) { void setOperand(uint32_t Index, Ice::Operand *Op) {
assert(Op); assert(Op || isIRGenerationDisabled());
// Check if simple push works. // Check if simple push works.
uint32_t LocalIndex = Index - CachedNumGlobalValueIDs; uint32_t LocalIndex = Index - CachedNumGlobalValueIDs;
if (LocalIndex == LocalOperands.size()) { if (LocalIndex == LocalOperands.size()) {
...@@ -1633,6 +1691,10 @@ void FunctionParser::ReportInvalidBinopOpcode(unsigned Opcode, Ice::Type Ty) { ...@@ -1633,6 +1691,10 @@ void FunctionParser::ReportInvalidBinopOpcode(unsigned Opcode, Ice::Type Ty) {
} }
void FunctionParser::ExitBlock() { void FunctionParser::ExitBlock() {
if (isIRGenerationDisabled()) {
popTimerIfTimingEachFunction();
return;
}
// Before translating, check for blocks without instructions, and // Before translating, check for blocks without instructions, and
// insert unreachable. This shouldn't happen, but be safe. // insert unreachable. This shouldn't happen, but be safe.
unsigned Index = 0; unsigned Index = 0;
...@@ -1654,11 +1716,7 @@ void FunctionParser::ExitBlock() { ...@@ -1654,11 +1716,7 @@ void FunctionParser::ExitBlock() {
// for such parsing errors. // for such parsing errors.
if (Context->getNumErrors() == 0) if (Context->getNumErrors() == 0)
getTranslator().translateFcn(Func); getTranslator().translateFcn(Func);
if (getFlags().TimeEachFunction) popTimerIfTimingEachFunction();
getTranslator().getContext()->popTimer(
getTranslator().getContext()->getTimerID(Ice::GlobalContext::TSK_Funcs,
Func->getFunctionName()),
Ice::GlobalContext::TSK_Funcs);
} }
void FunctionParser::ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op, void FunctionParser::ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op,
...@@ -1671,9 +1729,14 @@ void FunctionParser::ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op, ...@@ -1671,9 +1729,14 @@ void FunctionParser::ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op,
} }
void FunctionParser::ProcessRecord() { void FunctionParser::ProcessRecord() {
// Note: To better separate parse/IR generation times, when IR generation
// is disabled we do the following:
// 1) Delay exiting until after we extract operands.
// 2) return before we access operands, since all operands will be a nullptr.
const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
if (InstIsTerminating) { if (InstIsTerminating) {
InstIsTerminating = false; InstIsTerminating = false;
if (!isIRGenerationDisabled())
CurrentNode = getBasicBlock(++CurrentBbIndex); CurrentNode = getBasicBlock(++CurrentBbIndex);
} }
// The base index for relative indexing. // The base index for relative indexing.
...@@ -1683,16 +1746,18 @@ void FunctionParser::ProcessRecord() { ...@@ -1683,16 +1746,18 @@ void FunctionParser::ProcessRecord() {
// DECLAREBLOCKS: [n] // DECLAREBLOCKS: [n]
if (!isValidRecordSize(1, "function block count")) if (!isValidRecordSize(1, "function block count"))
return; return;
if (Func->getNodes().size() != 1) {
Error("Duplicate function block count record");
return;
}
uint32_t NumBbs = Values[0]; uint32_t NumBbs = Values[0];
if (NumBbs == 0) { if (NumBbs == 0) {
Error("Functions must contain at least one basic block."); Error("Functions must contain at least one basic block.");
// TODO(kschimpf) Remove error recovery once implementation complete. // TODO(kschimpf) Remove error recovery once implementation complete.
NumBbs = 1; NumBbs = 1;
} }
if (isIRGenerationDisabled())
return;
if (Func->getNodes().size() != 1) {
Error("Duplicate function block count record");
return;
}
// Install the basic blocks, skipping bb0 which was created in the // Install the basic blocks, skipping bb0 which was created in the
// constructor. // constructor.
for (size_t i = 1; i < NumBbs; ++i) for (size_t i = 1; i < NumBbs; ++i)
...@@ -1705,6 +1770,11 @@ void FunctionParser::ProcessRecord() { ...@@ -1705,6 +1770,11 @@ void FunctionParser::ProcessRecord() {
return; return;
Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex); Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex);
Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex); Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex);
if (isIRGenerationDisabled()) {
assert(Op1 == nullptr && Op2 == nullptr);
setNextLocalInstIndex(nullptr);
return;
}
Ice::Type Type1 = Op1->getType(); Ice::Type Type1 = Op1->getType();
Ice::Type Type2 = Op2->getType(); Ice::Type Type2 = Op2->getType();
if (Type1 != Type2) { if (Type1 != Type2) {
...@@ -1740,6 +1810,11 @@ void FunctionParser::ProcessRecord() { ...@@ -1740,6 +1810,11 @@ void FunctionParser::ProcessRecord() {
appendErrorInstruction(CastType); appendErrorInstruction(CastType);
return; return;
} }
if (isIRGenerationDisabled()) {
assert(Src == nullptr);
setNextLocalInstIndex(nullptr);
return;
}
Ice::Type SrcType = Src->getType(); Ice::Type SrcType = Src->getType();
if (!CastInst::castIsValid(LLVMCastOp, Context->convertToLLVMType(SrcType), if (!CastInst::castIsValid(LLVMCastOp, Context->convertToLLVMType(SrcType),
Context->convertToLLVMType(CastType))) { Context->convertToLLVMType(CastType))) {
...@@ -1757,9 +1832,17 @@ void FunctionParser::ProcessRecord() { ...@@ -1757,9 +1832,17 @@ void FunctionParser::ProcessRecord() {
} }
case naclbitc::FUNC_CODE_INST_VSELECT: { case naclbitc::FUNC_CODE_INST_VSELECT: {
// VSELECT: [opval, opval, pred] // VSELECT: [opval, opval, pred]
if (!isValidRecordSize(3, "function block select"))
return;
Ice::Operand *ThenVal = getRelativeOperand(Values[0], BaseIndex); Ice::Operand *ThenVal = getRelativeOperand(Values[0], BaseIndex);
Ice::Type ThenType = ThenVal->getType();
Ice::Operand *ElseVal = getRelativeOperand(Values[1], BaseIndex); Ice::Operand *ElseVal = getRelativeOperand(Values[1], BaseIndex);
Ice::Operand *CondVal = getRelativeOperand(Values[2], BaseIndex);
if (isIRGenerationDisabled()) {
assert(ThenVal == nullptr && ElseVal == nullptr && CondVal == nullptr);
setNextLocalInstIndex(nullptr);
return;
}
Ice::Type ThenType = ThenVal->getType();
Ice::Type ElseType = ElseVal->getType(); Ice::Type ElseType = ElseVal->getType();
if (ThenType != ElseType) { if (ThenType != ElseType) {
std::string Buffer; std::string Buffer;
...@@ -1770,7 +1853,6 @@ void FunctionParser::ProcessRecord() { ...@@ -1770,7 +1853,6 @@ void FunctionParser::ProcessRecord() {
appendErrorInstruction(ThenType); appendErrorInstruction(ThenType);
return; return;
} }
Ice::Operand *CondVal = getRelativeOperand(Values[2], BaseIndex);
Ice::Type CondType = CondVal->getType(); Ice::Type CondType = CondVal->getType();
if (isVectorType(CondType)) { if (isVectorType(CondType)) {
if (!isVectorType(ThenType) || if (!isVectorType(ThenType) ||
...@@ -1802,8 +1884,13 @@ void FunctionParser::ProcessRecord() { ...@@ -1802,8 +1884,13 @@ void FunctionParser::ProcessRecord() {
if (!isValidRecordSize(2, "function block extract element")) if (!isValidRecordSize(2, "function block extract element"))
return; return;
Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex); Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex);
Ice::Type VecType = Vec->getType();
Ice::Operand *Index = getRelativeOperand(Values[1], BaseIndex); Ice::Operand *Index = getRelativeOperand(Values[1], BaseIndex);
if (isIRGenerationDisabled()) {
assert(Vec == nullptr && Index == nullptr);
setNextLocalInstIndex(nullptr);
return;
}
Ice::Type VecType = Vec->getType();
VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index); VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index);
if (IndexCheckValue != VectorIndexValid) { if (IndexCheckValue != VectorIndexValid) {
std::string Buffer; std::string Buffer;
...@@ -1824,9 +1911,14 @@ void FunctionParser::ProcessRecord() { ...@@ -1824,9 +1911,14 @@ void FunctionParser::ProcessRecord() {
if (!isValidRecordSize(3, "function block insert element")) if (!isValidRecordSize(3, "function block insert element"))
return; return;
Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex); Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex);
Ice::Type VecType = Vec->getType();
Ice::Operand *Elt = getRelativeOperand(Values[1], BaseIndex); Ice::Operand *Elt = getRelativeOperand(Values[1], BaseIndex);
Ice::Operand *Index = getRelativeOperand(Values[2], BaseIndex); Ice::Operand *Index = getRelativeOperand(Values[2], BaseIndex);
if (isIRGenerationDisabled()) {
assert(Vec == nullptr && Elt == nullptr && Index == nullptr);
setNextLocalInstIndex(nullptr);
return;
}
Ice::Type VecType = Vec->getType();
VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index); VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index);
if (IndexCheckValue != VectorIndexValid) { if (IndexCheckValue != VectorIndexValid) {
std::string Buffer; std::string Buffer;
...@@ -1849,6 +1941,11 @@ void FunctionParser::ProcessRecord() { ...@@ -1849,6 +1941,11 @@ void FunctionParser::ProcessRecord() {
return; return;
Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex); Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex);
Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex); Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex);
if (isIRGenerationDisabled()) {
assert(Op1 == nullptr && Op2 == nullptr);
setNextLocalInstIndex(nullptr);
return;
}
Ice::Type Op1Type = Op1->getType(); Ice::Type Op1Type = Op1->getType();
Ice::Type Op2Type = Op2->getType(); Ice::Type Op2Type = Op2->getType();
Ice::Type DestType = getCompareResultType(Op1Type); Ice::Type DestType = getCompareResultType(Op1Type);
...@@ -1909,10 +2006,16 @@ void FunctionParser::ProcessRecord() { ...@@ -1909,10 +2006,16 @@ void FunctionParser::ProcessRecord() {
if (!isValidRecordSizeInRange(0, 1, "function block ret")) if (!isValidRecordSizeInRange(0, 1, "function block ret"))
return; return;
if (Values.empty()) { if (Values.empty()) {
if (isIRGenerationDisabled())
return;
CurrentNode->appendInst(Ice::InstRet::create(Func)); CurrentNode->appendInst(Ice::InstRet::create(Func));
} else { } else {
CurrentNode->appendInst( Ice::Operand *RetVal = getRelativeOperand(Values[0], BaseIndex);
Ice::InstRet::create(Func, getRelativeOperand(Values[0], BaseIndex))); if (isIRGenerationDisabled()) {
assert(RetVal == nullptr);
return;
}
CurrentNode->appendInst(Ice::InstRet::create(Func, RetVal));
} }
InstIsTerminating = true; InstIsTerminating = true;
return; return;
...@@ -1920,6 +2023,8 @@ void FunctionParser::ProcessRecord() { ...@@ -1920,6 +2023,8 @@ void FunctionParser::ProcessRecord() {
case naclbitc::FUNC_CODE_INST_BR: { case naclbitc::FUNC_CODE_INST_BR: {
if (Values.size() == 1) { if (Values.size() == 1) {
// BR: [bb#] // BR: [bb#]
if (isIRGenerationDisabled())
return;
Ice::CfgNode *Block = getBranchBasicBlock(Values[0]); Ice::CfgNode *Block = getBranchBasicBlock(Values[0]);
if (Block == nullptr) if (Block == nullptr)
return; return;
...@@ -1929,6 +2034,10 @@ void FunctionParser::ProcessRecord() { ...@@ -1929,6 +2034,10 @@ void FunctionParser::ProcessRecord() {
if (!isValidRecordSize(3, "function block branch")) if (!isValidRecordSize(3, "function block branch"))
return; return;
Ice::Operand *Cond = getRelativeOperand(Values[2], BaseIndex); Ice::Operand *Cond = getRelativeOperand(Values[2], BaseIndex);
if (isIRGenerationDisabled()) {
assert(Cond == nullptr);
return;
}
if (Cond->getType() != Ice::IceType_i1) { if (Cond->getType() != Ice::IceType_i1) {
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
...@@ -1958,6 +2067,7 @@ void FunctionParser::ProcessRecord() { ...@@ -1958,6 +2067,7 @@ void FunctionParser::ProcessRecord() {
// already frozen when the problem was noticed. // already frozen when the problem was noticed.
if (!isValidRecordSizeAtLeast(4, "function block switch")) if (!isValidRecordSizeAtLeast(4, "function block switch"))
return; return;
Ice::Type CondTy = Context->getSimpleTypeByID(Values[0]); Ice::Type CondTy = Context->getSimpleTypeByID(Values[0]);
if (!Ice::isScalarIntegerType(CondTy)) { if (!Ice::isScalarIntegerType(CondTy)) {
std::string Buffer; std::string Buffer;
...@@ -1968,7 +2078,11 @@ void FunctionParser::ProcessRecord() { ...@@ -1968,7 +2078,11 @@ void FunctionParser::ProcessRecord() {
} }
Ice::SizeT BitWidth = Ice::getScalarIntBitWidth(CondTy); Ice::SizeT BitWidth = Ice::getScalarIntBitWidth(CondTy);
Ice::Operand *Cond = getRelativeOperand(Values[1], BaseIndex); Ice::Operand *Cond = getRelativeOperand(Values[1], BaseIndex);
if (CondTy != Cond->getType()) {
const bool isIRGenDisabled = isIRGenerationDisabled();
if (isIRGenDisabled) {
assert(Cond == nullptr);
} else if (CondTy != Cond->getType()) {
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
StrBuf << "Case condition expects type " << CondTy StrBuf << "Case condition expects type " << CondTy
...@@ -1976,14 +2090,16 @@ void FunctionParser::ProcessRecord() { ...@@ -1976,14 +2090,16 @@ void FunctionParser::ProcessRecord() {
Error(StrBuf.str()); Error(StrBuf.str());
return; return;
} }
Ice::CfgNode *DefaultLabel = getBranchBasicBlock(Values[2]); Ice::CfgNode *DefaultLabel =
isIRGenDisabled ? nullptr : getBranchBasicBlock(Values[2]);
unsigned NumCases = Values[3]; unsigned NumCases = Values[3];
// Now recognize each of the cases. // Now recognize each of the cases.
if (!isValidRecordSize(4 + NumCases * 4, "Function block switch")) if (!isValidRecordSize(4 + NumCases * 4, "Function block switch"))
return; return;
Ice::InstSwitch *Switch = Ice::InstSwitch *Switch =
Ice::InstSwitch::create(Func, NumCases, Cond, DefaultLabel); isIRGenDisabled ? nullptr : Ice::InstSwitch::create(Func, NumCases,
Cond, DefaultLabel);
unsigned ValCaseIndex = 4; // index to beginning of case entry. unsigned ValCaseIndex = 4; // index to beginning of case entry.
for (unsigned CaseIndex = 0; CaseIndex < NumCases; for (unsigned CaseIndex = 0; CaseIndex < NumCases;
++CaseIndex, ValCaseIndex += 4) { ++CaseIndex, ValCaseIndex += 4) {
...@@ -1998,9 +2114,13 @@ void FunctionParser::ProcessRecord() { ...@@ -1998,9 +2114,13 @@ void FunctionParser::ProcessRecord() {
APInt Value(BitWidth, APInt Value(BitWidth,
NaClDecodeSignRotatedValue(Values[ValCaseIndex + 2]), NaClDecodeSignRotatedValue(Values[ValCaseIndex + 2]),
true); true);
if (isIRGenDisabled)
continue;
Ice::CfgNode *Label = getBranchBasicBlock(Values[ValCaseIndex + 3]); Ice::CfgNode *Label = getBranchBasicBlock(Values[ValCaseIndex + 3]);
Switch->addBranch(CaseIndex, Value.getSExtValue(), Label); Switch->addBranch(CaseIndex, Value.getSExtValue(), Label);
} }
if (isIRGenDisabled)
return;
CurrentNode->appendInst(Switch); CurrentNode->appendInst(Switch);
InstIsTerminating = true; InstIsTerminating = true;
return; return;
...@@ -2009,6 +2129,8 @@ void FunctionParser::ProcessRecord() { ...@@ -2009,6 +2129,8 @@ void FunctionParser::ProcessRecord() {
// UNREACHABLE: [] // UNREACHABLE: []
if (!isValidRecordSize(0, "function block unreachable")) if (!isValidRecordSize(0, "function block unreachable"))
return; return;
if (isIRGenerationDisabled())
return;
CurrentNode->appendInst( CurrentNode->appendInst(
Ice::InstUnreachable::create(Func)); Ice::InstUnreachable::create(Func));
InstIsTerminating = true; InstIsTerminating = true;
...@@ -2032,6 +2154,15 @@ void FunctionParser::ProcessRecord() { ...@@ -2032,6 +2154,15 @@ void FunctionParser::ProcessRecord() {
Error("Phi record using type void not allowed"); Error("Phi record using type void not allowed");
return; return;
} }
if (isIRGenerationDisabled()) {
// Verify arguments are defined before quitting.
for (unsigned i = 1; i < Values.size(); i += 2) {
assert(getRelativeOperand(NaClDecodeSignRotatedValue(Values[i]),
BaseIndex) == nullptr);
}
setNextLocalInstIndex(nullptr);
return;
}
Ice::Variable *Dest = getNextInstVar(Ty); Ice::Variable *Dest = getNextInstVar(Ty);
Ice::InstPhi *Phi = Ice::InstPhi::create(Func, Values.size() >> 1, Dest); Ice::InstPhi *Phi = Ice::InstPhi::create(Func, Values.size() >> 1, Dest);
for (unsigned i = 1; i < Values.size(); i += 2) { for (unsigned i = 1; i < Values.size(); i += 2) {
...@@ -2056,6 +2187,13 @@ void FunctionParser::ProcessRecord() { ...@@ -2056,6 +2187,13 @@ void FunctionParser::ProcessRecord() {
if (!isValidRecordSize(2, "function block alloca")) if (!isValidRecordSize(2, "function block alloca"))
return; return;
Ice::Operand *ByteCount = getRelativeOperand(Values[0], BaseIndex); Ice::Operand *ByteCount = getRelativeOperand(Values[0], BaseIndex);
unsigned Alignment;
extractAlignment("Alloca", Values[1], Alignment);
if (isIRGenerationDisabled()) {
assert(ByteCount == nullptr);
setNextLocalInstIndex(nullptr);
return;
}
Ice::Type PtrTy = Context->getIcePointerType(); Ice::Type PtrTy = Context->getIcePointerType();
if (ByteCount->getType() != Ice::IceType_i32) { if (ByteCount->getType() != Ice::IceType_i32) {
std::string Buffer; std::string Buffer;
...@@ -2065,8 +2203,6 @@ void FunctionParser::ProcessRecord() { ...@@ -2065,8 +2203,6 @@ void FunctionParser::ProcessRecord() {
appendErrorInstruction(PtrTy); appendErrorInstruction(PtrTy);
return; return;
} }
unsigned Alignment;
extractAlignment("Alloca", Values[1], Alignment);
CurrentNode->appendInst(Ice::InstAlloca::create(Func, ByteCount, Alignment, CurrentNode->appendInst(Ice::InstAlloca::create(Func, ByteCount, Alignment,
getNextInstVar(PtrTy))); getNextInstVar(PtrTy)));
return; return;
...@@ -2077,12 +2213,17 @@ void FunctionParser::ProcessRecord() { ...@@ -2077,12 +2213,17 @@ void FunctionParser::ProcessRecord() {
return; return;
Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex);
Ice::Type Ty = Context->getSimpleTypeByID(Values[2]); Ice::Type Ty = Context->getSimpleTypeByID(Values[2]);
unsigned Alignment;
extractAlignment("Load", Values[1], Alignment);
if (isIRGenerationDisabled()) {
assert(Address == nullptr);
setNextLocalInstIndex(nullptr);
return;
}
if (!isValidPointerType(Address, "Load")) { if (!isValidPointerType(Address, "Load")) {
appendErrorInstruction(Ty); appendErrorInstruction(Ty);
return; return;
} }
unsigned Alignment;
extractAlignment("Load", Values[1], Alignment);
if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) { if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) {
appendErrorInstruction(Ty); appendErrorInstruction(Ty);
return; return;
...@@ -2096,11 +2237,15 @@ void FunctionParser::ProcessRecord() { ...@@ -2096,11 +2237,15 @@ void FunctionParser::ProcessRecord() {
if (!isValidRecordSize(3, "function block store")) if (!isValidRecordSize(3, "function block store"))
return; return;
Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex);
if (!isValidPointerType(Address, "Store"))
return;
Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex); Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex);
unsigned Alignment; unsigned Alignment;
extractAlignment("Store", Values[2], Alignment); extractAlignment("Store", Values[2], Alignment);
if (isIRGenerationDisabled()) {
assert(Address == nullptr && Value == nullptr);
return;
}
if (!isValidPointerType(Address, "Store"))
return;
if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store"))
return; return;
CurrentNode->appendInst( CurrentNode->appendInst(
...@@ -2172,12 +2317,25 @@ void FunctionParser::ProcessRecord() { ...@@ -2172,12 +2317,25 @@ void FunctionParser::ProcessRecord() {
return; return;
} }
bool IsTailCall = static_cast<bool>(CCInfo & 1); bool IsTailCall = static_cast<bool>(CCInfo & 1);
Ice::SizeT NumParams = Values.size() - ParamsStartIndex;
if (isIRGenerationDisabled()) {
assert(Callee == nullptr);
// Check that parameters are defined.
for (Ice::SizeT ParamIndex = 0; ParamIndex < NumParams; ++ParamIndex) {
assert(getRelativeOperand(Values[ParamsStartIndex + ParamIndex],
BaseIndex) == nullptr);
}
// Define value slot only if value returned.
if (ReturnType != Ice::IceType_void)
setNextLocalInstIndex(nullptr);
return;
}
// Create the call instruction. // Create the call instruction.
Ice::Variable *Dest = (ReturnType == Ice::IceType_void) Ice::Variable *Dest = (ReturnType == Ice::IceType_void)
? nullptr ? nullptr
: getNextInstVar(ReturnType); : getNextInstVar(ReturnType);
Ice::SizeT NumParams = Values.size() - ParamsStartIndex;
Ice::InstCall *Inst = nullptr; Ice::InstCall *Inst = nullptr;
if (IntrinsicInfo) { if (IntrinsicInfo) {
Inst = Inst =
...@@ -2242,7 +2400,9 @@ void FunctionParser::ProcessRecord() { ...@@ -2242,7 +2400,9 @@ void FunctionParser::ProcessRecord() {
// FORWARDTYPEREF: [opval, ty] // FORWARDTYPEREF: [opval, ty]
if (!isValidRecordSize(2, "function block forward type ref")) if (!isValidRecordSize(2, "function block forward type ref"))
return; return;
setOperand(Values[0], createInstVar(Context->getSimpleTypeByID(Values[1]))); Ice::Type OpType = Context->getSimpleTypeByID(Values[1]);
setOperand(Values[0],
isIRGenerationDisabled() ? nullptr : createInstVar(OpType));
return; return;
} }
default: default:
...@@ -2304,6 +2464,10 @@ void ConstantsParser::ProcessRecord() { ...@@ -2304,6 +2464,10 @@ void ConstantsParser::ProcessRecord() {
return; return;
if (!isValidNextConstantType()) if (!isValidNextConstantType())
return; return;
if (isIRGenerationDisabled()) {
FuncParser->setNextConstantID(nullptr);
return;
}
FuncParser->setNextConstantID( FuncParser->setNextConstantID(
getContext()->getConstantUndef(NextConstantType)); getContext()->getConstantUndef(NextConstantType));
return; return;
...@@ -2314,6 +2478,10 @@ void ConstantsParser::ProcessRecord() { ...@@ -2314,6 +2478,10 @@ void ConstantsParser::ProcessRecord() {
return; return;
if (!isValidNextConstantType()) if (!isValidNextConstantType())
return; return;
if (isIRGenerationDisabled()) {
FuncParser->setNextConstantID(nullptr);
return;
}
if (IntegerType *IType = dyn_cast<IntegerType>( if (IntegerType *IType = dyn_cast<IntegerType>(
Context->convertToLLVMType(NextConstantType))) { Context->convertToLLVMType(NextConstantType))) {
APInt Value(IType->getBitWidth(), NaClDecodeSignRotatedValue(Values[0])); APInt Value(IType->getBitWidth(), NaClDecodeSignRotatedValue(Values[0]));
...@@ -2338,6 +2506,10 @@ void ConstantsParser::ProcessRecord() { ...@@ -2338,6 +2506,10 @@ void ConstantsParser::ProcessRecord() {
return; return;
if (!isValidNextConstantType()) if (!isValidNextConstantType())
return; return;
if (isIRGenerationDisabled()) {
FuncParser->setNextConstantID(nullptr);
return;
}
switch (NextConstantType) { switch (NextConstantType) {
case Ice::IceType_f32: { case Ice::IceType_f32: {
APFloat Value(APFloat::IEEEsingle, APFloat Value(APFloat::IEEEsingle,
...@@ -2410,6 +2582,8 @@ void FunctionValuesymtabParser::setValueName(uint64_t Index, StringType &Name) { ...@@ -2410,6 +2582,8 @@ void FunctionValuesymtabParser::setValueName(uint64_t Index, StringType &Name) {
// TODO(kschimpf) Remove error recovery once implementation complete. // TODO(kschimpf) Remove error recovery once implementation complete.
return; return;
} }
if (isIRGenerationDisabled())
return;
Ice::Operand *Op = getFunctionParser()->getOperand(Index); Ice::Operand *Op = getFunctionParser()->getOperand(Index);
if (Ice::Variable *V = dyn_cast<Ice::Variable>(Op)) { if (Ice::Variable *V = dyn_cast<Ice::Variable>(Op)) {
std::string Nm(Name.data(), Name.size()); std::string Nm(Name.data(), Name.size());
...@@ -2420,6 +2594,8 @@ void FunctionValuesymtabParser::setValueName(uint64_t Index, StringType &Name) { ...@@ -2420,6 +2594,8 @@ void FunctionValuesymtabParser::setValueName(uint64_t Index, StringType &Name) {
} }
void FunctionValuesymtabParser::setBbName(uint64_t Index, StringType &Name) { void FunctionValuesymtabParser::setBbName(uint64_t Index, StringType &Name) {
if (isIRGenerationDisabled())
return;
if (Index >= getFunctionParser()->Func->getNumNodes()) { if (Index >= getFunctionParser()->Func->getNumNodes()) {
reportUnableToAssign("block", Index, Name); reportUnableToAssign("block", Index, Name);
return; return;
......
...@@ -94,6 +94,10 @@ DisableInternal("externalize", ...@@ -94,6 +94,10 @@ DisableInternal("externalize",
cl::desc("Externalize all symbols")); cl::desc("Externalize all symbols"));
static cl::opt<bool> static cl::opt<bool>
DisableTranslation("notranslate", cl::desc("Disable Subzero translation")); DisableTranslation("notranslate", cl::desc("Disable Subzero translation"));
// Note: Modifiable only if ALLOW_DISABLE_IR_GEN.
static cl::opt<bool>
DisableIRGeneration("no-ir-gen",
cl::desc("Disable generating Subzero IR."));
static cl::opt<std::string> static cl::opt<std::string>
TranslateOnly("translate-only", cl::desc("Translate only the given function"), TranslateOnly("translate-only", cl::desc("Translate only the given function"),
cl::init("")); cl::init(""));
...@@ -188,12 +192,12 @@ static int GetReturnValue(int Val) { ...@@ -188,12 +192,12 @@ static int GetReturnValue(int Val) {
static struct { static struct {
const char *FlagName; const char *FlagName;
int FlagValue; int FlagValue;
} ConditionalBuildAttributes[] = { { "text_asm", ALLOW_TEXT_ASM }, } ConditionalBuildAttributes[] = {{"text_asm", ALLOW_TEXT_ASM},
{ "dump", ALLOW_DUMP }, {"dump", ALLOW_DUMP},
{ "llvm_cl", ALLOW_LLVM_CL }, {"llvm_cl", ALLOW_LLVM_CL},
{ "llvm_ir", ALLOW_LLVM_IR }, {"llvm_ir", ALLOW_LLVM_IR},
{ "llvm_ir_as_input", {"llvm_ir_as_input", ALLOW_LLVM_IR_AS_INPUT},
ALLOW_LLVM_IR_AS_INPUT } }; {"disable_ir_gen", ALLOW_DISABLE_IR_GEN}};
// Validates values of build attributes. Prints them to Stream if // Validates values of build attributes. Prints them to Stream if
// Stream is non-null. // Stream is non-null.
...@@ -228,6 +232,9 @@ int main(int argc, char **argv) { ...@@ -228,6 +232,9 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv); cl::ParseCommandLineOptions(argc, argv);
if (DisableIRGeneration)
DisableTranslation = true;
Ice::VerboseMask VMask = Ice::IceV_None; Ice::VerboseMask VMask = Ice::IceV_None;
for (unsigned i = 0; i != VerboseList.size(); ++i) for (unsigned i = 0; i != VerboseList.size(); ++i)
VMask |= VerboseList[i]; VMask |= VerboseList[i];
...@@ -251,6 +258,12 @@ int main(int argc, char **argv) { ...@@ -251,6 +258,12 @@ int main(int argc, char **argv) {
raw_os_ostream *Ls = new raw_os_ostream(LogFilename == "-" ? std::cout : Lfs); raw_os_ostream *Ls = new raw_os_ostream(LogFilename == "-" ? std::cout : Lfs);
Ls->SetUnbuffered(); Ls->SetUnbuffered();
if (!ALLOW_DISABLE_IR_GEN && DisableIRGeneration) {
*Ls << "Error: Build doesn't allow --no-ir-gen when not "
<< "ALLOW_DISABLE_IR_GEN!\n";
return GetReturnValue(1);
}
Ice::ClFlags Flags; Ice::ClFlags Flags;
Flags.DisableInternal = DisableInternal; Flags.DisableInternal = DisableInternal;
Flags.SubzeroTimingEnabled = SubzeroTimingEnabled; Flags.SubzeroTimingEnabled = SubzeroTimingEnabled;
...@@ -269,6 +282,7 @@ int main(int argc, char **argv) { ...@@ -269,6 +282,7 @@ int main(int argc, char **argv) {
Flags.TimingFocusOn = TimingFocusOn; Flags.TimingFocusOn = TimingFocusOn;
Flags.VerboseFocusOn = VerboseFocusOn; Flags.VerboseFocusOn = VerboseFocusOn;
Flags.TranslateOnly = TranslateOnly; Flags.TranslateOnly = TranslateOnly;
Flags.DisableIRGeneration = DisableIRGeneration;
Ice::GlobalContext Ctx(Ls, Os, VMask, TargetArch, OptLevel, TestPrefix, Ice::GlobalContext Ctx(Ls, Os, VMask, TargetArch, OptLevel, TestPrefix,
Flags); Flags);
......
...@@ -79,8 +79,7 @@ def if_cond_flag(Value): ...@@ -79,8 +79,7 @@ def if_cond_flag(Value):
# shell conditional commands. # shell conditional commands.
if_atts = [os.path.join(pydir, 'if.py')] if_atts = [os.path.join(pydir, 'if.py')]
if_atts_cmd = if_atts + ['--have=' + att if_atts_cmd = if_atts + ['--have=' + att for att in llvm2iceatts]
for att in llvm2iceatts] + ['--command']
ifl2i_atts_cmd = if_atts + [if_cond_flag('allow_llvm_ir' in llvm2iceatts), ifl2i_atts_cmd = if_atts + [if_cond_flag('allow_llvm_ir' in llvm2iceatts),
'--command'] '--command']
iflc2i_atts_cmd = if_atts + [if_cond_flag('allow_llvm_ir_as_input' iflc2i_atts_cmd = if_atts + [if_cond_flag('allow_llvm_ir_as_input'
......
; Test if we can read alloca instructions. ; Test if we can read alloca instructions.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
; Show examples where size is defined by a constant. ; Show examples where size is defined by a constant.
...@@ -159,3 +163,5 @@ entry: ...@@ -159,3 +163,5 @@ entry:
; CHECK-NEXT: %array = alloca i8, i32 %n, align 16 ; CHECK-NEXT: %array = alloca i8, i32 %n, align 16
; CHECK-NEXT: ret i32 %array ; CHECK-NEXT: ret i32 %array
} }
; NOIR: Total across all functions
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %l2i -i %s --insts | %ifl FileCheck %s ; RUN: %l2i -i %s --insts | %ifl FileCheck %s
; RUN: %lc2i -i %s --insts | %iflc FileCheck %s ; RUN: %lc2i -i %s --insts | %iflc FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
; TODO(kschimpf): add i8/i16. Needs bitcasts. ; TODO(kschimpf): add i8/i16. Needs bitcasts.
...@@ -965,3 +969,5 @@ entry: ...@@ -965,3 +969,5 @@ entry:
; CHECK-NEXT: %lshr = lshr <4 x i32> %b, %a ; CHECK-NEXT: %lshr = lshr <4 x i32> %b, %a
; CHECK-NEXT: ret <4 x i32> %lshr ; CHECK-NEXT: ret <4 x i32> %lshr
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Tests if we handle a branch instructions. ; Tests if we handle a branch instructions.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define void @SimpleBranch() { define void @SimpleBranch() {
entry: entry:
...@@ -43,3 +47,5 @@ b2: ...@@ -43,3 +47,5 @@ b2:
; CHECK-NEXT: b2: ; CHECK-NEXT: b2:
; CHECK-NEXT: br i1 %test, label %b2, label %b1 ; CHECK-NEXT: br i1 %test, label %b2, label %b1
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Test parsing indirect calls in Subzero. ; Test parsing indirect calls in Subzero.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define internal void @CallIndirectVoid(i32 %f_addr) { define internal void @CallIndirectVoid(i32 %f_addr) {
entry: entry:
...@@ -27,3 +31,5 @@ entry: ...@@ -27,3 +31,5 @@ entry:
; CHECK-NEXT: %r = call i32 %f_addr(i8 1, i1 false) ; CHECK-NEXT: %r = call i32 %f_addr(i8 1, i1 false)
; CHECK-NEXT: ret i32 %r ; CHECK-NEXT: ret i32 %r
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Test handling of call instructions. ; Test handling of call instructions.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define i32 @fib(i32 %n) { define i32 @fib(i32 %n) {
entry: entry:
...@@ -106,3 +110,4 @@ if.end: ; preds = %if.then, %entry ...@@ -106,3 +110,4 @@ if.end: ; preds = %if.then, %entry
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Tests if we can read cast operations. ; Tests if we can read cast operations.
; RUN: %p2i -i %s --insts --no-local-syms | FileCheck %s ; RUN: %p2i -i %s --insts --no-local-syms | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
; TODO(kschimpf) Find way to test pointer conversions (since they in general ; TODO(kschimpf) Find way to test pointer conversions (since they in general
; get removed by pnacl-freeze). ; get removed by pnacl-freeze).
...@@ -532,3 +536,5 @@ define void @BitcastV16xi8(<16 x i8> %v) { ...@@ -532,3 +536,5 @@ define void @BitcastV16xi8(<16 x i8> %v) {
; CHECK-NEXT: %__3 = bitcast <16 x i8> %__0 to <8 x i16> ; CHECK-NEXT: %__3 = bitcast <16 x i8> %__0 to <8 x i16>
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Test if we can read compare instructions. ; Test if we can read compare instructions.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define i1 @IcmpI1(i32 %p1, i32 %p2) { define i1 @IcmpI1(i32 %p1, i32 %p2) {
entry: entry:
...@@ -469,3 +473,5 @@ entry: ...@@ -469,3 +473,5 @@ entry:
; CHECK-NEXT: %vtrue = fcmp true <4 x float> %a1, %a2 ; CHECK-NEXT: %vtrue = fcmp true <4 x float> %a1, %a2
; CHECK-NEXT: ret <4 x i1> %voeq ; CHECK-NEXT: ret <4 x i1> %voeq
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Test handling of constants in function blocks. ; Test handling of constants in function blocks.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define void @TestIntegers() { define void @TestIntegers() {
entry: entry:
...@@ -152,3 +156,5 @@ entry: ...@@ -152,3 +156,5 @@ entry:
ret void ret void
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
} }
; NOIR: Total across all functions
; Test use forward type references in function blocks. ; Test use forward type references in function blocks.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: llvm-as < %s | pnacl-freeze | pnacl-bcdis -no-records \ ; RUN: llvm-as < %s | pnacl-freeze | pnacl-bcdis -no-records \
; RUN: | FileCheck --check-prefix=DUMP %s ; RUN: | FileCheck --check-prefix=DUMP %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define void @LoopCarriedDep() { define void @LoopCarriedDep() {
b0: b0:
...@@ -116,3 +119,5 @@ b6: ...@@ -116,3 +119,5 @@ b6:
; DUMP-NEXT: %b6: ; DUMP-NEXT: %b6:
; DUMP-NEXT: ret void; <@a3> ; DUMP-NEXT: ret void; <@a3>
; DUMP-NEXT: } ; DUMP-NEXT: }
; NOIR: Total across all functions
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %l2i -i %s --insts | %ifl FileCheck %s ; RUN: %l2i -i %s --insts | %ifl FileCheck %s
; RUN: %lc2i -i %s --insts | %iflc FileCheck %s ; RUN: %lc2i -i %s --insts | %iflc FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
@PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4 @PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4
; CHECK: @PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4 ; CHECK: @PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4
...@@ -74,3 +78,5 @@ entry: ...@@ -74,3 +78,5 @@ entry:
%result = sub i32 0, %size %result = sub i32 0, %size
ret i32 %result ret i32 %result
} }
; NOIR: Total across all functions
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %l2i -i %s --insts | %ifl FileCheck %s ; RUN: %l2i -i %s --insts | %ifl FileCheck %s
; RUN: %lc2i -i %s --insts | %iflc FileCheck %s ; RUN: %lc2i -i %s --insts | %iflc FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
@bytes = internal global [7 x i8] c"abcdefg" @bytes = internal global [7 x i8] c"abcdefg"
; CHECK: @bytes = internal global [7 x i8] c"abcdefg" ; CHECK: @bytes = internal global [7 x i8] c"abcdefg"
...@@ -95,3 +99,4 @@ define void @func() { ...@@ -95,3 +99,4 @@ define void @func() {
; CHECK-NEXT: define void @func() { ; CHECK-NEXT: define void @func() {
; NOIR: Total across all functions
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %l2i -i %s --insts | %ifl FileCheck %s ; RUN: %l2i -i %s --insts | %ifl FileCheck %s
; RUN: %lc2i -i %s --insts | %iflc FileCheck %s ; RUN: %lc2i -i %s --insts | %iflc FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define void @ExtractV4xi1(<4 x i1> %v) { define void @ExtractV4xi1(<4 x i1> %v) {
entry: entry:
...@@ -377,3 +381,5 @@ entry: ...@@ -377,3 +381,5 @@ entry:
; CHECK-NEXT: %r3 = insertelement <4 x float> %v, float %e, i32 3 ; CHECK-NEXT: %r3 = insertelement <4 x float> %v, float %e, i32 3
; CHECK-NEXT: ret <4 x float> %r3 ; CHECK-NEXT: ret <4 x float> %r3
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Test if we can read load instructions. ; Test if we can read load instructions.
; RUN: %p2i --no-local-syms -i %s --insts | FileCheck %s ; RUN: %p2i --no-local-syms -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define i32 @load_i8(i32 %addr) { define i32 @load_i8(i32 %addr) {
entry: entry:
...@@ -144,3 +148,4 @@ entry: ...@@ -144,3 +148,4 @@ entry:
; CHECK-NEXT: ret <4 x float> %__1 ; CHECK-NEXT: ret <4 x float> %__1
} }
; NOIR: Total across all functions
; Test parsing NaCl atomic instructions. ; Test parsing NaCl atomic instructions.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
declare i8 @llvm.nacl.atomic.load.i8(i8*, i32) declare i8 @llvm.nacl.atomic.load.i8(i8*, i32)
declare i16 @llvm.nacl.atomic.load.i16(i16*, i32) declare i16 @llvm.nacl.atomic.load.i16(i16*, i32)
...@@ -638,3 +642,4 @@ entry: ...@@ -638,3 +642,4 @@ entry:
; CHECK-NEXT: ret i32 %r ; CHECK-NEXT: ret i32 %r
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; This tests parsing NaCl intrinsics not related to atomic operations. ; This tests parsing NaCl intrinsics not related to atomic operations.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
declare i8* @llvm.nacl.read.tp() declare i8* @llvm.nacl.read.tp()
declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1) declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
...@@ -339,3 +343,4 @@ entry: ...@@ -339,3 +343,4 @@ entry:
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Test reading phi instructions. ; Test reading phi instructions.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
; TODO(kschimpf) Add forward reference examples. ; TODO(kschimpf) Add forward reference examples.
...@@ -28,3 +32,4 @@ target: ...@@ -28,3 +32,4 @@ target:
; CHECK-NEXT: ret i32 %result ; CHECK-NEXT: ret i32 %result
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Tests if we can read select instructions. ; Tests if we can read select instructions.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define void @Seli1(i32 %p) { define void @Seli1(i32 %p) {
entry: entry:
...@@ -293,3 +297,5 @@ entry: ...@@ -293,3 +297,5 @@ entry:
; CHECK-NEXT: %r = select <4 x i1> %pc, <4 x float> %pt, <4 x float> %pe ; CHECK-NEXT: %r = select <4 x i1> %pc, <4 x float> %pt, <4 x float> %pe
; CHECK-NEXT: ret <4 x float> %r ; CHECK-NEXT: ret <4 x float> %r
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
; Test if we can read store instructions. ; Test if we can read store instructions.
; RUN: %p2i -i %s --insts --no-local-syms | FileCheck %s ; RUN: %p2i -i %s --insts --no-local-syms | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define void @store_i8(i32 %addr) { define void @store_i8(i32 %addr) {
entry: entry:
...@@ -133,3 +137,5 @@ define void @store_v4xFloat(i32 %addr, <4 x float> %v) { ...@@ -133,3 +137,5 @@ define void @store_v4xFloat(i32 %addr, <4 x float> %v) {
; CHECK-NEXT: store <4 x float> %__1, <4 x float>* %__0, align 4 ; CHECK-NEXT: store <4 x float> %__1, <4 x float>* %__0, align 4
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
} }
; NOIR: Total across all functions
; Test switch instructions. ; Test switch instructions.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define void @testDefaultSwitch(i32 %a) { define void @testDefaultSwitch(i32 %a) {
entry: entry:
...@@ -490,3 +494,4 @@ exit: ...@@ -490,3 +494,4 @@ exit:
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
...@@ -12,6 +12,11 @@ ...@@ -12,6 +12,11 @@
; RUN: -default-function-prefix=h -default-global-prefix=g \ ; RUN: -default-function-prefix=h -default-global-prefix=g \
; RUN: | FileCheck --check-prefix=BAD %s ; RUN: | FileCheck --check-prefix=BAD %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
; TODO(kschimpf) Check global variable declarations, once generated. ; TODO(kschimpf) Check global variable declarations, once generated.
@0 = internal global [4 x i8] zeroinitializer, align 4 @0 = internal global [4 x i8] zeroinitializer, align 4
...@@ -57,3 +62,5 @@ define void @h5() { ...@@ -57,3 +62,5 @@ define void @h5() {
; BAD: Warning : Default global prefix 'g' potentially conflicts with name 'g'. ; BAD: Warning : Default global prefix 'g' potentially conflicts with name 'g'.
; BAD: Warning : Default function prefix 'h' potentially conflicts with name 'h5'. ; BAD: Warning : Default function prefix 'h' potentially conflicts with name 'h5'.
; NOIR: Total across all functions
; Test parsing unreachable instruction. ; Test parsing unreachable instruction.
; RUN: %p2i -i %s --insts | FileCheck %s ; RUN: %p2i -i %s --insts | FileCheck %s
; RUN: %if --need=allow_disable_ir_gen --command \
; RUN: %p2i -i %s --args -notranslate -timing -no-ir-gen \
; RUN: | %if --need=allow_disable_ir_gen --command \
; RUN: FileCheck --check-prefix=NOIR %s
define internal i32 @divide(i32 %num, i32 %den) { define internal i32 @divide(i32 %num, i32 %den) {
entry: entry:
...@@ -25,3 +29,5 @@ return: ; preds = %entry ...@@ -25,3 +29,5 @@ return: ; preds = %entry
; CHECK-NEXT: %div = sdiv i32 %num, %den ; CHECK-NEXT: %div = sdiv i32 %num, %den
; CHECK-NEXT: ret i32 %div ; CHECK-NEXT: ret i32 %div
; CHECK-NEXT: } ; CHECK-NEXT: }
; NOIR: Total across all functions
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment