* config/s390/s390-protos.h (s390_comparison): Add prototype.
* config/s390/s390.c (s390_comparison): New function.
(s390_branch_condition_mask): Return -1 for invalid comparisons.
(s390_branch_condition_mnemonic): Assert valid comparison.
* config/s390/s390.h (PREDICATE_CODES): Add s390_comparison.
* config/s390/s390.md ("*cjump_64", "*cjump_31", "*cjump_long",
"*icjump_64", "*icjump_31", "*icjump_long", "*trap"): Use
s390_comparison instead of comparison_operator.
* config/s390/s390.md (UNSPEC_CMPINT): New constant.
("cmpmemdi"): Remove.
("cmpmem_short", "*cmpmem_short"): Use CCUmode instead of CCSmode.
("cmpmem_long", "*cmpmem_long_64", "*cmpmem_long_31"): Likewise.
("cmpint_si"): Rename to ...
("*cmpint_si"): ... this. Use UNSPEC_CMPINT.
("cmpint_di", "*cmpint_di"): Likewise.
* config/s390/s390.c (s390_canonicalize_comparison): Remove
redundant UNSPEC_CMPINT conversions.
(s390_expand_cmpmem): Adapt to cmpint pattern changes.
From-SVN: r88410
+2004-10-01 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390-protos.h (s390_comparison): Add prototype.
+ * config/s390/s390.c (s390_comparison): New function.
+ (s390_branch_condition_mask): Return -1 for invalid comparisons.
+ (s390_branch_condition_mnemonic): Assert valid comparison.
+ * config/s390/s390.h (PREDICATE_CODES): Add s390_comparison.
+ * config/s390/s390.md ("*cjump_64", "*cjump_31", "*cjump_long",
+ "*icjump_64", "*icjump_31", "*icjump_long", "*trap"): Use
+ s390_comparison instead of comparison_operator.
+
+ * config/s390/s390.md (UNSPEC_CMPINT): New constant.
+ ("cmpmemdi"): Remove.
+ ("cmpmem_short", "*cmpmem_short"): Use CCUmode instead of CCSmode.
+ ("cmpmem_long", "*cmpmem_long_64", "*cmpmem_long_31"): Likewise.
+ ("cmpint_si"): Rename to ...
+ ("*cmpint_si"): ... this. Use UNSPEC_CMPINT.
+ ("cmpint_di", "*cmpint_di"): Likewise.
+ * config/s390/s390.c (s390_canonicalize_comparison): Remove
+ redundant UNSPEC_CMPINT conversions.
+ (s390_expand_cmpmem): Adapt to cmpint pattern changes.
+
2004-10-01 Kazu Hirata <kazu@cs.umass.edu>
* collect2.c (COLLECT_PARSE_FLAG): Remove.
extern enum machine_mode s390_tm_ccmode (rtx, rtx, int);
extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
+extern int s390_comparison (rtx op, enum machine_mode mode);
extern int s390_alc_comparison (rtx op, enum machine_mode mode);
extern int s390_slb_comparison (rtx op, enum machine_mode mode);
extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
}
/* Narrow comparisons against 0xffff to HImode if possible. */
-
if ((*code == EQ || *code == NE)
&& GET_CODE (*op1) == CONST_INT
&& INTVAL (*op1) == 0xffff
*op0 = gen_lowpart (HImode, *op0);
*op1 = constm1_rtx;
}
+
+
+ /* Remove redundant UNSPEC_CMPINT conversions if possible. */
+ if (GET_CODE (*op0) == UNSPEC
+ && XINT (*op0, 1) == UNSPEC_CMPINT
+ && XVECLEN (*op0, 0) == 1
+ && GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode
+ && GET_CODE (XVECEXP (*op0, 0, 0)) == REG
+ && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
+ && *op1 == const0_rtx)
+ {
+ enum rtx_code new_code = UNKNOWN;
+ switch (*code)
+ {
+ case EQ: new_code = EQ; break;
+ case NE: new_code = NE; break;
+ case LT: new_code = LTU; break;
+ case GT: new_code = GTU; break;
+ case LE: new_code = LEU; break;
+ case GE: new_code = GEU; break;
+ default: break;
+ }
+
+ if (new_code != UNKNOWN)
+ {
+ *op0 = XVECEXP (*op0, 0, 0);
+ *code = new_code;
+ }
+ }
}
/* Emit a compare instruction suitable to implement the comparison
emit_jump_insn (insn);
}
+/* Return nonzero if OP is a valid comparison operator
+ for a branch condition in mode MODE. */
+
+int
+s390_comparison (rtx op, enum machine_mode mode)
+{
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return 0;
+
+ if (!COMPARISON_P (op))
+ return 0;
+
+ if (GET_CODE (XEXP (op, 0)) != REG
+ || REGNO (XEXP (op, 0)) != CC_REGNUM
+ || XEXP (op, 1) != const0_rtx)
+ return 0;
+
+ return s390_branch_condition_mask (op) >= 0;
+}
+
/* Return nonzero if OP is a valid comparison operator
for an ALC condition in mode MODE. */
}
/* Return branch condition mask to implement a branch
- specified by CODE. */
+ specified by CODE. Return -1 for invalid comparisons. */
static int
s390_branch_condition_mask (rtx code)
{
case EQ: return CC0;
case NE: return CC1 | CC2 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
{
case EQ: return CC1;
case NE: return CC0 | CC2 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
{
case EQ: return CC2;
case NE: return CC0 | CC1 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
{
case EQ: return CC3;
case NE: return CC0 | CC1 | CC2;
- default:
- abort ();
+ default: return -1;
}
break;
{
case EQ: return CC0 | CC2;
case NE: return CC1 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
{
case LTU: return CC2 | CC3; /* carry */
case GEU: return CC0 | CC1; /* no carry */
- default:
- abort ();
+ default: return -1;
}
break;
{
case GTU: return CC0 | CC1; /* borrow */
case LEU: return CC2 | CC3; /* no borrow */
- default:
- abort ();
+ default: return -1;
}
break;
case GTU: return CC3;
case LEU: return CC1 | CC2;
case GEU: return CC2 | CC3;
- default:
- abort ();
+ default: return -1;
}
case CCUmode:
case GTU: return CC2;
case LEU: return CC0 | CC1;
case GEU: return CC0 | CC2;
- default:
- abort ();
+ default: return -1;
}
break;
case GTU: return CC1;
case LEU: return CC0 | CC2;
case GEU: return CC0 | CC1;
- default:
- abort ();
+ default: return -1;
}
break;
case GT: return CC2;
case LE: return CC0 | CC1 | CC3;
case GE: return CC0 | CC2;
- default:
- abort ();
+ default: return -1;
}
break;
case GT: return CC2 | CC3;
case LE: return CC0 | CC1;
case GE: return CC0 | CC2 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
case UNLE: return CC0 | CC1 | CC3;
case UNGE: return CC0 | CC2 | CC3;
case LTGT: return CC1 | CC2;
- default:
- abort ();
+ default: return -1;
}
break;
case UNLE: return CC0 | CC2 | CC3;
case UNGE: return CC0 | CC1 | CC3;
case LTGT: return CC2 | CC1;
- default:
- abort ();
+ default: return -1;
}
break;
default:
- abort ();
+ return -1;
}
}
};
int mask = s390_branch_condition_mask (code);
+ gcc_assert (mask >= 0);
if (inv)
mask ^= 15;
void
s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
{
- rtx (*gen_result) (rtx) =
- GET_MODE (target) == DImode ? gen_cmpint_di : gen_cmpint_si;
+ rtx ccreg = gen_rtx_REG (CCUmode, CC_REGNUM);
+ rtx result = gen_rtx_UNSPEC (SImode, gen_rtvec (1, ccreg), UNSPEC_CMPINT);
if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
{
if (INTVAL (len) > 0)
{
emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (INTVAL (len) - 1)));
- emit_insn (gen_result (target));
+ emit_move_insn (target, result);
}
else
emit_move_insn (target, const0_rtx);
else /* if (TARGET_MVCLE) */
{
emit_insn (gen_cmpmem_long (op0, op1, convert_to_mode (Pmode, len, 1)));
- emit_insn (gen_result (target));
+ emit_move_insn (target, result);
}
#if 0
emit_label (loop_start_label);
emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (255)));
- temp = gen_rtx_NE (VOIDmode, gen_rtx_REG (CCSmode, 33), const0_rtx);
+ temp = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
gen_rtx_LABEL_REF (VOIDmode, end_label), pc_rtx);
temp = gen_rtx_SET (VOIDmode, pc_rtx, temp);
convert_to_mode (Pmode, count, 1)));
emit_label (end_label);
- emit_insn (gen_result (target));
+ emit_move_insn (target, result);
}
#endif
}
{"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, \
CONST_INT, CONST_DOUBLE }}, \
{"s390_plus_operand", { PLUS }}, \
+ {"s390_comparison", { EQ, NE, LT, GT, LE, GE, LTU, GTU, LEU, GEU, \
+ UNEQ, UNLT, UNGT, UNLE, UNGE, LTGT, \
+ UNORDERED, ORDERED }}, \
{"s390_alc_comparison", { ZERO_EXTEND, SIGN_EXTEND, \
LTU, GTU, LEU, GEU }}, \
{"s390_slb_comparison", { ZERO_EXTEND, SIGN_EXTEND, \
(define_constants
[; Miscellaneous
(UNSPEC_ROUND 1)
+ (UNSPEC_CMPINT 2)
(UNSPEC_SETHIGH 10)
; GOT/PLT and lt-relative accesses
; cmpmemM instruction pattern(s).
;
-(define_expand "cmpmemdi"
- [(set (match_operand:DI 0 "register_operand" "")
- (compare:DI (match_operand:BLK 1 "memory_operand" "")
- (match_operand:BLK 2 "memory_operand" "") ) )
- (use (match_operand:DI 3 "general_operand" ""))
- (use (match_operand:DI 4 "" ""))]
- "TARGET_64BIT"
- "s390_expand_cmpmem (operands[0], operands[1],
- operands[2], operands[3]); DONE;")
-
(define_expand "cmpmemsi"
[(set (match_operand:SI 0 "register_operand" "")
(compare:SI (match_operand:BLK 1 "memory_operand" "")
(define_expand "cmpmem_short"
[(parallel
- [(set (reg:CCS 33)
- (compare:CCS (match_operand:BLK 0 "memory_operand" "")
+ [(set (reg:CCU 33)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "nonmemory_operand" ""))
(clobber (match_dup 3))])]
"operands[3] = gen_rtx_SCRATCH (Pmode);")
(define_insn "*cmpmem_short"
- [(set (reg:CCS 33)
- (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
+ [(set (reg:CCU 33)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "=Q,Q")
(match_operand:BLK 1 "memory_operand" "Q,Q")))
(use (match_operand 2 "nonmemory_operand" "n,a"))
(clobber (match_scratch 3 "=X,&a"))]
[(parallel
[(clobber (match_dup 2))
(clobber (match_dup 3))
- (set (reg:CCS 33)
- (compare:CCS (match_operand:BLK 0 "memory_operand" "")
+ (set (reg:CCU 33)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "general_operand" ""))
(use (match_dup 3))])]
(define_insn "*cmpmem_long_64"
[(clobber (match_operand:TI 0 "register_operand" "=d"))
(clobber (match_operand:TI 1 "register_operand" "=d"))
- (set (reg:CCS 33)
- (compare:CCS (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
+ (set (reg:CCU 33)
+ (compare:CCU (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
(mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0))))
(use (match_dup 2))
(use (match_dup 3))]
(define_insn "*cmpmem_long_31"
[(clobber (match_operand:DI 0 "register_operand" "=d"))
(clobber (match_operand:DI 1 "register_operand" "=d"))
- (set (reg:CCS 33)
- (compare:CCS (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
+ (set (reg:CCU 33)
+ (compare:CCU (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
(mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0))))
(use (match_dup 2))
(use (match_dup 3))]
; Convert condition code to integer in range (-1, 0, 1)
-(define_insn "cmpint_si"
+(define_insn "*cmpint_si"
[(set (match_operand:SI 0 "register_operand" "=d")
- (compare:SI (reg:CCS 33) (const_int 0)))]
+ (unspec:SI [(reg:CCU 33)] UNSPEC_CMPINT))]
""
{
output_asm_insn ("lhi\t%0,1", operands);
(set_attr "length" "16")
(set_attr "type" "other")])
-(define_insn "cmpint_di"
+(define_insn "*cmpint_di"
[(set (match_operand:DI 0 "register_operand" "=d")
- (compare:DI (reg:CCS 33) (const_int 0)))]
+ (sign_extend:DI (unspec:SI [(reg:CCU 33)] UNSPEC_CMPINT)))]
"TARGET_64BIT"
{
output_asm_insn ("lghi\t%0,1", operands);
(define_insn "*cjump_64"
[(set (pc)
(if_then_else
- (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (match_operator 1 "s390_comparison" [(reg 33) (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_CPU_ZARCH"
(define_insn "*cjump_31"
[(set (pc)
(if_then_else
- (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (match_operator 1 "s390_comparison" [(reg 33) (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
"!TARGET_CPU_ZARCH"
(define_insn "*cjump_long"
[(set (pc)
(if_then_else
- (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (match_operator 1 "s390_comparison" [(reg 33) (const_int 0)])
(match_operand 0 "address_operand" "U")
(pc)))]
""
(define_insn "*icjump_64"
[(set (pc)
(if_then_else
- (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (match_operator 1 "s390_comparison" [(reg 33) (const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
"TARGET_CPU_ZARCH"
(define_insn "*icjump_31"
[(set (pc)
(if_then_else
- (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (match_operator 1 "s390_comparison" [(reg 33) (const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
"!TARGET_CPU_ZARCH"
(define_insn "*icjump_long"
[(set (pc)
(if_then_else
- (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (match_operator 1 "s390_comparison" [(reg 33) (const_int 0)])
(pc)
(match_operand 0 "address_operand" "U")))]
""
})
(define_insn "*trap"
- [(trap_if (match_operator 0 "comparison_operator" [(reg 33) (const_int 0)])
+ [(trap_if (match_operator 0 "s390_comparison" [(reg 33) (const_int 0)])
(const_int 0))]
""
"j%C0\t.+2";