[llvm] [ARM] Port ConditionOptimizer to ARM (PR #151187)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 31 07:50:58 PDT 2025


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/151187

>From f4ebd1a4f6e55a5128dae701fac79ecae77396a3 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Tue, 29 Jul 2025 11:24:17 -0400
Subject: [PATCH 1/2] Pre-commit tests (NFC)

---
 .../CodeGen/ARM/combine-comparisons-by-cse.ll | 1787 +++++++++++++++++
 1 file changed, 1787 insertions(+)
 create mode 100644 llvm/test/CodeGen/ARM/combine-comparisons-by-cse.ll

diff --git a/llvm/test/CodeGen/ARM/combine-comparisons-by-cse.ll b/llvm/test/CodeGen/ARM/combine-comparisons-by-cse.ll
new file mode 100644
index 0000000000000..f53286fcedd3d
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/combine-comparisons-by-cse.ll
@@ -0,0 +1,1787 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=armv7a < %s | FileCheck %s --check-prefix=ARM
+; RUN: llc -mtriple=armv6m < %s | FileCheck %s --check-prefix=THUMB
+; RUN: llc -mtriple=armv7m < %s | FileCheck %s --check-prefix=THUMB2
+; RUN: llc -mtriple=thumbv8.1m.main < %s | FileCheck %s --check-prefix=THUMBV8
+
+; marked as external to prevent possible optimizations
+ at a = external global i32
+ at b = external global i32
+ at c = external global i32
+ at d = external global i32
+
+; (a > 10 && b == c) || (a >= 10 && b == d)
+define i32 @combine_gt_ge_10() #0 {
+; ARM-LABEL: combine_gt_ge_10:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movw r1, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    movt r1, :upper16:b
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #11
+; ARM-NEXT:    blt .LBB0_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    ldr r3, [r1]
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r3, r2
+; ARM-NEXT:    bxeq lr
+; ARM-NEXT:    b .LBB0_3
+; ARM-NEXT:  .LBB0_2: @ %lor.lhs.false
+; ARM-NEXT:    cmp r0, #10
+; ARM-NEXT:    blt .LBB0_4
+; ARM-NEXT:  .LBB0_3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    ldr r1, [r1]
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r1, r2
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB0_4: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_gt_ge_10:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI0_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #11
+; THUMB-NEXT:    blt .LBB0_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI0_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI0_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB0_4
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB0_3: @ %lor.lhs.false
+; THUMB-NEXT:    cmp r0, #10
+; THUMB-NEXT:    blt .LBB0_6
+; THUMB-NEXT:  .LBB0_4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI0_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI0_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB0_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB0_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI0_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI0_1:
+; THUMB-NEXT:    .long c
+; THUMB-NEXT:  .LCPI0_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI0_3:
+; THUMB-NEXT:    .long d
+;
+; THUMB2-LABEL: combine_gt_ge_10:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r1, [r0]
+; THUMB2-NEXT:    movw r0, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:b
+; THUMB2-NEXT:    cmp r1, #11
+; THUMB2-NEXT:    blt .LBB0_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r1, :lower16:c
+; THUMB2-NEXT:    ldr r2, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:c
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r2, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB0_3
+; THUMB2-NEXT:  .LBB0_2: @ %lor.lhs.false
+; THUMB2-NEXT:    cmp r1, #10
+; THUMB2-NEXT:    blt .LBB0_4
+; THUMB2-NEXT:  .LBB0_3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r1, :lower16:d
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:d
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r0, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB0_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_gt_ge_10:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r1, [r0]
+; THUMBV8-NEXT:    movw r0, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:b
+; THUMBV8-NEXT:    cmp r1, #11
+; THUMBV8-NEXT:    blt .LBB0_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r1, :lower16:c
+; THUMBV8-NEXT:    ldr r2, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:c
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r2, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB0_3
+; THUMBV8-NEXT:  .LBB0_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    cmp r1, #10
+; THUMBV8-NEXT:    blt .LBB0_4
+; THUMBV8-NEXT:  .LBB0_3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r1, :lower16:d
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:d
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r0, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB0_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp sgt i32 %0, 10
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %land.lhs.true3
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp sgt i32 %0, 9
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a > 5 && b == c) || (a < 5 && b == d)
+define i32 @combine_gt_lt_5() #0 {
+; ARM-LABEL: combine_gt_lt_5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #6
+; ARM-NEXT:    blt .LBB1_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB1_4
+; ARM-NEXT:  .LBB1_2: @ %lor.lhs.false
+; ARM-NEXT:    cmp r0, #4
+; ARM-NEXT:    bgt .LBB1_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB1_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB1_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_gt_lt_5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI1_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #6
+; THUMB-NEXT:    blt .LBB1_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI1_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI1_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB1_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB1_3: @ %lor.lhs.false
+; THUMB-NEXT:    cmp r0, #4
+; THUMB-NEXT:    bgt .LBB1_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI1_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI1_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB1_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB1_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI1_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI1_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI1_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI1_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_gt_lt_5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #6
+; THUMB2-NEXT:    blt .LBB1_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB1_4
+; THUMB2-NEXT:  .LBB1_2: @ %lor.lhs.false
+; THUMB2-NEXT:    cmp r0, #4
+; THUMB2-NEXT:    bgt .LBB1_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB1_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_gt_lt_5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #6
+; THUMBV8-NEXT:    blt .LBB1_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB1_4
+; THUMBV8-NEXT:  .LBB1_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    cmp r0, #4
+; THUMBV8-NEXT:    bgt .LBB1_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB1_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp sgt i32 %0, 5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp slt i32 %0, 5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a < 5 && b == c) || (a <= 5 && b == d)
+define i32 @combine_lt_ge_5() #0 {
+; ARM-LABEL: combine_lt_ge_5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movw r1, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    movt r1, :upper16:b
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #4
+; ARM-NEXT:    bgt .LBB2_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    ldr r3, [r1]
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r3, r2
+; ARM-NEXT:    bxeq lr
+; ARM-NEXT:    b .LBB2_3
+; ARM-NEXT:  .LBB2_2: @ %lor.lhs.false
+; ARM-NEXT:    cmp r0, #5
+; ARM-NEXT:    bgt .LBB2_4
+; ARM-NEXT:  .LBB2_3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    ldr r1, [r1]
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r1, r2
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB2_4: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_lt_ge_5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI2_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #4
+; THUMB-NEXT:    bgt .LBB2_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI2_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI2_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB2_4
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB2_3: @ %lor.lhs.false
+; THUMB-NEXT:    cmp r0, #5
+; THUMB-NEXT:    bgt .LBB2_6
+; THUMB-NEXT:  .LBB2_4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI2_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI2_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB2_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB2_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI2_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI2_1:
+; THUMB-NEXT:    .long c
+; THUMB-NEXT:  .LCPI2_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI2_3:
+; THUMB-NEXT:    .long d
+;
+; THUMB2-LABEL: combine_lt_ge_5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r1, [r0]
+; THUMB2-NEXT:    movw r0, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:b
+; THUMB2-NEXT:    cmp r1, #4
+; THUMB2-NEXT:    bgt .LBB2_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r1, :lower16:c
+; THUMB2-NEXT:    ldr r2, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:c
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r2, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB2_3
+; THUMB2-NEXT:  .LBB2_2: @ %lor.lhs.false
+; THUMB2-NEXT:    cmp r1, #5
+; THUMB2-NEXT:    bgt .LBB2_4
+; THUMB2-NEXT:  .LBB2_3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r1, :lower16:d
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:d
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r0, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB2_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_lt_ge_5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r1, [r0]
+; THUMBV8-NEXT:    movw r0, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:b
+; THUMBV8-NEXT:    cmp r1, #4
+; THUMBV8-NEXT:    bgt .LBB2_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r1, :lower16:c
+; THUMBV8-NEXT:    ldr r2, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:c
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r2, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB2_3
+; THUMBV8-NEXT:  .LBB2_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    cmp r1, #5
+; THUMBV8-NEXT:    bgt .LBB2_4
+; THUMBV8-NEXT:  .LBB2_3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r1, :lower16:d
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:d
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r0, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB2_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp slt i32 %0, 5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %land.lhs.true3
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp slt i32 %0, 6
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a < 5 && b == c) || (a > 5 && b == d)
+define i32 @combine_lt_gt_5() #0 {
+; ARM-LABEL: combine_lt_gt_5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #4
+; ARM-NEXT:    bgt .LBB3_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB3_4
+; ARM-NEXT:  .LBB3_2: @ %lor.lhs.false
+; ARM-NEXT:    cmp r0, #6
+; ARM-NEXT:    blt .LBB3_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB3_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB3_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_lt_gt_5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI3_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #4
+; THUMB-NEXT:    bgt .LBB3_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI3_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI3_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB3_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB3_3: @ %lor.lhs.false
+; THUMB-NEXT:    cmp r0, #6
+; THUMB-NEXT:    blt .LBB3_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI3_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI3_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB3_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB3_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI3_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI3_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI3_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI3_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_lt_gt_5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #4
+; THUMB2-NEXT:    bgt .LBB3_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB3_4
+; THUMB2-NEXT:  .LBB3_2: @ %lor.lhs.false
+; THUMB2-NEXT:    cmp r0, #6
+; THUMB2-NEXT:    blt .LBB3_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB3_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_lt_gt_5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #4
+; THUMBV8-NEXT:    bgt .LBB3_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB3_4
+; THUMBV8-NEXT:  .LBB3_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    cmp r0, #6
+; THUMBV8-NEXT:    blt .LBB3_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB3_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp slt i32 %0, 5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp sgt i32 %0, 5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a > -5 && b == c) || (a < -5 && b == d)
+define i32 @combine_gt_lt_n5() #0 {
+; ARM-LABEL: combine_gt_lt_n5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmn r0, #4
+; ARM-NEXT:    blt .LBB4_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB4_4
+; ARM-NEXT:  .LBB4_2: @ %lor.lhs.false
+; ARM-NEXT:    cmn r0, #6
+; ARM-NEXT:    bgt .LBB4_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB4_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB4_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_gt_lt_n5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI4_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    movs r1, #3
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    blt .LBB4_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI4_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI4_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB4_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB4_3: @ %lor.lhs.false
+; THUMB-NEXT:    movs r1, #5
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    bgt .LBB4_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI4_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI4_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB4_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB4_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI4_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI4_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI4_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI4_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_gt_lt_n5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmn.w r0, #4
+; THUMB2-NEXT:    blt .LBB4_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB4_4
+; THUMB2-NEXT:  .LBB4_2: @ %lor.lhs.false
+; THUMB2-NEXT:    cmn.w r0, #6
+; THUMB2-NEXT:    bgt .LBB4_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB4_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_gt_lt_n5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmn.w r0, #4
+; THUMBV8-NEXT:    blt .LBB4_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB4_4
+; THUMBV8-NEXT:  .LBB4_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    cmn.w r0, #6
+; THUMBV8-NEXT:    bgt .LBB4_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB4_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp sgt i32 %0, -5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp slt i32 %0, -5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a < -5 && b == c) || (a > -5 && b == d)
+define i32 @combine_lt_gt_n5() #0 {
+; ARM-LABEL: combine_lt_gt_n5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmn r0, #6
+; ARM-NEXT:    bgt .LBB5_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB5_4
+; ARM-NEXT:  .LBB5_2: @ %lor.lhs.false
+; ARM-NEXT:    cmn r0, #4
+; ARM-NEXT:    blt .LBB5_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB5_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB5_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_lt_gt_n5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI5_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    movs r1, #5
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    bgt .LBB5_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI5_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI5_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB5_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB5_3: @ %lor.lhs.false
+; THUMB-NEXT:    movs r1, #3
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    blt .LBB5_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI5_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI5_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB5_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB5_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI5_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI5_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI5_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI5_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_lt_gt_n5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmn.w r0, #6
+; THUMB2-NEXT:    bgt .LBB5_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB5_4
+; THUMB2-NEXT:  .LBB5_2: @ %lor.lhs.false
+; THUMB2-NEXT:    cmn.w r0, #4
+; THUMB2-NEXT:    blt .LBB5_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB5_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_lt_gt_n5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmn.w r0, #6
+; THUMBV8-NEXT:    bgt .LBB5_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB5_4
+; THUMBV8-NEXT:  .LBB5_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    cmn.w r0, #4
+; THUMBV8-NEXT:    blt .LBB5_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB5_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp slt i32 %0, -5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp sgt i32 %0, -5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+%struct.Struct = type { i32, i32 }
+
+ at glob = internal unnamed_addr global ptr null, align 8
+
+declare ptr @Update(ptr) #1
+
+; no checks for this case, it just should be processed without errors
+define void @combine_non_adjacent_cmp_br(ptr nocapture readonly %hdCall) #0 {
+; ARM-LABEL: combine_non_adjacent_cmp_br:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    push {r4, r5, r6, r7, r11, lr}
+; ARM-NEXT:    ldr r4, [r0]
+; ARM-NEXT:    movw r7, :lower16:glob
+; ARM-NEXT:    mov r6, #24
+; ARM-NEXT:    movt r7, :upper16:glob
+; ARM-NEXT:    add r5, r4, #2
+; ARM-NEXT:  .LBB6_1: @ %land.rhs
+; ARM-NEXT:    @ =>This Inner Loop Header: Depth=1
+; ARM-NEXT:    ldr r0, [r6]
+; ARM-NEXT:    cmp r0, #1
+; ARM-NEXT:    blt .LBB6_3
+; ARM-NEXT:  @ %bb.2: @ %while.body
+; ARM-NEXT:    @ in Loop: Header=BB6_1 Depth=1
+; ARM-NEXT:    ldr r0, [r7]
+; ARM-NEXT:    bl Update
+; ARM-NEXT:    sub r5, r5, #2
+; ARM-NEXT:    cmp r4, r5
+; ARM-NEXT:    blt .LBB6_1
+; ARM-NEXT:  .LBB6_3: @ %while.end
+; ARM-NEXT:    pop {r4, r5, r6, r7, r11, pc}
+;
+; THUMB-LABEL: combine_non_adjacent_cmp_br:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    push {r4, r5, r6, lr}
+; THUMB-NEXT:    ldr r4, [r0]
+; THUMB-NEXT:    adds r5, r4, #2
+; THUMB-NEXT:    ldr r6, .LCPI6_0
+; THUMB-NEXT:  .LBB6_1: @ %land.rhs
+; THUMB-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMB-NEXT:    movs r0, #24
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #1
+; THUMB-NEXT:    blt .LBB6_3
+; THUMB-NEXT:  @ %bb.2: @ %while.body
+; THUMB-NEXT:    @ in Loop: Header=BB6_1 Depth=1
+; THUMB-NEXT:    ldr r0, [r6]
+; THUMB-NEXT:    bl Update
+; THUMB-NEXT:    subs r5, r5, #2
+; THUMB-NEXT:    cmp r4, r5
+; THUMB-NEXT:    blt .LBB6_1
+; THUMB-NEXT:  .LBB6_3: @ %while.end
+; THUMB-NEXT:    pop {r4, r5, r6, pc}
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.4:
+; THUMB-NEXT:  .LCPI6_0:
+; THUMB-NEXT:    .long glob
+;
+; THUMB2-LABEL: combine_non_adjacent_cmp_br:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    push {r4, r5, r6, r7, lr}
+; THUMB2-NEXT:    sub sp, #4
+; THUMB2-NEXT:    ldr r4, [r0]
+; THUMB2-NEXT:    movw r7, :lower16:glob
+; THUMB2-NEXT:    movs r6, #24
+; THUMB2-NEXT:    movt r7, :upper16:glob
+; THUMB2-NEXT:    adds r5, r4, #2
+; THUMB2-NEXT:  .LBB6_1: @ %land.rhs
+; THUMB2-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMB2-NEXT:    ldr r0, [r6]
+; THUMB2-NEXT:    cmp r0, #1
+; THUMB2-NEXT:    blt .LBB6_3
+; THUMB2-NEXT:  @ %bb.2: @ %while.body
+; THUMB2-NEXT:    @ in Loop: Header=BB6_1 Depth=1
+; THUMB2-NEXT:    ldr r0, [r7]
+; THUMB2-NEXT:    bl Update
+; THUMB2-NEXT:    subs r5, #2
+; THUMB2-NEXT:    cmp r4, r5
+; THUMB2-NEXT:    blt .LBB6_1
+; THUMB2-NEXT:  .LBB6_3: @ %while.end
+; THUMB2-NEXT:    add sp, #4
+; THUMB2-NEXT:    pop {r4, r5, r6, r7, pc}
+;
+; THUMBV8-LABEL: combine_non_adjacent_cmp_br:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    push {r4, r5, r6, r7, lr}
+; THUMBV8-NEXT:    sub sp, #4
+; THUMBV8-NEXT:    ldr r4, [r0]
+; THUMBV8-NEXT:    movw r7, :lower16:glob
+; THUMBV8-NEXT:    movs r6, #24
+; THUMBV8-NEXT:    movt r7, :upper16:glob
+; THUMBV8-NEXT:    adds r5, r4, #2
+; THUMBV8-NEXT:  .LBB6_1: @ %land.rhs
+; THUMBV8-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMBV8-NEXT:    ldr r0, [r6]
+; THUMBV8-NEXT:    cmp r0, #1
+; THUMBV8-NEXT:    blt .LBB6_3
+; THUMBV8-NEXT:  @ %bb.2: @ %while.body
+; THUMBV8-NEXT:    @ in Loop: Header=BB6_1 Depth=1
+; THUMBV8-NEXT:    ldr r0, [r7]
+; THUMBV8-NEXT:    bl Update
+; THUMBV8-NEXT:    subs r5, #2
+; THUMBV8-NEXT:    cmp r4, r5
+; THUMBV8-NEXT:    blt .LBB6_1
+; THUMBV8-NEXT:  .LBB6_3: @ %while.end
+; THUMBV8-NEXT:    add sp, #4
+; THUMBV8-NEXT:    pop {r4, r5, r6, r7, pc}
+entry:
+  %0 = load i32, ptr %hdCall, align 8
+  br label %land.rhs
+
+land.rhs:
+  %rp.06 = phi i32 [ %0, %entry ], [ %sub, %while.body ]
+  %1 = load i32, ptr inttoptr (i32 24 to ptr), align 8
+  %cmp2 = icmp sgt i32 %1, 0
+  br i1 %cmp2, label %while.body, label %while.end
+
+while.body:
+  %2 = load ptr, ptr @glob, align 8
+  %call = tail call ptr @Update(ptr %2) #2
+  %sub = add nsw i32 %rp.06, -2
+  %cmp = icmp slt i32 %0, %rp.06
+  br i1 %cmp, label %land.rhs, label %while.end
+
+while.end:
+  ret void
+}
+
+; undefined external to prevent possible optimizations
+declare void @do_something() #1
+
+define i32 @do_nothing_if_resultant_opcodes_would_differ() #0 {
+; ARM-LABEL: do_nothing_if_resultant_opcodes_would_differ:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    push {r4, r5, r11, lr}
+; ARM-NEXT:    movw r4, :lower16:a
+; ARM-NEXT:    movt r4, :upper16:a
+; ARM-NEXT:    ldr r0, [r4]
+; ARM-NEXT:    cmn r0, #2
+; ARM-NEXT:    bgt .LBB7_4
+; ARM-NEXT:  @ %bb.1: @ %while.body.preheader
+; ARM-NEXT:    sub r5, r0, #1
+; ARM-NEXT:  .LBB7_2: @ %while.body
+; ARM-NEXT:    @ =>This Inner Loop Header: Depth=1
+; ARM-NEXT:    bl do_something
+; ARM-NEXT:    adds r5, r5, #1
+; ARM-NEXT:    bmi .LBB7_2
+; ARM-NEXT:  @ %bb.3: @ %while.cond.while.end_crit_edge
+; ARM-NEXT:    ldr r0, [r4]
+; ARM-NEXT:  .LBB7_4: @ %while.end
+; ARM-NEXT:    cmp r0, #1
+; ARM-NEXT:    bgt .LBB7_6
+; ARM-NEXT:  @ %bb.5: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #123
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    pop {r4, r5, r11, pc}
+; ARM-NEXT:  .LBB7_6: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    pop {r4, r5, r11, pc}
+;
+; THUMB-LABEL: do_nothing_if_resultant_opcodes_would_differ:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    push {r4, r5, r7, lr}
+; THUMB-NEXT:    ldr r4, .LCPI7_0
+; THUMB-NEXT:    ldr r0, [r4]
+; THUMB-NEXT:    movs r1, #1
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    bgt .LBB7_4
+; THUMB-NEXT:  @ %bb.1: @ %while.body.preheader
+; THUMB-NEXT:    subs r5, r0, #1
+; THUMB-NEXT:  .LBB7_2: @ %while.body
+; THUMB-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMB-NEXT:    bl do_something
+; THUMB-NEXT:    adds r5, r5, #1
+; THUMB-NEXT:    bmi .LBB7_2
+; THUMB-NEXT:  @ %bb.3: @ %while.cond.while.end_crit_edge
+; THUMB-NEXT:    ldr r0, [r4]
+; THUMB-NEXT:  .LBB7_4: @ %while.end
+; THUMB-NEXT:    cmp r0, #1
+; THUMB-NEXT:    bgt .LBB7_7
+; THUMB-NEXT:  @ %bb.5: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI7_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI7_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB7_7
+; THUMB-NEXT:  @ %bb.6:
+; THUMB-NEXT:    movs r0, #123
+; THUMB-NEXT:    pop {r4, r5, r7, pc}
+; THUMB-NEXT:  .LBB7_7: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    pop {r4, r5, r7, pc}
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.8:
+; THUMB-NEXT:  .LCPI7_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI7_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI7_2:
+; THUMB-NEXT:    .long b
+;
+; THUMB2-LABEL: do_nothing_if_resultant_opcodes_would_differ:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    push {r4, r5, r7, lr}
+; THUMB2-NEXT:    movw r4, :lower16:a
+; THUMB2-NEXT:    movt r4, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r4]
+; THUMB2-NEXT:    cmn.w r0, #2
+; THUMB2-NEXT:    bgt .LBB7_4
+; THUMB2-NEXT:  @ %bb.1: @ %while.body.preheader
+; THUMB2-NEXT:    subs r5, r0, #1
+; THUMB2-NEXT:  .LBB7_2: @ %while.body
+; THUMB2-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMB2-NEXT:    bl do_something
+; THUMB2-NEXT:    adds r5, #1
+; THUMB2-NEXT:    bmi .LBB7_2
+; THUMB2-NEXT:  @ %bb.3: @ %while.cond.while.end_crit_edge
+; THUMB2-NEXT:    ldr r0, [r4]
+; THUMB2-NEXT:  .LBB7_4: @ %while.end
+; THUMB2-NEXT:    cmp r0, #1
+; THUMB2-NEXT:    bgt .LBB7_7
+; THUMB2-NEXT:  @ %bb.5: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    bne .LBB7_7
+; THUMB2-NEXT:  @ %bb.6:
+; THUMB2-NEXT:    movs r0, #123
+; THUMB2-NEXT:    pop {r4, r5, r7, pc}
+; THUMB2-NEXT:  .LBB7_7: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    pop {r4, r5, r7, pc}
+;
+; THUMBV8-LABEL: do_nothing_if_resultant_opcodes_would_differ:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    push {r4, r5, r7, lr}
+; THUMBV8-NEXT:    movw r4, :lower16:a
+; THUMBV8-NEXT:    movt r4, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r4]
+; THUMBV8-NEXT:    cmn.w r0, #2
+; THUMBV8-NEXT:    bgt .LBB7_4
+; THUMBV8-NEXT:  @ %bb.1: @ %while.body.preheader
+; THUMBV8-NEXT:    subs r5, r0, #1
+; THUMBV8-NEXT:  .LBB7_2: @ %while.body
+; THUMBV8-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMBV8-NEXT:    bl do_something
+; THUMBV8-NEXT:    adds r5, #1
+; THUMBV8-NEXT:    bmi .LBB7_2
+; THUMBV8-NEXT:  @ %bb.3: @ %while.cond.while.end_crit_edge
+; THUMBV8-NEXT:    ldr r0, [r4]
+; THUMBV8-NEXT:  .LBB7_4: @ %while.end
+; THUMBV8-NEXT:    cmp r0, #1
+; THUMBV8-NEXT:    bgt .LBB7_7
+; THUMBV8-NEXT:  @ %bb.5: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    bne .LBB7_7
+; THUMBV8-NEXT:  @ %bb.6:
+; THUMBV8-NEXT:    movs r0, #123
+; THUMBV8-NEXT:    pop {r4, r5, r7, pc}
+; THUMBV8-NEXT:  .LBB7_7: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    pop {r4, r5, r7, pc}
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp4 = icmp slt i32 %0, -1
+  br i1 %cmp4, label %while.body.preheader, label %while.end
+
+while.body.preheader:                             ; preds = %entry
+  br label %while.body
+
+while.body:                                       ; preds = %while.body, %while.body.preheader
+  %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ]
+  tail call void @do_something() #2
+  %inc = add nsw i32 %i.05, 1
+  %cmp = icmp slt i32 %i.05, 0
+  br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge
+
+while.cond.while.end_crit_edge:                   ; preds = %while.body
+  %.pre = load i32, ptr @a, align 4
+  br label %while.end
+
+while.end:                                        ; preds = %while.cond.while.end_crit_edge, %entry
+  %1 = phi i32 [ %.pre, %while.cond.while.end_crit_edge ], [ %0, %entry ]
+  %cmp1 = icmp slt i32 %1, 2
+  br i1 %cmp1, label %land.lhs.true, label %if.end
+
+land.lhs.true:                                    ; preds = %while.end
+  %2 = load i32, ptr @b, align 4
+  %3 = load i32, ptr @d, align 4
+  %cmp2 = icmp eq i32 %2, %3
+  br i1 %cmp2, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true, %while.end
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+define i32 @do_nothing_if_compares_can_not_be_adjusted_to_each_other() #0 {
+; ARM-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    push {r4, lr}
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #0
+; ARM-NEXT:    bgt .LBB8_3
+; ARM-NEXT:  @ %bb.1: @ %while.body.preheader
+; ARM-NEXT:    sub r4, r0, #1
+; ARM-NEXT:  .LBB8_2: @ %while.body
+; ARM-NEXT:    @ =>This Inner Loop Header: Depth=1
+; ARM-NEXT:    bl do_something
+; ARM-NEXT:    adds r4, r4, #1
+; ARM-NEXT:    bmi .LBB8_2
+; ARM-NEXT:  .LBB8_3: @ %while.end
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmn r0, #2
+; ARM-NEXT:    blt .LBB8_5
+; ARM-NEXT:  @ %bb.4: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #123
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    pop {r4, pc}
+; ARM-NEXT:  .LBB8_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    pop {r4, pc}
+;
+; THUMB-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    push {r4, lr}
+; THUMB-NEXT:    ldr r0, .LCPI8_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #0
+; THUMB-NEXT:    bgt .LBB8_3
+; THUMB-NEXT:  @ %bb.1: @ %while.body.preheader
+; THUMB-NEXT:    subs r4, r0, #1
+; THUMB-NEXT:  .LBB8_2: @ %while.body
+; THUMB-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMB-NEXT:    bl do_something
+; THUMB-NEXT:    adds r4, r4, #1
+; THUMB-NEXT:    bmi .LBB8_2
+; THUMB-NEXT:  .LBB8_3: @ %while.end
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    mvns r0, r0
+; THUMB-NEXT:    ldr r1, .LCPI8_1
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    blt .LBB8_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI8_2
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI8_3
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB8_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #123
+; THUMB-NEXT:    pop {r4, pc}
+; THUMB-NEXT:  .LBB8_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    pop {r4, pc}
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI8_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI8_1:
+; THUMB-NEXT:    .long c
+; THUMB-NEXT:  .LCPI8_2:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI8_3:
+; THUMB-NEXT:    .long b
+;
+; THUMB2-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    push {r4, lr}
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #0
+; THUMB2-NEXT:    bgt .LBB8_3
+; THUMB2-NEXT:  @ %bb.1: @ %while.body.preheader
+; THUMB2-NEXT:    subs r4, r0, #1
+; THUMB2-NEXT:  .LBB8_2: @ %while.body
+; THUMB2-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMB2-NEXT:    bl do_something
+; THUMB2-NEXT:    adds r4, #1
+; THUMB2-NEXT:    bmi .LBB8_2
+; THUMB2-NEXT:  .LBB8_3: @ %while.end
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmn.w r0, #2
+; THUMB2-NEXT:    blt .LBB8_5
+; THUMB2-NEXT:  @ %bb.4: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #123
+; THUMB2-NEXT:    popeq {r4, pc}
+; THUMB2-NEXT:  .LBB8_5: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    pop {r4, pc}
+;
+; THUMBV8-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    push {r4, lr}
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #0
+; THUMBV8-NEXT:    bgt .LBB8_3
+; THUMBV8-NEXT:  @ %bb.1: @ %while.body.preheader
+; THUMBV8-NEXT:    subs r4, r0, #1
+; THUMBV8-NEXT:  .LBB8_2: @ %while.body
+; THUMBV8-NEXT:    @ =>This Inner Loop Header: Depth=1
+; THUMBV8-NEXT:    bl do_something
+; THUMBV8-NEXT:    adds r4, #1
+; THUMBV8-NEXT:    bmi .LBB8_2
+; THUMBV8-NEXT:  .LBB8_3: @ %while.end
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmn.w r0, #2
+; THUMBV8-NEXT:    blt .LBB8_5
+; THUMBV8-NEXT:  @ %bb.4: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #123
+; THUMBV8-NEXT:    popeq {r4, pc}
+; THUMBV8-NEXT:  .LBB8_5: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    pop {r4, pc}
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp4 = icmp slt i32 %0, 1
+  br i1 %cmp4, label %while.body.preheader, label %while.end
+
+while.body.preheader:                             ; preds = %entry
+  br label %while.body
+
+while.body:                                       ; preds = %while.body, %while.body.preheader
+  %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ]
+  tail call void @do_something() #2
+  %inc = add nsw i32 %i.05, 1
+  %cmp = icmp slt i32 %i.05, 0
+  br i1 %cmp, label %while.body, label %while.end.loopexit
+
+while.end.loopexit:                               ; preds = %while.body
+  br label %while.end
+
+while.end:                                        ; preds = %while.end.loopexit, %entry
+  %1 = load i32, ptr @c, align 4
+  %cmp1 = icmp sgt i32 %1, -3
+  br i1 %cmp1, label %land.lhs.true, label %if.end
+
+land.lhs.true:                                    ; preds = %while.end
+  %2 = load i32, ptr @b, align 4
+  %3 = load i32, ptr @d, align 4
+  %cmp2 = icmp eq i32 %2, %3
+  br i1 %cmp2, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true, %while.end
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+define i32 @combine_gt_ge_sel(i32 %v, ptr %p) #0 {
+; ARM-LABEL: combine_gt_ge_sel:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r2, :lower16:a
+; ARM-NEXT:    movt r2, :upper16:a
+; ARM-NEXT:    ldr r2, [r2]
+; ARM-NEXT:    cmp r2, #0
+; ARM-NEXT:    movle r0, #0
+; ARM-NEXT:    str r0, [r1]
+; ARM-NEXT:    ble .LBB9_3
+; ARM-NEXT:  @ %bb.1: @ %lor.lhs.false
+; ARM-NEXT:    cmp r2, #2
+; ARM-NEXT:    bge .LBB9_4
+; ARM-NEXT:  @ %bb.2: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB9_3: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    bxeq lr
+; ARM-NEXT:  .LBB9_4: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_gt_ge_sel:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r2, .LCPI9_0
+; THUMB-NEXT:    ldr r2, [r2]
+; THUMB-NEXT:    movs r3, #0
+; THUMB-NEXT:    cmp r2, #0
+; THUMB-NEXT:    bgt .LBB9_2
+; THUMB-NEXT:  @ %bb.1: @ %entry
+; THUMB-NEXT:    mov r0, r3
+; THUMB-NEXT:  .LBB9_2: @ %entry
+; THUMB-NEXT:    str r0, [r1]
+; THUMB-NEXT:    ble .LBB9_4
+; THUMB-NEXT:  @ %bb.3: @ %lor.lhs.false
+; THUMB-NEXT:    cmp r2, #2
+; THUMB-NEXT:    bge .LBB9_6
+; THUMB-NEXT:    b .LBB9_8
+; THUMB-NEXT:  .LBB9_4: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI9_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI9_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB9_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB9_6: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI9_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI9_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB9_8
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB9_8: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.9:
+; THUMB-NEXT:  .LCPI9_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI9_1:
+; THUMB-NEXT:    .long c
+; THUMB-NEXT:  .LCPI9_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI9_3:
+; THUMB-NEXT:    .long d
+;
+; THUMB2-LABEL: combine_gt_ge_sel:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r2, :lower16:a
+; THUMB2-NEXT:    movt r2, :upper16:a
+; THUMB2-NEXT:    ldr r2, [r2]
+; THUMB2-NEXT:    cmp r2, #0
+; THUMB2-NEXT:    it le
+; THUMB2-NEXT:    movle r0, #0
+; THUMB2-NEXT:    str r0, [r1]
+; THUMB2-NEXT:    ble .LBB9_2
+; THUMB2-NEXT:  @ %bb.1: @ %lor.lhs.false
+; THUMB2-NEXT:    cmp r2, #2
+; THUMB2-NEXT:    bge .LBB9_3
+; THUMB2-NEXT:    b .LBB9_4
+; THUMB2-NEXT:  .LBB9_2: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB9_3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB9_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_gt_ge_sel:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r2, :lower16:a
+; THUMBV8-NEXT:    movt r2, :upper16:a
+; THUMBV8-NEXT:    ldr r2, [r2]
+; THUMBV8-NEXT:    cmp r2, #0
+; THUMBV8-NEXT:    it le
+; THUMBV8-NEXT:    movle r0, #0
+; THUMBV8-NEXT:    str r0, [r1]
+; THUMBV8-NEXT:    ble .LBB9_2
+; THUMBV8-NEXT:  @ %bb.1: @ %lor.lhs.false
+; THUMBV8-NEXT:    cmp r2, #2
+; THUMBV8-NEXT:    bge .LBB9_3
+; THUMBV8-NEXT:    b .LBB9_4
+; THUMBV8-NEXT:  .LBB9_2: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB9_3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB9_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp sgt i32 %0, 0
+  %m = select i1 %cmp, i32 %v, i32 0
+  store i32 %m, ptr %p
+  br i1 %cmp, label %lor.lhs.false, label %land.lhs.true
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %land.lhs.true3
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp sgt i32 %0, 1
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}

