LaneDivide buildRightShift added

This commit is contained in:
caheckman 2019-10-21 12:08:48 -04:00
parent babc6d4d9b
commit fa82d8c8f3
2 changed files with 53 additions and 4 deletions

View file

@ -2008,13 +2008,12 @@ bool LaneDivide::buildPiece(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4
{ {
int4 highLanes,highSkip; int4 highLanes,highSkip;
int4 lowLanes,lowSkip; int4 lowLanes,lowSkip;
Varnode *outVn = op->getOut();
Varnode *highVn = op->getIn(0); Varnode *highVn = op->getIn(0);
Varnode *lowVn = op->getIn(1); Varnode *lowVn = op->getIn(1);
if (!description.restriction(numLanes,skipLanes,lowVn->getSize(),outVn->getSize(),highLanes,highSkip)) if (!description.restriction(numLanes,skipLanes,lowVn->getSize(),highVn->getSize(),highLanes,highSkip))
return false; return false;
if (!description.restriction(numLanes,skipLanes,0,outVn->getSize(),lowLanes,lowSkip)) if (!description.restriction(numLanes,skipLanes,0,lowVn->getSize(),lowLanes,lowSkip))
return false; return false;
if (highLanes == 1) { if (highLanes == 1) {
TransformVar *highRvn = getPreexistingVarnode(highVn); TransformVar *highRvn = getPreexistingVarnode(highVn);
@ -2175,6 +2174,43 @@ bool LaneDivide::buildLoad(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4
return true; return true;
} }
/// \brief Check that a CPUI_INT_RIGHT respects the lanes then generate lane placeholders
///
/// For the given lane scheme, check that the RIGHT shift is copying whole lanes to each other.
/// If so, generate the placeholder COPYs that model the shift.
/// \param op is the given CPUI_INT_RIGHT PcodeOp
/// \param outVars is the output placeholders for the RIGHT shift
/// \param numLanes is the number of lanes the shift is split into
/// \param skipLanes is the starting lane (within the global description) of the value being loaded
/// \return \b true if the CPUI_INT_RIGHT was successfully modeled on lanes
bool LaneDivide::buildRightShift(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4 skipLanes)
{
if (!op->getIn(1)->isConstant()) return false;
int4 shiftSize = (int4)op->getIn(1)->getOffset();
if ((shiftSize & 7) != 0) return false; // Not a multiple of 8
shiftSize /= 8;
int4 startPos = shiftSize + description.getPosition(skipLanes);
int4 startLane = description.getBoundary(startPos);
if (startLane < 0) return false; // Shift does not end on a lane boundary
int4 srcLane = startLane;
int4 destLane = skipLanes;
while(srcLane - skipLanes < numLanes) {
if (description.getSize(srcLane) != description.getSize(destLane)) return false;
srcLane += 1;
destLane += 1;
}
TransformVar *inVars = setReplacement(op->getIn(0), numLanes, skipLanes);
if (inVars == (TransformVar *)0) return false;
buildUnaryOp(CPUI_COPY, op, inVars + (startLane - skipLanes), outVars, numLanes - (startLane - skipLanes));
for(int4 zeroLane=numLanes - (startLane - skipLanes);zeroLane < numLanes;++zeroLane) {
TransformOp *rop = newOpReplace(1, CPUI_COPY, op);
opSetOutput(rop,outVars + zeroLane);
opSetInput(rop,newConstant(description.getSize(zeroLane), 0, 0),0);
}
return true;
}
/// \brief Push the logical lanes forward through any PcodeOp reading the given variable /// \brief Push the logical lanes forward through any PcodeOp reading the given variable
/// ///
/// Determine if the logical lanes can be pushed forward naturally, and create placeholder /// Determine if the logical lanes can be pushed forward naturally, and create placeholder
@ -2237,6 +2273,14 @@ bool LaneDivide::traceForward(TransformVar *rvn,int4 numLanes,int4 skipLanes)
// Don't create the placeholder ops, let traceBackward make them // Don't create the placeholder ops, let traceBackward make them
break; break;
} }
case CPUI_INT_RIGHT:
{
if (!op->getIn(1)->isConstant()) return false; // Trace must come through op->getIn(0)
TransformVar *outRvn = setReplacement(outvn, numLanes, skipLanes);
if (outRvn == (TransformVar *)0) return false;
// Don't create the placeholder ops, let traceBackward make them
break;
}
case CPUI_STORE: case CPUI_STORE:
if (op->getIn(2) != origvn) return false; // Can only propagate through value being stored if (op->getIn(2) != origvn) return false; // Can only propagate through value being stored
if (!buildStore(op,numLanes,skipLanes)) if (!buildStore(op,numLanes,skipLanes))
@ -2297,7 +2341,7 @@ bool LaneDivide::traceBackward(TransformVar *rvn,int4 numLanes,int4 skipLanes)
return false; return false;
TransformVar *inVars = setReplacement(inVn,inLanes,inSkip); TransformVar *inVars = setReplacement(inVn,inLanes,inSkip);
if (inVars == (TransformVar *)0) return false; if (inVars == (TransformVar *)0) return false;
buildUnaryOp(CPUI_COPY,op,inVars + (skipLanes - inSkip), rvn, inLanes); buildUnaryOp(CPUI_COPY,op,inVars + (skipLanes - inSkip), rvn, numLanes);
break; break;
} }
case CPUI_PIECE: case CPUI_PIECE:
@ -2308,6 +2352,10 @@ bool LaneDivide::traceBackward(TransformVar *rvn,int4 numLanes,int4 skipLanes)
if (!buildLoad(op, rvn, numLanes, skipLanes)) if (!buildLoad(op, rvn, numLanes, skipLanes))
return false; return false;
break; break;
case CPUI_INT_RIGHT:
if (!buildRightShift(op, rvn, numLanes, skipLanes))
return false;
break;
default: default:
return false; return false;
} }

View file

@ -173,6 +173,7 @@ class LaneDivide : public TransformManager {
bool buildMultiequal(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4 skipLanes); bool buildMultiequal(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4 skipLanes);
bool buildStore(PcodeOp *op,int4 numLanes,int4 skipLanes); bool buildStore(PcodeOp *op,int4 numLanes,int4 skipLanes);
bool buildLoad(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4 skipLanes); bool buildLoad(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4 skipLanes);
bool buildRightShift(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4 skipLanes);
bool traceForward(TransformVar *rvn,int4 numLanes,int4 skipLanes); bool traceForward(TransformVar *rvn,int4 numLanes,int4 skipLanes);
bool traceBackward(TransformVar *rvn,int4 numLanes,int4 skipLanes); bool traceBackward(TransformVar *rvn,int4 numLanes,int4 skipLanes);
bool processNextWork(void); ///< Process the next Varnode on the work list bool processNextWork(void); ///< Process the next Varnode on the work list