Commit f7ef6a9b authored by Doug Gilbert's avatar Doug Gilbert Committed by Patrick Williams

bnbwi support

parent de88a620
......@@ -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"
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment