Skip to content
Snippets Groups Projects
Commit fc6b4549 authored by clc5q's avatar clc5q
Browse files

SPARK translation; generalize Expandperand().

Former-commit-id: d342710327e6d57a15fc2527ce52f31564c54b86
parent eb04e4e9
No related branches found
No related tags found
No related merge requests found
......@@ -502,6 +502,7 @@ public:
void ComputeGlobalSets(void); // compute LiveOut, Kill sets for function
bool ComputeInOutRegs(bool InheritPass, bool &WritesMem, bool &CallChainNonReturning); // compute InputRegs and OutputRegs, only inherit from callees on InheritPass
void BuildLoopingStringMemExprs(SMPBasicBlock *CurrBlock, SMPInstr *CurrInst); // Build lower and upper bounds exprs for memory writes in looping string opcode
void FindMatchingMemDEFAddrs(STARS_ea_t UseAddr, SMPBasicBlock *CurrBlock, STARSOpndTypePtr &MemUseOp, std::list<STARS_ea_t> &MemDefAddrs); // Fill MemDefAddrs with inst addrs that DEF MemUseOp, tracing back from UseAddr.
void AnalyzeFunc(void); // Analyze all instructions in function
void AdvancedAnalysis(void); // Analyses that fix IDA stack frame info, sync RTLs with DEFs and USEs, Live Variable Analysis
bool AdvancedAnalysis2(void); // fix call inst DEFs and USEs; return true if changes
......
......@@ -455,6 +455,7 @@ private:
bool ElevateRightSide(STARSExpression *ParentExpr); // Expr simplifies to RightExpr or RightOperand, so raise it into ParentExpr; return true if RightOperand
bool ElevateLeftSide(STARSExpression *ParentExpr); // Expr simplifies to LeftExpr or LeftOperand, so raise it into ParentExpr; return true if LeftOperand
bool ExpandOperand(std::size_t LoopIndex, bool Left, bool StopOnIV, STARS_ea_t UseAddr, bool StopOnLoopBoundary, bool &StoppedOnIV); // return false if expansion is forced to stop before constant DEF or InArg DEF or IndVAr.
bool ExpandOperandHelper(STARS_ea_t DefAddr, STARSOpndTypePtr &SearchOp, std::size_t LoopIndex, bool Left, bool StopOnIV, bool StopOnLoopBoundary, bool &StoppedOnIV); // recursive helper for ExpandOperand()
void PrintSPARKArgLocationStringsHelper(FILE *OutputFile, bool LoopInvariant, const STARSOpndTypePtr &LeafOp, STARS_ea_t PreLoopDefAddr);
}; // end class STARSExpression
......
......@@ -697,6 +697,7 @@ bool SMPFunction::InheritCalleeMemRangeExpr(STARSExpression *CalleeMemRangeExpr,
CalleeMemRangeExpr->SetParentInst(CallInst);
bitset<1 + MD_LAST_REG_NO> InArgRegNums;
CalleeMemRangeExpr->ListInArgRegsUsed(InArgRegNums);
bool ReplacedInArgSSANum = false;
for (size_t RegNum = 0; RegNum < InArgRegNums.size(); ++RegNum) {
if (InArgRegNums[RegNum]) {
STARSOpndTypePtr CurrInArgOp = CallInst->MakeRegOpnd((STARS_regnum_t) RegNum);
......@@ -705,12 +706,16 @@ bool SMPFunction::InheritCalleeMemRangeExpr(STARSExpression *CalleeMemRangeExpr,
// Replace all SSANum == 0 instances of InArgOp with SSANum of InArg in this function.
// NOTE: Might we need to do the same for multiple InArgs, used as limits, etc.?
CalleeMemRangeExpr->SubstituteSSANum(CallInst, UseIter->GetSSANum(), CurrInArgOp);
ReplacedInArgSSANum = true;
}
else {
SMP_msg("ERROR: SPARK: Callee loop range does not trace to InArgUSE at call site %llx\n", (uint64_t) InstAddr);
}
}
} // end for all InArgRegNums
if (!ReplacedInArgSSANum) {
SMP_msg("ERROR: SPARK: Callee loop range expr did not see InArgSSANums replaced at call site %llx\n", (uint64_t) InstAddr);
}
SMP_msg("INFO: LoopCalleeMemRangeExpr before expansion:");
CalleeMemRangeExpr->Dump(0);
bool StoppedOnIV = false;
......@@ -4409,6 +4414,33 @@ void SMPFunction::EmitStackFrameAnnotations(FILE *AnnotFile, SMPInstr *Instr) {
} // end of SMPFunction::EmitStackFrameAnnotations()
#endif
 
// Fill MemDefAddrs with inst addrs that DEF MemUseOp, tracing back from UseAddr.
void SMPFunction::FindMatchingMemDEFAddrs(STARS_ea_t UseAddr, SMPBasicBlock *CurrBlock, STARSOpndTypePtr &MemUseOp, std::list<STARS_ea_t> &MemDefAddrs) {
// Trace back from UseAddr to find MemDEFs that match MemUseOp.
// If UseAddr == STARS_BADADDR, that means the mthod has been called recursively and it should
// trace back from the last instruction in CurrBlock. By ensuring that an inst addr is < UseAddr,
// we accomplish both cases without special cases in the code.
if (!CurrBlock->IsProcessed()) {
for (vector<SMPInstr *>::const_reverse_iterator InstIter = CurrBlock->GetRevInstCBegin(); InstIter != CurrBlock->GetRevInstCEnd(); ++InstIter) {
SMPInstr *CurrInst = (*InstIter);
STARS_ea_t InstAddr = CurrInst->GetAddr();
if ((InstAddr < UseAddr) && CurrInst->HasDestMemoryOperand()) {
if (IsEqOpIgnoreBitwidth(MemUseOp, CurrInst->GetMemDef())) {
MemDefAddrs.push_back(InstAddr);
}
}
}
CurrBlock->SetProcessed(true);
// Recurse into predecessors, passing in STARS_BADADDR as the UseAddr.
for (list<SMPBasicBlock *>::iterator PredIter = CurrBlock->GetFirstPred(); PredIter != CurrBlock->GetLastPred(); ++PredIter) {
SMPBasicBlock *PredBlock = (*PredIter);
this->FindMatchingMemDEFAddrs(STARS_BADADDR, PredBlock, MemUseOp, MemDefAddrs);
}
}
return;
} // end of SMPFunction::FindMatchingMemDEFAddrs()
// Mark functions with multiple entry points. These will be unsafe for fast returns and
// are probably IDA Pro disassembly problems rather than true multi-entry functions.
void SMPFunction::DetectMultiEntryFunction(void) {
......@@ -10666,12 +10698,14 @@ void SMPFunction::AnalyzeLoopIterations(void) {
LoopIndex, (uint64_t) this->GetFirstFuncAddr());
delete MemWriteLowerBound;
delete MemWriteUpperBound;
this->LoopMemWriteRangeExprs[LoopIndex] = nullptr;
}
}
else {
SMP_msg("INFO: Failure to ReplaceBIVWithInitExpr for loop %d in function at %llx\n",
LoopIndex, (uint64_t) this->GetFirstFuncAddr());
delete MemWriteLowerBound;
this->LoopMemWriteRangeExprs[LoopIndex] = nullptr;
}
}
else {
......
......@@ -2771,9 +2771,27 @@ bool STARSExpression::FindConstForOperand(bool Left, STARS_uval_t &ConstValue) {
return FoundConst;
} // end of STARSExpression::FindConstForOperand()
 
// Lots of compiler-generated x86-64 code has needless sign-extend or zero-extend opcodes because
// quick arithmetic is performed on 32-bit regs and the compiler extends it later before using the 64-bit reg.
// Expressions get hard to analyze; the prover can balk as a double-check on unsound simplifications, but
// get rid of these extensions for our purposes so we can produce simple exprs.
#define STARS_SPARK_DISCARD_BIT_EXTENSIONS 1
// Simplify operations with operands of zero or one, etc. Return true if expr was raised to parent.
bool STARSExpression::SimplifyExpr(STARSExpression *ParentExpr) {
bool RootLeftExprLifted = false;
#if STARS_SPARK_DISCARD_BIT_EXTENSIONS
if ((SMP_ZERO_EXTEND == this->GetOperator() || (SMP_SIGN_EXTEND == this->GetOperator())) && (nullptr != this->GetLeftOperand()) && (!this->HasLeftSubTree())) {
// Clone the operand and maximize its byte width. We want to print RDX, not EDX, in SPARK contracts.
if (this->GetLeftOperand()->IsRegOp()) {
STARSOpndTypePtr NewLeftOp = this->GetParentInst()->MakeRegOpnd(this->GetLeftOperand()->GetReg());
NewLeftOp->SetByteWidth(global_STARS_program->GetSTARS_ISA_Bytewidth());
this->SetLeftOperand(NewLeftOp);
RootLeftExprLifted = this->ElevateLeftSide(nullptr);
}
// now fall through to further simplifications
}
#else
if (SMP_ZERO_EXTEND == this->GetOperator() && (nullptr != this->GetLeftOperand()) && (!this->HasLeftSubTree())) {
// See if we are zero-extending a constant, and transform to just assigning the constant.
if (this->GetLeftOperand()->IsImmedOp()) {
......@@ -2781,6 +2799,7 @@ bool STARSExpression::SimplifyExpr(STARSExpression *ParentExpr) {
// now fall through to further simplifications
}
}
#endif
if (SMP_ASSIGN == this->GetOperator()) {
if (this->HasLeftSubTree()) {
assert(!this->HasRightSubTree());
......@@ -3326,181 +3345,226 @@ bool STARSExpression::ExpandOperand(std::size_t LoopIndex, bool Left, bool StopO
STARSInductionVarFamilyList::iterator IVFamilyIter;
size_t FamilyIndex;
 
// 1. Check if operand meets criteria for ending the expansion.
// Check if operand meets criteria for ending the expansion.
if (SearchOp->IsImmedOp() | SearchOp->IsVoidOp()) {
success = true;
}
else if (SearchOp->IsMemOp() && (!MDIsDirectStackAccessOpnd(SearchOp, UseFP))) {
list<STARS_ea_t> MemDefAddrs;
this->GetParentFunc()->ResetProcessedBlocks();
this->GetParentFunc()->FindMatchingMemDEFAddrs(UseAddr, this->GetParentInst()->GetBlock(), SearchOp, MemDefAddrs);
success = (1 >= MemDefAddrs.size()); // reached top of function, or found a MemDef
if (!success) {
SMP_msg("ERROR: MemDefAddrs set is of size %zu\n", MemDefAddrs.size());
}
else if (1 == MemDefAddrs.size()) {
// Replace the current operand with the MemDefAddr right-hand-side move source operand and recurse.
STARS_ea_t NewDefAddr = MemDefAddrs.front();
SMPInstr *NewDefInst = this->GetParentFunc()->GetInstFromAddr(NewDefAddr);
STARSOpndTypePtr RHSOperand;
success = NewDefInst->IsSimpleCopy(RHSOperand);
if (success) {
STARSOpndTypePtr NewSearchOp = CloneIfSubwordReg(RHSOperand);
STARSDefUseIter UseIter = NewDefInst->FindUse(NewSearchOp);
assert(UseIter != NewDefInst->GetLastUse());
int UseSSANum = UseIter->GetSSANum();
if (Left)
this->SetLeftSSANum(UseSSANum);
else
this->SetRightSSANum(UseSSANum);
this->SetParentInst(NewDefInst);
// Replace current operand with new operand.
if (Left)
this->SetLeftOperand(RHSOperand);
else
this->SetRightOperand(RHSOperand);
// Recurse into new operand at NewDefAddr.
success = this->ExpandOperand(LoopIndex, Left, StopOnIV, NewDefAddr, StopOnLoopBoundary, StoppedOnIV);
}
}
}
else if (!MDIsDataFlowOpnd(SearchOp, UseFP)) {
success = false;
SMP_msg("SPARK: Non-DataFlowOpnd: ");
PrintOperand(SearchOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at non-DataFlowOpnd at %llx\n", (uint64_t) UseAddr);
}
else {
// 2. Find DEF instruction for operand.
else { // we found a reg or direct stack access operand
// Find DEF instruction for operand.
CanonicalizeOpnd(SearchOp);
int SSANum = (Left) ? this->GetLeftSSANum() : this->GetRightSSANum();
SMPBasicBlock *CurrBlock = this->GetParentFunc()->GetBlockFromInstAddr(UseAddr);
bool LocalName = CurrBlock->IsLocalName(SearchOp);
STARS_ea_t DefAddr = CurrBlock->GetDefAddrFromUseAddr(SearchOp, UseAddr, SSANum, LocalName);
 
// See if we have crossed the beginning-of-loop boundary for the first time.
STARS_ea_t CurrLoopDefAddr = Left ? this->GetLeftPreLoopDefAddr() : this->GetRightPreLoopDefAddr();
success = this->ExpandOperandHelper(DefAddr, SearchOp, LoopIndex, Left, StopOnIV, StopOnLoopBoundary, StoppedOnIV);
}
 
if (STARS_IsSSAMarkerPseudoID(DefAddr)) {
success = true; // DEF is in SSA marker, such as an incoming arg; expansion terminates successfully.
if (STARS_BADADDR == CurrLoopDefAddr) {
// Crossed from within the loop to the SSA Marker.
if (success) {
// Inherit PreLoopDefAddr.
if (Left && (STARS_BADADDR == this->GetLeftPreLoopDefAddr()) && this->HasLeftSubTree()) {
// We expanded our left operand into an expr. Our PreLoopDefAddr is not informative.
// Inherit the LeftPreLoopDefAddr of the LeftTree we expanded our LeftOperand into.
this->SetLeftPreLoopDefAddr(this->GetLeftTree()->GetLeftPreLoopDefAddr());
}
else if (!Left && (STARS_BADADDR == this->GetRightPreLoopDefAddr()) && this->HasRightSubTree()) {
// We expanded our right operand into an expr. Our PreLoopDefAddr is not informative.
// Inherit the LeftPreLoopDefAddr of the RightTree we expanded our RightOperand into.
this->SetRightPreLoopDefAddr(this->GetRightTree()->GetLeftPreLoopDefAddr());
}
}
return success;
} // end of STARSExpression::ExpandOperand()
// recursive helper for ExpandOperand()
bool STARSExpression::ExpandOperandHelper(STARS_ea_t DefAddr, STARSOpndTypePtr &SearchOp, std::size_t LoopIndex, bool Left, bool StopOnIV, bool StopOnLoopBoundary, bool &StoppedOnIV) {
bool success = true;
bool UseFP = this->GetParentFunc()->UsesFramePointer();
// See if we have crossed the beginning-of-loop boundary for the first time.
STARS_ea_t CurrLoopDefAddr = Left ? this->GetLeftPreLoopDefAddr() : this->GetRightPreLoopDefAddr();
STARSInductionVarFamilyList::iterator IVFamilyIter;
size_t FamilyIndex;
if (STARS_IsSSAMarkerPseudoID(DefAddr)) {
success = true; // DEF is in SSA marker, such as an incoming arg; expansion terminates successfully.
if (STARS_BADADDR == CurrLoopDefAddr) {
// Crossed from within the loop to the SSA Marker.
if (Left)
this->SetLeftPreLoopDefAddr(DefAddr);
else
this->SetRightPreLoopDefAddr(DefAddr);
}
}
else if ((STARS_BADADDR == DefAddr) || STARS_IsLiveInPseudoID(DefAddr)) {
success = false; // bad addr, or other non-instruction address.
SMP_msg("SPARK: Bad DefAddr SearchOp:");
PrintOperand(SearchOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at bad DefAddr: %llx\n", (uint64_t) DefAddr);
}
else if (STARS_IsBlockNumPseudoID(DefAddr)) {
// Hitting a Phi function is only acceptable for induction variables when StopOnIV is our mode.
success = (StopOnIV && this->GetParentFunc()->IsLoopInductionVar(LoopIndex, SearchOp, this->GetParentInst(), IVFamilyIter, FamilyIndex));
if (success)
StoppedOnIV = true;
if (success && (STARS_BADADDR == CurrLoopDefAddr)) {
#if 0
// Did we cross loop boundary?
int NewBlockNum = (int) STARS_GetBlockNumFromPseudoID(DefAddr);
if (!this->GetParentFunc()->IsBlockInLoop(NewBlockNum, LoopIndex)) {
// Crossed from within the loop to a Phi function before the loop.
if (Left)
this->SetLeftPreLoopDefAddr(DefAddr);
else
this->SetRightPreLoopDefAddr(DefAddr);
}
#else
// Even the Phi at the top of the loop represents a pre-loop address that is better than STARS_BADADDR
if (Left)
this->SetLeftPreLoopDefAddr(DefAddr);
else
this->SetRightPreLoopDefAddr(DefAddr);
#endif
}
else if ((STARS_BADADDR == DefAddr) || STARS_IsLiveInPseudoID(DefAddr)) {
success = false; // bad addr, or other non-instruction address.
SMP_msg("SPARK: Bad DefAddr SearchOp:");
else if (!success) {
SMP_msg("SPARK: Phi function SearchOp:");
PrintOperand(SearchOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at bad DefAddr: %llx\n", (uint64_t) DefAddr);
}
else if (STARS_IsBlockNumPseudoID(DefAddr)) {
// Hitting a Phi function is only acceptable for induction variables when StopOnIV is our mode.
success = (StopOnIV && this->GetParentFunc()->IsLoopInductionVar(LoopIndex, SearchOp, this->GetParentInst(), IVFamilyIter, FamilyIndex));
if (success)
StoppedOnIV = true;
if (success && (STARS_BADADDR == CurrLoopDefAddr)) {
#if 0
// Did we cross loop boundary?
int NewBlockNum = (int) STARS_GetBlockNumFromPseudoID(DefAddr);
if (!this->GetParentFunc()->IsBlockInLoop(NewBlockNum, LoopIndex)) {
// Crossed from within the loop to a Phi function before the loop.
if (Left)
this->SetLeftPreLoopDefAddr(DefAddr);
else
this->SetRightPreLoopDefAddr(DefAddr);
}
#else
// Even the Phi at the top of the loop represents a pre-loop address that is better than STARS_BADADDR
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at phi function at %llx\n", (uint64_t) DefAddr);
}
}
else { // found DEF inst.
// 3. Get DEF right-hand-side SMPRegTransfer and create expression from it.
SMPInstr *DefInst = this->GetParentFunc()->GetInstFromAddr(DefAddr);
int NewBlockNum = this->GetParentFunc()->GetBlockNumFromInstAddr(DefAddr);
bool WentBeforeLoop = !this->GetParentFunc()->IsBlockInLoop(NewBlockNum, LoopIndex);
if (WentBeforeLoop && StopOnLoopBoundary) {
// Do not replace USE with its DEF, as DEF precedes the loop. Stop
// inside the loop and declare victory.
return true;
}
if (DEFAULT != DefInst->GetDataFlowType()) {
SMP_msg("SPARK: Bad control flow type SearchOp:");
PrintOperand(SearchOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at bad control flow type at %llx\n", (uint64_t) DefAddr);
return false; // don't want CALL DEFs, etc.
}
SMPRegTransfer *DefRT = DefInst->GetDefRT(SearchOp);
if (nullptr == DefRT) {
SMP_msg("SPARK: Bad DefRT SearchOp:");
PrintOperand(SearchOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at bad DefRT at %llx\n", (uint64_t) DefAddr);
return false; // some odd opcodes might have a DEF but no normal RT, e.g. "fnstsw ax"
}
if ((STARS_BADADDR == CurrLoopDefAddr) && (this->GetParentFunc()->GetNumLoops() > LoopIndex)) {
// Did we cross loop boundary?
if (WentBeforeLoop) {
// Crossed from within the loop to a DefInst before the loop.
if (Left)
this->SetLeftPreLoopDefAddr(DefAddr);
else
this->SetRightPreLoopDefAddr(DefAddr);
#endif
}
else if (!success) {
SMP_msg("SPARK: Phi function SearchOp:");
PrintOperand(SearchOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at phi function at %llx\n", (uint64_t)DefAddr);
}
}
else { // found DEF inst.
// 3. Get DEF right-hand-side SMPRegTransfer and create expression from it.
SMPInstr *DefInst = this->GetParentFunc()->GetInstFromAddr(DefAddr);
int NewBlockNum = this->GetParentFunc()->GetBlockNumFromInstAddr(DefAddr);
bool WentBeforeLoop = !this->GetParentFunc()->IsBlockInLoop(NewBlockNum, LoopIndex);
if (WentBeforeLoop && StopOnLoopBoundary) {
// Do not replace USE with its DEF, as DEF precedes the loop. Stop
// inside the loop and declare victory.
return true;
}
 
if (DEFAULT != DefInst->GetDataFlowType()) {
SMP_msg("SPARK: Bad control flow type SearchOp:");
PrintOperand(SearchOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at bad control flow type at %llx\n", (uint64_t) DefAddr);
return false; // don't want CALL DEFs, etc.
}
SMPRegTransfer *DefRT = DefInst->GetDefRT(SearchOp);
if (nullptr == DefRT) {
SMP_msg("SPARK: Bad DefRT SearchOp:");
PrintOperand(SearchOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at bad DefRT at %llx\n", (uint64_t) DefAddr);
return false; // some odd opcodes might have a DEF but no normal RT, e.g. "fnstsw ax"
// If an SMP_ASSIGN RT was returned, it means that RT was DEF := USE and
// we should use only the USE, i.e. the RightOperand, else use the whole RT.
if (SMP_ASSIGN == DefRT->GetOperator()) {
// 4. Replace current operand with the USE operand.
assert(!DefRT->HasRightSubTree());
STARSOpndTypePtr UseOp = DefRT->GetRightOperand();
bool ConstUse = UseOp->IsImmedOp();
if (!(ConstUse || UseOp->IsRegOp() || UseOp->IsMemOp())) {
SMP_msg("SPARK: Non-DataFlowOpnd: ");
PrintOperand(UseOp);
SMP_msg("\nINFO: SPARK: ExpandOperand() hit non-DataFlow UseOp at %llx\n", (uint64_t) DefAddr);
}
if ((STARS_BADADDR == CurrLoopDefAddr) && (this->GetParentFunc()->GetNumLoops() > LoopIndex)) {
// Did we cross loop boundary?
if (WentBeforeLoop) {
// Crossed from within the loop to a DefInst before the loop.
else {
STARSOpndTypePtr SearchOp = CloneIfSubwordReg(UseOp);
if (!ConstUse) {
STARSDefUseIter UseIter = DefInst->FindUse(SearchOp);
assert(UseIter != DefInst->GetLastUse());
int UseSSANum = UseIter->GetSSANum();
if (Left)
this->SetLeftPreLoopDefAddr(DefAddr);
this->SetLeftSSANum(UseSSANum);
else
this->SetRightPreLoopDefAddr(DefAddr);
this->SetRightSSANum(UseSSANum);
this->ParentInst = DefInst;
}
}
// Replace current operand with new operand.
if (Left)
this->SetLeftOperand(UseOp);
else
this->SetRightOperand(UseOp);
 
// If an SMP_ASSIGN RT was returned, it means that RT was DEF := USE and
// we should use only the USE, i.e. the RightOperand, else use the whole RT.
if (SMP_ASSIGN == DefRT->GetOperator()) {
// 4. Replace current operand with the USE operand.
assert(!DefRT->HasRightSubTree());
STARSOpndTypePtr UseOp = DefRT->GetRightOperand();
bool ConstUse = UseOp->IsImmedOp();
if (!ConstUse && !MDIsDataFlowOpnd(UseOp, UseFP)) {
SMP_msg("SPARK: Non-DataFlowOpnd: ");
PrintOperand(UseOp);
SMP_msg("\nERROR: SPARK: ExpandOperand() stopped at non-DataFlow UseOp at %llx\n", (uint64_t) DefAddr);
success = false;
if (!ConstUse) {
// 5. Recurse into new operand at DefAddr.
success = this->ExpandOperand(LoopIndex, Left, StopOnIV, DefAddr, StopOnLoopBoundary, StoppedOnIV);
}
else {
STARSOpndTypePtr SearchOp = CloneIfSubwordReg(UseOp);
if (!ConstUse) {
STARSDefUseIter UseIter = DefInst->FindUse(SearchOp);
assert(UseIter != DefInst->GetLastUse());
int UseSSANum = UseIter->GetSSANum();
if (Left)
this->SetLeftSSANum(UseSSANum);
else
this->SetRightSSANum(UseSSANum);
this->ParentInst = DefInst;
}
// Replace current operand with new operand.
if (Left)
this->SetLeftOperand(UseOp);
else
this->SetRightOperand(UseOp);
if (!ConstUse) {
// 5. Recurse into new operand at DefAddr.
success = this->ExpandOperand(LoopIndex, Left, StopOnIV, DefAddr, StopOnLoopBoundary, StoppedOnIV);
}
else {
success = true;
}
success = true;
}
}
else {
STARSExpression *DefExpr = new STARSExpression(DefRT);
}
else {
STARSExpression *DefExpr = new STARSExpression(DefRT);
 
// 4. Make new expression the sub-tree that replaces the operand.
// 5. Recurse into new sub-tree.
if (Left) {
this->SetLeftTree(DefExpr);
success = this->GetLeftTree()->ExpandExpr(DefAddr, LoopIndex, false, StopOnIV, StopOnLoopBoundary, StoppedOnIV);
}
else {
this->SetRightTree(DefExpr);
success = this->GetRightTree()->ExpandExpr(DefAddr, LoopIndex, false, StopOnIV, StopOnLoopBoundary, StoppedOnIV);
}
// 4. Make new expression the sub-tree that replaces the operand.
// 5. Recurse into new sub-tree.
if (Left) {
this->SetLeftTree(DefExpr);
success = this->GetLeftTree()->ExpandExpr(DefAddr, LoopIndex, false, StopOnIV, StopOnLoopBoundary, StoppedOnIV);
}
else {
this->SetRightTree(DefExpr);
success = this->GetRightTree()->ExpandExpr(DefAddr, LoopIndex, false, StopOnIV, StopOnLoopBoundary, StoppedOnIV);
}
}
}
if (success) {
// Inherit PreLoopDefAddr.
if (Left && (STARS_BADADDR == this->GetLeftPreLoopDefAddr()) && this->HasLeftSubTree()) {
// We expanded our left operand into an expr. Our PreLoopDefAddr is not informative.
// Inherit the LeftPreLoopDefAddr of the LeftTree we expanded our LeftOperand into.
this->SetLeftPreLoopDefAddr(this->GetLeftTree()->GetLeftPreLoopDefAddr());
}
else if (!Left && (STARS_BADADDR == this->GetRightPreLoopDefAddr()) && this->HasRightSubTree()) {
// We expanded our right operand into an expr. Our PreLoopDefAddr is not informative.
// Inherit the LeftPreLoopDefAddr of the RightTree we expanded our RightOperand into.
this->SetRightPreLoopDefAddr(this->GetRightTree()->GetLeftPreLoopDefAddr());
}
}
return success;
} // end of STARSExpression::ExpandOperand()
} // end of STARSExpression::ExpandOperandHelper()
 
// list incoming argument register numbers encountered (SSA #0 in an InArg reg)
void STARSExpression::ListInArgRegsUsed(std::bitset<1 + MD_LAST_REG_NO> &RegNums) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment