blob: 27b231cb56d706b2f314f93f8f583a6d816cac63 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -debugify-and-strip-all-safe < %s -mtriple=aarch64-linux-gnu | FileCheck %s
; marked as external to prevent possible optimizations
@a = external global i32
@b = external global i32
@c = external global i32
@d = external global i32
; Test intra-block CSINC optimization with (a > 10) and (a >= 10)
; Two CSINC instructions should share a single CMP after optimization
define void @intra_block_csinc(i32 %x, i32 %y, ptr %out1, ptr %out2) #0 {
; CHECK-LABEL: intra_block_csinc:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #10
; CHECK-NEXT: csinc w8, w0, w1, gt
; CHECK-NEXT: csinc w9, w0, w1, ge
; CHECK-NEXT: str w8, [x2]
; CHECK-NEXT: str w9, [x3]
; CHECK-NEXT: ret
entry:
%val = load i32, ptr @a, align 4
; First: result1 = (a > 10) ? x : (y + 1)
%cond1 = icmp sgt i32 %val, 10
%y_inc1 = add i32 %y, 1
%result1 = select i1 %cond1, i32 %x, i32 %y_inc1
store i32 %result1, ptr %out1
; Second: result2 = (a >= 10) ? x : (y + 1)
; Canonicalizes to (a > 9), then optimizes to reuse first CMP with adjusted condition
%cond2 = icmp sge i32 %val, 10
%y_inc2 = add i32 %y, 1
%result2 = select i1 %cond2, i32 %x, i32 %y_inc2
store i32 %result2, ptr %out2
ret void
}
; Negative test: different registers should not be optimized
define void @intra_block_csinc_different_regs(i32 %x, i32 %y, ptr %out1, ptr %out2) #0 {
; CHECK-LABEL: intra_block_csinc_different_regs:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: adrp x9, :got:b
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:b]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, #10
; CHECK-NEXT: csinc w8, w0, w1, gt
; CHECK-NEXT: cmp w9, #9
; CHECK-NEXT: str w8, [x2]
; CHECK-NEXT: csinc w8, w0, w1, gt
; CHECK-NEXT: str w8, [x3]
; CHECK-NEXT: ret
entry:
%val1 = load i32, ptr @a, align 4
%val2 = load i32, ptr @b, align 4
; First: result1 = (a > 10) ? x : (y + 1)
%cond1 = icmp sgt i32 %val1, 10
%y_inc1 = add i32 %y, 1
%result1 = select i1 %cond1, i32 %x, i32 %y_inc1
store i32 %result1, ptr %out1
; Second: result2 = (b > 9) ? x : (y + 1) - compares DIFFERENT register
; Should NOT optimize - need both CMPs
%cond2 = icmp sgt i32 %val2, 9
%y_inc2 = add i32 %y, 1
%result2 = select i1 %cond2, i32 %x, i32 %y_inc2
store i32 %result2, ptr %out2
ret void
}
; Test intra-block CSINC optimization with (a < 5) and (a < 6)
; LT/LT pattern - symmetric to GT/GT case
define void @intra_block_csinc_lt(i32 %x, i32 %y, ptr %out1, ptr %out2) #0 {
; CHECK-LABEL: intra_block_csinc_lt:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #5
; CHECK-NEXT: csinc w8, w0, w1, lt
; CHECK-NEXT: csinc w9, w0, w1, le
; CHECK-NEXT: str w8, [x2]
; CHECK-NEXT: str w9, [x3]
; CHECK-NEXT: ret
entry:
%val = load i32, ptr @a, align 4
; First: result1 = (a < 5) ? x : (y + 1)
%cond1 = icmp slt i32 %val, 5
%y_inc1 = add i32 %y, 1
%result1 = select i1 %cond1, i32 %x, i32 %y_inc1
store i32 %result1, ptr %out1
; Second: result2 = (a < 6) ? x : (y + 1)
; Optimizes to reuse first CMP (#5) with adjusted condition (le)
%cond2 = icmp slt i32 %val, 6
%y_inc2 = add i32 %y, 1
%result2 = select i1 %cond2, i32 %x, i32 %y_inc2
store i32 %result2, ptr %out2
ret void
}
; (a > 10 && b == c) || (a >= 10 && b == d)
define i32 @combine_gt_ge_10() #0 {
; CHECK-LABEL: combine_gt_ge_10:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #10
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: b.le .LBB3_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w10, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w10, w9
; CHECK-NEXT: b.ne .LBB3_4
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB3_3: // %lor.lhs.false
; CHECK-NEXT: b.lt .LBB3_6
; CHECK-NEXT: .LBB3_4: // %land.lhs.true3
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB3_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB3_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_gt_lt_5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #5
; CHECK-NEXT: b.le .LBB4_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB4_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB4_3: // %lor.lhs.false
; CHECK-NEXT: b.ge .LBB4_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB4_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB4_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_lt_ge_5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #5
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: b.ge .LBB5_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w10, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w10, w9
; CHECK-NEXT: b.ne .LBB5_4
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB5_3: // %lor.lhs.false
; CHECK-NEXT: b.gt .LBB5_6
; CHECK-NEXT: .LBB5_4: // %land.lhs.true3
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB5_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB5_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_lt_gt_5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #5
; CHECK-NEXT: b.ge .LBB6_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB6_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB6_3: // %lor.lhs.false
; CHECK-NEXT: b.le .LBB6_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB6_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB6_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_gt_lt_n5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmn w8, #5
; CHECK-NEXT: b.le .LBB7_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB7_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB7_3: // %lor.lhs.false
; CHECK-NEXT: b.ge .LBB7_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB7_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB7_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_lt_gt_n5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmn w8, #5
; CHECK-NEXT: b.ge .LBB8_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB8_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB8_3: // %lor.lhs.false
; CHECK-NEXT: b.le .LBB8_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB8_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB8_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 { i64, i64 }
@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 {
; CHECK-LABEL: combine_non_adjacent_cmp_br:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: str x30, [sp, #-48]! // 8-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 48
; CHECK-NEXT: stp x22, x21, [sp, #16] // 16-byte Folded Spill
; CHECK-NEXT: stp x20, x19, [sp, #32] // 16-byte Folded Spill
; CHECK-NEXT: .cfi_offset w19, -8
; CHECK-NEXT: .cfi_offset w20, -16
; CHECK-NEXT: .cfi_offset w21, -24
; CHECK-NEXT: .cfi_offset w22, -32
; CHECK-NEXT: .cfi_offset w30, -48
; CHECK-NEXT: ldr x20, [x0]
; CHECK-NEXT: mov w19, #24 // =0x18
; CHECK-NEXT: adrp x22, glob
; CHECK-NEXT: add x21, x20, #2
; CHECK-NEXT: .LBB9_1: // %land.rhs
; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: ldr x8, [x19]
; CHECK-NEXT: cmp x8, #1
; CHECK-NEXT: b.lt .LBB9_3
; CHECK-NEXT: // %bb.2: // %while.body
; CHECK-NEXT: // in Loop: Header=BB9_1 Depth=1
; CHECK-NEXT: ldr x0, [x22, :lo12:glob]
; CHECK-NEXT: bl Update
; CHECK-NEXT: sub x21, x21, #2
; CHECK-NEXT: cmp x20, x21
; CHECK-NEXT: b.lt .LBB9_1
; CHECK-NEXT: .LBB9_3: // %while.end
; CHECK-NEXT: ldp x20, x19, [sp, #32] // 16-byte Folded Reload
; CHECK-NEXT: ldp x22, x21, [sp, #16] // 16-byte Folded Reload
; CHECK-NEXT: ldr x30, [sp], #48 // 8-byte Folded Reload
; CHECK-NEXT: .cfi_def_cfa_offset 0
; CHECK-NEXT: .cfi_restore w19
; CHECK-NEXT: .cfi_restore w20
; CHECK-NEXT: .cfi_restore w21
; CHECK-NEXT: .cfi_restore w22
; CHECK-NEXT: .cfi_restore w30
; CHECK-NEXT: ret
entry:
%0 = load i64, ptr %hdCall, align 8
br label %land.rhs
land.rhs:
%rp.06 = phi i64 [ %0, %entry ], [ %sub, %while.body ]
%1 = load i64, ptr inttoptr (i64 24 to ptr), align 8
%cmp2 = icmp sgt i64 %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 i64 %rp.06, -2
%cmp = icmp slt i64 %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 {
; CHECK-LABEL: do_nothing_if_resultant_opcodes_would_differ:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill
; CHECK-NEXT: .cfi_offset w19, -8
; CHECK-NEXT: .cfi_offset w20, -16
; CHECK-NEXT: .cfi_offset w30, -32
; CHECK-NEXT: adrp x19, :got:a
; CHECK-NEXT: ldr x19, [x19, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x19]
; CHECK-NEXT: cmn w8, #2
; CHECK-NEXT: b.gt .LBB10_4
; CHECK-NEXT: // %bb.1: // %while.body.preheader
; CHECK-NEXT: sub w20, w8, #1
; CHECK-NEXT: .LBB10_2: // %while.body
; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: bl do_something
; CHECK-NEXT: adds w20, w20, #1
; CHECK-NEXT: b.mi .LBB10_2
; CHECK-NEXT: // %bb.3: // %while.cond.while.end_crit_edge
; CHECK-NEXT: ldr w8, [x19]
; CHECK-NEXT: .LBB10_4: // %while.end
; CHECK-NEXT: cmp w8, #1
; CHECK-NEXT: b.gt .LBB10_7
; CHECK-NEXT: // %bb.5: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB10_7
; CHECK-NEXT: // %bb.6:
; CHECK-NEXT: mov w0, #123 // =0x7b
; CHECK-NEXT: b .LBB10_8
; CHECK-NEXT: .LBB10_7: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: .LBB10_8: // %return
; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload
; CHECK-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload
; CHECK-NEXT: .cfi_def_cfa_offset 0
; CHECK-NEXT: .cfi_restore w19
; CHECK-NEXT: .cfi_restore w20
; CHECK-NEXT: .cfi_restore w30
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset w19, -8
; CHECK-NEXT: .cfi_offset w30, -16
; CHECK-NEXT: .cfi_remember_state
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #0
; CHECK-NEXT: b.gt .LBB11_3
; CHECK-NEXT: // %bb.1: // %while.body.preheader
; CHECK-NEXT: sub w19, w8, #1
; CHECK-NEXT: .LBB11_2: // %while.body
; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
; CHECK-NEXT: bl do_something
; CHECK-NEXT: adds w19, w19, #1
; CHECK-NEXT: b.mi .LBB11_2
; CHECK-NEXT: .LBB11_3: // %while.end
; CHECK-NEXT: adrp x8, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmn w8, #2
; CHECK-NEXT: b.lt .LBB11_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB11_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #123 // =0x7b
; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload
; CHECK-NEXT: .cfi_def_cfa_offset 0
; CHECK-NEXT: .cfi_restore w19
; CHECK-NEXT: .cfi_restore w30
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB11_6: // %if.end
; CHECK-NEXT: .cfi_restore_state
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload
; CHECK-NEXT: .cfi_def_cfa_offset 0
; CHECK-NEXT: .cfi_restore w19
; CHECK-NEXT: .cfi_restore w30
; CHECK-NEXT: ret
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
}
; Test in the following case, we don't hit 'cmp' and trigger a false positive
; cmp w19, #0
; cinc w0, w19, gt
; ...
; fcmp d8, #0.0
; b.gt .LBB0_5
define i32 @fcmpri(i32 %argc, ptr nocapture readonly %argv) #0 {
; CHECK-LABEL: fcmpri:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp w0, #2
; CHECK-NEXT: b.lt .LBB12_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: ldr x8, [x1, #8]
; CHECK-NEXT: cbz x8, .LBB12_3
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #3 // =0x3
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB12_3: // %if.end
; CHECK-NEXT: str d8, [sp, #-32]! // 8-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: stp x30, x19, [sp, #16] // 16-byte Folded Spill
; CHECK-NEXT: .cfi_offset w19, -8
; CHECK-NEXT: .cfi_offset w30, -16
; CHECK-NEXT: .cfi_offset b8, -32
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: bl zoo
; CHECK-NEXT: mov w19, w0
; CHECK-NEXT: mov w0, #-1 // =0xffffffff
; CHECK-NEXT: bl yoo
; CHECK-NEXT: cmp w19, #0
; CHECK-NEXT: mov w1, #2 // =0x2
; CHECK-NEXT: fmov d8, d0
; CHECK-NEXT: cinc w0, w19, gt
; CHECK-NEXT: bl xoo
; CHECK-NEXT: fmov d0, #-1.00000000
; CHECK-NEXT: fcmp d8, #0.0
; CHECK-NEXT: fmov d1, #-2.00000000
; CHECK-NEXT: fadd d0, d8, d0
; CHECK-NEXT: fcsel d0, d8, d0, gt
; CHECK-NEXT: bl woo
; CHECK-NEXT: ldp x30, x19, [sp, #16] // 16-byte Folded Reload
; CHECK-NEXT: mov w0, #4 // =0x4
; CHECK-NEXT: ldr d8, [sp], #32 // 8-byte Folded Reload
; CHECK-NEXT: .cfi_def_cfa_offset 0
; CHECK-NEXT: .cfi_restore w19
; CHECK-NEXT: .cfi_restore w30
; CHECK-NEXT: .cfi_restore b8
; CHECK-NEXT: ret
; CHECK-LABEL-DAG: .LBB9_3
entry:
%cmp = icmp sgt i32 %argc, 1
br i1 %cmp, label %land.lhs.true, label %if.end
land.lhs.true: ; preds = %entry
%arrayidx = getelementptr inbounds ptr, ptr %argv, i64 1
%0 = load ptr, ptr %arrayidx, align 8
%cmp1 = icmp eq ptr %0, null
br i1 %cmp1, label %if.end, label %return
if.end: ; preds = %land.lhs.true, %entry
%call = call i32 @zoo(i32 1)
%call2 = call double @yoo(i32 -1)
%cmp4 = icmp sgt i32 %call, 0
%add = zext i1 %cmp4 to i32
%cond = add nsw i32 %add, %call
%call7 = call i32 @xoo(i32 %cond, i32 2)
%cmp9 = fcmp ogt double %call2, 0.000000e+00
br i1 %cmp9, label %cond.end14, label %cond.false12
cond.false12: ; preds = %if.end
%sub = fadd fast double %call2, -1.000000e+00
br label %cond.end14
cond.end14: ; preds = %if.end, %cond.false12
%cond15 = phi double [ %sub, %cond.false12 ], [ %call2, %if.end ]
%call16 = call i32 @woo(double %cond15, double -2.000000e+00)
br label %return
return: ; preds = %land.lhs.true, %cond.end14
%retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ]
ret i32 %retval.0
}
define void @cmp_shifted(i32 %in, i32 %lhs, i32 %rhs) #0 {
; CHECK-LABEL: cmp_shifted:
; CHECK: // %bb.0: // %common.ret
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset w30, -16
; CHECK-NEXT: mov w8, #42 // =0x2a
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: mov w9, #128 // =0x80
; CHECK-NEXT: csinc w8, w8, wzr, gt
; CHECK-NEXT: cmp w0, #2, lsl #12 // =8192
; CHECK-NEXT: csel w0, w9, w8, ge
; CHECK-NEXT: bl zoo
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
; CHECK-NEXT: .cfi_def_cfa_offset 0
; CHECK-NEXT: .cfi_restore w30
; CHECK-NEXT: ret
; [...]
%tst_low = icmp sgt i32 %in, 8191
br i1 %tst_low, label %true, label %false
true:
call i32 @zoo(i32 128)
ret void
false:
%tst = icmp sgt i32 %in, 0
br i1 %tst, label %truer, label %falser
truer:
call i32 @zoo(i32 42)
ret void
falser:
call i32 @zoo(i32 1)
ret void
}
define i32 @combine_gt_ge_sel(i64 %v, ptr %p) #0 {
; CHECK-LABEL: combine_gt_ge_sel:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #0
; CHECK-NEXT: csel x9, x0, xzr, gt
; CHECK-NEXT: str x9, [x1]
; CHECK-NEXT: b.le .LBB14_2
; CHECK-NEXT: // %bb.1: // %lor.lhs.false
; CHECK-NEXT: cmp w8, #2
; CHECK-NEXT: b.ge .LBB14_4
; CHECK-NEXT: b .LBB14_6
; CHECK-NEXT: .LBB14_2: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB14_4
; CHECK-NEXT: // %bb.3:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB14_4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB14_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB14_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
entry:
%0 = load i32, ptr @a, align 4
%cmp = icmp sgt i32 %0, 0
%m = select i1 %cmp, i64 %v, i64 0
store i64 %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
}
; Negative test: cross-block with different registers should not be optimized.
; Identical to combine_gt_ge_10, but lor.lhs.false compares @b instead of @a.
; (a > 10 && b == c) || (b >= 10 && b == d)
define i32 @combine_gt_ge_different_regs() #0 {
; CHECK-LABEL: combine_gt_ge_different_regs:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w10, [x8]
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: cmp w10, #11
; CHECK-NEXT: ldr w9, [x8]
; CHECK-NEXT: b.lt .LBB15_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x10, :got:c
; CHECK-NEXT: ldr x10, [x10, :got_lo12:c]
; CHECK-NEXT: ldr w10, [x10]
; CHECK-NEXT: cmp w9, w10
; CHECK-NEXT: b.ne .LBB15_4
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB15_3: // %lor.lhs.false
; CHECK-NEXT: cmp w9, #10
; CHECK-NEXT: b.lt .LBB15_6
; CHECK-NEXT: .LBB15_4: // %land.lhs.true3
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB15_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB15_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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
%3 = load i32, ptr @b, align 4
%cmp2 = icmp sgt i32 %3, 9
br i1 %cmp2, label %land.lhs.true3, label %if.end
land.lhs.true3: ; preds = %lor.lhs.false, %land.lhs.true
%4 = load i32, ptr @b, align 4
%5 = load i32, ptr @d, align 4
%cmp4 = icmp eq i32 %4, %5
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 > 10 && b == c) || (a >= 10 && b == d)
define i32 @combine_ugt_uge_10() #0 {
; CHECK-LABEL: combine_ugt_uge_10:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #10
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: b.ls .LBB16_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w10, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w10, w9
; CHECK-NEXT: b.ne .LBB16_4
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB16_3: // %lor.lhs.false
; CHECK-NEXT: b.lo .LBB16_6
; CHECK-NEXT: .LBB16_4: // %land.lhs.true3
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB16_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB16_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_ugt_ult_5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #5
; CHECK-NEXT: b.ls .LBB17_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB17_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB17_3: // %lor.lhs.false
; CHECK-NEXT: b.hs .LBB17_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB17_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB17_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_ult_uge_5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #5
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: b.hs .LBB18_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w10, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w10, w9
; CHECK-NEXT: b.ne .LBB18_4
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB18_3: // %lor.lhs.false
; CHECK-NEXT: b.hi .LBB18_6
; CHECK-NEXT: .LBB18_4: // %land.lhs.true3
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB18_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB18_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_ult_ugt_5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmp w8, #5
; CHECK-NEXT: b.hs .LBB19_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB19_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB19_3: // %lor.lhs.false
; CHECK-NEXT: b.ls .LBB19_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB19_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB19_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_ugt_ult_n5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmn w8, #5
; CHECK-NEXT: b.ls .LBB20_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB20_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB20_3: // %lor.lhs.false
; CHECK-NEXT: b.hs .LBB20_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB20_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB20_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_ult_ugt_n5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmn w8, #5
; CHECK-NEXT: b.hs .LBB21_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB21_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB21_3: // %lor.lhs.false
; CHECK-NEXT: b.ls .LBB21_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB21_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB21_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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 {
; CHECK-LABEL: combine_ult_gt_n5:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cmn w8, #5
; CHECK-NEXT: b.hs .LBB22_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB22_6
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB22_3: // %lor.lhs.false
; CHECK-NEXT: b.le .LBB22_6
; CHECK-NEXT: // %bb.4: // %land.lhs.true3
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB22_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB22_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
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
}
; Test in the following case, we don't hit 'cmp' and trigger a false positive
; cmp w19, #0
; cinc w0, w19, gt
; ...
; fcmp d8, #0.0
; b.gt .LBB0_5
define i32 @fcmpri_u(i32 %argc, ptr nocapture readonly %argv) #0 {
; CHECK-LABEL: fcmpri_u:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: cmp w0, #2
; CHECK-NEXT: b.lo .LBB23_3
; CHECK-NEXT: // %bb.1: // %land.lhs.true
; CHECK-NEXT: ldr x8, [x1, #8]
; CHECK-NEXT: cbz x8, .LBB23_3
; CHECK-NEXT: // %bb.2:
; CHECK-NEXT: mov w0, #3 // =0x3
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB23_3: // %if.end
; CHECK-NEXT: str d8, [sp, #-32]! // 8-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: stp x30, x19, [sp, #16] // 16-byte Folded Spill
; CHECK-NEXT: .cfi_offset w19, -8
; CHECK-NEXT: .cfi_offset w30, -16
; CHECK-NEXT: .cfi_offset b8, -32
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: bl zoo
; CHECK-NEXT: mov w19, w0
; CHECK-NEXT: mov w0, #-1 // =0xffffffff
; CHECK-NEXT: bl yoo
; CHECK-NEXT: cmp w19, #0
; CHECK-NEXT: mov w1, #2 // =0x2
; CHECK-NEXT: fmov d8, d0
; CHECK-NEXT: cinc w0, w19, ne
; CHECK-NEXT: bl xoo
; CHECK-NEXT: fmov d0, #-1.00000000
; CHECK-NEXT: fcmp d8, #0.0
; CHECK-NEXT: fmov d1, #-2.00000000
; CHECK-NEXT: fadd d0, d8, d0
; CHECK-NEXT: fcsel d0, d8, d0, gt
; CHECK-NEXT: bl woo
; CHECK-NEXT: ldp x30, x19, [sp, #16] // 16-byte Folded Reload
; CHECK-NEXT: mov w0, #4 // =0x4
; CHECK-NEXT: ldr d8, [sp], #32 // 8-byte Folded Reload
; CHECK-NEXT: .cfi_def_cfa_offset 0
; CHECK-NEXT: .cfi_restore w19
; CHECK-NEXT: .cfi_restore w30
; CHECK-NEXT: .cfi_restore b8
; CHECK-NEXT: ret
; CHECK-LABEL-DAG: .LBB9_3
entry:
%cmp = icmp ugt i32 %argc, 1
br i1 %cmp, label %land.lhs.true, label %if.end
land.lhs.true: ; preds = %entry
%arrayidx = getelementptr inbounds ptr, ptr %argv, i64 1
%0 = load ptr, ptr %arrayidx, align 8
%cmp1 = icmp eq ptr %0, null
br i1 %cmp1, label %if.end, label %return
if.end: ; preds = %land.lhs.true, %entry
%call = call i32 @zoo(i32 1)
%call2 = call double @yoo(i32 -1)
%cmp4 = icmp ugt i32 %call, 0
%add = zext i1 %cmp4 to i32
%cond = add nuw i32 %add, %call
%call7 = call i32 @xoo(i32 %cond, i32 2)
%cmp9 = fcmp ogt double %call2, 0.000000e+00
br i1 %cmp9, label %cond.end14, label %cond.false12
cond.false12: ; preds = %if.end
%sub = fadd fast double %call2, -1.000000e+00
br label %cond.end14
cond.end14: ; preds = %if.end, %cond.false12
%cond15 = phi double [ %sub, %cond.false12 ], [ %call2, %if.end ]
%call16 = call i32 @woo(double %cond15, double -2.000000e+00)
br label %return
return: ; preds = %land.lhs.true, %cond.end14
%retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ]
ret i32 %retval.0
}
define void @cmp_shifted_unsigned(i32 %in, i32 %lhs, i32 %rhs) #0 {
; CHECK-LABEL: cmp_shifted_unsigned:
; CHECK: // %bb.0: // %common.ret
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset w30, -16
; CHECK-NEXT: lsr w9, w0, #13
; CHECK-NEXT: mov w8, #42 // =0x2a
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: csinc w8, w8, wzr, ne
; CHECK-NEXT: cmp w9, #0
; CHECK-NEXT: mov w9, #128 // =0x80
; CHECK-NEXT: csel w0, w9, w8, ne
; CHECK-NEXT: bl zoo
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
; CHECK-NEXT: .cfi_def_cfa_offset 0
; CHECK-NEXT: .cfi_restore w30
; CHECK-NEXT: ret
; [...]
%tst_low = icmp ugt i32 %in, 8191
br i1 %tst_low, label %true, label %false
true:
call i32 @zoo(i32 128)
ret void
false:
%tst = icmp ugt i32 %in, 0
br i1 %tst, label %truer, label %falser
truer:
call i32 @zoo(i32 42)
ret void
falser:
call i32 @zoo(i32 1)
ret void
}
define i32 @combine_ugt_uge_sel(i64 %v, ptr %p) #0 {
; CHECK-LABEL: combine_ugt_uge_sel:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: adrp x8, :got:a
; CHECK-NEXT: ldr x8, [x8, :got_lo12:a]
; CHECK-NEXT: ldr w9, [x8]
; CHECK-NEXT: adrp x8, :got:b
; CHECK-NEXT: ldr x8, [x8, :got_lo12:b]
; CHECK-NEXT: cmp w9, #0
; CHECK-NEXT: csel x10, x0, xzr, ne
; CHECK-NEXT: str x10, [x1]
; CHECK-NEXT: cbz w9, .LBB25_2
; CHECK-NEXT: // %bb.1: // %lor.lhs.false
; CHECK-NEXT: cmp w9, #2
; CHECK-NEXT: b.hs .LBB25_4
; CHECK-NEXT: b .LBB25_6
; CHECK-NEXT: .LBB25_2: // %land.lhs.true
; CHECK-NEXT: adrp x9, :got:c
; CHECK-NEXT: ldr x9, [x9, :got_lo12:c]
; CHECK-NEXT: ldr w10, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w10, w9
; CHECK-NEXT: b.ne .LBB25_4
; CHECK-NEXT: // %bb.3:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB25_4: // %land.lhs.true3
; CHECK-NEXT: adrp x9, :got:d
; CHECK-NEXT: ldr x9, [x9, :got_lo12:d]
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: ldr w9, [x9]
; CHECK-NEXT: cmp w8, w9
; CHECK-NEXT: b.ne .LBB25_6
; CHECK-NEXT: // %bb.5:
; CHECK-NEXT: mov w0, #1 // =0x1
; CHECK-NEXT: ret
; CHECK-NEXT: .LBB25_6: // %if.end
; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ret
entry:
%0 = load i32, ptr @a, align 4
%cmp = icmp ugt i32 %0, 0
%m = select i1 %cmp, i64 %v, i64 0
store i64 %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
}
declare i32 @zoo(i32)
declare double @yoo(i32)
declare i32 @xoo(i32, i32)
declare i32 @woo(double, double)
attributes #0 = { uwtable }