>From c9313aa14ceaec9a5605a4cd5369842c9f84e83a Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Tue, 29 Jul 2025 12:35:00 -0400
Subject: [PATCH 2/2] [ARM] Port ConditionOptimizer to ARM

Following the same principles, we can optimize conditions to make it better for the CSE.
---
 llvm/lib/Target/ARM/ARM.h                     |    2 +
 llvm/lib/Target/ARM/ARMConditionOptimizer.cpp |  514 ++++++
 llvm/lib/Target/ARM/ARMTargetMachine.cpp      |   12 +
 llvm/lib/Target/ARM/CMakeLists.txt            |    1 +
 llvm/test/CodeGen/ARM/O3-pipeline.ll          |    1 +
 .../CodeGen/ARM/combine-comparisons-by-cse.ll | 1565 ++++++++++++++++-
 llvm/test/CodeGen/ARM/fpclamptosat.ll         |   12 +-
 llvm/test/CodeGen/Thumb/smul_fix_sat.ll       |    4 +-
 8 files changed, 2019 insertions(+), 92 deletions(-)
 create mode 100644 llvm/lib/Target/ARM/ARMConditionOptimizer.cpp

diff --git a/llvm/lib/Target/ARM/ARM.h b/llvm/lib/Target/ARM/ARM.h
index 3847f4e966afe..dd5cfb7a8a062 100644
--- a/llvm/lib/Target/ARM/ARM.h
+++ b/llvm/lib/Target/ARM/ARM.h
@@ -35,6 +35,7 @@ Pass *createMVETailPredicationPass();
 FunctionPass *createARMLowOverheadLoopsPass();
 FunctionPass *createARMBlockPlacementPass();
 Pass *createARMParallelDSPPass();
+FunctionPass *createARMConditionOptimizerPass();
 FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM,
                                CodeGenOptLevel OptLevel);
 FunctionPass *createA15SDOptimizerPass();
@@ -64,6 +65,7 @@ void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
 void initializeARMAsmPrinterPass(PassRegistry &);
 void initializeARMBlockPlacementPass(PassRegistry &);
 void initializeARMBranchTargetsPass(PassRegistry &);
+void initializeARMConditionOptimizerPass(PassRegistry &);
 void initializeARMConstantIslandsPass(PassRegistry &);
 void initializeARMDAGToDAGISelLegacyPass(PassRegistry &);
 void initializeARMExpandPseudoPass(PassRegistry &);
diff --git a/llvm/lib/Target/ARM/ARMConditionOptimizer.cpp b/llvm/lib/Target/ARM/ARMConditionOptimizer.cpp
new file mode 100644
index 0000000000000..70d5b06da61a5
--- /dev/null
+++ b/llvm/lib/Target/ARM/ARMConditionOptimizer.cpp
@@ -0,0 +1,514 @@
+//=- ARMConditionOptimizer.cpp - Remove useless comparisons for ARM -=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass tries to make consecutive compares of values use same operands to
+// allow CSE pass to remove duplicated instructions.  For this it analyzes
+// branches and adjusts comparisons with immediate values by converting:
+//  * GE -> GT
+//  * GT -> GE
+//  * LT -> LE
+//  * LE -> LT
+// and adjusting immediate values appropriately.  It basically corrects two
+// immediate values towards each other to make them equal.
+//
+// Consider the following example in C:
+//
+//   if ((a < 5 && ...) || (a > 5 && ...)) {
+//        ~~~~~             ~~~~~
+//          ^                 ^
+//          x                 y
+//
+// Here both "x" and "y" expressions compare "a" with "5".  When "x" evaluates
+// to "false", "y" can just check flags set by the first comparison.  As a
+// result of the canonicalization employed by
+// SelectionDAGBuilder::visitSwitchCase, DAGCombine, and other target-specific
+// code, assembly ends up in the form that is not CSE friendly:
+//
+//     ...
+//     cmp      r8, #4
+//     bgt     .LBB0_3
+//     ...
+//   .LBB0_3:
+//     cmp      r8, #6
+//     blt     .LBB0_6
+//     ...
+//
+// Same assembly after the pass:
+//
+//     ...
+//     cmp      r8, #5
+//     bge     .LBB0_3
+//     ...
+//   .LBB0_3:
+//     cmp      r8, #5     // <-- CSE pass removes this instruction
+//     ble     .LBB0_6
+//     ...
+//
+// Currently only CMP and CMN followed by branches are supported.
+//
+// TODO: maybe deal with predicated instructions
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARM.h"
+#include "ARMSubtarget.h"
+#include "MCTargetDesc/ARMAddressingModes.h"
+#include "Utils/ARMBaseInfo.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdlib>
+#include <tuple>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "arm-condopt"
+
+STATISTIC(NumConditionsAdjusted, "Number of conditions adjusted");
+
+namespace {
+
+class ARMConditionOptimizer : public MachineFunctionPass {
+  const TargetInstrInfo *TII;
+  MachineDominatorTree *DomTree;
+  const MachineRegisterInfo *MRI;
+
+public:
+  // Stores immediate, compare instruction opcode and branch condition (in this
+  // order) of adjusted comparison.
+  using CmpInfo = std::tuple<int, unsigned, ARMCC::CondCodes>;
+
+  static char ID;
+
+  ARMConditionOptimizer() : MachineFunctionPass(ID) {}
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override;
+  MachineInstr *findSuitableCompare(MachineBasicBlock *MBB);
+  CmpInfo adjustCmp(MachineInstr *CmpMI, ARMCC::CondCodes Cmp);
+  void modifyCmp(MachineInstr *CmpMI, const CmpInfo &Info);
+  bool adjustTo(MachineInstr *CmpMI, ARMCC::CondCodes Cmp, MachineInstr *To,
+                int ToImm);
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  StringRef getPassName() const override { return "ARM Condition Optimizer"; }
+};
+
+} // end anonymous namespace
+
+char ARMConditionOptimizer::ID = 0;
+
+INITIALIZE_PASS_BEGIN(ARMConditionOptimizer, "ARM-condopt", "ARM CondOpt Pass",
+                      false, false)
+INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
+INITIALIZE_PASS_END(ARMConditionOptimizer, "ARM-condopt", "ARM CondOpt Pass",
+                    false, false)
+
+FunctionPass *llvm::createARMConditionOptimizerPass() {
+  return new ARMConditionOptimizer();
+}
+
+void ARMConditionOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<MachineDominatorTreeWrapperPass>();
+  AU.addPreserved<MachineDominatorTreeWrapperPass>();
+  MachineFunctionPass::getAnalysisUsage(AU);
+}
+
+// Finds compare instruction that corresponds to supported types of branching.
+// Returns the instruction or nullptr on failures or detecting unsupported
+// instructions.
+MachineInstr *
+ARMConditionOptimizer::findSuitableCompare(MachineBasicBlock *MBB) {
+  MachineBasicBlock::iterator Term = MBB->getFirstTerminator();
+  if (Term == MBB->end())
+    return nullptr;
+
+  // Accept ARM, Thumb, and Thumb2 conditional branches
+  if (Term->getOpcode() != ARM::Bcc && Term->getOpcode() != ARM::tBcc &&
+      Term->getOpcode() != ARM::t2Bcc)
+    return nullptr;
+
+  // Since we may modify cmp of this MBB, make sure NZCV does not live out.
+  for (auto *SuccBB : MBB->successors())
+    if (SuccBB->isLiveIn(ARM::CPSR))
+      return nullptr;
+
+  // Now find the instruction controlling the terminator.
+  for (MachineBasicBlock::iterator B = MBB->begin(), It = Term; It != B;) {
+    It = prev_nodbg(It, B);
+    MachineInstr &I = *It;
+    assert(!I.isTerminator() && "Spurious terminator");
+    // Check if there is any use of CPSR between CMP and Bcc.
+    if (I.readsRegister(ARM::CPSR, /*TRI=*/nullptr))
+      return nullptr;
+    switch (I.getOpcode()) {
+    // Thumb-1, Thumb-2, and ARM CMP instructions - immediate variants only
+    case ARM::tCMPi8:
+    case ARM::t2CMPri:
+    case ARM::t2CMNri:
+    case ARM::CMPri:
+    case ARM::CMNri:
+      // Only handle unpredicated CMP/CMN instructions
+      // ARM and Thumb2 instructions can be predicated, Thumb-1 cannot.
+      if (I.getOpcode() != ARM::tCMPi8) {
+        int PIdx = I.findFirstPredOperandIdx();
+        if (PIdx != -1 && I.getOperand(PIdx).getImm() != (int64_t)ARMCC::AL) {
+          LLVM_DEBUG(dbgs()
+                     << "Skipping predicated instruction: " << I << '\n');
+          return nullptr;
+        }
+      }
+
+      // Check that the immediate operand is valid
+      if (!I.getOperand(1).isImm()) {
+        LLVM_DEBUG(dbgs() << "Immediate of cmp/cmn is symbolic, " << I << '\n');
+        return nullptr;
+      }
+      return &I;
+    default:
+      if (I.modifiesRegister(ARM::CPSR, /*TRI=*/nullptr))
+        return nullptr;
+    }
+  }
+  LLVM_DEBUG(dbgs() << "Flags not defined in " << printMBBReference(*MBB)
+                    << '\n');
+  return nullptr;
+}
+
+// Changes opcode cmp <-> cmn considering register operand width.
+static int getComplementOpc(int Opc) {
+  switch (Opc) {
+  // ARM CMN/CMP immediate instructions
+  case ARM::CMNri:
+    return ARM::CMPri;
+  case ARM::CMPri:
+    return ARM::CMNri;
+  // Thumb CMP immediate instructions - NOTE: Thumb1 doesn't have CMN!
+  case ARM::tCMPi8:
+    return ARM::INSTRUCTION_LIST_END; // No complement for Thumb1
+  // Thumb2 CMN/CMP immediate instructions
+  case ARM::t2CMPri:
+    return ARM::t2CMNri;
+  case ARM::t2CMNri:
+    return ARM::t2CMPri;
+  default:
+    llvm_unreachable("Unexpected opcode");
+  }
+}
+
+// Changes form of comparison inclusive <-> exclusive.
+static ARMCC::CondCodes getAdjustedCmp(ARMCC::CondCodes Cmp) {
+  switch (Cmp) {
+  case ARMCC::GT:
+    return ARMCC::GE;
+  case ARMCC::GE:
+    return ARMCC::GT;
+  case ARMCC::LT:
+    return ARMCC::LE;
+  case ARMCC::LE:
+    return ARMCC::LT;
+  case ARMCC::HI:
+    return ARMCC::HS;
+  case ARMCC::HS:
+    return ARMCC::HI;
+  case ARMCC::LO:
+    return ARMCC::LS;
+  case ARMCC::LS:
+    return ARMCC::LO;
+  default:
+    llvm_unreachable("Unexpected condition code");
+  }
+}
+
+// Transforms GT -> GE, GE -> GT, LT -> LE, LE -> LT by updating comparison
+// operator and condition code.
+ARMConditionOptimizer::CmpInfo
+ARMConditionOptimizer::adjustCmp(MachineInstr *CmpMI, ARMCC::CondCodes Cmp) {
+  unsigned Opc = CmpMI->getOpcode();
+  unsigned OldOpc = Opc;
+
+  bool IsSigned = Cmp == ARMCC::GT || Cmp == ARMCC::GE || Cmp == ARMCC::LT ||
+                  Cmp == ARMCC::LE;
+
+  // CMN (compare with negative immediate) is an alias to ADDS (as
+  // "operand - negative" == "operand + positive")
+  bool Negative = (Opc == ARM::CMNri || Opc == ARM::t2CMNri);
+
+  int Correction = (Cmp == ARMCC::GT || Cmp == ARMCC::HI) ? 1 : -1;
+  // Negate Correction value for comparison with negative immediate (CMN).
+  if (Negative) {
+    Correction = -Correction;
+  }
+
+  const int OldImm = (int)CmpMI->getOperand(1).getImm();
+  const int NewImm = std::abs(OldImm + Correction);
+
+  // Handle cmn 1 -> cmp 0, transitions by adjusting compare instruction opcode.
+  if (OldImm == 1 && Negative && Correction == -1) {
+    // If we are adjusting from -1 to 0, we need to change the opcode.
+    Opc = getComplementOpc(Opc);
+  }
+
+  // Handle +0 -> -1 transitions by adjusting compare instruction opcode.
+  if (OldImm == 0 && Correction == -1) {
+    Opc = getComplementOpc(Opc);
+  }
+
+  // If we change opcodes, this means we did an unsigned wrap, so return the old
+  // cmp for unsigned comparisons.
+
+  // If we have an invalid value, return the old cmp
+  if (Opc == ARM::INSTRUCTION_LIST_END || (!IsSigned && Opc != OldOpc))
+    return CmpInfo(OldImm, OldOpc, Cmp);
+
+  return CmpInfo(NewImm, Opc, getAdjustedCmp(Cmp));
+}
+
+// Applies changes to comparison instruction suggested by adjustCmp().
+void ARMConditionOptimizer::modifyCmp(MachineInstr *CmpMI,
+                                      const CmpInfo &Info) {
+  int Imm;
+  unsigned Opc;
+  ARMCC::CondCodes Cmp;
+  std::tie(Imm, Opc, Cmp) = Info;
+  if (Imm == 0) {
+    if (Cmp == ARMCC::GE)
+      Cmp = ARMCC::PL;
+    if (Cmp == ARMCC::LT)
+      Cmp = ARMCC::MI;
+  }
+
+  MachineBasicBlock *const MBB = CmpMI->getParent();
+
+  // Build the new instruction with the correct format for the target opcode.
+  MachineInstrBuilder MIB = BuildMI(*MBB, CmpMI, CmpMI->getDebugLoc(),
+                                    TII->get(Opc))
+                                .add(CmpMI->getOperand(0)) // Rn
+                                .addImm(Imm);              // Immediate
+
+  // Add predicate operands for all CMP/CMN instructions.
+  // Even Thumb-1 CMP instructions have predicate operands.
+  MIB.add(predOps(ARMCC::AL));
+
+  CmpMI->eraseFromParent();
+
+  // The fact that this comparison was picked ensures that it's related to the
+  // first terminator instruction.
+  MachineInstr &BrMI = *MBB->getFirstTerminator();
+
+  // Change condition in branch instruction.
+  // Rebuild the branch instruction correctly for all subtargets.
+  unsigned BranchOpc = BrMI.getOpcode();
+  MachineInstrBuilder BranchMIB =
+      BuildMI(*MBB, BrMI, BrMI.getDebugLoc(), TII->get(BranchOpc))
+          .add(BrMI.getOperand(0)); // Target MBB
+
+  // Add the new condition code.
+  BranchMIB.addImm(Cmp);
+
+  // Add the predicate register operand for all branch types.
+  // All ARM/Thumb/Thumb2 conditional branches need this.
+  BranchMIB.add(BrMI.getOperand(2));
+
+  BrMI.eraseFromParent();
+
+  ++NumConditionsAdjusted;
+}
+
+// Parse a condition code returned by analyzeBranch, and compute the CondCode
+// corresponding to TBB.
+// Returns true if parsing was successful, otherwise false is returned.
+static bool parseCond(ArrayRef<MachineOperand> Cond, ARMCC::CondCodes &CC) {
+  // A normal br.cond simply has the condition code (size == 2 for ARM/Thumb)
+  if (Cond.size() == 2 && Cond[0].isImm()) {
+    CC = (ARMCC::CondCodes)(int)Cond[0].getImm();
+    return true;
+  }
+  return false;
+}
+
+// Adjusts one cmp instruction to another one if result of adjustment will allow
+// CSE.  Returns true if compare instruction was changed, otherwise false is
+// returned.
+bool ARMConditionOptimizer::adjustTo(MachineInstr *CmpMI, ARMCC::CondCodes Cmp,
+                                     MachineInstr *To, int ToImm) {
+  CmpInfo Info = adjustCmp(CmpMI, Cmp);
+  if (std::get<0>(Info) == ToImm && std::get<1>(Info) == To->getOpcode()) {
+    modifyCmp(CmpMI, Info);
+    return true;
+  }
+  return false;
+}
+
+static bool isGreaterThan(ARMCC::CondCodes Cmp) {
+  return Cmp == ARMCC::GT || Cmp == ARMCC::HI;
+}
+
+static bool isLessThan(ARMCC::CondCodes Cmp) {
+  return Cmp == ARMCC::LT || Cmp == ARMCC::LO;
+}
+
+bool ARMConditionOptimizer::runOnMachineFunction(MachineFunction &MF) {
+  LLVM_DEBUG(dbgs() << "********** ARM Conditional Compares **********\n"
+                    << "********** Function: " << MF.getName() << '\n');
+  if (skipFunction(MF.getFunction()))
+    return false;
+
+  TII = MF.getSubtarget<ARMSubtarget>().getInstrInfo();
+  DomTree = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
+  MRI = &MF.getRegInfo();
+
+  bool Changed = false;
+
+  // Visit blocks in dominator tree pre-order. The pre-order enables multiple
+  // cmp-conversions from the same head block.
+  // Note that updateDomTree() modifies the children of the DomTree node
+  // currently being visited. The df_iterator supports that; it doesn't look at
+  // child_begin() / child_end() until after a node has been visited.
+  for (MachineDomTreeNode *I : depth_first(DomTree)) {
+    MachineBasicBlock *HBB = I->getBlock();
+
+    SmallVector<MachineOperand, 4> HeadCond;
+    MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
+    if (TII->analyzeBranch(*HBB, TBB, FBB, HeadCond)) {
+      continue;
+    }
+
+    // Equivalence check is to skip loops.
+    if (!TBB || TBB == HBB) {
+      continue;
+    }
+
+    SmallVector<MachineOperand, 4> TrueCond;
+    MachineBasicBlock *TBB_TBB = nullptr, *TBB_FBB = nullptr;
+    if (TII->analyzeBranch(*TBB, TBB_TBB, TBB_FBB, TrueCond)) {
+      continue;
+    }
+
+    MachineInstr *HeadCmpMI = findSuitableCompare(HBB);
+    if (!HeadCmpMI) {
+      continue;
+    }
+
+    ARMCC::CondCodes HeadCmp;
+    if (HeadCond.empty() || !parseCond(HeadCond, HeadCmp)) {
+      continue;
+    }
+
+    ARMCC::CondCodes TrueCmp;
+    if (TrueCond.empty() || !parseCond(TrueCond, TrueCmp)) {
+      continue;
+    }
+
+    const int HeadImm = (int)HeadCmpMI->getOperand(1).getImm();
+
+    // Convert PL/MI to GE/LT for comparisons with 0.
+    if (HeadImm == 0) {
+      if (HeadCmp == ARMCC::PL)
+        HeadCmp = ARMCC::GE;
+      if (HeadCmp == ARMCC::MI)
+        HeadCmp = ARMCC::LT;
+    }
+
+    int HeadImmTrueValue = HeadImm;
+
+    unsigned HeadOpc = HeadCmpMI->getOpcode();
+    if (HeadOpc == ARM::CMNri || HeadOpc == ARM::t2CMNri)
+      HeadImmTrueValue = -HeadImmTrueValue;
+
+    // Try to find a suitable compare in TBB, but don't require it yet
+    MachineInstr *TrueCmpMI = findSuitableCompare(TBB);
+
+    // If we have a suitable compare in TBB, try the optimization
+    if (TrueCmpMI) {
+      const int TrueImm = (int)TrueCmpMI->getOperand(1).getImm();
+
+      // Special Case 0.
+      if (TrueImm == 0) {
+        if (TrueCmp == ARMCC::PL)
+          TrueCmp = ARMCC::GE;
+        if (TrueCmp == ARMCC::MI)
+          TrueCmp = ARMCC::LT;
+      }
+
+      int TrueImmTrueValue = TrueImm;
+
+      unsigned TrueOpc = TrueCmpMI->getOpcode();
+      if (TrueOpc == ARM::CMNri || TrueOpc == ARM::t2CMNri)
+        TrueImmTrueValue = -TrueImmTrueValue;
+
+      if (((isGreaterThan(HeadCmp) && isLessThan(TrueCmp)) ||
+           (isLessThan(HeadCmp) && isGreaterThan(TrueCmp))) &&
+          std::abs(TrueImmTrueValue - HeadImmTrueValue) == 2) {
+        // This branch transforms machine instructions that correspond to
+        //
+        // 1) (a > {TrueImm} && ...) || (a < {HeadImm} && ...)
+        // 2) (a < {TrueImm} && ...) || (a > {HeadImm} && ...)
+        //
+        // into
+        //
+        // 1) (a >= {NewImm} && ...) || (a <= {NewImm} && ...)
+        // 2) (a <= {NewImm} && ...) || (a >= {NewImm} && ...)
+
+        CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);
+        CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);
+        if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&
+            std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {
+          modifyCmp(HeadCmpMI, HeadCmpInfo);
+          modifyCmp(TrueCmpMI, TrueCmpInfo);
+          Changed = true;
+        }
+      } else if (((isGreaterThan(HeadCmp) && isGreaterThan(TrueCmp)) ||
+                  (isLessThan(HeadCmp) && isLessThan(TrueCmp))) &&
+                 std::abs(TrueImmTrueValue - HeadImmTrueValue) == 1) {
+        // This branch transforms machine instructions that correspond to
+        //
+        // 1) (a > {TrueImm} && ...) || (a > {HeadImm} && ...)
+        // 2) (a < {TrueImm} && ...) || (a < {HeadImm} && ...)
+        //
+        // into
+        //
+        // 1) (a <= {NewImm} && ...) || (a >  {NewImm} && ...)
+        // 2) (a <  {NewImm} && ...) || (a >= {NewImm} && ...)
+
+        // GT -> GE transformation increases immediate value, so picking the
+        // smaller one; LT -> LE decreases immediate value so invert the choice.
+        bool adjustHeadCond = (HeadImmTrueValue < TrueImmTrueValue);
+        if (isLessThan(HeadCmp)) {
+          adjustHeadCond = !adjustHeadCond;
+        }
+
+        if (adjustHeadCond) {
+          Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);
+        } else {
+          Changed |= adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm);
+        }
+      }
+    }
+    // Other transformation cases almost never occur due to generation of < or >
+    // comparisons instead of <= and >=.
+  }
+
+  return Changed;
+}
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index e8d0d35080775..4f817db555c98 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -79,6 +79,11 @@ static cl::opt<cl::boolOrDefault>
 EnableGlobalMerge("arm-global-merge", cl::Hidden,
                   cl::desc("Enable the global merge pass"));
 
