diff options
author | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-07-24 11:28:06 +0000 |
---|---|---|
committer | krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-07-24 11:28:06 +0000 |
commit | 02a8efd2e8a89927d3a11f283e414e2f1824a0da (patch) | |
tree | ebb22a10af14a6b8498dfe67c1ae6abb2122c957 /gcc/config/s390 | |
parent | 117d67d0153528d5a8d406461907e5b646fb46ac (diff) | |
download | gcc-02a8efd2e8a89927d3a11f283e414e2f1824a0da.tar.gz |
[PATCH] S/390: Improve risbg usage
gcc/ChangeLog:
2015-07-24 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* config/s390/s390.c (s390_rtx_costs): Make risbg patterns
cheaper.
(s390_expand_insv): Don't generate risbg pattern for constant zero
sources.
* config/s390/s390.md ("*insv<mode>_zEC12_appendbitsleft")
("*insv<mode>_z10_appendbitsleft"): New pattern definitions. New
splitters.
gcc/testsuite/ChangeLog:
2015-07-24 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* gcc.target/s390/insv-1.c: New test.
* gcc.target/s390/insv-2.c: New test.
* gcc.target/s390/insv-3.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@226148 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/s390')
-rw-r--r-- | gcc/config/s390/s390.c | 28 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 65 |
2 files changed, 90 insertions, 3 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 17642435cbc..f421e884c66 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -3321,13 +3321,26 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, *total = 0; return true; + case IOR: + /* risbg */ + if (GET_CODE (XEXP (x, 0)) == AND + && GET_CODE (XEXP (x, 1)) == ASHIFT + && REG_P (XEXP (XEXP (x, 0), 0)) + && REG_P (XEXP (XEXP (x, 1), 0)) + && CONST_INT_P (XEXP (XEXP (x, 0), 1)) + && CONST_INT_P (XEXP (XEXP (x, 1), 1)) + && (UINTVAL (XEXP (XEXP (x, 0), 1)) == + (1UL << UINTVAL (XEXP (XEXP (x, 1), 1))) - 1)) + { + *total = COSTS_N_INSNS (2); + return true; + } case ASHIFT: case ASHIFTRT: case LSHIFTRT: case ROTATE: case ROTATERT: case AND: - case IOR: case XOR: case NEG: case NOT: @@ -5839,8 +5852,17 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src) if (mode_s == VOIDmode) { - /* Assume const_int etc already in the proper mode. */ - src = force_reg (mode, src); + /* For constant zero values the representation with AND + appears to be folded in more situations than the (set + (zero_extract) ...). + We only do this when the start and end of the bitfield + remain in the same SImode chunk. That way nihf or nilf + can be used. + The AND patterns might still generate a risbg for this. */ + if (src == const0_rtx && bitpos / 32 == (bitpos + bitsize - 1) / 32) + return false; + else + src = force_reg (mode, src); } else if (mode_s != mode) { diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 8c07d1bea57..b23973e4dd0 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -3776,6 +3776,71 @@ [(set_attr "op_type" "RIE") (set_attr "z10prop" "z10_super_E1")]) +; Implement appending Y on the left of S bits of X +; x = (y << s) | (x & ((1 << s) - 1)) +(define_insn "*insv<mode>_zEC12_appendbitsleft" + [(set (match_operand:GPR 0 "nonimmediate_operand" "=d") + (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "0") + (match_operand:GPR 2 "immediate_operand" "")) + (ashift:GPR (match_operand:GPR 3 "nonimmediate_operand" "d") + (match_operand:GPR 4 "nonzero_shift_count_operand" ""))))] + "TARGET_ZEC12 && UINTVAL (operands[2]) == (1UL << UINTVAL (operands[4])) - 1" + "risbgn\t%0,%3,64-<bitsize>,64-%4-1,%4" + [(set_attr "op_type" "RIE") + (set_attr "z10prop" "z10_super_E1")]) + +(define_insn "*insv<mode>_z10_appendbitsleft" + [(set (match_operand:GPR 0 "nonimmediate_operand" "=d") + (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "0") + (match_operand:GPR 2 "immediate_operand" "")) + (ashift:GPR (match_operand:GPR 3 "nonimmediate_operand" "d") + (match_operand:GPR 4 "nonzero_shift_count_operand" "")))) + (clobber (reg:CC CC_REGNUM))] + "TARGET_Z10 && !TARGET_ZEC12 && UINTVAL (operands[2]) == (1UL << UINTVAL (operands[4])) - 1" + "risbg\t%0,%3,64-<bitsize>,64-%4-1,%4" + [(set_attr "op_type" "RIE") + (set_attr "z10prop" "z10_super_E1")]) + +; z = (x << c) | (y >> d) with (x << c) and (y >> d) not overlapping after shifting +; -> z = y >> d; z = (x << c) | (z & ((1 << c) - 1)) +; -> z = y >> d; z = risbg; + +(define_split + [(set (match_operand:GPR 0 "nonimmediate_operand" "") + (ior:GPR (lshiftrt:GPR (match_operand:GPR 1 "nonimmediate_operand" "") + (match_operand:GPR 2 "nonzero_shift_count_operand" "")) + (ashift:GPR (match_operand:GPR 3 "nonimmediate_operand" "") + (match_operand:GPR 4 "nonzero_shift_count_operand" ""))))] + "TARGET_ZEC12 && UINTVAL (operands[2]) + UINTVAL (operands[4]) >= <bitsize>" + [(set (match_dup 0) + (lshiftrt:GPR (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (ior:GPR (and:GPR (match_dup 0) (match_dup 5)) + (ashift:GPR (match_dup 3) (match_dup 4))))] +{ + operands[5] = GEN_INT ((1UL << UINTVAL (operands[4])) - 1); +}) + +(define_split + [(parallel + [(set (match_operand:GPR 0 "nonimmediate_operand" "") + (ior:GPR (lshiftrt:GPR (match_operand:GPR 1 "nonimmediate_operand" "") + (match_operand:GPR 2 "nonzero_shift_count_operand" "")) + (ashift:GPR (match_operand:GPR 3 "nonimmediate_operand" "") + (match_operand:GPR 4 "nonzero_shift_count_operand" "")))) + (clobber (reg:CC CC_REGNUM))])] + "TARGET_Z10 && !TARGET_ZEC12 && UINTVAL (operands[2]) + UINTVAL (operands[4]) >= <bitsize>" + [(set (match_dup 0) + (lshiftrt:GPR (match_dup 1) (match_dup 2))) + (parallel + [(set (match_dup 0) + (ior:GPR (and:GPR (match_dup 0) (match_dup 5)) + (ashift:GPR (match_dup 3) (match_dup 4)))) + (clobber (reg:CC CC_REGNUM))])] +{ + operands[5] = GEN_INT ((1UL << UINTVAL (operands[4])) - 1); +}) + (define_insn "*r<noxa>sbg_<mode>_noshift" [(set (match_operand:GPR 0 "nonimmediate_operand" "=d") (IXOR:GPR |