-
Notifications
You must be signed in to change notification settings - Fork 738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix ICF assert in pdcmpgt vector evaluator #3330
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2701,8 +2701,8 @@ J9::Z::TreeEvaluator::pdcmpVectorEvaluatorHelper(TR::Node *node, TR::CodeGenerat | |
generateRRInstruction(cg, TR::Compiler->target.is64Bit() ? TR::InstOpCode::XGR : TR::InstOpCode::XR, node, resultReg, resultReg); | ||
generateLoad32BitConstant(cg, node, 1, resultReg, true); | ||
|
||
TR::RegisterDependencyConditions* deps = new(cg->trHeapMemory()) TR::RegisterDependencyConditions(0, 1, cg); | ||
TR::LabelSymbol* doneCompareLabel = TR::LabelSymbol::create(cg->trHeapMemory(), cg); | ||
TR::RegisterDependencyConditions* deps = new(cg->trHeapMemory()) TR::RegisterDependencyConditions(0, 2, cg); | ||
deps->addPostConditionIfNotAlreadyInserted(resultReg, TR::RealRegister::AssignAny); | ||
|
||
TR::Node* pd1Node = node->getFirstChild(); | ||
TR::Node* pd2Node = node->getSecondChild(); | ||
|
@@ -2713,40 +2713,45 @@ J9::Z::TreeEvaluator::pdcmpVectorEvaluatorHelper(TR::Node *node, TR::CodeGenerat | |
// TODO: should we correct bad sign before comparing them | ||
TR::Instruction* cursor = generateVRRhInstruction(cg, TR::InstOpCode::VCP, node, pd1Value, pd2Value, 0); | ||
|
||
TR::LabelSymbol* ifcStartLabel = generateLabelSymbol(cg); | ||
cursor = generateS390LabelInstruction(cg, TR::InstOpCode::LABEL, node, ifcStartLabel); | ||
cursor->setStartInternalControlFlow(); | ||
deps->addPostConditionIfNotAlreadyInserted(resultReg, TR::RealRegister::AssignAny); | ||
|
||
TR::LabelSymbol* icfEndLabel = generateLabelSymbol(cg); | ||
|
||
// Generate Branch Instructions | ||
switch(node->getOpCodeValue()) | ||
{ | ||
case TR::pdcmpeq: | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC0, node, doneCompareLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC0, node, icfEndLabel); | ||
break; | ||
case TR::pdcmpne: | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC1, node, doneCompareLabel); | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC2, node, doneCompareLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC1, node, icfEndLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC2, node, icfEndLabel); | ||
break; | ||
case TR::pdcmplt: | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC1, node, doneCompareLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC1, node, icfEndLabel); | ||
break; | ||
case TR::pdcmple: | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC0, node, doneCompareLabel); | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC1, node, doneCompareLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC0, node, icfEndLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC1, node, icfEndLabel); | ||
break; | ||
case TR::pdcmpgt: | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC2, node, doneCompareLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC2, node, icfEndLabel); | ||
break; | ||
case TR::pdcmpge: | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC0, node, doneCompareLabel); | ||
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC2, node, doneCompareLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC0, node, icfEndLabel); | ||
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_CC2, node, icfEndLabel); | ||
break; | ||
default: | ||
TR_ASSERT(0, "Unrecognized op code in pd cmp vector evaluator helper."); | ||
} | ||
|
||
cursor = generateLoad32BitConstant(cg, node, 0, resultReg, true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually think we should assert inside of these APIs that can take in dependencies for ICF. i.e. if you have ICF start already marked and you call this API and you don't pass in dependencies then assert because you're doing something wrong. This API can potentially allocate a register depending on the constant being loaded and that register has to be added to the dependencies. Food for thought. |
||
cursor = generateS390LabelInstruction(cg, TR::InstOpCode::LABEL, node, doneCompareLabel); | ||
cursor->setDependencyConditions(deps); | ||
// TODO: The only reason we keep track of the cursor here is because `deps` has to be passed in after `cursor`. We | ||
// don't really need this restriction however if we rearrange the parameters. | ||
cursor = generateLoad32BitConstant(cg, node, 0, resultReg, true, cursor, deps); | ||
|
||
cursor = generateS390LabelInstruction(cg, TR::InstOpCode::LABEL, node, icfEndLabel, deps); | ||
cursor->setEndInternalControlFlow(); | ||
|
||
node->setRegister(resultReg); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why 2 post dependencies? I only see one call of
addPostCondition
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it because
generateLoad32BitConstant
can potentially allocate another register?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implicit dependency changes in APIs like
generateLoad32BitConstant()
can be tricky.. How do we know the number of dependencies they are adding?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is precisely it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a problem today. I can't fix the issue at the moment but I opened one a long time ago that we need to have dynamically allocated register dependencies. It's absurd to expect developers do count them manually when it costs basically nothing to just allocate them dynamically.