Exemplo n.º 1
0
void TR_ExpressionsSimplification::tranformStoreMotionCandidate(TR::TreeTop *treeTop, bool *isPreheaderBlockInvalid)
   {
   TR::Node *node = treeTop->getNode();

   TR_ASSERT(node->getOpCode().isStore() && !node->getSymbol()->isStatic() && !node->getSymbol()->holdsMonitoredObject(),
      "node %p was expected to be a non-static non-monitored object store and was not.", node);

   // this candidate should be valid, either direct or indirect

   if (trace())
      comp()->getDebug()->print(comp()->getOutFile(), node, 0, true);

   TR::Block *entryBlock = _currentRegion->getEntryBlock();
   TR::Block *preheaderBlock = findPredecessorBlock(entryBlock);

   if (!preheaderBlock)
      {
      if (trace())
         traceMsg(comp(), "Fail to find a place to put the hoist code in\n");
      *isPreheaderBlockInvalid = true;
      return;
      }

   // Earlier post-dominance test ensures that the loop is executed as least once, or is canonicalized.
   // but to be safe we still perform on canonicalized loops only.
   if (_currentRegion->isCanonicalizedLoop())  // make sure that the loop is canonicalized, in which case the preheader is
      {                                        // executed in its first iteration and is protected.
      if (performTransformation(comp(), "%sMove out loop-invariant store [%p] to block_%d\n", OPT_DETAILS, node, preheaderBlock->getNumber()))
         {
         TR::Node *newNode = node->duplicateTree();
         transformNode(newNode, preheaderBlock);
         TR::TransformUtil::removeTree(comp(), treeTop);
         }
      }
   else
      {
      if (trace())
         traceMsg(comp(), "No canonicalized loop for this candidate\n");
      }
   }
Exemplo n.º 2
0
/*
 * A loop is considered optimizable if:
 * 1) It has one basic induction variable.
 * 2) The loop back branch compares the BIV with a constant.
 * 3) We need to normalize the loop exit condition so that the loop is exited
 *    via the taken path.
 * 4) If it is a count-up loop, the condition is GE/GT. Otherwise it is
 *    LE/LT/LEZ/LTZ for a count-down loop.
 *
 * Return false for loops that fail the above tests.
 */
