ARM: Optimize Div/Rem by positive const for non-negative dividends
When a constant divisor is positive and it can be proved that dividends
are non-negative, there is no need to generate instructions correcting
the result.
The CL implements this optimization for ARM32/ARM64.
Test: 411-checker-hdiv-hrem-const
Test: test.py --host --optimizing --jit --gtest --interpreter
Test: test.py -target --optimizing --jit --interpreter
Test: run-gtests.sh
Change-Id: Idf9aa740f14700000948b5ca58311be403a269ee
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index ba5b1b7..7d1af05 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -3242,13 +3242,23 @@
// Extract the result from the high 32 bits and apply the final right shift.
DCHECK_LT(shift, 32);
- __ Asr(temp.X(), temp.X(), 32 + shift);
-
- if (instruction->IsRem()) {
- GenerateIncrementNegativeByOne(temp, temp, use_cond_inc);
- GenerateResultRemWithAnyConstant(out, dividend, temp, imm, &temps);
+ if (imm > 0 && IsGEZero(instruction->GetLeft())) {
+ // No need to adjust the result for a non-negative dividend and a positive divisor.
+ if (instruction->IsDiv()) {
+ __ Lsr(out.X(), temp.X(), 32 + shift);
+ } else {
+ __ Lsr(temp.X(), temp.X(), 32 + shift);
+ GenerateResultRemWithAnyConstant(out, dividend, temp, imm, &temps);
+ }
} else {
- GenerateIncrementNegativeByOne(out, temp, use_cond_inc);
+ __ Asr(temp.X(), temp.X(), 32 + shift);
+
+ if (instruction->IsRem()) {
+ GenerateIncrementNegativeByOne(temp, temp, use_cond_inc);
+ GenerateResultRemWithAnyConstant(out, dividend, temp, imm, &temps);
+ } else {
+ GenerateIncrementNegativeByOne(out, temp, use_cond_inc);
+ }
}
}