diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/s390/predicates.md | 12 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/s390/s390.cc | 27 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 36 |
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 |