static bool isSimpleCountedLoop(CompilationUnit *cUnit)
{
    unsigned int i;
    BasicBlock *loopBackBlock = cUnit->entryBlock->fallThrough;
    LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;

    if (loopAnalysis->numBasicIV != 1) return false;
    for (i = 0; i < loopAnalysis->ivList->numUsed; i++) {
        InductionVariableInfo *ivInfo;

        ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i);
        /* Count up or down loop? */
        if (ivInfo->ssaReg == ivInfo->basicSSAReg) {
            /* Infinite loop */
            if (ivInfo->inc == 0) {
                return false;
            }
            loopAnalysis->isCountUpLoop = ivInfo->inc > 0;
            break;
        }
    }

    /* Find the block that ends with a branch to exit the loop */
    while (true) {
        loopBackBlock = findPredecessorBlock(cUnit, loopBackBlock);
        /* Loop structure not recognized as counted blocks */
        if (loopBackBlock == NULL) {
            return false;
        }
        /* Unconditional goto - continue to trace up the predecessor chain */
        if (loopBackBlock->taken == NULL) {
            continue;
        }
        break;
    }

    MIR *branch = loopBackBlock->lastMIRInsn;
    Opcode opcode = branch->dalvikInsn.opcode;

    /* Last instruction is not a conditional branch - bail */
    if (dexGetFlagsFromOpcode(opcode) != (kInstrCanContinue|kInstrCanBranch)) {
        return false;
    }

    int endSSAReg;
    int endDalvikReg;

    /* reg/reg comparison */
    if (branch->ssaRep->numUses == 2) {
        if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) {
            endSSAReg = branch->ssaRep->uses[1];
        } else if (branch->ssaRep->uses[1] == loopAnalysis->ssaBIV) {
            endSSAReg = branch->ssaRep->uses[0];
            opcode = negateOpcode(opcode);
        } else {
            return false;
        }
        endDalvikReg = dvmConvertSSARegToDalvik(cUnit, endSSAReg);
        /*
         * If the comparison is not between the BIV and a loop invariant,
         * return false. endDalvikReg is loop invariant if one of the
         * following is true:
         * - It is not defined in the loop (ie DECODE_SUB returns 0)
         * - It is reloaded with a constant
         */
        if ((DECODE_SUB(endDalvikReg) != 0) &&
            !dvmIsBitSet(cUnit->isConstantV, endSSAReg)) {
            return false;
        }
    /* Compare against zero */
    } else if (branch->ssaRep->numUses == 1) {
        if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) {
            /* Keep the compiler happy */
            endDalvikReg = -1;
        } else {
            return false;
        }
    } else {
        return false;
    }

    /* Normalize the loop exit check as "if (iv op end) exit;" */
    if (loopBackBlock->taken->blockType == kDalvikByteCode) {
        opcode = negateOpcode(opcode);
    }

    if (loopAnalysis->isCountUpLoop) {
        /*
         * If the normalized condition op is not > or >=, this is not an
         * optimization candidate.
         */
        switch (opcode) {
            case OP_IF_GT:
            case OP_IF_GE:
                break;
            default:
                return false;
        }
        loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg);
    } else  {
        /*
         * If the normalized condition op is not < or <=, this is not an
         * optimization candidate.
         */
        switch (opcode) {
            case OP_IF_LT:
            case OP_IF_LE:
                loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg);
                break;
            case OP_IF_LTZ:
            case OP_IF_LEZ:
                break;
            default:
                return false;
        }
    }
    /*
     * Remember the normalized opcode, which will be used to determine the end
     * value used for the yanked range checks.
     */
    loopAnalysis->loopBranchOpcode = opcode;
    return true;
}
Exemplo n.º 3
0
bool TR_ExpressionsSimplification::tranformSummationReductionCandidate(TR::TreeTop *treeTop, LoopInfo *loopInfo, bool *isPreheaderBlockInvalid)
   {
   TR::Node *node = treeTop->getNode();
   TR::Node *opNode = node->getFirstChild();
   TR::Node *expNode = NULL;
   int32_t expChildNumber = 0;
   bool removeOnly = false;
   bool replaceWithNewNode = false;

   if (opNode->getOpCodeValue() == TR::iadd || opNode->getOpCodeValue() == TR::isub)
      {
      if (opNode->getSecondChild()->getOpCode().hasSymbolReference() &&
            node->getSymbolReference() == opNode->getSecondChild()->getSymbolReference())
         {
         expChildNumber = 0;
         expNode = opNode->getFirstChild();
         }
      else
         {
         expChildNumber = 1;
         expNode = opNode->getSecondChild();
         }
      expNode = iaddisubSimplifier(expNode, loopInfo);
      replaceWithNewNode = true;
      }
   else if (opNode->getOpCodeValue() == TR::ixor || opNode->getOpCodeValue() == TR::ineg)
      {
      expNode = ixorinegSimplifier(opNode, loopInfo, &removeOnly);
      }

   if (expNode)
      {
      if (trace())
         comp()->getDebug()->print(comp()->getOutFile(), expNode, 0, true);

      TR::Block *entryBlock = _currentRegion->getEntryBlock();
      TR::Block *preheaderBlock = findPredecessorBlock(entryBlock);

      if (!preheaderBlock)
         {
         if (trace())
            traceMsg(comp(), "Fail to find a place to put the hoist code in\n");
         *isPreheaderBlockInvalid = true;
         return true;
         }

      if (loopInfo->getNumIterations() > 0 ||     // make sure that the loop is going to be executed at least once
            _currentRegion->isCanonicalizedLoop())  // or that the loop is canonicalized, in which case the preheader is
         {                                        // executed in its first iteration and is protected.
         if (performTransformation(comp(), "%sMove out loop-invariant node [%p] to block_%d\n", OPT_DETAILS, node, preheaderBlock->getNumber()))
            {
            if (!(removeOnly))
               {
               TR::Node *newNode = node->duplicateTree();
               if (replaceWithNewNode)
                  newNode->getFirstChild()->setAndIncChild(expChildNumber, expNode);
               transformNode(newNode, preheaderBlock);
               }
            TR::TransformUtil::removeTree(comp(), treeTop);
            }
         }
      }
      return (expNode != NULL);
   }