Index: llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
===================================================================
--- llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -211,6 +211,17 @@
   /// Return true if a G_STORE instruction \p MI is storing an undef value.
   bool matchUndefStore(MachineInstr &MI);
 
+  /// Return true if a G_SELECT instruction \p MI has an undef comparison.
+  bool matchUndefSelectCmp(MachineInstr &MI);
+
+  /// Return true if a G_SELECT instruction \p MI has an undef select value. If
+  /// true, \p OpIdx will store the operand index of the known selected value.
+  bool matchUndefSelectVals(MachineInstr &MI, unsigned &ValIdx);
+
+  /// Return true if a G_SELECT instruction \p MI has a constant comparison. If
+  /// true, \p OpIdx will store the operand index of the known selected value.
+  bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx);
+
   /// Replace an instruction with a G_FCONSTANT with value \p C.
   bool replaceInstWithFConstant(MachineInstr &MI, double C);
 
Index: llvm/include/llvm/Target/GlobalISel/Combine.td
===================================================================
--- llvm/include/llvm/Target/GlobalISel/Combine.td
+++ llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -203,6 +203,35 @@
   (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
 >;
 
+// Fold (undef ? x : y) -> x
+def select_undef_cmp: GICombineRule<
+  (defs root:$root),
+  (match (wip_match_opcode G_SELECT):$root,
+    [{ return Helper.matchUndefSelectCmp(*${root}); }]),
+  (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
+>;
+
+// Fold (cmp ? x : undef) -> x
+// Fold (cmp ? undef : y) -> y
+// Fold (cmp ? undef : undef) -> undef
+def select_undef_val_matchdata : GIDefMatchData<"unsigned">;
+def select_undef_val: GICombineRule<
+  (defs root:$root, select_undef_val_matchdata:$matchinfo),
+  (match (wip_match_opcode G_SELECT):$root,
+    [{ return Helper.matchUndefSelectVals(*${root}, ${matchinfo}); }]),
+  (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }])
+>;
+
+// Fold (true ? x : y) -> x
+// Fold (false ? x : y) -> y
+def select_constant_cmp_matchdata : GIDefMatchData<"unsigned">;
+def select_constant_cmp: GICombineRule<
+  (defs root:$root, select_constant_cmp_matchdata:$matchinfo),
+  (match (wip_match_opcode G_SELECT):$root,
+    [{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]),
+  (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }])
+>;
+
 // Fold x op 0 -> x
 def right_identity_zero: GICombineRule<
   (defs root:$root),
@@ -263,7 +292,10 @@
                                         binop_same_val, binop_left_to_zero,
                                         binop_right_to_zero]>;
 
+def select_combines : GICombineGroup<[select_undef_cmp, select_undef_val,
+                                      select_constant_cmp]>;
+
 def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl]>;
 def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
     combines_for_extload, combine_indexed_load_store, undef_combines,
-    identity_combines, simplify_add_to_sub]>;
+    identity_combines, select_combines, simplify_add_to_sub]>;
Index: llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
===================================================================
--- llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -1537,6 +1537,39 @@
                       MRI);
 }
 
