[optimizing] Improve 32 bit long shift by 1.
Also change FOO << 1 to FOO+FOO in the instruction simplifier. This is
an architecture independent simplification, which helps 'long << 1' for
32 bit architectures.
Generate an add/adc for long << 1 in x86, in case something is generated
after the simplifier.
Add test cases for the simplification.
Change-Id: I0d512331ef13cc4ccf10c80f11c370a10ed02294
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index cfb8702..2848a48 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -2830,7 +2830,11 @@
void InstructionCodeGeneratorX86::GenerateShlLong(const Location& loc, int shift) {
Register low = loc.AsRegisterPairLow<Register>();
Register high = loc.AsRegisterPairHigh<Register>();
- if (shift == 32) {
+ if (shift == 1) {
+ // This is just an addition.
+ __ addl(low, low);
+ __ adcl(high, high);
+ } else if (shift == 32) {
// Shift by 32 is easy. High gets low, and low gets 0.
codegen_->EmitParallelMoves(
loc.ToLow(),
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index e79d4f4..46fad17 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -137,13 +137,25 @@
HConstant* input_cst = instruction->GetConstantRight();
HInstruction* input_other = instruction->GetLeastConstantLeft();
- if ((input_cst != nullptr) && input_cst->IsZero()) {
- // Replace code looking like
- // SHL dst, src, 0
- // with
- // src
- instruction->ReplaceWith(input_other);
- instruction->GetBlock()->RemoveInstruction(instruction);
+ if (input_cst != nullptr) {
+ if (input_cst->IsZero()) {
+ // Replace code looking like
+ // SHL dst, src, 0
+ // with
+ // src
+ instruction->ReplaceWith(input_other);
+ instruction->GetBlock()->RemoveInstruction(instruction);
+ } else if (instruction->IsShl() && input_cst->IsOne()) {
+ // Replace Shl looking like
+ // SHL dst, src, 1
+ // with
+ // ADD dst, src, src
+ HAdd *add = new(GetGraph()->GetArena()) HAdd(instruction->GetType(),
+ input_other,
+ input_other);
+ instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add);
+ RecordSimplification();
+ }
}
}
diff --git a/test/431-optimizing-arith-shifts/src/Main.java b/test/431-optimizing-arith-shifts/src/Main.java
index d8667c6..86422bd 100644
--- a/test/431-optimizing-arith-shifts/src/Main.java
+++ b/test/431-optimizing-arith-shifts/src/Main.java
@@ -52,7 +52,7 @@
expectEquals(Integer.MIN_VALUE, $opt$Shl(1073741824, 1)); // overflow
expectEquals(1073741824, $opt$Shl(268435456, 2));
- // othe nly 5 lower bits should be used for shifting (& 0x1f).
+ // Only the 5 lower bits should be used for shifting (& 0x1f).
expectEquals(7, $opt$Shl(7, 32)); // 32 & 0x1f = 0
expectEquals(14, $opt$Shl(7, 33)); // 33 & 0x1f = 1
expectEquals(32, $opt$Shl(1, 101)); // 101 & 0x1f = 5
@@ -97,6 +97,13 @@
expectEquals(Long.MIN_VALUE, $opt$Shl(7L, Long.MAX_VALUE));
expectEquals(7L, $opt$Shl(7L, Long.MIN_VALUE));
+
+ // Exercise some special cases handled by backends/simplifier.
+ expectEquals(24L, $opt$ShlConst1(12L));
+ expectEquals(0x2345678900000000L, $opt$ShlConst32(0x123456789L));
+ expectEquals(0x2490249000000000L, $opt$ShlConst33(0x12481248L));
+ expectEquals(0x4920492000000000L, $opt$ShlConst34(0x12481248L));
+ expectEquals(0x9240924000000000L, $opt$ShlConst35(0x12481248L));
}
private static void shrInt() {
@@ -277,7 +284,7 @@
return a >>> 2L;
}
- static int $opt$ShlConst0(int a) {
+ static int $opt$ShlConst0(int a) {
return a << 0;
}
@@ -301,5 +308,25 @@
return a >>> 0L;
}
+ static long $opt$ShlConst1(long a) {
+ return a << 1L;
+ }
+
+ static long $opt$ShlConst32(long a) {
+ return a << 32L;
+ }
+
+ static long $opt$ShlConst33(long a) {
+ return a << 33L;
+ }
+
+ static long $opt$ShlConst34(long a) {
+ return a << 34L;
+ }
+
+ static long $opt$ShlConst35(long a) {
+ return a << 35L;
+ }
+
}
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index 5d5a6b3..efb7b83 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -223,6 +223,24 @@
return arg << 0;
}
+ // CHECK-START: int Main.Shl1(int) instruction_simplifier (before)
+ // CHECK-DAG: [[Arg:i\d+]] ParameterValue
+ // CHECK-DAG: [[Const1:i\d+]] IntConstant 1
+ // CHECK-DAG: [[Shl:i\d+]] Shl [ [[Arg]] [[Const1]] ]
+ // CHECK-DAG: Return [ [[Shl]] ]
+
+ // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
+ // CHECK-DAG: [[Arg:i\d+]] ParameterValue
+ // CHECK-DAG: [[Add:i\d+]] Add [ [[Arg]] [[Arg]] ]
+ // CHECK-DAG: Return [ [[Add]] ]
+
+ // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
+ // CHECK-NOT: Shl
+
+ public static int Shl1(int arg) {
+ return arg << 1;
+ }
+
// CHECK-START: long Main.Shr0(long) instruction_simplifier (before)
// CHECK-DAG: [[Arg:j\d+]] ParameterValue
// CHECK-DAG: [[Const0:i\d+]] IntConstant 0
@@ -1060,5 +1078,6 @@
assertDoubleEquals(Div2(150.0), 75.0);
assertFloatEquals(DivMP25(100.0f), -400.0f);
assertDoubleEquals(DivMP25(150.0), -600.0);
+ assertLongEquals(Shl1(100), 200);
}
}