From f7ef6a9b864039927dc90002a5306cf7d6c7d7d4 Mon Sep 17 00:00:00 2001 From: Doug Gilbert Date: Fri, 1 May 2015 18:10:56 -0500 Subject: bnbwi support --- gcc/config/rs6000/predicates.md | 5 +++ gcc/config/rs6000/rs6000-protos.h | 2 ++ gcc/config/rs6000/rs6000.c | 71 +++++++++++++++++++++++++++++++++++++- gcc/config/rs6000/rs6000.md | 72 ++++++++++++++++++++++++++++++++++++--- 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; @@ -19269,6 +19269,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) { 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 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. -- cgit v1.2.1