diff options
Diffstat (limited to 'vm/compiler/codegen/arm/LocalOptimizations.cpp')
| -rw-r--r-- | vm/compiler/codegen/arm/LocalOptimizations.cpp | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/vm/compiler/codegen/arm/LocalOptimizations.cpp b/vm/compiler/codegen/arm/LocalOptimizations.cpp index 8013d0059..cb35d745d 100644 --- a/vm/compiler/codegen/arm/LocalOptimizations.cpp +++ b/vm/compiler/codegen/arm/LocalOptimizations.cpp @@ -453,6 +453,136 @@ static void applyLoadHoisting(CompilationUnit *cUnit, } } +/* + * Find all lsl/lsr and add that can be replaced with a + * combined lsl/lsr + add + */ +static void applyShiftArithmeticOpts(CompilationUnit *cUnit, + ArmLIR *headLIR, + ArmLIR *tailLIR) { + ArmLIR *thisLIR = NULL; + + for (thisLIR = headLIR; + thisLIR != tailLIR; + thisLIR = NEXT_LIR(thisLIR)) { + + if(thisLIR->flags.isNop) { + continue; + } + + if(thisLIR->opcode == kThumb2LslRRI5 || thisLIR->opcode == kThumb2LsrRRI5 || + thisLIR->opcode == kThumbLslRRI5 || thisLIR->opcode == kThumbLsrRRI5) { + + /* Find next that is not nop and not pseudo code */ + ArmLIR *nextLIR = NULL; + for(nextLIR = NEXT_LIR(thisLIR); + nextLIR != tailLIR; + nextLIR = NEXT_LIR(nextLIR)) { + if (!nextLIR->flags.isNop && !isPseudoOpcode(nextLIR->opcode)) { + break; + } + } + + if(nextLIR == tailLIR) { + return; + } + + if(nextLIR->opcode == kThumb2AddRRR && + nextLIR->operands[3] == 0 && + (nextLIR->operands[1] == thisLIR->operands[0] || + nextLIR->operands[2] == thisLIR->operands[0])) { + + bool applyOpt = true; + if(!(thisLIR->operands[0] == nextLIR->operands[0])) { + /* Check that shift dest reg is not used after + * the addition. */ + ArmLIR* tmpLIR = NULL; + for(tmpLIR = NEXT_LIR(nextLIR); + tmpLIR != tailLIR; + tmpLIR = NEXT_LIR(tmpLIR)) { + + if (!tmpLIR->flags.isNop && + !(EncodingMap[tmpLIR->opcode].flags & IS_BRANCH) && + (tmpLIR->defMask | tmpLIR->useMask) & thisLIR->defMask) { + if(tmpLIR->useMask & thisLIR->defMask) { + /* Shift dest reg is used for src, skip opt. */ + applyOpt = false; + } + break; + } + } + } + + if(applyOpt) { + + /* + * Found lsl/lsr & add, use barrel shifter for add instead + * + * (1) Normal case + * [lsl/lsr] r9, r1, #x + * [add] r0, r2, r9 + * + * (2) Changing place of args for add + * [lsl/lsr] r9, r1, #x + * [add] r0, r9, r2 + * + * (3) Using r1 and r1 shifted as args for add + * [lsl/lsr] r9, r1, #x + * [add] r0, r1, r9 + * + * (4) Using r1 and r1 shifted as args for add, variant 2 + * [lsl/lsr] r9, r1, #x + * [add] r0, r9, r1 + * + * Result: + * [add] rDest, rSrc1, rSrc2, [lsl/lsr] x + */ + + int type = kArmLsl; + if(thisLIR->opcode == kThumb2LsrRRI5 || thisLIR->opcode == kThumbLsrRRI5) { + type = kArmLsr; + } + + /* For most cases keep original rSrc1 */ + int rSrc1 = nextLIR->operands[1]; + + if(thisLIR->operands[0] == nextLIR->operands[1]) { + /* Case 2 & 4: move original rSrc2 to rScr1 since + reg to be shifted need to be in rSrc2 */ + rSrc1 = nextLIR->operands[2]; + } + + /* Reg to be shifted need to be in rSrc2 */ + int rSrc2 = thisLIR->operands[1]; + + /* Encode type of shift and amount */ + int shift = ((thisLIR->operands[2] & 0x1f) << 2) | type; + + /* Keep rDest, but change rSrc1, rSrc2 and use shift */ + ArmLIR* newLIR = (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true); + newLIR->opcode = nextLIR->opcode; + newLIR->operands[0] = nextLIR->operands[0]; + newLIR->operands[1] = rSrc1; + newLIR->operands[2] = rSrc2; + newLIR->operands[3] = shift; + dvmCompilerSetupResourceMasks(newLIR); + dvmCompilerInsertLIRBefore((LIR *) nextLIR, (LIR *) newLIR); + + thisLIR->flags.isNop = true; + nextLIR->flags.isNop = true; + } + + /* + * Avoid looping through nops already identified. + * Continue directly after the updated instruction + * instead. + */ + thisLIR = nextLIR; + } + } + } +} + void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR, LIR *tailLIR) { @@ -463,4 +593,7 @@ void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR, if (!(gDvmJit.disableOpt & (1 << kLoadHoisting))) { applyLoadHoisting(cUnit, (ArmLIR *) headLIR, (ArmLIR *) tailLIR); } + if (!(gDvmJit.disableOpt & (1 << kShiftArithmetic))) { + applyShiftArithmeticOpts(cUnit, (ArmLIR *) headLIR, (ArmLIR* ) tailLIR); + } } |
