diff options
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 6 | ||||
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 26 | ||||
-rw-r--r-- | test/431-optimizing-arith-shifts/src/Main.java | 31 | ||||
-rw-r--r-- | test/458-checker-instruction-simplification/src/Main.java | 19 |
4 files changed, 72 insertions, 10 deletions
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::HandleShift(HBinaryOperation* op) { 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 @@ void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) { 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 @@ public class Main { 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 @@ public class Main { 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 @@ public class Main { return a >>> 2L; } - static int $opt$ShlConst0(int a) { + static int $opt$ShlConst0(int a) { return a << 0; } @@ -301,5 +308,25 @@ public class Main { 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 @@ public class Main { 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 @@ public class Main { assertDoubleEquals(Div2(150.0), 75.0); assertFloatEquals(DivMP25(100.0f), -400.0f); assertDoubleEquals(DivMP25(150.0), -600.0); + assertLongEquals(Shl1(100), 200); } } |