(match_dup 0))]
"peep2_reg_dead_p (2, operands[0])"
[(set (match_dup 2) (match_dup 1))])
+
+;; umax (a, add (a, b)) => [sum, ovf] = add (a, b); ovf ? a : sum
+;; umin (a, add (a, b)) => [sum, ovf] = add (a, b); ovf ? sum : a
+
+(define_code_attr ovf_add_cmp [(umax "geu") (umin "ltu")])
+
+(define_int_iterator ovf_comm [1 2])
+
+(define_insn_and_split "*plus_within_<code><mode>3_<ovf_comm>"
+ [(set (match_operand:SWI248 0 "register_operand")
+ (umaxmin:SWI248
+ (plus:SWI248 (match_operand:SWI248 1 "nonimmediate_operand")
+ (match_operand:SWI248 2 "<general_operand>"))
+ (match_dup ovf_comm)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_CMOVE
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(parallel
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (plus:SWI248 (match_dup 1) (match_dup 2))
+ (match_dup ovf_comm)))
+ (set (match_dup 3)
+ (plus:SWI248 (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SWI248
+ (<ovf_add_cmp> (reg:CCC FLAGS_REG) (const_int 0))
+ (match_dup 3)
+ (match_dup ovf_comm)))]
+{
+ operands[<ovf_comm>] = force_reg (<MODE>mode, operands[<ovf_comm>]);
+ operands[3] = gen_reg_rtx (<MODE>mode);
+})
+
+;; umax (a, sub (a, b)) => [diff, udf] = sub (a, b); udf ? diff : a
+;; umin (a, sub (a, b)) => [diff, udf] = sub (a, b); udf ? a : diff
+
+(define_code_attr udf_sub_cmp [(umax "ltu") (umin "geu")])
+
+(define_insn_and_split "*minus_within_<code><mode>3"
+ [(set (match_operand:SWI248 0 "register_operand")
+ (umaxmin:SWI248
+ (minus:SWI248 (match_operand:SWI248 1 "nonimmediate_operand")
+ (match_operand:SWI248 2 "<general_operand>"))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_CMOVE
+ && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(parallel
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 3)
+ (minus:SWI248 (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SWI248
+ (<udf_sub_cmp> (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 3)
+ (match_dup 1)))]
+{
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ operands[3] = gen_reg_rtx (<MODE>mode);
+})
\f
;; Misc patterns (?)
--- /dev/null
+/* PR target/116815 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+[[gnu::always_inline]]
+inline unsigned min (unsigned a, unsigned b)
+{
+ return (a < b) ? a : b;
+}
+
+[[gnu::always_inline]]
+inline unsigned max (unsigned a, unsigned b)
+{
+ return (a > b) ? a : b;
+}
+
+[[gnu::noipa]] unsigned
+umaxadd (unsigned a, unsigned b)
+{
+ return max (a + b, a);
+}
+
+[[gnu::noipa]] unsigned
+umaxsub (unsigned a, unsigned b)
+{
+ return max (a - b, a);
+}
+
+[[gnu::noipa]] unsigned
+uminadd (unsigned a, unsigned b)
+{
+ return min (a + b, a);
+}
+
+[[gnu::noipa]] unsigned
+uminsub (unsigned a, unsigned b)
+{
+ return min (a - b, a);
+}
+
+int
+main ()
+{
+ /* Overflows to 0x30000000. */
+ if (umaxadd (0x90000000, 0xa0000000) != 0x90000000)
+ __builtin_abort ();
+
+ if (uminadd (0x90000000, 0xa0000000) != 0x30000000)
+ __builtin_abort ();
+
+ /* Underflows to 0x60000000. */
+ if (umaxsub (0x00000000, 0xa0000000) != 0x60000000)
+ __builtin_abort ();
+
+ if (uminsub (0x00000000, 0xa0000000) != 0x00000000)
+ __builtin_abort ();
+}
--- /dev/null
+/* PR target/116815 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-march=pentiumpro" { target ia32 } } */
+
+static inline __attribute__ ((always_inline))
+unsigned max (unsigned a, unsigned b) { return a > b ? a : b; }
+
+static inline __attribute__ ((always_inline))
+unsigned min (unsigned a, unsigned b) { return a < b ? a : b; }
+
+#define OPERATION(op, type, N, exp1, exp2) \
+ unsigned u##op##type##N (unsigned a, unsigned b) { return op (exp1, exp2); }
+
+OPERATION (max, add, 1, a, a + b)
+OPERATION (max, add, 2, a, b + a)
+OPERATION (max, add, 3, a + b, a)
+OPERATION (max, add, 4, b + a, a)
+
+OPERATION (min, add, 1, a, a + b)
+OPERATION (min, add, 2, a, b + a)
+OPERATION (min, add, 3, a + b, a)
+OPERATION (min, add, 4, b + a, a)
+
+OPERATION (max, sub, 1, a, a - b)
+OPERATION (max, sub, 2, a - b, a)
+
+OPERATION (min, sub, 1, a, a - b)
+OPERATION (min, sub, 2, a - b, a)
+
+/* { dg-final { scan-assembler-not "cmp" } } */