aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/s390/predicates.md12
-rw-r--r--gcc/config/s390/s390-protos.h1
-rw-r--r--gcc/config/s390/s390.cc27
-rw-r--r--gcc/config/s390/s390.md36
4 files changed, 54 insertions, 22 deletions
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 33194d3..430cf6e 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -594,3 +594,15 @@
(define_predicate "addv_const_operand"
(and (match_code "const_int")
(match_test "INTVAL (op) >= -32768 && INTVAL (op) <= 32767")))
+
+; Match (subreg (reg ...)) operands.
+; Used for movstrict destination operands
+; When replacing pseudos with hard regs reload strips away the
+; subregs. Accept also plain registers then to prevent the insn from
+; becoming unrecognizable.
+(define_predicate "subreg_register_operand"
+ (ior (and (match_code "subreg")
+ (match_test "register_operand (SUBREG_REG (op), GET_MODE (SUBREG_REG (op)))"))
+ (and (match_code "reg")
+ (match_test "reload_completed || reload_in_progress")
+ (match_test "register_operand (op, GET_MODE (op))"))))
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index fd4acaa..765d843a 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -50,6 +50,7 @@ extern void s390_set_has_landing_pad_p (bool);
extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int);
extern int s390_class_max_nregs (enum reg_class, machine_mode);
extern bool s390_return_addr_from_memory(void);
+extern rtx s390_gen_lowpart_subreg (machine_mode, rtx);
extern bool s390_fma_allowed_p (machine_mode);
#if S390_USE_TARGET_ATTRIBUTE
extern tree s390_valid_target_attribute_tree (tree args,
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 5aaf76a..5e06bf9 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -458,6 +458,31 @@ s390_return_addr_from_memory ()
return cfun_gpr_save_slot(RETURN_REGNUM) == SAVE_SLOT_STACK;
}
+/* Generate a SUBREG for the MODE lowpart of EXPR.
+
+ In contrast to gen_lowpart it will always return a SUBREG
+ expression. This is useful to generate STRICT_LOW_PART
+ expressions. */
+rtx
+s390_gen_lowpart_subreg (machine_mode mode, rtx expr)
+{
+ rtx lowpart = gen_lowpart (mode, expr);
+
+ /* There might be no SUBREG in case it could be applied to the hard
+ REG rtx or it could be folded with a paradoxical subreg. Bring
+ it back. */
+ if (!SUBREG_P (lowpart))
+ {
+ machine_mode reg_mode = TARGET_ZARCH ? DImode : SImode;
+ gcc_assert (REG_P (lowpart));
+ lowpart = gen_lowpart_SUBREG (mode,
+ gen_rtx_REG (reg_mode,
+ REGNO (lowpart)));
+ }
+
+ return lowpart;
+}
+
/* Return nonzero if it's OK to use fused multiply-add for MODE. */
bool
s390_fma_allowed_p (machine_mode mode)
@@ -6520,7 +6545,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
/* Emit a strict_low_part pattern if possible. */
if (smode_bsize == bitsize && bitpos == mode_bsize - smode_bsize)
{
- rtx low_dest = gen_lowpart (smode, dest);
+ rtx low_dest = s390_gen_lowpart_subreg (smode, dest);
rtx low_src = gen_lowpart (smode, src);
switch (smode)
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 55c0064..aaa247d 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1971,11 +1971,12 @@
"TARGET_ZARCH"
"#"
"&& reload_completed"
- [(set (match_dup 2) (match_dup 3))
+ [(set (match_dup 2) (match_dup 4))
(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32)))
- (set (strict_low_part (match_dup 2)) (match_dup 4))]
+ (set (strict_low_part (match_dup 3)) (match_dup 5))]
"operands[2] = gen_lowpart (SImode, operands[0]);
- s390_split_access_reg (operands[1], &operands[4], &operands[3]);")
+ operands[3] = s390_gen_lowpart_subreg (SImode, operands[0]);
+ s390_split_access_reg (operands[1], &operands[5], &operands[4]);")
; Splitters for storing TLS pointer to %a0:DI.
@@ -2522,13 +2523,14 @@
[(set (match_dup 0) (match_dup 2))]
"operands[2] = get_pool_constant (operands[1]);")
+
;
-; movstrictqi instruction pattern(s).
+; movstrict instruction pattern(s).
;
(define_insn "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d,d"))
- (match_operand:QI 1 "memory_operand" "R,T"))]
+ [(set (strict_low_part (match_operand:QI 0 "subreg_register_operand" "+d,d"))
+ (match_operand:QI 1 "memory_operand" "R,T"))]
""
"@
ic\t%0,%1
@@ -2537,13 +2539,9 @@
(set_attr "cpu_facility" "*,longdisp")
(set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-;
-; movstricthi instruction pattern(s).
-;
-
(define_insn "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d,d"))
- (match_operand:HI 1 "memory_operand" "Q,S"))
+ [(set (strict_low_part (match_operand:HI 0 "subreg_register_operand" "+d,d"))
+ (match_operand:HI 1 "memory_operand" "Q,S"))
(clobber (reg:CC CC_REGNUM))]
""
"@
@@ -2553,13 +2551,9 @@
(set_attr "cpu_facility" "*,longdisp")
(set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-;
-; movstrictsi instruction pattern(s).
-;
-
(define_insn "movstrictsi"
- [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d,d"))
- (match_operand:SI 1 "general_operand" "d,R,T,t"))]
+ [(set (strict_low_part (match_operand:SI 0 "subreg_register_operand" "+d,d,d,d"))
+ (match_operand:SI 1 "general_operand" "d,R,T,t"))]
"TARGET_ZARCH"
"@
lr\t%0,%1
@@ -5019,7 +5013,7 @@
(parallel
[(set (strict_low_part (match_dup 2)) (match_dup 1))
(clobber (reg:CC CC_REGNUM))])]
- "operands[2] = gen_lowpart (HImode, operands[0]);")
+ "operands[2] = s390_gen_lowpart_subreg (HImode, operands[0]);")
(define_insn_and_split "*zero_extendqisi2_31"
[(set (match_operand:SI 0 "register_operand" "=&d")
@@ -5029,7 +5023,7 @@
"&& reload_completed"
[(set (match_dup 0) (const_int 0))
(set (strict_low_part (match_dup 2)) (match_dup 1))]
- "operands[2] = gen_lowpart (QImode, operands[0]);")
+ "operands[2] = s390_gen_lowpart_subreg (QImode, operands[0]);")
;
; zero_extendqihi2 instruction pattern(s).
@@ -5061,7 +5055,7 @@
"&& reload_completed"
[(set (match_dup 0) (const_int 0))
(set (strict_low_part (match_dup 2)) (match_dup 1))]
- "operands[2] = gen_lowpart (QImode, operands[0]);")
+ "operands[2] = s390_gen_lowpart_subreg (QImode, operands[0]);")
;
; fixuns_trunc(dd|td|sf|df|tf)(si|di)2 expander