+bool CombinerHelper::matchUndefSelectCmp(MachineInstr &MI) {
+  assert(MI.getOpcode() == TargetOpcode::G_SELECT);
+  return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(1).getReg(),
+                      MRI);
+}
+
+bool CombinerHelper::matchUndefSelectVals(MachineInstr &MI, unsigned &OpIdx) {
+  assert(MI.getOpcode() == TargetOpcode::G_SELECT);
+  if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(2).getReg(),
+                   MRI)) {
+    // Select val0 is undef, choose select val1.
+    OpIdx = 3;
+    return true;
+  }
+  if (getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(3).getReg(),
+                   MRI)) {
+    // Select val1 is undef, choose select val0.
+    OpIdx = 2;
+    return true;
+  }
+  return false;
+}
+
+bool CombinerHelper::matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx) {
+  assert(MI.getOpcode() == TargetOpcode::G_SELECT);
+  if (auto MaybeCstCmp =
+          getConstantVRegValWithLookThrough(MI.getOperand(1).getReg(), MRI)) {
+    OpIdx = MaybeCstCmp->Value ? 2 : 3;
+    return true;
+  }
+  return false;
+}
+
 bool CombinerHelper::eraseInst(MachineInstr &MI) {
   MI.eraseFromParent();
   return true;
Index: llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
@@ -0,0 +1,108 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
+# RUN: llc -debugify-and-strip-all-safe -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
+---
+# select (c, x, x) -> x
+name:            test_combine_select_same_res
+body:             |
+  bb.1:
+    liveins: $x0, $x1
+    ; CHECK-LABEL: name: test_combine_select_same_res
+    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+    ; CHECK: $x0 = COPY [[COPY]](s64)
+    %0:_(s64) = COPY $x0
+    %1:_(s1) = G_TRUNC %0
+    %2:_(s64) = G_SELECT %1, %0, %0
+    $x0 = COPY %2(s64)
+...
+---
+# select (undef, x, y) -> x
+name:            test_combine_select_undef_res0_res1
+body:             |
+  bb.1:
+    liveins: $x0, $x1
+    ; CHECK-LABEL: name: test_combine_select_undef_res0_res1
+    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+    ; CHECK: $x0 = COPY [[COPY]](s64)
+    %0:_(s64) = COPY $x0
+    %1:_(s64) = COPY $x1
+    %2:_(s1) = G_IMPLICIT_DEF
+    %3:_(s64) = G_SELECT %2, %0, %1
+    $x0 = COPY %3(s64)
+...
+---
+# select (c, undef, y) -> y
+name:            test_combine_select_cmp_undef_res1
+body:             |
+  bb.1:
+    liveins: $x0
+    ; CHECK-LABEL: name: test_combine_select_cmp_undef_res1
+    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+    ; CHECK: $x0 = COPY [[COPY]](s64)
+    %0:_(s64) = COPY $x0
+    %1:_(s1) = G_TRUNC %0
+    %2:_(s64) = G_IMPLICIT_DEF
+    %3:_(s64) = G_SELECT %1, %2, %0
+    $x0 = COPY %3(s64)
+...
+---
+# select (c, x, undef) -> x
+name:            test_combine_select_cmp_res0_undef
+body:             |
+  bb.1:
+    liveins: $x0
+    ; CHECK-LABEL: name: test_combine_select_cmp_res0_undef
+    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+    ; CHECK: $x0 = COPY [[COPY]](s64)
+    %0:_(s64) = COPY $x0
+    %1:_(s1) = G_TRUNC %0
+    %2:_(s64) = G_IMPLICIT_DEF
+    %3:_(s64) = G_SELECT %1, %0, %2
+    $x0 = COPY %3(s64)
+...
+---
+# select (c, undef, undef) -> undef
+name:            test_combine_select_cmp_undef_undef
+body:             |
+  bb.1:
+    liveins: $x0
+    ; CHECK-LABEL: name: test_combine_select_cmp_undef_undef
+    ; CHECK: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
+    ; CHECK: $x0 = COPY [[DEF]](s64)
+    %0:_(s64) = COPY $x0
+    %1:_(s1) = G_TRUNC %0
+    %2:_(s64) = G_IMPLICIT_DEF
+    %3:_(s64) = G_IMPLICIT_DEF
+    %4:_(s64) = G_SELECT %1, %2, %3
+    $x0 = COPY %3(s64)
+...
+---
+# select (false, x, y) -> y
+name:            test_combine_select_false_res0_res1
+body:             |
+  bb.1:
+    liveins: $x0, $x1
+    ; CHECK-LABEL: name: test_combine_select_false_res0_res1
+    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x1
+    ; CHECK: $x0 = COPY [[COPY]](s64)
+    %0:_(s64) = COPY $x0
+    %1:_(s64) = COPY $x1
+    %2:_(s1) = G_CONSTANT i1 false
+    %3:_(s64) = G_SELECT %2, %0, %1
+    $x0 = COPY %3(s64)
+...
+---
+# select (true, x, y) -> x
+name:            test_combine_select_true_res0_res1
+body:             |
+  bb.1:
+    liveins: $x0, $x1
+    ; CHECK-LABEL: name: test_combine_select_true_res0_res1
+    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+    ; CHECK: $x0 = COPY [[COPY]](s64)
+    %0:_(s64) = COPY $x0
+    %1:_(s64) = COPY $x1
+    %2:_(s1) = G_CONSTANT i1 true
+    %3:_(s64) = G_SELECT %2, %0, %1
+    $x0 = COPY %3(s64)
+...