+static cl::opt<bool>
+    EnableCondOpt("arm-enable-condopt",
+                  cl::desc("Enable the condition optimizer pass"),
+                  cl::init(true), cl::Hidden);
+
 namespace llvm {
   void initializeARMExecutionDomainFixPass(PassRegistry&);
 }
@@ -360,6 +365,7 @@ class ARMPassConfig : public TargetPassConfig {
   void addIRPasses() override;
   void addCodeGenPrepare() override;
   bool addPreISel() override;
+  bool addILPOpts() override;
   bool addInstSelector() override;
   bool addIRTranslator() override;
   bool addLegalizeMachineIR() override;
@@ -484,6 +490,12 @@ bool ARMPassConfig::addPreISel() {
   return false;
 }
 
+bool ARMPassConfig::addILPOpts() {
+  if (EnableCondOpt)
+    addPass(createARMConditionOptimizerPass());
+  return false;
+}
+
 bool ARMPassConfig::addInstSelector() {
   addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
   return false;
diff --git a/llvm/lib/Target/ARM/CMakeLists.txt b/llvm/lib/Target/ARM/CMakeLists.txt
index a39629bd8aeb0..9e5e15610eb1c 100644
--- a/llvm/lib/Target/ARM/CMakeLists.txt
+++ b/llvm/lib/Target/ARM/CMakeLists.txt
@@ -28,6 +28,7 @@ add_llvm_target(ARMCodeGen
   ARMBranchTargets.cpp
   ARMCallingConv.cpp
   ARMCallLowering.cpp
+  ARMConditionOptimizer.cpp
   ARMConstantIslandPass.cpp
   ARMConstantPoolValue.cpp
   ARMExpandPseudoInsts.cpp
diff --git a/llvm/test/CodeGen/ARM/O3-pipeline.ll b/llvm/test/CodeGen/ARM/O3-pipeline.ll
index 960d7305e66f6..bbef0b9da9d67 100644
--- a/llvm/test/CodeGen/ARM/O3-pipeline.ll
+++ b/llvm/test/CodeGen/ARM/O3-pipeline.ll
@@ -92,6 +92,7 @@
 ; CHECK-NEXT:      Local Stack Slot Allocation
 ; CHECK-NEXT:      Remove dead machine instructions
 ; CHECK-NEXT:      MachineDominator Tree Construction
+; CHECK-NEXT:      ARM Condition Optimizer 
 ; CHECK-NEXT:      Machine Natural Loop Construction
 ; CHECK-NEXT:      Machine Block Frequency Analysis
 ; CHECK-NEXT:      Early Machine Loop Invariant Code Motion
diff --git a/llvm/test/CodeGen/ARM/combine-comparisons-by-cse.ll b/llvm/test/CodeGen/ARM/combine-comparisons-by-cse.ll
index f53286fcedd3d..b97b0bd0a7eef 100644
--- a/llvm/test/CodeGen/ARM/combine-comparisons-by-cse.ll
+++ b/llvm/test/CodeGen/ARM/combine-comparisons-by-cse.ll
@@ -19,8 +19,8 @@ define i32 @combine_gt_ge_10() #0 {
 ; ARM-NEXT:    movt r0, :upper16:a
 ; ARM-NEXT:    movt r1, :upper16:b
 ; ARM-NEXT:    ldr r0, [r0]
-; ARM-NEXT:    cmp r0, #11
-; ARM-NEXT:    blt .LBB0_2
+; ARM-NEXT:    cmp r0, #10
+; ARM-NEXT:    ble .LBB0_2
 ; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
 ; ARM-NEXT:    movw r0, :lower16:c
 ; ARM-NEXT:    ldr r3, [r1]
@@ -31,7 +31,6 @@ define i32 @combine_gt_ge_10() #0 {
 ; ARM-NEXT:    bxeq lr
 ; ARM-NEXT:    b .LBB0_3
 ; ARM-NEXT:  .LBB0_2: @ %lor.lhs.false
-; ARM-NEXT:    cmp r0, #10
 ; ARM-NEXT:    blt .LBB0_4
 ; ARM-NEXT:  .LBB0_3: @ %land.lhs.true3
 ; ARM-NEXT:    movw r0, :lower16:d
@@ -50,8 +49,8 @@ define i32 @combine_gt_ge_10() #0 {
 ; THUMB:       @ %bb.0: @ %entry
 ; THUMB-NEXT:    ldr r0, .LCPI0_0
 ; THUMB-NEXT:    ldr r0, [r0]
-; THUMB-NEXT:    cmp r0, #11
-; THUMB-NEXT:    blt .LBB0_3
+; THUMB-NEXT:    cmp r0, #10
+; THUMB-NEXT:    ble .LBB0_3
 ; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB-NEXT:    ldr r0, .LCPI0_1
 ; THUMB-NEXT:    ldr r0, [r0]
@@ -63,7 +62,6 @@ define i32 @combine_gt_ge_10() #0 {
 ; THUMB-NEXT:    movs r0, #1
 ; THUMB-NEXT:    bx lr
 ; THUMB-NEXT:  .LBB0_3: @ %lor.lhs.false
-; THUMB-NEXT:    cmp r0, #10
 ; THUMB-NEXT:    blt .LBB0_6
 ; THUMB-NEXT:  .LBB0_4: @ %land.lhs.true3
 ; THUMB-NEXT:    ldr r0, .LCPI0_3
@@ -93,11 +91,11 @@ define i32 @combine_gt_ge_10() #0 {
 ; THUMB2:       @ %bb.0: @ %entry
 ; THUMB2-NEXT:    movw r0, :lower16:a
 ; THUMB2-NEXT:    movt r0, :upper16:a
-; THUMB2-NEXT:    ldr r1, [r0]
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #10
 ; THUMB2-NEXT:    movw r0, :lower16:b
 ; THUMB2-NEXT:    movt r0, :upper16:b
-; THUMB2-NEXT:    cmp r1, #11
-; THUMB2-NEXT:    blt .LBB0_2
+; THUMB2-NEXT:    ble .LBB0_2
 ; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB2-NEXT:    movw r1, :lower16:c
 ; THUMB2-NEXT:    ldr r2, [r0]
@@ -109,7 +107,6 @@ define i32 @combine_gt_ge_10() #0 {
 ; THUMB2-NEXT:    bxeq lr
 ; THUMB2-NEXT:    b .LBB0_3
 ; THUMB2-NEXT:  .LBB0_2: @ %lor.lhs.false
-; THUMB2-NEXT:    cmp r1, #10
 ; THUMB2-NEXT:    blt .LBB0_4
 ; THUMB2-NEXT:  .LBB0_3: @ %land.lhs.true3
 ; THUMB2-NEXT:    movw r1, :lower16:d
@@ -128,11 +125,11 @@ define i32 @combine_gt_ge_10() #0 {
 ; THUMBV8:       @ %bb.0: @ %entry
 ; THUMBV8-NEXT:    movw r0, :lower16:a
 ; THUMBV8-NEXT:    movt r0, :upper16:a
-; THUMBV8-NEXT:    ldr r1, [r0]
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #10
 ; THUMBV8-NEXT:    movw r0, :lower16:b
 ; THUMBV8-NEXT:    movt r0, :upper16:b
-; THUMBV8-NEXT:    cmp r1, #11
-; THUMBV8-NEXT:    blt .LBB0_2
+; THUMBV8-NEXT:    ble .LBB0_2
 ; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMBV8-NEXT:    movw r1, :lower16:c
 ; THUMBV8-NEXT:    ldr r2, [r0]
@@ -144,7 +141,6 @@ define i32 @combine_gt_ge_10() #0 {
 ; THUMBV8-NEXT:    bxeq lr
 ; THUMBV8-NEXT:    b .LBB0_3
 ; THUMBV8-NEXT:  .LBB0_2: @ %lor.lhs.false
-; THUMBV8-NEXT:    cmp r1, #10
 ; THUMBV8-NEXT:    blt .LBB0_4
 ; THUMBV8-NEXT:  .LBB0_3: @ %land.lhs.true3
 ; THUMBV8-NEXT:    movw r1, :lower16:d
@@ -194,15 +190,14 @@ define i32 @combine_gt_lt_5() #0 {
 ; ARM-NEXT:    movw r0, :lower16:a
 ; ARM-NEXT:    movt r0, :upper16:a
 ; ARM-NEXT:    ldr r0, [r0]
-; ARM-NEXT:    cmp r0, #6
-; ARM-NEXT:    blt .LBB1_2
+; ARM-NEXT:    cmp r0, #5
+; ARM-NEXT:    ble .LBB1_2
 ; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
 ; ARM-NEXT:    movw r0, :lower16:c
 ; ARM-NEXT:    movt r0, :upper16:c
 ; ARM-NEXT:    b .LBB1_4
 ; ARM-NEXT:  .LBB1_2: @ %lor.lhs.false
-; ARM-NEXT:    cmp r0, #4
-; ARM-NEXT:    bgt .LBB1_5
+; ARM-NEXT:    bge .LBB1_5
 ; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; ARM-NEXT:    movw r0, :lower16:d
 ; ARM-NEXT:    movt r0, :upper16:d
@@ -223,8 +218,8 @@ define i32 @combine_gt_lt_5() #0 {
 ; THUMB:       @ %bb.0: @ %entry
 ; THUMB-NEXT:    ldr r0, .LCPI1_0
 ; THUMB-NEXT:    ldr r0, [r0]
-; THUMB-NEXT:    cmp r0, #6
-; THUMB-NEXT:    blt .LBB1_3
+; THUMB-NEXT:    cmp r0, #5
+; THUMB-NEXT:    ble .LBB1_3
 ; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB-NEXT:    ldr r0, .LCPI1_3
 ; THUMB-NEXT:    ldr r0, [r0]
@@ -236,8 +231,7 @@ define i32 @combine_gt_lt_5() #0 {
 ; THUMB-NEXT:    movs r0, #1
 ; THUMB-NEXT:    bx lr
 ; THUMB-NEXT:  .LBB1_3: @ %lor.lhs.false
-; THUMB-NEXT:    cmp r0, #4
-; THUMB-NEXT:    bgt .LBB1_6
+; THUMB-NEXT:    bge .LBB1_6
 ; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
 ; THUMB-NEXT:    ldr r0, .LCPI1_1
 ; THUMB-NEXT:    ldr r0, [r0]
@@ -267,8 +261,8 @@ define i32 @combine_gt_lt_5() #0 {
 ; THUMB2-NEXT:    movw r0, :lower16:a
 ; THUMB2-NEXT:    movt r0, :upper16:a
 ; THUMB2-NEXT:    ldr r0, [r0]
-; THUMB2-NEXT:    cmp r0, #6
-; THUMB2-NEXT:    blt .LBB1_2
+; THUMB2-NEXT:    cmp r0, #5
+; THUMB2-NEXT:    ble .LBB1_2
 ; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB2-NEXT:    movw r0, :lower16:c
 ; THUMB2-NEXT:    movw r1, :lower16:b
@@ -282,8 +276,7 @@ define i32 @combine_gt_lt_5() #0 {
 ; THUMB2-NEXT:    bxeq lr
 ; THUMB2-NEXT:    b .LBB1_4
 ; THUMB2-NEXT:  .LBB1_2: @ %lor.lhs.false
-; THUMB2-NEXT:    cmp r0, #4
-; THUMB2-NEXT:    bgt .LBB1_4
+; THUMB2-NEXT:    bge .LBB1_4
 ; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; THUMB2-NEXT:    movw r0, :lower16:d
 ; THUMB2-NEXT:    movw r1, :lower16:b
@@ -304,8 +297,8 @@ define i32 @combine_gt_lt_5() #0 {
 ; THUMBV8-NEXT:    movw r0, :lower16:a
 ; THUMBV8-NEXT:    movt r0, :upper16:a
 ; THUMBV8-NEXT:    ldr r0, [r0]
-; THUMBV8-NEXT:    cmp r0, #6
-; THUMBV8-NEXT:    blt .LBB1_2
+; THUMBV8-NEXT:    cmp r0, #5
+; THUMBV8-NEXT:    ble .LBB1_2
 ; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMBV8-NEXT:    movw r0, :lower16:c
 ; THUMBV8-NEXT:    movw r1, :lower16:b
@@ -319,8 +312,7 @@ define i32 @combine_gt_lt_5() #0 {
 ; THUMBV8-NEXT:    bxeq lr
 ; THUMBV8-NEXT:    b .LBB1_4
 ; THUMBV8-NEXT:  .LBB1_2: @ %lor.lhs.false
-; THUMBV8-NEXT:    cmp r0, #4
-; THUMBV8-NEXT:    bgt .LBB1_4
+; THUMBV8-NEXT:    bge .LBB1_4
 ; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; THUMBV8-NEXT:    movw r0, :lower16:d
 ; THUMBV8-NEXT:    movw r1, :lower16:b
@@ -373,8 +365,8 @@ define i32 @combine_lt_ge_5() #0 {
 ; ARM-NEXT:    movt r0, :upper16:a
 ; ARM-NEXT:    movt r1, :upper16:b
 ; ARM-NEXT:    ldr r0, [r0]
-; ARM-NEXT:    cmp r0, #4
-; ARM-NEXT:    bgt .LBB2_2
+; ARM-NEXT:    cmp r0, #5
+; ARM-NEXT:    bge .LBB2_2
 ; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
 ; ARM-NEXT:    movw r0, :lower16:c
 ; ARM-NEXT:    ldr r3, [r1]
@@ -385,7 +377,6 @@ define i32 @combine_lt_ge_5() #0 {
 ; ARM-NEXT:    bxeq lr
 ; ARM-NEXT:    b .LBB2_3
 ; ARM-NEXT:  .LBB2_2: @ %lor.lhs.false
-; ARM-NEXT:    cmp r0, #5
 ; ARM-NEXT:    bgt .LBB2_4
 ; ARM-NEXT:  .LBB2_3: @ %land.lhs.true3
 ; ARM-NEXT:    movw r0, :lower16:d
@@ -404,8 +395,8 @@ define i32 @combine_lt_ge_5() #0 {
 ; THUMB:       @ %bb.0: @ %entry
 ; THUMB-NEXT:    ldr r0, .LCPI2_0
 ; THUMB-NEXT:    ldr r0, [r0]
-; THUMB-NEXT:    cmp r0, #4
-; THUMB-NEXT:    bgt .LBB2_3
+; THUMB-NEXT:    cmp r0, #5
+; THUMB-NEXT:    bge .LBB2_3
 ; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB-NEXT:    ldr r0, .LCPI2_1
 ; THUMB-NEXT:    ldr r0, [r0]
@@ -417,7 +408,6 @@ define i32 @combine_lt_ge_5() #0 {
 ; THUMB-NEXT:    movs r0, #1
 ; THUMB-NEXT:    bx lr
 ; THUMB-NEXT:  .LBB2_3: @ %lor.lhs.false
-; THUMB-NEXT:    cmp r0, #5
 ; THUMB-NEXT:    bgt .LBB2_6
 ; THUMB-NEXT:  .LBB2_4: @ %land.lhs.true3
 ; THUMB-NEXT:    ldr r0, .LCPI2_3
@@ -447,11 +437,11 @@ define i32 @combine_lt_ge_5() #0 {
 ; THUMB2:       @ %bb.0: @ %entry
 ; THUMB2-NEXT:    movw r0, :lower16:a
 ; THUMB2-NEXT:    movt r0, :upper16:a
-; THUMB2-NEXT:    ldr r1, [r0]
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #5
 ; THUMB2-NEXT:    movw r0, :lower16:b
 ; THUMB2-NEXT:    movt r0, :upper16:b
-; THUMB2-NEXT:    cmp r1, #4
-; THUMB2-NEXT:    bgt .LBB2_2
+; THUMB2-NEXT:    bge .LBB2_2
 ; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB2-NEXT:    movw r1, :lower16:c
 ; THUMB2-NEXT:    ldr r2, [r0]
@@ -463,7 +453,6 @@ define i32 @combine_lt_ge_5() #0 {
 ; THUMB2-NEXT:    bxeq lr
 ; THUMB2-NEXT:    b .LBB2_3
 ; THUMB2-NEXT:  .LBB2_2: @ %lor.lhs.false
-; THUMB2-NEXT:    cmp r1, #5
 ; THUMB2-NEXT:    bgt .LBB2_4
 ; THUMB2-NEXT:  .LBB2_3: @ %land.lhs.true3
 ; THUMB2-NEXT:    movw r1, :lower16:d
@@ -482,11 +471,11 @@ define i32 @combine_lt_ge_5() #0 {
 ; THUMBV8:       @ %bb.0: @ %entry
 ; THUMBV8-NEXT:    movw r0, :lower16:a
 ; THUMBV8-NEXT:    movt r0, :upper16:a
-; THUMBV8-NEXT:    ldr r1, [r0]
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #5
 ; THUMBV8-NEXT:    movw r0, :lower16:b
 ; THUMBV8-NEXT:    movt r0, :upper16:b
-; THUMBV8-NEXT:    cmp r1, #4
-; THUMBV8-NEXT:    bgt .LBB2_2
+; THUMBV8-NEXT:    bge .LBB2_2
 ; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMBV8-NEXT:    movw r1, :lower16:c
 ; THUMBV8-NEXT:    ldr r2, [r0]
@@ -498,7 +487,6 @@ define i32 @combine_lt_ge_5() #0 {
 ; THUMBV8-NEXT:    bxeq lr
 ; THUMBV8-NEXT:    b .LBB2_3
 ; THUMBV8-NEXT:  .LBB2_2: @ %lor.lhs.false
-; THUMBV8-NEXT:    cmp r1, #5
 ; THUMBV8-NEXT:    bgt .LBB2_4
 ; THUMBV8-NEXT:  .LBB2_3: @ %land.lhs.true3
 ; THUMBV8-NEXT:    movw r1, :lower16:d
@@ -548,15 +536,14 @@ define i32 @combine_lt_gt_5() #0 {
 ; ARM-NEXT:    movw r0, :lower16:a
 ; ARM-NEXT:    movt r0, :upper16:a
 ; ARM-NEXT:    ldr r0, [r0]
-; ARM-NEXT:    cmp r0, #4
-; ARM-NEXT:    bgt .LBB3_2
+; ARM-NEXT:    cmp r0, #5
+; ARM-NEXT:    bge .LBB3_2
 ; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
 ; ARM-NEXT:    movw r0, :lower16:c
 ; ARM-NEXT:    movt r0, :upper16:c
 ; ARM-NEXT:    b .LBB3_4
 ; ARM-NEXT:  .LBB3_2: @ %lor.lhs.false
-; ARM-NEXT:    cmp r0, #6
-; ARM-NEXT:    blt .LBB3_5
+; ARM-NEXT:    ble .LBB3_5
 ; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; ARM-NEXT:    movw r0, :lower16:d
 ; ARM-NEXT:    movt r0, :upper16:d
@@ -577,8 +564,8 @@ define i32 @combine_lt_gt_5() #0 {
 ; THUMB:       @ %bb.0: @ %entry
 ; THUMB-NEXT:    ldr r0, .LCPI3_0
 ; THUMB-NEXT:    ldr r0, [r0]
-; THUMB-NEXT:    cmp r0, #4
-; THUMB-NEXT:    bgt .LBB3_3
+; THUMB-NEXT:    cmp r0, #5
+; THUMB-NEXT:    bge .LBB3_3
 ; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB-NEXT:    ldr r0, .LCPI3_3
 ; THUMB-NEXT:    ldr r0, [r0]
@@ -590,8 +577,7 @@ define i32 @combine_lt_gt_5() #0 {
 ; THUMB-NEXT:    movs r0, #1
 ; THUMB-NEXT:    bx lr
 ; THUMB-NEXT:  .LBB3_3: @ %lor.lhs.false
-; THUMB-NEXT:    cmp r0, #6
-; THUMB-NEXT:    blt .LBB3_6
+; THUMB-NEXT:    ble .LBB3_6
 ; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
 ; THUMB-NEXT:    ldr r0, .LCPI3_1
 ; THUMB-NEXT:    ldr r0, [r0]
@@ -621,8 +607,8 @@ define i32 @combine_lt_gt_5() #0 {
 ; THUMB2-NEXT:    movw r0, :lower16:a
 ; THUMB2-NEXT:    movt r0, :upper16:a
 ; THUMB2-NEXT:    ldr r0, [r0]
-; THUMB2-NEXT:    cmp r0, #4
-; THUMB2-NEXT:    bgt .LBB3_2
+; THUMB2-NEXT:    cmp r0, #5
+; THUMB2-NEXT:    bge .LBB3_2
 ; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB2-NEXT:    movw r0, :lower16:c
 ; THUMB2-NEXT:    movw r1, :lower16:b
@@ -636,8 +622,7 @@ define i32 @combine_lt_gt_5() #0 {
 ; THUMB2-NEXT:    bxeq lr
 ; THUMB2-NEXT:    b .LBB3_4
 ; THUMB2-NEXT:  .LBB3_2: @ %lor.lhs.false
-; THUMB2-NEXT:    cmp r0, #6
-; THUMB2-NEXT:    blt .LBB3_4
+; THUMB2-NEXT:    ble .LBB3_4
 ; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; THUMB2-NEXT:    movw r0, :lower16:d
 ; THUMB2-NEXT:    movw r1, :lower16:b
@@ -658,8 +643,8 @@ define i32 @combine_lt_gt_5() #0 {
 ; THUMBV8-NEXT:    movw r0, :lower16:a
 ; THUMBV8-NEXT:    movt r0, :upper16:a
 ; THUMBV8-NEXT:    ldr r0, [r0]
-; THUMBV8-NEXT:    cmp r0, #4
-; THUMBV8-NEXT:    bgt .LBB3_2
+; THUMBV8-NEXT:    cmp r0, #5
+; THUMBV8-NEXT:    bge .LBB3_2
 ; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMBV8-NEXT:    movw r0, :lower16:c
 ; THUMBV8-NEXT:    movw r1, :lower16:b
@@ -673,8 +658,7 @@ define i32 @combine_lt_gt_5() #0 {
 ; THUMBV8-NEXT:    bxeq lr
 ; THUMBV8-NEXT:    b .LBB3_4
 ; THUMBV8-NEXT:  .LBB3_2: @ %lor.lhs.false
-; THUMBV8-NEXT:    cmp r0, #6
-; THUMBV8-NEXT:    blt .LBB3_4
+; THUMBV8-NEXT:    ble .LBB3_4
 ; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; THUMBV8-NEXT:    movw r0, :lower16:d
 ; THUMBV8-NEXT:    movw r1, :lower16:b
@@ -725,15 +709,14 @@ define i32 @combine_gt_lt_n5() #0 {
 ; ARM-NEXT:    movw r0, :lower16:a
 ; ARM-NEXT:    movt r0, :upper16:a
 ; ARM-NEXT:    ldr r0, [r0]
-; ARM-NEXT:    cmn r0, #4
-; ARM-NEXT:    blt .LBB4_2
+; ARM-NEXT:    cmn r0, #5
+; ARM-NEXT:    ble .LBB4_2
 ; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
 ; ARM-NEXT:    movw r0, :lower16:c
 ; ARM-NEXT:    movt r0, :upper16:c
 ; ARM-NEXT:    b .LBB4_4
 ; ARM-NEXT:  .LBB4_2: @ %lor.lhs.false
-; ARM-NEXT:    cmn r0, #6
-; ARM-NEXT:    bgt .LBB4_5
+; ARM-NEXT:    bge .LBB4_5
 ; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; ARM-NEXT:    movw r0, :lower16:d
 ; ARM-NEXT:    movt r0, :upper16:d
@@ -802,8 +785,8 @@ define i32 @combine_gt_lt_n5() #0 {
 ; THUMB2-NEXT:    movw r0, :lower16:a
 ; THUMB2-NEXT:    movt r0, :upper16:a
 ; THUMB2-NEXT:    ldr r0, [r0]
-; THUMB2-NEXT:    cmn.w r0, #4
-; THUMB2-NEXT:    blt .LBB4_2
+; THUMB2-NEXT:    cmn.w r0, #5
+; THUMB2-NEXT:    ble .LBB4_2
 ; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB2-NEXT:    movw r0, :lower16:c
 ; THUMB2-NEXT:    movw r1, :lower16:b
@@ -817,8 +800,7 @@ define i32 @combine_gt_lt_n5() #0 {
 ; THUMB2-NEXT:    bxeq lr
 ; THUMB2-NEXT:    b .LBB4_4
 ; THUMB2-NEXT:  .LBB4_2: @ %lor.lhs.false
-; THUMB2-NEXT:    cmn.w r0, #6
-; THUMB2-NEXT:    bgt .LBB4_4
+; THUMB2-NEXT:    bge .LBB4_4
 ; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; THUMB2-NEXT:    movw r0, :lower16:d
 ; THUMB2-NEXT:    movw r1, :lower16:b
@@ -839,8 +821,8 @@ define i32 @combine_gt_lt_n5() #0 {
 ; THUMBV8-NEXT:    movw r0, :lower16:a
 ; THUMBV8-NEXT:    movt r0, :upper16:a
 ; THUMBV8-NEXT:    ldr r0, [r0]
-; THUMBV8-NEXT:    cmn.w r0, #4
-; THUMBV8-NEXT:    blt .LBB4_2
+; THUMBV8-NEXT:    cmn.w r0, #5
+; THUMBV8-NEXT:    ble .LBB4_2
 ; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMBV8-NEXT:    movw r0, :lower16:c
 ; THUMBV8-NEXT:    movw r1, :lower16:b
@@ -854,8 +836,7 @@ define i32 @combine_gt_lt_n5() #0 {
 ; THUMBV8-NEXT:    bxeq lr
 ; THUMBV8-NEXT:    b .LBB4_4
 ; THUMBV8-NEXT:  .LBB4_2: @ %lor.lhs.false
-; THUMBV8-NEXT:    cmn.w r0, #6
-; THUMBV8-NEXT:    bgt .LBB4_4
+; THUMBV8-NEXT:    bge .LBB4_4
 ; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; THUMBV8-NEXT:    movw r0, :lower16:d
 ; THUMBV8-NEXT:    movw r1, :lower16:b
@@ -906,15 +887,14 @@ define i32 @combine_lt_gt_n5() #0 {
 ; ARM-NEXT:    movw r0, :lower16:a
 ; ARM-NEXT:    movt r0, :upper16:a
 ; ARM-NEXT:    ldr r0, [r0]
-; ARM-NEXT:    cmn r0, #6
-; ARM-NEXT:    bgt .LBB5_2
+; ARM-NEXT:    cmn r0, #5
+; ARM-NEXT:    bge .LBB5_2
 ; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
 ; ARM-NEXT:    movw r0, :lower16:c
 ; ARM-NEXT:    movt r0, :upper16:c
 ; ARM-NEXT:    b .LBB5_4
 ; ARM-NEXT:  .LBB5_2: @ %lor.lhs.false
-; ARM-NEXT:    cmn r0, #4
-; ARM-NEXT:    blt .LBB5_5
+; ARM-NEXT:    ble .LBB5_5
 ; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; ARM-NEXT:    movw r0, :lower16:d
 ; ARM-NEXT:    movt r0, :upper16:d
@@ -983,8 +963,8 @@ define i32 @combine_lt_gt_n5() #0 {
 ; THUMB2-NEXT:    movw r0, :lower16:a
 ; THUMB2-NEXT:    movt r0, :upper16:a
 ; THUMB2-NEXT:    ldr r0, [r0]
-; THUMB2-NEXT:    cmn.w r0, #6
-; THUMB2-NEXT:    bgt .LBB5_2
+; THUMB2-NEXT:    cmn.w r0, #5
+; THUMB2-NEXT:    bge .LBB5_2
 ; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMB2-NEXT:    movw r0, :lower16:c
 ; THUMB2-NEXT:    movw r1, :lower16:b
@@ -998,8 +978,7 @@ define i32 @combine_lt_gt_n5() #0 {
 ; THUMB2-NEXT:    bxeq lr
 ; THUMB2-NEXT:    b .LBB5_4
 ; THUMB2-NEXT:  .LBB5_2: @ %lor.lhs.false
-; THUMB2-NEXT:    cmn.w r0, #4
-; THUMB2-NEXT:    blt .LBB5_4
+; THUMB2-NEXT:    ble .LBB5_4
 ; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; THUMB2-NEXT:    movw r0, :lower16:d
 ; THUMB2-NEXT:    movw r1, :lower16:b
@@ -1020,8 +999,8 @@ define i32 @combine_lt_gt_n5() #0 {
 ; THUMBV8-NEXT:    movw r0, :lower16:a
 ; THUMBV8-NEXT:    movt r0, :upper16:a
 ; THUMBV8-NEXT:    ldr r0, [r0]
-; THUMBV8-NEXT:    cmn.w r0, #6
-; THUMBV8-NEXT:    bgt .LBB5_2
+; THUMBV8-NEXT:    cmn.w r0, #5
+; THUMBV8-NEXT:    bge .LBB5_2
 ; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
 ; THUMBV8-NEXT:    movw r0, :lower16:c
 ; THUMBV8-NEXT:    movw r1, :lower16:b
@@ -1035,8 +1014,7 @@ define i32 @combine_lt_gt_n5() #0 {
 ; THUMBV8-NEXT:    bxeq lr
 ; THUMBV8-NEXT:    b .LBB5_4
 ; THUMBV8-NEXT:  .LBB5_2: @ %lor.lhs.false
-; THUMBV8-NEXT:    cmn.w r0, #4
-; THUMBV8-NEXT:    blt .LBB5_4
+; THUMBV8-NEXT:    ble .LBB5_4
 ; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
 ; THUMBV8-NEXT:    movw r0, :lower16:d
 ; THUMBV8-NEXT:    movw r1, :lower16:b
@@ -1785,3 +1763,1422 @@ return:                                           ; preds = %if.end, %land.lhs.t
   %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
   ret i32 %retval.0
 }
+
+; (a > 10 && b == c) || (a >= 10 && b == d)
+define i32 @combine_ugt_uge_10() #0 {
+; ARM-LABEL: combine_ugt_uge_10:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movw r1, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    movt r1, :upper16:b
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #10
+; ARM-NEXT:    bls .LBB10_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    ldr r3, [r1]
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r3, r2
+; ARM-NEXT:    bxeq lr
+; ARM-NEXT:    b .LBB10_3
+; ARM-NEXT:  .LBB10_2: @ %lor.lhs.false
+; ARM-NEXT:    blo .LBB10_4
+; ARM-NEXT:  .LBB10_3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    ldr r1, [r1]
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r1, r2
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB10_4: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_ugt_uge_10:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI10_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #10
+; THUMB-NEXT:    bls .LBB10_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI10_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI10_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB10_4
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB10_3: @ %lor.lhs.false
+; THUMB-NEXT:    blo .LBB10_6
+; THUMB-NEXT:  .LBB10_4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI10_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI10_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB10_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB10_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI10_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI10_1:
+; THUMB-NEXT:    .long c
+; THUMB-NEXT:  .LCPI10_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI10_3:
+; THUMB-NEXT:    .long d
+;
+; THUMB2-LABEL: combine_ugt_uge_10:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #10
+; THUMB2-NEXT:    movw r0, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:b
+; THUMB2-NEXT:    bls .LBB10_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r1, :lower16:c
+; THUMB2-NEXT:    ldr r2, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:c
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r2, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB10_3
+; THUMB2-NEXT:  .LBB10_2: @ %lor.lhs.false
+; THUMB2-NEXT:    blo .LBB10_4
+; THUMB2-NEXT:  .LBB10_3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r1, :lower16:d
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:d
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r0, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB10_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_ugt_uge_10:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #10
+; THUMBV8-NEXT:    movw r0, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:b
+; THUMBV8-NEXT:    bls .LBB10_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r1, :lower16:c
+; THUMBV8-NEXT:    ldr r2, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:c
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r2, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB10_3
+; THUMBV8-NEXT:  .LBB10_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    blo .LBB10_4
+; THUMBV8-NEXT:  .LBB10_3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r1, :lower16:d
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:d
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r0, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB10_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp ugt i32 %0, 10
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %land.lhs.true3
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp ugt i32 %0, 9
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a > 5 && b == c) || (a < 5 && b == d)
+define i32 @combine_ugt_ult_5() #0 {
+; ARM-LABEL: combine_ugt_ult_5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #5
+; ARM-NEXT:    bls .LBB11_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB11_4
+; ARM-NEXT:  .LBB11_2: @ %lor.lhs.false
+; ARM-NEXT:    bhs .LBB11_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB11_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB11_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_ugt_ult_5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI11_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #5
+; THUMB-NEXT:    bls .LBB11_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI11_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI11_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB11_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB11_3: @ %lor.lhs.false
+; THUMB-NEXT:    bhs .LBB11_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI11_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI11_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB11_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB11_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI11_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI11_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI11_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI11_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_ugt_ult_5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #5
+; THUMB2-NEXT:    bls .LBB11_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB11_4
+; THUMB2-NEXT:  .LBB11_2: @ %lor.lhs.false
+; THUMB2-NEXT:    bhs .LBB11_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB11_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_ugt_ult_5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #5
+; THUMBV8-NEXT:    bls .LBB11_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB11_4
+; THUMBV8-NEXT:  .LBB11_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    bhs .LBB11_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB11_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp ugt i32 %0, 5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp ult i32 %0, 5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a < 5 && b == c) || (a <= 5 && b == d)
+define i32 @combine_ult_uge_5() #0 {
+; ARM-LABEL: combine_ult_uge_5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movw r1, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    movt r1, :upper16:b
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #5
+; ARM-NEXT:    bhs .LBB12_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    ldr r3, [r1]
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r3, r2
+; ARM-NEXT:    bxeq lr
+; ARM-NEXT:    b .LBB12_3
+; ARM-NEXT:  .LBB12_2: @ %lor.lhs.false
+; ARM-NEXT:    bhi .LBB12_4
+; ARM-NEXT:  .LBB12_3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    ldr r1, [r1]
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r1, r2
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB12_4: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_ult_uge_5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI12_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #5
+; THUMB-NEXT:    bhs .LBB12_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI12_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI12_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB12_4
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB12_3: @ %lor.lhs.false
+; THUMB-NEXT:    bhi .LBB12_6
+; THUMB-NEXT:  .LBB12_4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI12_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI12_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB12_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB12_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI12_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI12_1:
+; THUMB-NEXT:    .long c
+; THUMB-NEXT:  .LCPI12_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI12_3:
+; THUMB-NEXT:    .long d
+;
+; THUMB2-LABEL: combine_ult_uge_5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #5
+; THUMB2-NEXT:    movw r0, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:b
+; THUMB2-NEXT:    bhs .LBB12_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r1, :lower16:c
+; THUMB2-NEXT:    ldr r2, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:c
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r2, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB12_3
+; THUMB2-NEXT:  .LBB12_2: @ %lor.lhs.false
+; THUMB2-NEXT:    bhi .LBB12_4
+; THUMB2-NEXT:  .LBB12_3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r1, :lower16:d
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:d
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r0, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB12_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_ult_uge_5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #5
+; THUMBV8-NEXT:    movw r0, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:b
+; THUMBV8-NEXT:    bhs .LBB12_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r1, :lower16:c
+; THUMBV8-NEXT:    ldr r2, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:c
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r2, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB12_3
+; THUMBV8-NEXT:  .LBB12_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    bhi .LBB12_4
+; THUMBV8-NEXT:  .LBB12_3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r1, :lower16:d
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:d
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r0, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB12_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp ult i32 %0, 5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %land.lhs.true3
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp ult i32 %0, 6
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a < 5 && b == c) || (a > 5 && b == d)
+define i32 @combine_ult_ugt_5() #0 {
+; ARM-LABEL: combine_ult_ugt_5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmp r0, #5
+; ARM-NEXT:    bhs .LBB13_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB13_4
+; ARM-NEXT:  .LBB13_2: @ %lor.lhs.false
+; ARM-NEXT:    bls .LBB13_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB13_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB13_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_ult_ugt_5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI13_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    cmp r0, #5
+; THUMB-NEXT:    bhs .LBB13_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI13_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI13_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB13_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB13_3: @ %lor.lhs.false
+; THUMB-NEXT:    bls .LBB13_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI13_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI13_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB13_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB13_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI13_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI13_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI13_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI13_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_ult_ugt_5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmp r0, #5
+; THUMB2-NEXT:    bhs .LBB13_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB13_4
+; THUMB2-NEXT:  .LBB13_2: @ %lor.lhs.false
+; THUMB2-NEXT:    bls .LBB13_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB13_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_ult_ugt_5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmp r0, #5
+; THUMBV8-NEXT:    bhs .LBB13_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB13_4
+; THUMBV8-NEXT:  .LBB13_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    bls .LBB13_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB13_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp ult i32 %0, 5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp ugt i32 %0, 5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a > -5 && b == c) || (a < -5 && b == d)
+define i32 @combine_ugt_ult_n5() #0 {
+; ARM-LABEL: combine_ugt_ult_n5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmn r0, #5
+; ARM-NEXT:    bls .LBB14_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB14_4
+; ARM-NEXT:  .LBB14_2: @ %lor.lhs.false
+; ARM-NEXT:    bhs .LBB14_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB14_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB14_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_ugt_ult_n5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI14_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    movs r1, #3
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    blo .LBB14_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI14_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI14_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB14_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB14_3: @ %lor.lhs.false
+; THUMB-NEXT:    movs r1, #5
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    bhi .LBB14_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI14_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI14_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB14_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB14_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI14_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI14_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI14_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI14_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_ugt_ult_n5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmn.w r0, #5
+; THUMB2-NEXT:    bls .LBB14_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB14_4
+; THUMB2-NEXT:  .LBB14_2: @ %lor.lhs.false
+; THUMB2-NEXT:    bhs .LBB14_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB14_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_ugt_ult_n5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmn.w r0, #5
+; THUMBV8-NEXT:    bls .LBB14_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB14_4
+; THUMBV8-NEXT:  .LBB14_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    bhs .LBB14_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB14_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp ugt i32 %0, -5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp ult i32 %0, -5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; (a < -5 && b == c) || (a > -5 && b == d)
+define i32 @combine_ult_ugt_n5() #0 {
+; ARM-LABEL: combine_ult_ugt_n5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmn r0, #5
+; ARM-NEXT:    bhs .LBB15_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB15_4
+; ARM-NEXT:  .LBB15_2: @ %lor.lhs.false
+; ARM-NEXT:    bls .LBB15_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB15_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB15_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_ult_ugt_n5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI15_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    movs r1, #5
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    bhi .LBB15_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI15_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI15_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB15_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB15_3: @ %lor.lhs.false
+; THUMB-NEXT:    movs r1, #3
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    blo .LBB15_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI15_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI15_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB15_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB15_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI15_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI15_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI15_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI15_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_ult_ugt_n5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmn.w r0, #5
+; THUMB2-NEXT:    bhs .LBB15_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB15_4
+; THUMB2-NEXT:  .LBB15_2: @ %lor.lhs.false
+; THUMB2-NEXT:    bls .LBB15_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB15_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_ult_ugt_n5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmn.w r0, #5
+; THUMBV8-NEXT:    bhs .LBB15_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB15_4
+; THUMBV8-NEXT:  .LBB15_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    bls .LBB15_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB15_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp ult i32 %0, -5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp ugt i32 %0, -5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+; Yes, you can mix them too!
+; (a < -5 && b == c) || (a u> -5 && b == d)
+define i32 @combine_ult_gt_n5() #0 {
+; ARM-LABEL: combine_ult_gt_n5:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r0, :lower16:a
+; ARM-NEXT:    movt r0, :upper16:a
+; ARM-NEXT:    ldr r0, [r0]
+; ARM-NEXT:    cmn r0, #5
+; ARM-NEXT:    bhs .LBB16_2
+; ARM-NEXT:  @ %bb.1: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    b .LBB16_4
+; ARM-NEXT:  .LBB16_2: @ %lor.lhs.false
+; ARM-NEXT:    ble .LBB16_5
+; ARM-NEXT:  @ %bb.3: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:  .LBB16_4: @ %land.lhs.true3
+; ARM-NEXT:    ldr r1, [r0]
+; ARM-NEXT:    movw r0, :lower16:b
+; ARM-NEXT:    movt r0, :upper16:b
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r2, r1
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB16_5: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_ult_gt_n5:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r0, .LCPI16_0
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    movs r1, #5
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    bhi .LBB16_3
+; THUMB-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI16_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI16_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB16_6
+; THUMB-NEXT:  @ %bb.2:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB16_3: @ %lor.lhs.false
+; THUMB-NEXT:    movs r1, #3
+; THUMB-NEXT:    mvns r1, r1
+; THUMB-NEXT:    cmp r0, r1
+; THUMB-NEXT:    blt .LBB16_6
+; THUMB-NEXT:  @ %bb.4: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI16_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI16_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB16_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB16_6: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:  .LCPI16_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI16_1:
+; THUMB-NEXT:    .long d
+; THUMB-NEXT:  .LCPI16_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI16_3:
+; THUMB-NEXT:    .long c
+;
+; THUMB2-LABEL: combine_ult_gt_n5:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r0, :lower16:a
+; THUMB2-NEXT:    movt r0, :upper16:a
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    cmn.w r0, #5
+; THUMB2-NEXT:    bhs .LBB16_2
+; THUMB2-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMB2-NEXT:    movw r0, :lower16:c
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:c
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:    b .LBB16_4
+; THUMB2-NEXT:  .LBB16_2: @ %lor.lhs.false
+; THUMB2-NEXT:    ble .LBB16_4
+; THUMB2-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r0, :lower16:d
+; THUMB2-NEXT:    movw r1, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:d
+; THUMB2-NEXT:    movt r1, :upper16:b
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r1, r0
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB16_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_ult_gt_n5:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r0, :lower16:a
+; THUMBV8-NEXT:    movt r0, :upper16:a
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    cmn.w r0, #5
+; THUMBV8-NEXT:    bhs .LBB16_2
+; THUMBV8-NEXT:  @ %bb.1: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r0, :lower16:c
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:c
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:    b .LBB16_4
+; THUMBV8-NEXT:  .LBB16_2: @ %lor.lhs.false
+; THUMBV8-NEXT:    ble .LBB16_4
+; THUMBV8-NEXT:  @ %bb.3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r0, :lower16:d
+; THUMBV8-NEXT:    movw r1, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:d
+; THUMBV8-NEXT:    movt r1, :upper16:b
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r1, r0
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB16_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp ult i32 %0, -5
+  br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp sgt i32 %0, -5
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+define i32 @combine_ugt_uge_sel(i32 %v, ptr %p) #0 {
+; ARM-LABEL: combine_ugt_uge_sel:
+; ARM:       @ %bb.0: @ %entry
+; ARM-NEXT:    movw r2, :lower16:a
+; ARM-NEXT:    movt r2, :upper16:a
+; ARM-NEXT:    ldr r2, [r2]
+; ARM-NEXT:    cmp r2, #0
+; ARM-NEXT:    moveq r0, r2
+; ARM-NEXT:    str r0, [r1]
+; ARM-NEXT:    movw r1, :lower16:b
+; ARM-NEXT:    movt r1, :upper16:b
+; ARM-NEXT:    beq .LBB17_3
+; ARM-NEXT:  @ %bb.1: @ %lor.lhs.false
+; ARM-NEXT:    cmp r2, #2
+; ARM-NEXT:    bhs .LBB17_4
+; ARM-NEXT:  @ %bb.2: @ %if.end
+; ARM-NEXT:    mov r0, #0
+; ARM-NEXT:    bx lr
+; ARM-NEXT:  .LBB17_3: @ %land.lhs.true
+; ARM-NEXT:    movw r0, :lower16:c
+; ARM-NEXT:    ldr r3, [r1]
+; ARM-NEXT:    movt r0, :upper16:c
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r3, r2
+; ARM-NEXT:    bxeq lr
+; ARM-NEXT:  .LBB17_4: @ %land.lhs.true3
+; ARM-NEXT:    movw r0, :lower16:d
+; ARM-NEXT:    ldr r1, [r1]
+; ARM-NEXT:    movt r0, :upper16:d
+; ARM-NEXT:    ldr r2, [r0]
+; ARM-NEXT:    mov r0, #1
+; ARM-NEXT:    cmp r1, r2
+; ARM-NEXT:    movne r0, #0
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: combine_ugt_uge_sel:
+; THUMB:       @ %bb.0: @ %entry
+; THUMB-NEXT:    ldr r2, .LCPI17_0
+; THUMB-NEXT:    ldr r2, [r2]
+; THUMB-NEXT:    cmp r2, #0
+; THUMB-NEXT:    bne .LBB17_2
+; THUMB-NEXT:  @ %bb.1: @ %entry
+; THUMB-NEXT:    mov r0, r2
+; THUMB-NEXT:  .LBB17_2: @ %entry
+; THUMB-NEXT:    str r0, [r1]
+; THUMB-NEXT:    beq .LBB17_4
+; THUMB-NEXT:  @ %bb.3: @ %lor.lhs.false
+; THUMB-NEXT:    cmp r2, #2
+; THUMB-NEXT:    bhs .LBB17_6
+; THUMB-NEXT:    b .LBB17_8
+; THUMB-NEXT:  .LBB17_4: @ %land.lhs.true
+; THUMB-NEXT:    ldr r0, .LCPI17_1
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI17_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB17_6
+; THUMB-NEXT:  @ %bb.5:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB17_6: @ %land.lhs.true3
+; THUMB-NEXT:    ldr r0, .LCPI17_3
+; THUMB-NEXT:    ldr r0, [r0]
+; THUMB-NEXT:    ldr r1, .LCPI17_2
+; THUMB-NEXT:    ldr r1, [r1]
+; THUMB-NEXT:    cmp r1, r0
+; THUMB-NEXT:    bne .LBB17_8
+; THUMB-NEXT:  @ %bb.7:
+; THUMB-NEXT:    movs r0, #1
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:  .LBB17_8: @ %if.end
+; THUMB-NEXT:    movs r0, #0
+; THUMB-NEXT:    bx lr
+; THUMB-NEXT:    .p2align 2
+; THUMB-NEXT:  @ %bb.9:
+; THUMB-NEXT:  .LCPI17_0:
+; THUMB-NEXT:    .long a
+; THUMB-NEXT:  .LCPI17_1:
+; THUMB-NEXT:    .long c
+; THUMB-NEXT:  .LCPI17_2:
+; THUMB-NEXT:    .long b
+; THUMB-NEXT:  .LCPI17_3:
+; THUMB-NEXT:    .long d
+;
+; THUMB2-LABEL: combine_ugt_uge_sel:
+; THUMB2:       @ %bb.0: @ %entry
+; THUMB2-NEXT:    movw r2, :lower16:a
+; THUMB2-NEXT:    movt r2, :upper16:a
+; THUMB2-NEXT:    ldr r2, [r2]
+; THUMB2-NEXT:    cmp r2, #0
+; THUMB2-NEXT:    it eq
+; THUMB2-NEXT:    moveq r0, r2
+; THUMB2-NEXT:    str r0, [r1]
+; THUMB2-NEXT:    movw r0, :lower16:b
+; THUMB2-NEXT:    movt r0, :upper16:b
+; THUMB2-NEXT:    beq .LBB17_2
+; THUMB2-NEXT:  @ %bb.1: @ %lor.lhs.false
+; THUMB2-NEXT:    cmp r2, #2
+; THUMB2-NEXT:    bhs .LBB17_3
+; THUMB2-NEXT:    b .LBB17_4
+; THUMB2-NEXT:  .LBB17_2: @ %land.lhs.true
+; THUMB2-NEXT:    movw r1, :lower16:c
+; THUMB2-NEXT:    ldr r2, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:c
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r2, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB17_3: @ %land.lhs.true3
+; THUMB2-NEXT:    movw r1, :lower16:d
+; THUMB2-NEXT:    ldr r0, [r0]
+; THUMB2-NEXT:    movt r1, :upper16:d
+; THUMB2-NEXT:    ldr r1, [r1]
+; THUMB2-NEXT:    cmp r0, r1
+; THUMB2-NEXT:    itt eq
+; THUMB2-NEXT:    moveq r0, #1
+; THUMB2-NEXT:    bxeq lr
+; THUMB2-NEXT:  .LBB17_4: @ %if.end
+; THUMB2-NEXT:    movs r0, #0
+; THUMB2-NEXT:    bx lr
+;
+; THUMBV8-LABEL: combine_ugt_uge_sel:
+; THUMBV8:       @ %bb.0: @ %entry
+; THUMBV8-NEXT:    movw r2, :lower16:a
+; THUMBV8-NEXT:    movt r2, :upper16:a
+; THUMBV8-NEXT:    ldr r2, [r2]
+; THUMBV8-NEXT:    cmp r2, #0
+; THUMBV8-NEXT:    csel r0, r0, r2, ne
+; THUMBV8-NEXT:    str r0, [r1]
+; THUMBV8-NEXT:    movw r0, :lower16:b
+; THUMBV8-NEXT:    movt r0, :upper16:b
+; THUMBV8-NEXT:    beq .LBB17_2
+; THUMBV8-NEXT:  @ %bb.1: @ %lor.lhs.false
+; THUMBV8-NEXT:    cmp r2, #2
+; THUMBV8-NEXT:    bhs .LBB17_3
+; THUMBV8-NEXT:    b .LBB17_4
+; THUMBV8-NEXT:  .LBB17_2: @ %land.lhs.true
+; THUMBV8-NEXT:    movw r1, :lower16:c
+; THUMBV8-NEXT:    ldr r2, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:c
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r2, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB17_3: @ %land.lhs.true3
+; THUMBV8-NEXT:    movw r1, :lower16:d
+; THUMBV8-NEXT:    ldr r0, [r0]
+; THUMBV8-NEXT:    movt r1, :upper16:d
+; THUMBV8-NEXT:    ldr r1, [r1]
+; THUMBV8-NEXT:    cmp r0, r1
+; THUMBV8-NEXT:    itt eq
+; THUMBV8-NEXT:    moveq r0, #1
+; THUMBV8-NEXT:    bxeq lr
+; THUMBV8-NEXT:  .LBB17_4: @ %if.end
+; THUMBV8-NEXT:    movs r0, #0
+; THUMBV8-NEXT:    bx lr
+entry:
+  %0 = load i32, ptr @a, align 4
+  %cmp = icmp ugt i32 %0, 0
+  %m = select i1 %cmp, i32 %v, i32 0
+  store i32 %m, ptr %p
+  br i1 %cmp, label %lor.lhs.false, label %land.lhs.true
+
+land.lhs.true:                                    ; preds = %entry
+  %1 = load i32, ptr @b, align 4
+  %2 = load i32, ptr @c, align 4
+  %cmp1 = icmp eq i32 %1, %2
+  br i1 %cmp1, label %return, label %land.lhs.true3
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp2 = icmp ugt i32 %0, 1
+  br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
+  %3 = load i32, ptr @b, align 4
+  %4 = load i32, ptr @d, align 4
+  %cmp4 = icmp eq i32 %3, %4
+  br i1 %cmp4, label %return, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
+  br label %return
+
+return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
+  %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+  ret i32 %retval.0
+}
+
+attributes #0 = { uwtable }
diff --git a/llvm/test/CodeGen/ARM/fpclamptosat.ll b/llvm/test/CodeGen/ARM/fpclamptosat.ll
index 8ab56b228d2a7..43b0e71dafdef 100644
--- a/llvm/test/CodeGen/ARM/fpclamptosat.ll
+++ b/llvm/test/CodeGen/ARM/fpclamptosat.ll
@@ -1862,8 +1862,8 @@ define i32 @ustest_f64i32_mm(double %x) {
 ; SOFT-NEXT:    bl __aeabi_d2lz
 ; SOFT-NEXT:    mov r2, r0
 ; SOFT-NEXT:    movs r0, #0
-; SOFT-NEXT:    cmp r1, #1
-; SOFT-NEXT:    blt .LBB29_2
+; SOFT-NEXT:    cmp r1, #0
+; SOFT-NEXT:    ble .LBB29_2
 ; SOFT-NEXT:  @ %bb.1: @ %entry
 ; SOFT-NEXT:    mvns r2, r0
 ; SOFT-NEXT:  .LBB29_2: @ %entry
@@ -1994,8 +1994,8 @@ define i32 @ustest_f32i32_mm(float %x) {
 ; SOFT-NEXT:    bl __aeabi_f2lz
 ; SOFT-NEXT:    mov r2, r0
 ; SOFT-NEXT:    movs r0, #0
-; SOFT-NEXT:    cmp r1, #1
-; SOFT-NEXT:    blt .LBB32_2
+; SOFT-NEXT:    cmp r1, #0
+; SOFT-NEXT:    ble .LBB32_2
 ; SOFT-NEXT:  @ %bb.1: @ %entry
 ; SOFT-NEXT:    mvns r2, r0
 ; SOFT-NEXT:  .LBB32_2: @ %entry
@@ -2140,8 +2140,8 @@ define i32 @ustest_f16i32_mm(half %x) {
 ; SOFT-NEXT:    bl __aeabi_f2lz
 ; SOFT-NEXT:    mov r2, r0
 ; SOFT-NEXT:    movs r0, #0
-; SOFT-NEXT:    cmp r1, #1
-; SOFT-NEXT:    blt .LBB35_2
+; SOFT-NEXT:    cmp r1, #0
+; SOFT-NEXT:    ble .LBB35_2
 ; SOFT-NEXT:  @ %bb.1: @ %entry
 ; SOFT-NEXT:    mvns r2, r0
 ; SOFT-NEXT:  .LBB35_2: @ %entry
diff --git a/llvm/test/CodeGen/Thumb/smul_fix_sat.ll b/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
index 24209b45e302d..bae539ec3bb95 100644
--- a/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
+++ b/llvm/test/CodeGen/Thumb/smul_fix_sat.ll
@@ -104,9 +104,9 @@ define i64 @func2(i64 %x, i64 %y) nounwind {
 ; ARM-NEXT:    mov r5, r4
 ; ARM-NEXT:  .LBB1_2:
 ; ARM-NEXT:    ands r2, r5
-; ARM-NEXT:    cmp r1, #0
+; ARM-NEXT:    cmp r1, #1
 ; ARM-NEXT:    mov r5, r0
-; ARM-NEXT:    bgt .LBB1_4
+; ARM-NEXT:    bge .LBB1_4
 ; ARM-NEXT:  @ %bb.3:
 ; ARM-NEXT:    mov r5, r4
 ; ARM-NEXT:  .LBB1_4:



More information about the llvm-commits mailing list