diff --git a/gcc/match-sat-alu.pd b/gcc/match-sat-alu.pd
index dfb2eb9800f..b3dd8db0d27 100644
--- a/gcc/match-sat-alu.pd
+++ b/gcc/match-sat-alu.pd
@@ -131,6 +131,35 @@ along with GCC; see the file COPYING3.  If not see
   /* SAT_U_SUB = (X - Y) * (X >= Y)  */
   (mult:c (minus @0 @1) (convert (ge @0 @1)))
   (if (types_match (type, @0, @1))))
+ /* Accept the comparison with its operands in the opposite order.  */
+ (match (unsigned_integer_sat_sub @0 @1)
+  (cond^ (lt @1 @0) (minus @0 @1) integer_zerop)
+  (if (types_match (type, @0, @1))))
+ (match (unsigned_integer_sat_sub @0 @1)
+  (cond^ (le @1 @0) (convert? (minus (convert1? @0) (convert1? @1)))
+	 integer_zerop)
+  (if (TYPE_UNSIGNED (TREE_TYPE (@0)) && types_match (@0, @1))))
+ (match (unsigned_integer_sat_sub @0 @1)
+  (mult:c (minus @0 @1) (convert (lt @1 @0)))
+  (if (types_match (type, @0, @1))))
+ (match (unsigned_integer_sat_sub @0 @1)
+  (mult:c (minus @0 @1) (convert (le @1 @0)))
+  (if (types_match (type, @0, @1))))
+ /* A source with two returns can keep zero on the taken arm.  */
+ (match (unsigned_integer_sat_sub @0 @1)
+  (cond^ (lt @0 @1) integer_zerop (minus @0 @1))
+  (if (types_match (type, @0, @1))))
+ (match (unsigned_integer_sat_sub @0 @1)
+  (cond^ (le @0 @1) integer_zerop
+	 (convert? (minus (convert1? @0) (convert1? @1))))
+  (if (TYPE_UNSIGNED (TREE_TYPE (@0)) && types_match (@0, @1))))
+ (match (unsigned_integer_sat_sub @0 @1)
+  (cond^ (gt @1 @0) integer_zerop (minus @0 @1))
+  (if (types_match (type, @0, @1))))
+ (match (unsigned_integer_sat_sub @0 @1)
+  (cond^ (ge @1 @0) integer_zerop
+	 (convert? (minus (convert1? @0) (convert1? @1))))
+  (if (TYPE_UNSIGNED (TREE_TYPE (@0)) && types_match (@0, @1))))
  /* The wrapped difference exceeds the minuend exactly when the subtraction
     borrows, so a source that names the difference and then tests it against
     the minuend is a saturating subtract.  */
diff --git a/gcc/testsuite/gcc.target/aarch64/sat_u_sub_swapped-1.c b/gcc/testsuite/gcc.target/aarch64/sat_u_sub_swapped-1.c
new file mode 100644
index 00000000000..fb42b6b07e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sat_u_sub_swapped-1.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+/* The same saturating subtract with the subtrahend written on the left of
+   the comparison.  GIMPLE orders comparison operands by SSA version, so
+   which spelling survives does not follow the source.  */
+
+#define DEF(N, T)						\
+  T f1_##N (T a, T b) { return b < a ? a - b : 0; }		\
+  T f2_##N (T a, T b) { return b <= a ? a - b : 0; }		\
+  T f3_##N (T a, T b) { return (T) ((a - b) * (T) (b < a)); }	\
+  T f4_##N (T a, T b) { return (T) ((a - b) * (T) (b <= a)); }	\
+  T f5_##N (T a, T b) { if (b >= a) return 0; return a - b; }	\
+  T f6_##N (T a, T b) { return b >= a ? 0 : a - b; }		\
+  T f7_##N (T a, T b) { if (a < b) return 0; return a - b; }
+
+DEF (8, u8)
+DEF (16, u16)
+DEF (32, u32)
+DEF (64, u64)
+
+/* { dg-final { scan-tree-dump-times "\\.SAT_SUB " 28 "optimized" } } */
