Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
ppe42-gcc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
OpenPOWER Firmware
ppe42-gcc
Commits
fed58818
Commit
fed58818
authored
Apr 21, 2015
by
Doug Gilbert
Committed by
Patrick Williams
Aug 15, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Compare-branch fused instructions
parent
0081fa34
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
204 additions
and
31 deletions
+204
-31
gcc/config/rs6000/predicates.md
gcc/config/rs6000/predicates.md
+13
-0
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000-protos.h
+1
-0
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.c
+119
-4
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/rs6000.md
+71
-27
No files found.
gcc/config/rs6000/predicates.md
View file @
fed58818
...
...
@@ -1195,6 +1195,19 @@
(match_code ("unlt,unle,ungt,unge"))))
(match_operand 0 "comparison_operator")))
;; Return 1 if OP is a valid comparison operator for "fused cbranch"
;; instructions
(define_predicate "rs6000_fused_cbranch_operator"
(match_operand 0 "comparison_operator")
{
if(GET_CODE(XEXP(op,1)) == CONST_INT )
{
if((INTVAL(XEXP(op,1))
<
32
)
&&
(
INTVAL
(
XEXP
(
op
,
1
))
>
= 0)) return 1;
else return 0;
}
return 1;
})
;; 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"
...
...
gcc/config/rs6000/rs6000-protos.h
View file @
fed58818
...
...
@@ -111,6 +111,7 @@ extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
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_cbranch
(
rtx
,
const
char
*
,
int
,
rtx
);
extern
char
*
output_e500_flip_gt_bit
(
rtx
,
rtx
);
extern
const
char
*
output_probe_stack_range
(
rtx
,
rtx
);
...
...
gcc/config/rs6000/rs6000.c
View file @
fed58818
...
...
@@ -19134,13 +19134,51 @@ rs6000_emit_cbranch (enum machine_mode mode, rtx operands[])
{
rtx condition_rtx, loc_ref;
condition_rtx = rs6000_generate_compare (operands[0], mode);
// For fused compare-branch
// jump distance +- 2k
// Compare immediate limited to uint_5 (0-31)
//
//debug_rtx(operands[0]); // (eq (reg/v:SI 157 [ a ]) (const_int 31 [0x1f]))
//debug_rtx(operands[1]); // (reg/v:SI 157 [ a ])
//debug_rtx(operands[2]); // (const_int 31 [0x1f])
//debug_rtx(operands[3]); // (code_label 0 0 0 9 "" [0 uses])
//debug_rtx(condition_rtx); // (eq (reg:CC 158) (const_int 0 [0]))
//debug_rtx(loc_ref); // (label_ref 0)
loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
loc_ref, pc_rtx)));
// TODO if not PPE42
// Split the compare and branch if not optimized for size
// or can't meet the constraints of fused compare-branch.
if(!optimize_size ||
((GET_CODE (operands[2]) == CONST_INT) &&
((INTVAL(operands[2]) < 0) || (INTVAL(operands[2]) > 31))))
{
condition_rtx = rs6000_generate_compare (operands[0], mode);
emit_jump_insn (gen_rtx_SET (VOIDmode,
pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode,
condition_rtx,
loc_ref,
pc_rtx)));
// Note: even if the compare/branch is split here, the compiler might
// re-combine them (fuse) later in the 201r.combine step based
// on the *.md match - that can be controlled with the
// rs6000_fused_cbranch_operator predicate and the optimize_size flag.
}
else // Use the PPE fused compare-branch instructions
{
emit_jump_insn(gen_rtx_SET(VOIDmode,
pc_rtx,
gen_rtx_IF_THEN_ELSE(VOIDmode,
operands[0],
loc_ref,
pc_rtx)));
}
}
/* Return the string to output a conditional branch to LABEL, which is
the operand template of the label, or NULL if the branch is really a
conditional return.
...
...
@@ -19153,6 +19191,83 @@ rs6000_emit_cbranch (enum machine_mode mode, rtx operands[])
INSN is the insn. */
char *
output_fused_cbranch (rtx operands[], const char *label, rtx insn)
{
static char string[64];
enum rtx_code code = GET_CODE (operands[1]);
int need_longbranch = get_attr_length (insn) == 8;
char *s = string;
const char *ccode;
const char *immed = "";
const char *logical = "";
int op3 = 0;
if(need_longbranch)
code = reverse_condition (code);
switch (code)
{
case NE:
case LTGT:
ccode = "ne";
break;
case EQ:
case UNEQ:
ccode = "eq";
break;
case GE:
case GEU:
ccode = "ge";
break;
case GT:
case GTU:
case UNGT:
ccode = "gt";
break;
case LE:
case LEU:
ccode = "le";
break;
case LT:
case LTU: case UNLT:
ccode = "lt";
break;
default:
gcc_unreachable();
}
// Set immediate
// Can't do unsigned(logical) compare on immediate
if(GET_CODE (operands[3]) == CONST_INT)
{
op3 = INTVAL(operands[3]);
immed = "i";
}
else if( unsigned_reg_p (operands[2]) &&
unsigned_reg_p (operands[3]))
{
logical = "l";
op3 = REGNO(operands[3]);
}
else
{
op3 = REGNO(operands[3]);
}
s += sprintf(s, "cmp%sw%sb%s %d, %d", logical,
immed, ccode, REGNO(operands[2]), op3);
if (need_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)
{
...
...
gcc/config/rs6000/rs6000.md
View file @
fed58818
...
...
@@ -160,7 +160,8 @@
;; Define an insn type attribute. This is used in function unit delay
;; computations.
(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto,htm"
(define_attr "type"
"integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,fused_branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto,htm"
(const_string "integer"))
;; Define floating point instruction sub-types for use with Xfpu.md
...
...
@@ -177,7 +178,14 @@
(const_int 32764)))
(const_int 4)
(const_int 8))
(const_int 4)))
(if_then_else (eq_attr "type" "fused_branch")
(if_then_else (and (ge(minus (match_dup 0) (pc))
(const_int -2048))
(lt (minus (match_dup 0) (pc))
(const_int 2044)))
(const_int 4)
(const_int 8))
(const_int 4))))
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in rs6000-opts.h.
...
...
@@ -1221,7 +1229,8 @@
(match_test "update_address_mem (operands[1], VOIDmode)")
(const_string "load_ext_u")
(const_string "load_ext")))
(const_string "exts")])])
(const_string "exts")])
(set_attr "length" "8,4")])
(define_insn ""
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
...
...
@@ -10202,13 +10211,13 @@
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
"@
#
#
#
stvd%U0%X0 %1, %0
lvd%U1%X1 %0, %1
#
ret to reg not supported
stfd%U0%X0 %1,%0
lfd%U1%X1 %0,%1
fmr %0,%1
#"
#
What is this? movdi_internal32
"
[(set_attr_alternative "type"
[(const_string "store")
(const_string "load")
...
...
@@ -10249,14 +10258,15 @@
operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
}")
(define_split
[(set (match_operand:DIFD 0 "rs6000_nonimmediate_operand" "")
(match_operand:DIFD 1 "input_operand" ""))]
"reload_completed && !TARGET_POWERPC64
&& gpr_or_gpr_p (operands[0], operands[1])
&& !direct_move_p (operands[0], operands[1])"
[(pc)]
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
;; disable DImode load/store splits for PPE - use 64-bit load/store instructions
;;(define_split
;; [(set (match_operand:DIFD 0 "rs6000_nonimmediate_operand" "")
;; (match_operand:DIFD 1 "input_operand" ""))]
;; "reload_completed && !TARGET_POWERPC64
;; && gpr_or_gpr_p (operands[0], operands[1])
;; && !direct_move_p (operands[0], operands[1])"
;; [(pc)]
;;{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_insn "
*
movdi_internal64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?
*d,?*
d,r,
*h,*
h,r,?
*wg,r,?*
wj,?
*
wi")
...
...
@@ -11043,7 +11053,8 @@
"@
lwzx %3,%0,%2
\;
add %0,%0,%2
lwzu %3,%2(%0)"
[(set_attr "type" "load_ux,load_u")])
[(set_attr "type" "load_ux,load_u")
(set_attr "length" "8,4")])
(define_insn "
*
movsi_update2"
[(set (match_operand:DI 3 "gpc_reg_operand" "=r")
...
...
@@ -11071,7 +11082,8 @@
"@
stwx %3,%0,%2
\;
add %0,%0,%2
stwu %3,%2(%0)"
[(set_attr "type" "store_ux,store_u")])
[(set_attr "type" "store_ux,store_u")
(set_attr "length" "8,4")])
;; This is an unconditional pattern; needed for stack allocation, even
;; if the user passes -mno-update.
...
...
@@ -11085,7 +11097,8 @@
"@
stwx %3,%0,%2
\;
add %0,%0,%2
stwu %3,%2(%0)"
[(set_attr "type" "store_ux,store_u")])
[(set_attr "type" "store_ux,store_u")
(set_attr "length" "8,4")])
(define_insn "
*
movhi_update1"
[(set (match_operand:HI 3 "gpc_reg_operand" "=r,r")
...
...
@@ -11099,7 +11112,8 @@
"@
lhzx %3,%0,%2
\;
add %0,%0,%2
lhzu %3,%2(%0)"
[(set_attr "type" "load_ux,load_u")])
[(set_attr "type" "load_ux,load_u")
(set_attr "length" "8,4")])
(define_insn "
*
movhi_update2"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
...
...
@@ -11114,7 +11128,8 @@
"@
lhzx %3,%0,%2
\;
add %0,%0,%2
lhzu %3,%2(%0)"
[(set_attr "type" "load_ux,load_u")])
[(set_attr "type" "load_ux,load_u")
(set_attr "length" "8,4")])
(define_insn "
*
movhi_update3"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
...
...
@@ -11129,7 +11144,8 @@
"@
lhzx %3,%0,%2
\;
add %0,%0,%2
\;
extsh %3,%3
lhzu %3,%2(%0)
\;
extsh %3,%3"
[(set_attr "type" "load_ext_ux,load_ext_u")])
[(set_attr "type" "load_ext_ux,load_ext_u")
(set_attr "length" "12,8")])
(define_insn "
*
movhi_update4"
[(set (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
...
...
@@ -11143,7 +11159,8 @@
"@
sthx %3,%0,%2
\;
add %0,%0,%2
sthu %3,%2(%0)"
[(set_attr "type" "store_ux,store_u")])
[(set_attr "type" "store_ux,store_u")
(set_attr "length" "8,4")])
(define_insn "
*
movqi_update1"
[(set (match_operand:QI 3 "gpc_reg_operand" "=r,r")
...
...
@@ -11157,7 +11174,8 @@
"@
lbzx %3, %0, %2
\;
add %0,%0,%2
lbzu %3,%2(%0)"
[(set_attr "type" "load_ux,load_u")])
[(set_attr "type" "load_ux,load_u")
(set_attr "length" "8,4")])
(define_insn "
*
movqi_update2"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
...
...
@@ -11172,7 +11190,8 @@
"@
lbzx %3,%0,%2
\;
add %0,%0,%2
lbzu %3,%2(%0)"
[(set_attr "type" "load_ux,load_u")])
[(set_attr "type" "load_ux,load_u")
(set_attr "length" "8,4")])
(define_insn "
*
movqi_update3"
[(set (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
...
...
@@ -11186,7 +11205,8 @@
"@
stbx %3,%0,%2
\;
add %0,%0,%2
stbu %3,%2(%0)"
[(set_attr "type" "store_ux,store_u")])
[(set_attr "type" "store_ux,store_u")
(set_attr "length" "8,4")])
(define_insn "
*
movsf_update1"
[(set (match_operand:SF 3 "gpc_reg_operand" "=f,f")
...
...
@@ -11228,7 +11248,8 @@
"@
lwzx %3,%0,%2
\;
add %0,%0,%2
lwzu %3,%2(%0)"
[(set_attr "type" "load_ux,load_u")])
[(set_attr "type" "load_ux,load_u")
(set_attr "length" "8,4")])
(define_insn "
*
movsf_update4"
[(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
...
...
@@ -11242,7 +11263,8 @@
"@
stwx %3,%0,%2
\;
add %0,%0,%2
stwu %3,%2(%0)"
[(set_attr "type" "store_ux,store_u")])
[(set_attr "type" "store_ux,store_u")
(set_attr "length" "8,4")])
(define_insn "
*
movdf_update1"
[(set (match_operand:DF 3 "gpc_reg_operand" "=d,d")
...
...
@@ -14657,6 +14679,28 @@
[(set_attr "type" "jmpreg")
(set_attr "length" "4")])
;; 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 ""
[(set (pc)
(if_then_else (match_operator 1 "rs6000_fused_cbranch_operator"
[(match_operand:GPR 2 "gpc_reg_operand" "r")
(match_operand:GPR 3 "reg_or_short_operand" "rI")])
(label_ref (match_operand 0 "" ""))
(pc)))]
"optimize_size"
"
*
{
return output_fused_cbranch (operands,
\"
%l0
\"
, insn);
}"
[(set_attr "type" "fused_branch")])
;; Logic on condition register values.
; This pattern matches things like
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment