; of whole values in GPRs.
(define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")])
+; And again, for patterns that need two (potentially) different integer modes.
+(define_mode_iterator GPR2 [SI (DI "TARGET_POWERPC64")])
+
; Any supported integer mode.
(define_mode_iterator INT [QI HI SI DI TI PTI])
(clobber (match_operand:GPR 0 "gpc_reg_operand"))]
""
{
- /* Use ISEL if the user asked for it. */
- if (TARGET_ISEL)
- rs6000_emit_int_cmove (operands[0], operands[1], const1_rtx, const0_rtx);
-
/* Expanding EQ and NE directly to some machine instructions does not help
but does hurt combine. So don't. */
- else if (GET_CODE (operands[1]) == EQ)
+ if (GET_CODE (operands[1]) == EQ)
emit_insn (gen_eq<mode>3 (operands[0], operands[2], operands[3]));
else if (<MODE>mode == Pmode
&& GET_CODE (operands[1]) == NE)
emit_insn (gen_xor<mode>3 (operands[0], tmp, const1_rtx));
}
- /* Expanding the unsigned comparisons however helps a lot: all the neg_ltu
+ /* If ISEL is fast, expand to it. */
+ else if (TARGET_ISEL)
+ rs6000_emit_int_cmove (operands[0], operands[1], const1_rtx, const0_rtx);
+
+ /* Expanding the unsigned comparisons helps a lot: all the neg_ltu
etc. combinations magically work out just right. */
else if (<MODE>mode == Pmode
&& unsigned_comparison_operator (operands[1], VOIDmode))
"")
+(define_code_iterator cmp [eq ne lt ltu gt gtu le leu ge geu])
+(define_code_attr UNS [(eq "CC")
+ (ne "CC")
+ (lt "CC") (ltu "CCUNS")
+ (gt "CC") (gtu "CCUNS")
+ (le "CC") (leu "CCUNS")
+ (ge "CC") (geu "CCUNS")])
+(define_code_attr UNSu_ [(eq "")
+ (ne "")
+ (lt "") (ltu "u_")
+ (gt "") (gtu "u_")
+ (le "") (leu "u_")
+ (ge "") (geu "u_")])
+(define_code_attr UNSIK [(eq "I")
+ (ne "I")
+ (lt "I") (ltu "K")
+ (gt "I") (gtu "K")
+ (le "I") (leu "K")
+ (ge "I") (geu "K")])
+
+(define_insn_and_split "<code><GPR:mode><GPR2:mode>2_isel"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (cmp:GPR (match_operand:GPR2 1 "gpc_reg_operand" "r")
+ (match_operand:GPR2 2 "reg_or_<cmp:UNSu_>short_operand" "r<cmp:UNSIK>")))
+ (clobber (match_scratch:GPR 3 "=r"))
+ (clobber (match_scratch:GPR 4 "=r"))
+ (clobber (match_scratch:<UNS> 5 "=y"))]
+ "TARGET_ISEL
+ && !(<CODE> == EQ && operands[2] == const0_rtx)
+ && !(<CODE> == NE && operands[2] == const0_rtx
+ && <GPR:MODE>mode == Pmode && <GPR2:MODE>mode == Pmode)"
+ "#"
+ "&& 1"
+ [(pc)]
+{
+ if (<CODE> == NE || <CODE> == LE || <CODE> == GE
+ || <CODE> == LEU || <CODE> == GEU)
+ operands[3] = const0_rtx;
+ else
+ {
+ if (GET_CODE (operands[3]) == SCRATCH)
+ operands[3] = gen_reg_rtx (<GPR:MODE>mode);
+ emit_move_insn (operands[3], const0_rtx);
+ }
+
+ if (GET_CODE (operands[4]) == SCRATCH)
+ operands[4] = gen_reg_rtx (<GPR:MODE>mode);
+ emit_move_insn (operands[4], const1_rtx);
+
+ if (GET_CODE (operands[5]) == SCRATCH)
+ operands[5] = gen_reg_rtx (<UNS>mode);
+
+ rtx c1 = gen_rtx_COMPARE (<UNS>mode, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (operands[5], c1));
+
+ rtx c2 = gen_rtx_fmt_ee (<CODE>, <GPR:MODE>mode, operands[5], const0_rtx);
+ rtx x = gen_rtx_IF_THEN_ELSE (<GPR:MODE>mode, c2, operands[4], operands[3]);
+ emit_move_insn (operands[0], x);
+
+ DONE;
+}
+ [(set (attr "cost")
+ (if_then_else (match_test "<CODE> == NE || <CODE> == LE || <CODE> == GE
+ || <CODE> == LEU || <CODE> == GEU")
+ (const_string "9")
+ (const_string "10")))])
+
(define_mode_attr scc_eq_op2 [(SI "rKLI")
(DI "rKJI")])
-(define_insn_and_split "eq<mode>3"
+(define_expand "eq<mode>3"
+ [(parallel [
+ (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))
+ (clobber (match_scratch:GPR 3 "=r"))
+ (clobber (match_scratch:GPR 4 "=r"))])]
+ ""
+{
+ if (TARGET_ISEL && operands[2] != const0_rtx)
+ {
+ emit_insn (gen_eq<mode><mode>2_isel (operands[0], operands[1],
+ operands[2]));
+ DONE;
+ }
+})
+
+(define_insn_and_split "*eq<mode>3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))
(clobber (match_scratch:GPR 3 "=r"))
(clobber (match_scratch:GPR 4 "=r"))]
- ""
+ "!(TARGET_ISEL && operands[2] != const0_rtx)"
"#"
- ""
+ "&& 1"
[(set (match_dup 4)
(clz:GPR (match_dup 3)))
(set (match_dup 0)
(const_string "8")
(const_string "12")))])
-(define_insn_and_split "ne<mode>3"
+(define_expand "ne<mode>3"
+ [(parallel [
+ (set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>")))
+ (clobber (match_scratch:P 3 "=r"))
+ (clobber (match_scratch:P 4 "=r"))
+ (clobber (reg:P CA_REGNO))])]
+ ""
+{
+ if (TARGET_ISEL && operands[2] != const0_rtx)
+ {
+ emit_insn (gen_ne<mode><mode>2_isel (operands[0], operands[1],
+ operands[2]));
+ DONE;
+ }
+})
+
+(define_insn_and_split "*ne<mode>3"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(ne:P (match_operand:P 1 "gpc_reg_operand" "r")
(match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>")))
(clobber (match_scratch:P 3 "=r"))
(clobber (match_scratch:P 4 "=r"))
(clobber (reg:P CA_REGNO))]
- "!TARGET_ISEL"
+ "!(TARGET_ISEL && operands[2] != const0_rtx)"
"#"
- ""
+ "&& 1"
[(parallel [(set (match_dup 4)
(plus:P (match_dup 3)
(const_int -1)))
(clobber (match_scratch:SI 3 "=r"))
(clobber (match_scratch:SI 4 "=r"))
(clobber (match_scratch:EXTSI 5 "=r"))]
- ""
+ "!TARGET_ISEL"
"#"
- ""
+ "&& 1"
[(set (match_dup 4)
(clz:SI (match_dup 3)))
(set (match_dup 5)