[aarch64-port-dev ] C2: a few more patterns
Andrew Haley
aph at redhat.com
Wed Nov 6 09:27:51 PST 2013
These are a few improvements.
The most important change is support for CBZ and CBNZ.
Andrew.
# HG changeset patch
# User aph
# Date 1383758741 0
# Node ID dff5d8f37d2ea6d5de4714762e26a2cba3db3257
# Parent 78820f808f67d55ebc887b471f0fe79514f951ec
Minor improvements to aarch64.ad.
Use iRegIorL2I in shift patterns.
Add lshift_ext instruction.
Add cbz and cbnz instructions.
diff -r 78820f808f67 -r dff5d8f37d2e src/cpu/aarch64/vm/aarch64.ad
--- a/src/cpu/aarch64/vm/aarch64.ad Wed Nov 06 13:50:01 2013 +0000
+++ b/src/cpu/aarch64/vm/aarch64.ad Wed Nov 06 17:25:41 2013 +0000
@@ -1591,7 +1591,7 @@
// Should the Matcher clone shifts on addressing modes, expecting them
// to be subsumed into complex addressing expressions or compute them
// into registers? True for Intel but false for most RISCs
-const bool Matcher::clone_shift_expressions = true;
+const bool Matcher::clone_shift_expressions = false;
// Do we need to mask the count passed to shift instructions or does
// the cpu only look at the lower 5/6 bits anyway?
@@ -6765,7 +6765,7 @@
ins_pipe(pipe_class_default);
%}
-instruct addP_reg_reg_ext(iRegPNoSp dst, iRegP src1, iRegI src2) %{
+instruct addP_reg_reg_ext(iRegPNoSp dst, iRegP src1, iRegIorL2I src2) %{
match(Set dst (AddP src1 (ConvI2L src2)));
ins_cost(DEFAULT_COST);
@@ -6795,7 +6795,7 @@
ins_pipe(pipe_class_default);
%}
-instruct addP_reg_reg_ext_shift(iRegPNoSp dst, iRegP src1, iRegI src2, immIScale scale) %{
+instruct addP_reg_reg_ext_shift(iRegPNoSp dst, iRegP src1, iRegIorL2I src2, immIScale scale) %{
match(Set dst (AddP src1 (LShiftL (ConvI2L src2) scale)));
ins_cost(DEFAULT_COST);
@@ -6810,6 +6810,20 @@
ins_pipe(pipe_class_default);
%}
+instruct lshift_ext(iRegLNoSp dst, iRegIorL2I src, immI scale, rFlagsReg cr) %{
+ match(Set dst (LShiftL (ConvI2L src) scale));
+
+ ins_cost(DEFAULT_COST);
+ format %{ "sbfm $dst, $src, 64-$scale, 31\t" %}
+
+ ins_encode %{
+ __ sbfm(as_Register($dst$$reg),
+ as_Register($src$$reg), (64u - $scale$$constant) & 63, 31);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
// Pointer Immediate Addition
// n.b. this needs to be more expensive than using an indirect memory
// operand
@@ -8505,7 +8519,7 @@
// We can use ubfx when extending an And with a mask when we know mask
// is positive. We know that because immI_bitmask guarantees it.
-instruct ubfxIConvI2L(iRegLNoSp dst, iRegI src, immI rshift, immI_bitmask mask)
+instruct ubfxIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask)
%{
match(Set dst (ConvI2L (AndI (URShiftI src rshift) mask)));
@@ -8720,7 +8734,7 @@
// Add/subtract (extended)
-instruct AddExtI(iRegLNoSp dst, iRegL src1, iRegI src2, rFlagsReg cr)
+instruct AddExtI(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, rFlagsReg cr)
%{
match(Set dst (AddL src1 (ConvI2L src2)));
ins_cost(DEFAULT_COST);
@@ -8733,7 +8747,7 @@
ins_pipe(pipe_class_default);
%};
-instruct SubExtI(iRegLNoSp dst, iRegL src1, iRegI src2, rFlagsReg cr)
+instruct SubExtI(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, rFlagsReg cr)
%{
match(Set dst (SubL src1 (ConvI2L src2)));
ins_cost(DEFAULT_COST);
@@ -9447,7 +9461,7 @@
ins_pipe(pipe_class_default);
%}
-instruct convI2L_reg_reg(iRegLNoSp dst, iRegI src)
+instruct convI2L_reg_reg(iRegLNoSp dst, iRegIorL2I src)
%{
match(Set dst (ConvI2L src));
@@ -10400,6 +10414,67 @@
ins_pipe(pipe_class_default);
%}
+// Make use of CBZ and CBNZ. These instructions, as well as being
+// shorter than (cmp; branch), have the additional benefit of not
+// killing the flags.
+
+instruct cmpI_imm0_branch(cmpOp cmp, iRegI op1, immI0 op2, label labl, rFlagsReg cr) %{
+ match(If cmp (CmpI op1 op2));
+ predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
+ || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ effect(USE labl);
+
+ ins_cost(BRANCH_COST);
+ format %{ "cbw$cmp $op1, $labl" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+ if (cond == Assembler::EQ)
+ __ cbzw($op1$$Register, *L);
+ else
+ __ cbnzw($op1$$Register, *L);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct cmpL_imm0_branch(cmpOp cmp, iRegL op1, immL0 op2, label labl, rFlagsReg cr) %{
+ match(If cmp (CmpL op1 op2));
+ predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
+ || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ effect(USE labl);
+
+ ins_cost(BRANCH_COST);
+ format %{ "cb$cmp $op1, $labl" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+ if (cond == Assembler::EQ)
+ __ cbz($op1$$Register, *L);
+ else
+ __ cbnz($op1$$Register, *L);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct cmpP_imm0_branch(cmpOp cmp, iRegP op1, immP0 op2, label labl, rFlagsReg cr) %{
+ match(If cmp (CmpP op1 op2));
+ predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
+ || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ effect(USE labl);
+
+ ins_cost(BRANCH_COST);
+ format %{ "cb$cmp $op1, $labl" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+ if (cond == Assembler::EQ)
+ __ cbz($op1$$Register, *L);
+ else
+ __ cbnz($op1$$Register, *L);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
// Conditional Far Branch
// Conditional Far Branch Unsigned
// TODO: fixme
diff -r 78820f808f67 -r dff5d8f37d2e src/cpu/aarch64/vm/aarch64_ad.m4
--- a/src/cpu/aarch64/vm/aarch64_ad.m4 Wed Nov 06 13:50:01 2013 +0000
+++ b/src/cpu/aarch64/vm/aarch64_ad.m4 Wed Nov 06 17:25:41 2013 +0000
@@ -171,7 +171,7 @@
// We can use ubfx when extending an And with a mask when we know mask
// is positive. We know that because immI_bitmask guarantees it.
-instruct ubfxIConvI2L(iRegLNoSp dst, iRegI src, immI rshift, immI_bitmask mask)
+instruct ubfxIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI rshift, immI_bitmask mask)
%{
match(Set dst (ConvI2L (AndI (URShiftI src rshift) mask)));
@@ -274,7 +274,7 @@
// Add/subtract (extended)
dnl ADD_SUB_EXTENDED(mode, size, add node, shift node, insn, shift type, wordsize
define(`ADD_SUB_CONV', `
-instruct $3Ext$1(iReg$2NoSp dst, iReg$2 src1, iReg$1 src2, rFlagsReg cr)
+instruct $3Ext$1(iReg$2NoSp dst, iReg$2 src1, iReg$1orL2I src2, rFlagsReg cr)
%{
match(Set dst ($3$2 src1 (ConvI2L src2)));
ins_cost(DEFAULT_COST);
More information about the aarch64-port-dev
mailing list