diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/s390/s390-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 20 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 16 |
3 files changed, 33 insertions, 7 deletions
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 01a3584fe86..4f1eb42a73f 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -80,9 +80,9 @@ extern void s390_reload_symref_address (rtx , rtx , rtx , bool); extern void s390_expand_plus_operand (rtx, rtx, rtx); extern void emit_symbolic_move (rtx *); extern void s390_load_address (rtx, rtx); -extern void s390_expand_movmem (rtx, rtx, rtx); +extern bool s390_expand_movmem (rtx, rtx, rtx); extern void s390_expand_setmem (rtx, rtx, rtx); -extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx); +extern bool s390_expand_cmpmem (rtx, rtx, rtx, rtx); extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx); extern bool s390_expand_insv (rtx, rtx, rtx, rtx); extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx, rtx); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index ca33d4e3498..f72f49fd023 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -3986,9 +3986,16 @@ legitimize_reload_address (rtx ad, enum machine_mode mode ATTRIBUTE_UNUSED, /* Emit code to move LEN bytes from DST to SRC. */ -void +bool s390_expand_movmem (rtx dst, rtx src, rtx len) { + /* When tuning for z10 or higher we rely on the Glibc functions to + do the right thing. Only for constant lengths below 64k we will + generate inline code. */ + if (s390_tune >= PROCESSOR_2097_Z10 + && (GET_CODE (len) != CONST_INT || INTVAL (len) > (1<<16))) + return false; + if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256) { if (INTVAL (len) > 0) @@ -4080,6 +4087,7 @@ s390_expand_movmem (rtx dst, rtx src, rtx len) convert_to_mode (Pmode, count, 1))); emit_label (end_label); } + return true; } /* Emit code to set LEN bytes at DST to VAL. @@ -4218,12 +4226,19 @@ s390_expand_setmem (rtx dst, rtx len, rtx val) /* Emit code to compare LEN bytes at OP0 with those at OP1, and return the result in TARGET. */ -void +bool s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len) { rtx ccreg = gen_rtx_REG (CCUmode, CC_REGNUM); rtx tmp; + /* When tuning for z10 or higher we rely on the Glibc functions to + do the right thing. Only for constant lengths below 64k we will + generate inline code. */ + if (s390_tune >= PROCESSOR_2097_Z10 + && (GET_CODE (len) != CONST_INT || INTVAL (len) > (1<<16))) + return false; + /* As the result of CMPINT is inverted compared to what we need, we have to swap the operands. */ tmp = op0; op0 = op1; op1 = tmp; @@ -4331,6 +4346,7 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len) emit_insn (gen_cmpint (target, ccreg)); } + return true; } diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index a467d4a10ec..096f2665534 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -2640,7 +2640,12 @@ (use (match_operand:GPR 2 "general_operand" "")) ; count (match_operand 3 "" "")] "" - "s390_expand_movmem (operands[0], operands[1], operands[2]); DONE;") +{ + if (s390_expand_movmem (operands[0], operands[1], operands[2])) + DONE; + else + FAIL; +}) ; Move a block that is up to 256 bytes in length. ; The block length is taken as (operands[2] % 256) + 1. @@ -3017,8 +3022,13 @@ (use (match_operand:SI 3 "general_operand" "")) (use (match_operand:SI 4 "" ""))] "" - "s390_expand_cmpmem (operands[0], operands[1], - operands[2], operands[3]); DONE;") +{ + if (s390_expand_cmpmem (operands[0], operands[1], + operands[2], operands[3])) + DONE; + else + FAIL; +}) ; Compare a block that is up to 256 bytes in length. ; The block length is taken as (operands[2] % 256) + 1. |