summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Gilbert <dgilbert@us.ibm.com>2015-05-01 18:10:56 -0500
committerPatrick Williams <patrick@stwcx.xyz>2016-08-15 11:45:09 -0500
commitf7ef6a9b864039927dc90002a5306cf7d6c7d7d4 (patch)
tree12a6342d72a1b7a444056ba4302d8f561a32b26b
parentde88a62034ec32537c71bfa130f030c6a387ba77 (diff)
downloadppe42-gcc-f7ef6a9b864039927dc90002a5306cf7d6c7d7d4.tar.gz
ppe42-gcc-f7ef6a9b864039927dc90002a5306cf7d6c7d7d4.zip
bnbwi support
-rw-r--r--gcc/config/rs6000/predicates.md5
-rw-r--r--gcc/config/rs6000/rs6000-protos.h2
-rw-r--r--gcc/config/rs6000/rs6000.c71
-rw-r--r--gcc/config/rs6000/rs6000.md72
4 files changed, 144 insertions, 6 deletions
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index b45cda1b981..42d931a8ae2 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1208,6 +1208,11 @@
return 1;
})
+;; Return 1 of op is "eq","ne" and int is Nlog
+(define_predicate "rs6000_eq_or_ne_operator"
+ (match_code "eq,ne"))
+
+
;; Return 1 if OP is a comparison operation that is valid for an SCC insn --
;; it must be a positive comparison.
(define_predicate "scc_comparison_operator"
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 90af4f1baa4..3c313b1bcaf 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -112,6 +112,8 @@ extern void rs6000_emit_sISEL (enum machine_mode, rtx[]);
extern void rs6000_emit_sCOND (enum machine_mode, rtx[]);
extern void rs6000_emit_cbranch (enum machine_mode, rtx[]);
extern char * output_fused_cbranch (rtx operands[], const char *, rtx);
+extern char * output_fused_bnbwi(rtx operands[], const char *, bool);
+extern char * output_fused_clrbwib(int, enum rtx_code, int, const char *, bool);
extern char * output_cbranch (rtx, const char *, int, rtx);
extern char * output_e500_flip_gt_bit (rtx, rtx);
extern const char * output_probe_stack_range (rtx, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 34afd972f0f..a1442c9453d 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -19195,7 +19195,7 @@ rs6000_emit_cbranch (enum machine_mode mode, rtx operands[])
char *
output_fused_cbranch (rtx operands[], const char *label, rtx insn)
{
- static char string[64];
+ static char string[32];
enum rtx_code code = GET_CODE (operands[1]);
int need_longbranch = get_attr_length (insn) == 8;
char *s = string;
@@ -19270,6 +19270,75 @@ output_fused_cbranch (rtx operands[], const char *label, rtx insn)
char *
+output_fused_bnbwi(rtx operands[], const char *label, bool longbranch)
+{
+ static char string[32];
+ enum rtx_code code = GET_CODE (operands[1]);
+ int regno = REGNO(operands[2]);
+ int bitpos = INTVAL(operands[3]); //31 - exact_log2(INTVAL(operands[3]));
+ char *s = string;
+ int bit_value = 0;
+
+ if(longbranch)
+ code = reverse_condition (code);
+
+ switch (code)
+ {
+ case NE: // not eq zero so it's 1
+ bit_value = 1;
+ break;
+ case EQ: // eq zero
+ bit_value = 0;
+ break;
+ default:
+ gcc_unreachable();
+ }
+
+ s += sprintf(s, "bb%dwi %d, %d",
+ bit_value,
+ regno,
+ bitpos);
+
+ if (longbranch)
+ s += sprintf(s, ",$+8\n\tb %s", label);
+ else
+ s += sprintf(s, ",%s", label);
+
+ return string;
+}
+
+char *
+output_fused_clrbwib(int regno, enum rtx_code code, int bit_pos, const char * label, bool longbranch)
+{
+ static char string[64];
+ char *s = string;
+
+ if(longbranch)
+ code = reverse_condition (code);
+
+ switch(code)
+ {
+ case EQ:
+ s += sprintf(s,"clrbwibz %d, %d",
+ regno, bit_pos);
+ break;
+ case NE:
+ s += sprintf(s,"clrbwibnz %d, %d",
+ regno, bit_pos);
+ break;
+ default:
+ gcc_unreachable();
+ }
+
+ if (longbranch)
+ s += sprintf(s, ",$+8\n\tb %s", label);
+ else
+ s += sprintf(s, ",%s", label);
+
+ return string;
+}
+
+char *
output_cbranch (rtx op, const char *label, int reversed, rtx insn)
{
static char string[64];
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 1d01f725523..243811c1c58 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -14731,12 +14731,51 @@
[(set_attr "type" "jmpreg")
(set_attr "length" "4")])
+;; PPE fused bit-compare and branch
+(define_insn "*bnbwi"
+ [(set (pc)
+ (if_then_else (match_operator 1 "rs6000_eq_or_ne_operator"
+ [(zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 1)
+ (match_operand:SI 3 "const_int_operand" ""))
+ (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "(rs6000_cpu == PROCESSOR_PPE42) && optimize_size"
+ "*
+{
+ return output_fused_bnbwi(operands,\"%l0\", get_attr_length(insn) == 8);
+
+}"
+ [(set_attr "type" "fused_branch")])
+
+(define_insn "*clrbwib"
+ [(set (pc)
+ (if_then_else (match_operator 1 "rs6000_eq_or_ne_operator"
+ [(zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 31)
+ (match_operand:SI 3 "const_int_operand" ""))
+ (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "(rs6000_cpu == PROCESSOR_PPE42) && optimize_size"
+ "*
+{
+ return output_fused_clrbwib(REGNO(operands[2]),
+ GET_CODE(operands[1]),
+ INTVAL(operands[3]),
+ \"%l0\", get_attr_length(insn) == 8);
+
+}"
+ [(set_attr "type" "fused_branch")])
+
+
+
;; Define PPE fused compare and branch
-;; TODO handle branch outside of signed short int range?
;; There is no cmplwib<cond> fused instruction!!!
;; If op 3 is a reg then no problem - if op3 is short then use
-;; something else
-(define_insn ""
+;; something else - checked in predicate rs6000_fused_cbranch_operator
+(define_insn "*cmpwb"
[(set (pc)
(if_then_else (match_operator 1 "rs6000_fused_cbranch_operator"
[(match_operand:GPR 2 "gpc_reg_operand" "r")
@@ -14751,8 +14790,6 @@
[(set_attr "type" "fused_branch")])
-
-
;; Logic on condition register values.
; This pattern matches things like
@@ -15826,6 +15863,31 @@
"mtfsf %0,%1")
+
+;;(define_peephole2
+;; [(parallel [(set (match_operand:SI 0 "gpc_reg_operand")
+;; (and:SI (match_operand:SI 1 "gpc_reg_operand")
+;; (match_operand:SI 2 "exact_log2_cint_operand")))
+;; (clobber (match_scratch:CC 3 "=X,X,x,x"))])
+;; (set (pc)
+;; (if_then_else (match_operator 5 "rs6000_eq_or_ne_operator"
+;; [(match_operand:GPR 6 "gpc_reg_operand")
+;; (const_int 0)])
+;; (label_ref (match_operand 4 "" ))
+;; (pc)))]
+;;"(rs6000_cpu == PROCESSOR_PPE42) && optimize_size &&
+;; rtx_equal_p(operands[0],operands[1]) &&
+;; rtx_equal_p(operands[0],operands[6])"
+;; [(const_int 0)]
+;;{
+;; return output_fused_clrbwib(REGNO(operands[0]),
+;; GET_CODE(operands[5]),
+;; 31 - exact_log2(INTVAL(operands[2])),
+;; \"%l4\",
+;; get_attr_length(insn) == 8);
+;; DONE;
+;;})
+
;; Power8 fusion support for fusing an addis instruction with a D-form load of
;; a GPR. The addis instruction must be adjacent to the load, and use the same
;; register that is being loaded. The fused ops must be physically adjacent.
OpenPOWER on IntegriCloud