[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