summaryrefslogtreecommitdiff
path: root/gcc/config/s390
diff options
context:
space:
mode:
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2015-07-24 11:28:06 +0000
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2015-07-24 11:28:06 +0000
commit02a8efd2e8a89927d3a11f283e414e2f1824a0da (patch)
treeebb22a10af14a6b8498dfe67c1ae6abb2122c957 /gcc/config/s390
parent117d67d0153528d5a8d406461907e5b646fb46ac (diff)
downloadgcc-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.c28
-rw-r--r--gcc/config/s390/s390.md65
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