Index: lib/Target/X86/X86InstructionSelector.cpp
===================================================================
--- lib/Target/X86/X86InstructionSelector.cpp
+++ lib/Target/X86/X86InstructionSelector.cpp
@@ -19,6 +19,7 @@
 #include "X86Subtarget.h"
 #include "X86TargetMachine.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstr.h"
@@ -76,6 +77,9 @@
   bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
                  MachineFunction &MF) const;
 
+  bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
+                   MachineFunction &MF) const;
+
   const X86TargetMachine &TM;
   const X86Subtarget &STI;
   const X86InstrInfo &TII;
@@ -249,6 +253,8 @@
     return true;
   if (selectCmp(I, MRI, MF))
     return true;
+  if (selectUadde(I, MRI, MF))
+    return true;
 
   return false;
 }
@@ -669,6 +675,53 @@
   return true;
 }
 
+bool X86InstructionSelector::selectUadde(MachineInstr &I,
+                                         MachineRegisterInfo &MRI,
+                                         MachineFunction &MF) const {
+  if (I.getOpcode() != TargetOpcode::G_UADDE)
+    return false;
+
+  const unsigned DstReg = I.getOperand(0).getReg();
+  unsigned CarryInReg = I.getOperand(4).getReg();
+
+  const LLT DstTy = MRI.getType(DstReg);
+
+  if (DstTy != LLT::scalar(32))
+    return false;
+
+  // find CarryIn def instruction.
+  MachineInstr *Def = MRI.getVRegDef(CarryInReg);
+  while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
+    CarryInReg = Def->getOperand(1).getReg();
+    Def = MRI.getVRegDef(CarryInReg);
+  }
+
+  MachineInstrBuilder MIB(MF, I);
+  unsigned Opcode;
+  if (Def->getOpcode() == TargetOpcode::G_UADDE) {
+    // carry set by prev ADD
+    Opcode = X86::ADC32rr;
+    MIB.addDef(X86::EFLAGS, RegState::Implicit);
+    MIB.addUse(X86::EFLAGS, RegState::Implicit);
+  } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
+    // carry is constant, support only 0.
+    if (*val != 0)
+      return false;
+
+    Opcode = X86::ADD32rr;
+    MIB.addDef(X86::EFLAGS, RegState::Implicit);
+  } else
+    return false;
+
+  // remove carryIn/Out
+  I.RemoveOperand(4);
+  I.RemoveOperand(1);
+
+  I.setDesc(TII.get(Opcode));
+
+  return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+}
+
 InstructionSelector *
 llvm::createX86InstructionSelector(const X86TargetMachine &TM,
                                    X86Subtarget &Subtarget,
Index: lib/Target/X86/X86LegalizerInfo.cpp
===================================================================
--- lib/Target/X86/X86LegalizerInfo.cpp
+++ lib/Target/X86/X86LegalizerInfo.cpp
@@ -59,6 +59,11 @@
     for (auto Ty : {s8, s16, s32})
       setAction({BinOp, Ty}, Legal);
 
+  for (unsigned Op : {G_UADDE}) {
+    setAction({Op, s32}, Legal);
+    setAction({Op, 1, s1}, Legal);
+  }
+
   for (unsigned MemOp : {G_LOAD, G_STORE}) {
     for (auto Ty : {s8, s16, s32, p0})
       setAction({MemOp, Ty}, Legal);
Index: test/CodeGen/X86/GlobalISel/add-scalar.ll
===================================================================
--- test/CodeGen/X86/GlobalISel/add-scalar.ll
+++ test/CodeGen/X86/GlobalISel/add-scalar.ll
@@ -1,44 +1,87 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
+; RUN: llc -mtriple=i386-linux-gnu   -global-isel < %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32
 
 define i64 @test_add_i64(i64 %arg1, i64 %arg2) {
-; ALL-LABEL: test_add_i64:
-; ALL:       # BB#0:
-; ALL-NEXT:    leaq (%rsi,%rdi), %rax
-; ALL-NEXT:    retq
+; X64-LABEL: test_add_i64:
+; X64:       # BB#0:
+; X64-NEXT:    leaq (%rsi,%rdi), %rax
+; X64-NEXT:    retq
+;
+; X32-LABEL: test_add_i64:
+; X32:       # BB#0:
+; X32-NEXT:    pushl %esi
+; X32-NEXT:  .Lcfi0:
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:  .Lcfi1:
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    leal 8(%esp), %ecx
+; X32-NEXT:    leal 12(%esp), %esi
+; X32-NEXT:    leal 16(%esp), %eax
+; X32-NEXT:    movl (%eax), %eax
+; X32-NEXT:    leal 20(%esp), %edx
+; X32-NEXT:    movl (%edx), %edx
+; X32-NEXT:    addl (%ecx), %eax
+; X32-NEXT:    adcl (%esi), %edx
+; X32-NEXT:    popl %esi
+; X32-NEXT:    retl
   %ret = add i64 %arg1, %arg2
   ret i64 %ret
 }
 
 define i32 @test_add_i32(i32 %arg1, i32 %arg2) {
-; ALL-LABEL: test_add_i32:
-; ALL:       # BB#0:
-; ALL-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
-; ALL-NEXT:    # kill: %ESI<def> %ESI<kill> %RSI<def>
-; ALL-NEXT:    leal (%rsi,%rdi), %eax
-; ALL-NEXT:    retq
+; X64-LABEL: test_add_i32:
+; X64:       # BB#0:
+; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; X64-NEXT:    # kill: %ESI<def> %ESI<kill> %RSI<def>
+; X64-NEXT:    leal (%rsi,%rdi), %eax
+; X64-NEXT:    retq
+;
+; X32-LABEL: test_add_i32:
+; X32:       # BB#0:
+; X32-NEXT:    leal 4(%esp), %ecx
+; X32-NEXT:    leal 8(%esp), %eax
+; X32-NEXT:    movl (%eax), %eax
+; X32-NEXT:    addl (%ecx), %eax
+; X32-NEXT:    retl
   %ret = add i32 %arg1, %arg2
   ret i32 %ret
 }
 
 define i16 @test_add_i16(i16 %arg1, i16 %arg2) {
-; ALL-LABEL: test_add_i16:
-; ALL:       # BB#0:
-; ALL-NEXT:    # kill: %DI<def> %DI<kill> %RDI<def>
-; ALL-NEXT:    # kill: %SI<def> %SI<kill> %RSI<def>
-; ALL-NEXT:    leal (%rsi,%rdi), %eax
-; ALL-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
-; ALL-NEXT:    retq
+; X64-LABEL: test_add_i16:
+; X64:       # BB#0:
+; X64-NEXT:    # kill: %DI<def> %DI<kill> %RDI<def>
+; X64-NEXT:    # kill: %SI<def> %SI<kill> %RSI<def>
+; X64-NEXT:    leal (%rsi,%rdi), %eax
+; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
+; X64-NEXT:    retq
+;
+; X32-LABEL: test_add_i16:
+; X32:       # BB#0:
+; X32-NEXT:    leal 4(%esp), %ecx
+; X32-NEXT:    leal 8(%esp), %eax
+; X32-NEXT:    movzwl (%eax), %eax
+; X32-NEXT:    addw (%ecx), %ax
+; X32-NEXT:    retl
   %ret = add i16 %arg1, %arg2
   ret i16 %ret
 }
 
 define i8 @test_add_i8(i8 %arg1, i8 %arg2) {
-; ALL-LABEL: test_add_i8:
-; ALL:       # BB#0:
-; ALL-NEXT:    addb %dil, %sil
-; ALL-NEXT:    movl %esi, %eax
-; ALL-NEXT:    retq
+; X64-LABEL: test_add_i8:
+; X64:       # BB#0:
+; X64-NEXT:    addb %dil, %sil
+; X64-NEXT:    movl %esi, %eax
+; X64-NEXT:    retq
+;
+; X32-LABEL: test_add_i8:
+; X32:       # BB#0:
+; X32-NEXT:    leal 4(%esp), %ecx
+; X32-NEXT:    leal 8(%esp), %eax
+; X32-NEXT:    movb (%eax), %al
+; X32-NEXT:    addb (%ecx), %al
+; X32-NEXT:    retl
   %ret = add i8 %arg1, %arg2
   ret i8 %ret
 }
Index: test/CodeGen/X86/GlobalISel/legalize-add.mir
===================================================================
--- test/CodeGen/X86/GlobalISel/legalize-add.mir
+++ test/CodeGen/X86/GlobalISel/legalize-add.mir
@@ -1,40 +1,67 @@
-# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s
-
+# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X64
+# RUN: llc -mtriple=i386-linux-gnu   -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL --check-prefix=X32
 --- |
-  ; ModuleID = '<stdin>'
-  source_filename = "<stdin>"
-  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-  target triple = "x86_64--linux-gnu"
+  define void @test_add_i32() {
+    ret void
+  }
 
-  define i32 @test_add_i32(i32 %arg1, i32 %arg2) {
-    %ret = add i32 %arg1, %arg2
-    ret i32 %ret
+  define void @test_add_i64() {
+    ret void
   }
 
 ...
 ---
 name:            test_add_i32
+# ALL-LABEL: name:  test_add_i32
 alignment:       4
 legalized:       false
 regBankSelected: false
-selected:        false
-tracksRegLiveness: true
 registers:
   - { id: 0, class: _ }
   - { id: 1, class: _ }
   - { id: 2, class: _ }
+# ALL:          %0(s32) = IMPLICIT_DEF
+# ALL-NEXT:     %1(s32) = IMPLICIT_DEF
+# ALL-NEXT:     %2(s32) = G_ADD %0, %1
+# ALL-NEXT:     RET 0
 body:             |
   bb.1 (%ir-block.0):
-    liveins: %edi, %esi
-    ;  CHECK-LABEL: name: test_add_i32
-    ;  CHECK: [[VAL1:%.*]](s32) = COPY %edi
-    ;  CHECK: [[VAL2:%.*]](s32) = COPY %esi
-    ;  CHECK: [[RES:%.*]](s32) = G_ADD [[VAL1:%.*]], [[VAL2:%.*]]
-
-    %0(s32) = COPY %edi
-    %1(s32) = COPY %esi
+    %0(s32) = IMPLICIT_DEF
+    %1(s32) = IMPLICIT_DEF
     %2(s32) = G_ADD %0, %1
-    %eax = COPY %2(s32)
-    RET 0, implicit %eax
+    RET 0
+
+...
+---
+name:            test_add_i64
+# ALL-LABEL: name:  test_add_i64
+alignment:       4
+legalized:       false
+regBankSelected: false
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+# X64:          %0(s64) = IMPLICIT_DEF
+# X64-NEXT:     %1(s64) = IMPLICIT_DEF
+# X64-NEXT:     %2(s64) = G_ADD %0, %1
+# X64-NEXT:     RET 0
+#
+# X32:          %0(s64) = IMPLICIT_DEF
+# X32-NEXT:     %1(s64) = IMPLICIT_DEF
+# X32-NEXT:     %3(s32), %4(s32) = G_UNMERGE_VALUES %0(s64)
+# X32-NEXT:     %5(s32), %6(s32) = G_UNMERGE_VALUES %1(s64)
+# X32-NEXT:     %12(s8) = G_CONSTANT i8 0
+# X32-NEXT:     %7(s1) = G_TRUNC %12(s8)
+# X32-NEXT:     %8(s32), %9(s1) = G_UADDE %3, %5, %7
+# X32-NEXT:     %10(s32), %11(s1) = G_UADDE %4, %6, %9
+# X32-NEXT:     %2(s64) = G_MERGE_VALUES %8(s32), %10(s32)
+# X32-NEXT:     RET 0
+body:             |
+  bb.1 (%ir-block.0):
+    %0(s64) = IMPLICIT_DEF
+    %1(s64) = IMPLICIT_DEF
+    %2(s64) = G_ADD %0, %1
+    RET 0
 
 ...
Index: test/CodeGen/X86/GlobalISel/regbankselect-X32.mir
===================================================================
--- /dev/null
+++ test/CodeGen/X86/GlobalISel/regbankselect-X32.mir
@@ -0,0 +1,36 @@
+# RUN: llc -mtriple=i386-linux-gnu -global-isel                       -run-pass=regbankselect %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
+# RUN: llc -mtriple=i386-linux-gnu -global-isel -regbankselect-greedy -run-pass=regbankselect %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=GREEDY
+
+--- |
+  define void @test_uadde_i32() {
+    ret void
+  }
+
+...
+---
+name:            test_uadde_i32
+# CHECK-LABEL: name:  test_uadde_i32
+alignment:       4
+legalized:       true
+regBankSelected: false
+# CHECK:      registers:
+# CHECK-NEXT:   - { id: 0, class: gpr }
+# CHECK-NEXT:   - { id: 1, class: gpr }
+# CHECK-NEXT:   - { id: 2, class: gpr }
+# CHECK-NEXT:   - { id: 3, class: gpr }
+# CHECK-NEXT:   - { id: 4, class: gpr }
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+  - { id: 3, class: _ }
+  - { id: 4, class: _ }
+body:             |
+  bb.0 (%ir-block.0):
+    %0(s32) = IMPLICIT_DEF
+    %1(s32) = IMPLICIT_DEF
+    %2(s1) = IMPLICIT_DEF
+    %3(s32), %4(s1) = G_UADDE %0, %1, %2
+    RET 0
+
+...
Index: test/CodeGen/X86/GlobalISel/select-add-x32.mir
===================================================================
--- /dev/null
+++ test/CodeGen/X86/GlobalISel/select-add-x32.mir
@@ -0,0 +1,60 @@
+# RUN: llc -mtriple=i386-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=X32
+--- |
+  define i64 @test_add_i64(i64 %a, i64 %b) {
+    %r = add i64 %a, %b
+    ret i64 %r
+  }
+
+...
+---
+name:            test_add_i64
+# X32-LABEL: name:  test_add_i64
+alignment:       4
+legalized:       true
+regBankSelected: true
+# X32:      registers:
+# X32-NEXT:   - { id: 0, class: gr32 }
+# X32-NEXT:   - { id: 1, class: gr32 }
+# X32-NEXT:   - { id: 2, class: gr32 }
+# X32-NEXT:   - { id: 3, class: gr32 }
+# X32-NEXT:   - { id: 4, class: gpr }
+# X32-NEXT:   - { id: 5, class: gr32 }
+# X32-NEXT:   - { id: 6, class: gpr }
+# X32-NEXT:   - { id: 7, class: gr32 }
+# X32-NEXT:   - { id: 8, class: gpr }
+# X32-NEXT:   - { id: 9, class: gpr }
+registers:
+  - { id: 0, class: gpr }
+  - { id: 1, class: gpr }
+  - { id: 2, class: gpr }
+  - { id: 3, class: gpr }
+  - { id: 4, class: gpr }
+  - { id: 5, class: gpr }
+  - { id: 6, class: gpr }
+  - { id: 7, class: gpr }
+  - { id: 8, class: gpr }
+  - { id: 9, class: gpr }
+# X32:          %0 = IMPLICIT_DEF
+# X32-NEXT:     %1 = IMPLICIT_DEF
+# X32-NEXT:     %2 = IMPLICIT_DEF
+# X32-NEXT:     %3 = IMPLICIT_DEF
+# X32-NEXT:     %5 = ADD32rr %0, %2, implicit-def %eflags
+# X32-NEXT:     %7 = ADC32rr %1, %3, implicit-def %eflags, implicit %eflags
+# X32-NEXT:     %eax = COPY %5
+# X32-NEXT:     %edx = COPY %7
+# X32-NEXT:     RET 0, implicit %eax, implicit %edx
+body:             |
+  bb.0 (%ir-block.0):
+    %0(s32) = IMPLICIT_DEF
+    %1(s32) = IMPLICIT_DEF
+    %2(s32) = IMPLICIT_DEF
+    %3(s32) = IMPLICIT_DEF
+    %9(s8) = G_CONSTANT i8 0
+    %4(s1) = G_TRUNC %9(s8)
+    %5(s32), %6(s1) = G_UADDE %0, %2, %4
+    %7(s32), %8(s1) = G_UADDE %1, %3, %6
+    %eax = COPY %5(s32)
+    %edx = COPY %7(s32)
+    RET 0, implicit %eax, implicit %edx
+
+...