[llvm] [ARM] Port ConditionOptimizer to ARM (PR #151187)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 29 10:00:15 PDT 2025
https://github.com/AZero13 created https://github.com/llvm/llvm-project/pull/151187
Following the same principles, we can optimize conditions to make it better for the CSE.
>From 4e640bf7b347206f06b7bbc137168dd22f3d3ed0 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 4cccd3c7246c70232ebd5d275aa90f8cdd1bba2d 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 +-
7 files changed, 2017 insertions(+), 90 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..461c392d46b0d
--- /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:
+ break;
+ default:
+ return nullptr;
+ }
+
+ // 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;
+ }
+ 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();
+
+ int TrueImmTrueValue = TrueImm;
+
+ // Special Case 0.
+ if (TrueImm == 0) {
+ if (TrueCmp == ARMCC::PL)
+ TrueCmp = ARMCC::GE;
+ if (TrueCmp == ARMCC::MI)
+ TrueCmp = ARMCC::LT;
+ }
+
+ 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
More information about the llvm-commits
mailing list