Optimizing/ARM: Improve long shifts by 1.
Implement long
Shl(x,1) as LSLS+ADC,
Shr(x,1) as ASR+RRX and
UShr(x,1) as LSR+RRX.
Remove the simplification substituting Shl(x,1) with
ADD(x,x) as it interferes with some other optimizations
instead of helping them. And since it didn't help 64-bit
architectures anyway, codegen is the correct place for it.
This is now implemented for ARM and x86, so only mips32 can
be improved.
Change-Id: Idd14f23292198b2260189e1497ca5411b21743b3
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 12ab68e..c7e412c 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -3361,7 +3361,19 @@
__ mov(o_l, ShifterOperand(high));
__ LoadImmediate(o_h, 0);
}
- } else { // shift_value < 32
+ } else if (shift_value == 1) {
+ if (op->IsShl()) {
+ __ Lsls(o_l, low, 1);
+ __ adc(o_h, high, ShifterOperand(high));
+ } else if (op->IsShr()) {
+ __ Asrs(o_h, high, 1);
+ __ Rrx(o_l, low);
+ } else {
+ __ Lsrs(o_h, high, 1);
+ __ Rrx(o_l, low);
+ }
+ } else {
+ DCHECK(2 <= shift_value && shift_value < 32) << shift_value;
if (op->IsShl()) {
__ Lsl(o_h, high, shift_value);
__ orr(o_h, o_h, ShifterOperand(low, LSR, 32 - shift_value));
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index b97dc1a..b36870c 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -169,16 +169,6 @@
// 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/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 297cc54..584a597 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -3220,7 +3220,7 @@
void Thumb2Assembler::Rrx(Register rd, Register rm, Condition cond, SetCc set_cc) {
CheckCondition(cond);
- EmitShift(rd, rm, RRX, rm, cond, set_cc);
+ EmitShift(rd, rm, RRX, 0, cond, set_cc);
}
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 2ae8841..2e7021d 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -466,6 +466,38 @@
EmitAndCheck(&assembler, "DataProcessingShiftedRegister");
}
+TEST(Thumb2AssemblerTest, ShiftImmediate) {
+ // Note: This test produces the same results as DataProcessingShiftedRegister
+ // but it does so using shift functions instead of mov().
+ arm::Thumb2Assembler assembler;
+
+ // 16-bit variants.
+ __ Lsl(R3, R4, 4);
+ __ Lsr(R3, R4, 5);
+ __ Asr(R3, R4, 6);
+
+ // 32-bit ROR because ROR immediate doesn't have the same 16-bit version as other shifts.
+ __ Ror(R3, R4, 7);
+
+ // 32-bit RRX because RRX has no 16-bit version.
+ __ Rrx(R3, R4);
+
+ // 32 bit variants (not setting condition codes).
+ __ Lsl(R3, R4, 4, AL, kCcKeep);
+ __ Lsr(R3, R4, 5, AL, kCcKeep);
+ __ Asr(R3, R4, 6, AL, kCcKeep);
+ __ Ror(R3, R4, 7, AL, kCcKeep);
+ __ Rrx(R3, R4, AL, kCcKeep);
+
+ // 32 bit variants (high registers).
+ __ Lsls(R8, R4, 4);
+ __ Lsrs(R8, R4, 5);
+ __ Asrs(R8, R4, 6);
+ __ Rors(R8, R4, 7);
+ __ Rrxs(R8, R4);
+
+ EmitAndCheck(&assembler, "ShiftImmediate");
+}
TEST(Thumb2AssemblerTest, BasicLoad) {
arm::Thumb2Assembler assembler;
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index b79c2e4..3fda09f 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -201,6 +201,24 @@
" 32: ea5f 0834 movs.w r8, r4, rrx\n",
nullptr
};
+const char* ShiftImmediateResults[] = {
+ " 0: 0123 lsls r3, r4, #4\n",
+ " 2: 0963 lsrs r3, r4, #5\n",
+ " 4: 11a3 asrs r3, r4, #6\n",
+ " 6: ea4f 13f4 mov.w r3, r4, ror #7\n",
+ " a: ea4f 0334 mov.w r3, r4, rrx\n",
+ " e: ea4f 1304 mov.w r3, r4, lsl #4\n",
+ " 12: ea4f 1354 mov.w r3, r4, lsr #5\n",
+ " 16: ea4f 13a4 mov.w r3, r4, asr #6\n",
+ " 1a: ea4f 13f4 mov.w r3, r4, ror #7\n",
+ " 1e: ea4f 0334 mov.w r3, r4, rrx\n",
+ " 22: ea5f 1804 movs.w r8, r4, lsl #4\n",
+ " 26: ea5f 1854 movs.w r8, r4, lsr #5\n",
+ " 2a: ea5f 18a4 movs.w r8, r4, asr #6\n",
+ " 2e: ea5f 18f4 movs.w r8, r4, ror #7\n",
+ " 32: ea5f 0834 movs.w r8, r4, rrx\n",
+ nullptr
+};
const char* BasicLoadResults[] = {
" 0: 69a3 ldr r3, [r4, #24]\n",
" 2: 7e23 ldrb r3, [r4, #24]\n",
@@ -4952,6 +4970,7 @@
test_results["DataProcessingModifiedImmediate"] = DataProcessingModifiedImmediateResults;
test_results["DataProcessingModifiedImmediates"] = DataProcessingModifiedImmediatesResults;
test_results["DataProcessingShiftedRegister"] = DataProcessingShiftedRegisterResults;
+ test_results["ShiftImmediate"] = ShiftImmediateResults;
test_results["BasicLoad"] = BasicLoadResults;
test_results["BasicStore"] = BasicStoreResults;
test_results["ComplexLoad"] = ComplexLoadResults;
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index c32d34a..bad857c 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -389,24 +389,6 @@
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
@@ -1274,7 +1256,6 @@
assertDoubleEquals(Div2(150.0), 75.0);
assertFloatEquals(DivMP25(100.0f), -400.0f);
assertDoubleEquals(DivMP25(150.0), -600.0);
- assertLongEquals(Shl1(100), 200);
assertIntEquals(UShr28And15(0xc1234567), 0xc);
assertLongEquals(UShr60And15(0xc123456787654321L), 0xcL);
assertIntEquals(UShr28And7(0xc1234567), 0x4);
diff --git a/test/538-checker-embed-constants/src/Main.java b/test/538-checker-embed-constants/src/Main.java
index 12f0380..f791adf 100644
--- a/test/538-checker-embed-constants/src/Main.java
+++ b/test/538-checker-embed-constants/src/Main.java
@@ -260,26 +260,43 @@
return arg ^ 0xf00000000000000fL;
}
- /// CHECK-START-ARM: long Main.shl2(long) disassembly (after)
- /// CHECK: lsl{{s?|.w}} <<oh:r\d+>>, {{r\d+}}, #2
- /// CHECK: orr.w <<oh>>, <<oh>>, <<low:r\d+>>, lsr #30
- /// CHECK-DAG: lsl{{s?|.w}} {{r\d+}}, <<low>>, #2
+ /// CHECK-START-ARM: long Main.shl1(long) disassembly (after)
+ /// CHECK: lsls{{(\.w)?}} {{r\d+}}, {{r\d+}}, #1
+ /// CHECK: adc{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+
+ /// CHECK-START-ARM: long Main.shl1(long) disassembly (after)
+ /// CHECK-NOT: lsl{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+
+ /// CHECK-START-X86: long Main.shl1(long) disassembly (after)
+ /// CHECK: add
+ /// CHECK: adc
+
+ /// CHECK-START-X86: long Main.shl1(long) disassembly (after)
+ /// CHECK-NOT: shl
+
+ public static long shl1(long arg) {
+ return arg << 1;
+ }
/// CHECK-START-ARM: long Main.shl2(long) disassembly (after)
- /// CHECK-NOT: lsl{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK: lsl{{s?|\.w}} <<oh:r\d+>>, {{r\d+}}, #2
+ /// CHECK: orr.w <<oh>>, <<oh>>, <<low:r\d+>>, lsr #30
+ /// CHECK: lsl{{s?|\.w}} {{r\d+}}, <<low>>, #2
+
+ /// CHECK-START-ARM: long Main.shl2(long) disassembly (after)
+ /// CHECK-NOT: lsl{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long shl2(long arg) {
- // Note: Shl(x, 1) is transformed to Add(x, x), so test Shl(x, 2).
return arg << 2;
}
/// CHECK-START-ARM: long Main.shl31(long) disassembly (after)
- /// CHECK: lsl{{s?|.w}} <<oh:r\d+>>, {{r\d+}}, #31
+ /// CHECK: lsl{{s?|\.w}} <<oh:r\d+>>, {{r\d+}}, #31
/// CHECK: orr.w <<oh>>, <<oh>>, <<low:r\d+>>, lsr #1
- /// CHECK: lsl{{s?|.w}} {{r\d+}}, <<low>>, #31
+ /// CHECK: lsl{{s?|\.w}} {{r\d+}}, <<low>>, #31
/// CHECK-START-ARM: long Main.shl31(long) disassembly (after)
- /// CHECK-NOT: lsl{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: lsl{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long shl31(long arg) {
return arg << 31;
@@ -287,114 +304,136 @@
/// CHECK-START-ARM: long Main.shl32(long) disassembly (after)
/// CHECK-DAG: mov {{r\d+}}, {{r\d+}}
- /// CHECK-DAG: mov{{s?|.w}} {{r\d+}}, #0
+ /// CHECK-DAG: mov{{s?|\.w}} {{r\d+}}, #0
/// CHECK-START-ARM: long Main.shl32(long) disassembly (after)
- /// CHECK-NOT: lsl{{s?|.w}}
+ /// CHECK-NOT: lsl{{s?|\.w}}
public static long shl32(long arg) {
return arg << 32;
}
/// CHECK-START-ARM: long Main.shl33(long) disassembly (after)
- /// CHECK-DAG: lsl{{s?|.w}} {{r\d+}}, <<high:r\d+>>, #1
- /// CHECK-DAG: mov{{s?|.w}} {{r\d+}}, #0
+ /// CHECK-DAG: lsl{{s?|\.w}} {{r\d+}}, <<high:r\d+>>, #1
+ /// CHECK-DAG: mov{{s?|\.w}} {{r\d+}}, #0
/// CHECK-START-ARM: long Main.shl33(long) disassembly (after)
- /// CHECK-NOT: lsl{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: lsl{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long shl33(long arg) {
return arg << 33;
}
/// CHECK-START-ARM: long Main.shl63(long) disassembly (after)
- /// CHECK-DAG: lsl{{s?|.w}} {{r\d+}}, <<high:r\d+>>, #31
- /// CHECK-DAG: mov{{s?|.w}} {{r\d+}}, #0
+ /// CHECK-DAG: lsl{{s?|\.w}} {{r\d+}}, <<high:r\d+>>, #31
+ /// CHECK-DAG: mov{{s?|\.w}} {{r\d+}}, #0
/// CHECK-START-ARM: long Main.shl63(long) disassembly (after)
- /// CHECK-NOT: lsl{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: lsl{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long shl63(long arg) {
return arg << 63;
}
/// CHECK-START-ARM: long Main.shr1(long) disassembly (after)
- /// CHECK: lsr{{s?|.w}} <<ol:r\d+>>, {{r\d+}}, #1
- /// CHECK: orr.w <<ol>>, <<ol>>, <<high:r\d+>>, lsl #31
- /// CHECK-DAG: asr{{s?|.w}} {{r\d+}}, <<high>>, #1
+ /// CHECK: asrs{{(\.w)?}} {{r\d+}}, {{r\d+}}, #1
+ /// CHECK: mov.w {{r\d+}}, {{r\d+}}, rrx
/// CHECK-START-ARM: long Main.shr1(long) disassembly (after)
- /// CHECK-NOT: asr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: asr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long shr1(long arg) {
return arg >> 1;
}
- /// CHECK-START-ARM: long Main.shr31(long) disassembly (after)
- /// CHECK: lsr{{s?|.w}} <<ol:r\d+>>, {{r\d+}}, #31
- /// CHECK: orr.w <<ol>>, <<ol>>, <<high:r\d+>>, lsl #1
- /// CHECK: asr{{s?|.w}} {{r\d+}}, <<high>>, #31
+ /// CHECK-START-ARM: long Main.shr2(long) disassembly (after)
+ /// CHECK: lsr{{s?|\.w}} <<ol:r\d+>>, {{r\d+}}, #2
+ /// CHECK: orr.w <<ol>>, <<ol>>, <<high:r\d+>>, lsl #30
+ /// CHECK-DAG: asr{{s?|\.w}} {{r\d+}}, <<high>>, #2
+
+ /// CHECK-START-ARM: long Main.shr2(long) disassembly (after)
+ /// CHECK-NOT: asr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+
+ public static long shr2(long arg) {
+ return arg >> 2;
+ }
/// CHECK-START-ARM: long Main.shr31(long) disassembly (after)
- /// CHECK-NOT: asr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK: lsr{{s?|\.w}} <<ol:r\d+>>, {{r\d+}}, #31
+ /// CHECK: orr.w <<ol>>, <<ol>>, <<high:r\d+>>, lsl #1
+ /// CHECK: asr{{s?|\.w}} {{r\d+}}, <<high>>, #31
+
+ /// CHECK-START-ARM: long Main.shr31(long) disassembly (after)
+ /// CHECK-NOT: asr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long shr31(long arg) {
return arg >> 31;
}
/// CHECK-START-ARM: long Main.shr32(long) disassembly (after)
- /// CHECK-DAG: asr{{s?|.w}} {{r\d+}}, <<high:r\d+>>, #31
+ /// CHECK-DAG: asr{{s?|\.w}} {{r\d+}}, <<high:r\d+>>, #31
/// CHECK-DAG: mov {{r\d+}}, <<high>>
/// CHECK-START-ARM: long Main.shr32(long) disassembly (after)
- /// CHECK-NOT: asr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
- /// CHECK-NOT: lsr{{s?|.w}}
+ /// CHECK-NOT: asr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: lsr{{s?|\.w}}
public static long shr32(long arg) {
return arg >> 32;
}
/// CHECK-START-ARM: long Main.shr33(long) disassembly (after)
- /// CHECK-DAG: asr{{s?|.w}} {{r\d+}}, <<high:r\d+>>, #1
- /// CHECK-DAG: asr{{s?|.w}} {{r\d+}}, <<high>>, #31
+ /// CHECK-DAG: asr{{s?|\.w}} {{r\d+}}, <<high:r\d+>>, #1
+ /// CHECK-DAG: asr{{s?|\.w}} {{r\d+}}, <<high>>, #31
/// CHECK-START-ARM: long Main.shr33(long) disassembly (after)
- /// CHECK-NOT: asr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: asr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long shr33(long arg) {
return arg >> 33;
}
/// CHECK-START-ARM: long Main.shr63(long) disassembly (after)
- /// CHECK-DAG: asr{{s?|.w}} {{r\d+}}, <<high:r\d+>>, #31
- /// CHECK-DAG: asr{{s?|.w}} {{r\d+}}, <<high>>, #31
+ /// CHECK-DAG: asr{{s?|\.w}} {{r\d+}}, <<high:r\d+>>, #31
+ /// CHECK-DAG: asr{{s?|\.w}} {{r\d+}}, <<high>>, #31
/// CHECK-START-ARM: long Main.shr63(long) disassembly (after)
- /// CHECK-NOT: asr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: asr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long shr63(long arg) {
return arg >> 63;
}
/// CHECK-START-ARM: long Main.ushr1(long) disassembly (after)
- /// CHECK: lsr{{s?|.w}} <<ol:r\d+>>, {{r\d+}}, #1
- /// CHECK: orr.w <<ol>>, <<ol>>, <<high:r\d+>>, lsl #31
- /// CHECK-DAG: lsr{{s?|.w}} {{r\d+}}, <<high>>, #1
+ /// CHECK: lsrs{{|.w}} {{r\d+}}, {{r\d+}}, #1
+ /// CHECK: mov.w {{r\d+}}, {{r\d+}}, rrx
/// CHECK-START-ARM: long Main.ushr1(long) disassembly (after)
- /// CHECK-NOT: lsr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: lsr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long ushr1(long arg) {
return arg >>> 1;
}
- /// CHECK-START-ARM: long Main.ushr31(long) disassembly (after)
- /// CHECK: lsr{{s?|.w}} <<ol:r\d+>>, {{r\d+}}, #31
- /// CHECK: orr.w <<ol>>, <<ol>>, <<high:r\d+>>, lsl #1
- /// CHECK: lsr{{s?|.w}} {{r\d+}}, <<high>>, #31
+ /// CHECK-START-ARM: long Main.ushr2(long) disassembly (after)
+ /// CHECK: lsr{{s?|\.w}} <<ol:r\d+>>, {{r\d+}}, #2
+ /// CHECK: orr.w <<ol>>, <<ol>>, <<high:r\d+>>, lsl #30
+ /// CHECK-DAG: lsr{{s?|\.w}} {{r\d+}}, <<high>>, #2
+
+ /// CHECK-START-ARM: long Main.ushr2(long) disassembly (after)
+ /// CHECK-NOT: lsr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+
+ public static long ushr2(long arg) {
+ return arg >>> 2;
+ }
/// CHECK-START-ARM: long Main.ushr31(long) disassembly (after)
- /// CHECK-NOT: lsr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK: lsr{{s?|\.w}} <<ol:r\d+>>, {{r\d+}}, #31
+ /// CHECK: orr.w <<ol>>, <<ol>>, <<high:r\d+>>, lsl #1
+ /// CHECK: lsr{{s?|\.w}} {{r\d+}}, <<high>>, #31
+
+ /// CHECK-START-ARM: long Main.ushr31(long) disassembly (after)
+ /// CHECK-NOT: lsr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long ushr31(long arg) {
return arg >>> 31;
@@ -402,32 +441,32 @@
/// CHECK-START-ARM: long Main.ushr32(long) disassembly (after)
/// CHECK-DAG: mov {{r\d+}}, {{r\d+}}
- /// CHECK-DAG: mov{{s?|.w}} {{r\d+}}, #0
+ /// CHECK-DAG: mov{{s?|\.w}} {{r\d+}}, #0
/// CHECK-START-ARM: long Main.ushr32(long) disassembly (after)
- /// CHECK-NOT: lsr{{s?|.w}}
+ /// CHECK-NOT: lsr{{s?|\.w}}
public static long ushr32(long arg) {
return arg >>> 32;
}
/// CHECK-START-ARM: long Main.ushr33(long) disassembly (after)
- /// CHECK-DAG: lsr{{s?|.w}} {{r\d+}}, {{r\d+}}, #1
- /// CHECK-DAG: mov{{s?|.w}} {{r\d+}}, #0
+ /// CHECK-DAG: lsr{{s?|\.w}} {{r\d+}}, {{r\d+}}, #1
+ /// CHECK-DAG: mov{{s?|\.w}} {{r\d+}}, #0
/// CHECK-START-ARM: long Main.ushr33(long) disassembly (after)
- /// CHECK-NOT: lsr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: lsr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long ushr33(long arg) {
return arg >>> 33;
}
/// CHECK-START-ARM: long Main.ushr63(long) disassembly (after)
- /// CHECK-DAG: lsr{{s?|.w}} {{r\d+}}, {{r\d+}}, #31
- /// CHECK-DAG: mov{{s?|.w}} {{r\d+}}, #0
+ /// CHECK-DAG: lsr{{s?|\.w}} {{r\d+}}, {{r\d+}}, #31
+ /// CHECK-DAG: mov{{s?|\.w}} {{r\d+}}, #0
/// CHECK-START-ARM: long Main.ushr63(long) disassembly (after)
- /// CHECK-NOT: lsr{{s?|.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: lsr{{s?|\.w}} {{r\d+}}, {{r\d+}}, {{r\d+}}
public static long ushr63(long arg) {
return arg >>> 63;
@@ -485,11 +524,13 @@
assertLongEquals(14, addM1(7));
+ assertLongEquals(shl1(longArg), 0x2468acf10eca8642L);
assertLongEquals(shl2(longArg), 0x48d159e21d950c84L);
assertLongEquals(shl31(longArg), 0x43b2a19080000000L);
assertLongEquals(shl32(longArg), 0x8765432100000000L);
assertLongEquals(shl33(longArg), 0x0eca864200000000L);
assertLongEquals(shl63(longArg), 0x8000000000000000L);
+ assertLongEquals(shl1(~longArg), 0xdb97530ef13579bcL);
assertLongEquals(shl2(~longArg), 0xb72ea61de26af378L);
assertLongEquals(shl31(~longArg), 0xbc4d5e6f00000000L);
assertLongEquals(shl32(~longArg), 0x789abcde00000000L);
@@ -497,22 +538,26 @@
assertLongEquals(shl63(~longArg), 0x0000000000000000L);
assertLongEquals(shr1(longArg), 0x091a2b3c43b2a190L);
+ assertLongEquals(shr2(longArg), 0x048d159e21d950c8L);
assertLongEquals(shr31(longArg), 0x000000002468acf1L);
assertLongEquals(shr32(longArg), 0x0000000012345678L);
assertLongEquals(shr33(longArg), 0x00000000091a2b3cL);
assertLongEquals(shr63(longArg), 0x0000000000000000L);
assertLongEquals(shr1(~longArg), 0xf6e5d4c3bc4d5e6fL);
+ assertLongEquals(shr2(~longArg), 0xfb72ea61de26af37L);
assertLongEquals(shr31(~longArg), 0xffffffffdb97530eL);
assertLongEquals(shr32(~longArg), 0xffffffffedcba987L);
assertLongEquals(shr33(~longArg), 0xfffffffff6e5d4c3L);
assertLongEquals(shr63(~longArg), 0xffffffffffffffffL);
assertLongEquals(ushr1(longArg), 0x091a2b3c43b2a190L);
+ assertLongEquals(ushr2(longArg), 0x048d159e21d950c8L);
assertLongEquals(ushr31(longArg), 0x000000002468acf1L);
assertLongEquals(ushr32(longArg), 0x0000000012345678L);
assertLongEquals(ushr33(longArg), 0x00000000091a2b3cL);
assertLongEquals(ushr63(longArg), 0x0000000000000000L);
assertLongEquals(ushr1(~longArg), 0x76e5d4c3bc4d5e6fL);
+ assertLongEquals(ushr2(~longArg), 0x3b72ea61de26af37L);
assertLongEquals(ushr31(~longArg), 0x00000001db97530eL);
assertLongEquals(ushr32(~longArg), 0x00000000edcba987L);
assertLongEquals(ushr33(~longArg), 0x0000000076e5d4c3L);