1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00
llvm-mirror/test/CodeGen/SystemZ/int-cmp-44.ll
Jonas Paulsson 61f35cd2aa [SystemZ] Bugfix and improve the handling of CC values.
It was recently discovered that the handling of CC values was actually broken
since overflow was not properly handled ('nsw' flag not checked for).

Add and sub instructions now have a new target specific instruction flag
named SystemZII::CCIfNoSignedWrap. It means that the CC result can be used
instead of a compare with 0, but only if the instruction has the 'nsw' flag
set.

This patch also adds the improvements of conversion to logical instructions
and the analyzing of add with immediates, to be able to eliminate more
compares.

Review: Ulrich Weigand
https://reviews.llvm.org/D66868
2019-12-20 10:20:23 -08:00

890 lines
18 KiB
LLVM

; Test that compares are omitted if CC already has the right value
; (z10 version).
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -no-integrated-as \
; RUN: -verify-machineinstrs| FileCheck %s
declare void @foo()
; Addition provides enough for comparisons with zero if we know no
; signed overflow happens, which is when the "nsw" flag is set.
; First test the EQ case.
define i32 @f1(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f1:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: ber %r14
; CHECK: br %r14
entry:
%res = add nsw i32 %a, 1000000
%cmp = icmp eq i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and again with NE.
define i32 @f2(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f2:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: blhr %r14
; CHECK: br %r14
entry:
%res = add nsw i32 %a, 1000000
%cmp = icmp ne i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and again with SLT.
define i32 @f3(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f3:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: blr %r14
entry:
%res = add nsw i32 %a, 1000000
%cmp = icmp slt i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and again with SLE.
define i32 @f4(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f4:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: bler %r14
entry:
%res = add nsw i32 %a, 1000000
%cmp = icmp sle i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and again with SGT.
define i32 @f5(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f5:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: bhr %r14
entry:
%res = add nsw i32 %a, 1000000
%cmp = icmp sgt i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and again with SGE.
define i32 @f6(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f6:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: bher %r14
entry:
%res = add nsw i32 %a, 1000000
%cmp = icmp sge i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; Subtraction provides in addition also enough for equality comparisons with
; zero even without "nsw".
define i32 @f7(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f7:
; CHECK: s %r2, 0(%r4)
; CHECK-NEXT: bner %r14
; CHECK: br %r14
entry:
%cur = load i32, i32 *%dest
%res = sub i32 %a, %cur
%cmp = icmp ne i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and again with SLT.
define i32 @f8(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f8:
; CHECK: s %r2, 0(%r4)
; CHECK-NEXT: blr %r14
entry:
%cur = load i32, i32 *%dest
%res = sub nsw i32 %a, %cur
%cmp = icmp slt i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; Logic register-register instructions also provide enough for equality
; comparisons with zero.
define i32 @f9(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f9:
; CHECK: nr %r2, %r3
; CHECK-NEXT: blr %r14
; CHECK: br %r14
entry:
%res = and i32 %a, %b
%cmp = icmp ne i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...but not for ordered comparisons.
define i32 @f10(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f10:
; CHECK: nr %r2, %r3
; CHECK-NEXT: cibl %r2, 0, 0(%r14)
; CHECK: br %r14
entry:
%res = and i32 %a, %b
%cmp = icmp slt i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; Logic register-immediate instructions also provide enough for equality
; comparisons with zero if the immediate covers the whole register.
define i32 @f11(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f11:
; CHECK: nilf %r2, 100000001
; CHECK-NEXT: blr %r14
; CHECK: br %r14
entry:
%res = and i32 %a, 100000001
%cmp = icmp ne i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; Partial logic register-immediate instructions do not provide simple
; zero results.
define i32 @f12(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f12:
; CHECK: nill %r2, 65436
; CHECK-NEXT: ciblh %r2, 0, 0(%r14)
; CHECK: br %r14
entry:
%res = and i32 %a, -100
%cmp = icmp ne i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; SRA provides the same CC result as a comparison with zero.
define i32 @f13(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f13:
; CHECK: sra %r2, 0(%r3)
; CHECK-NEXT: ber %r14
; CHECK: br %r14
entry:
%res = ashr i32 %a, %b
%cmp = icmp eq i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and again with NE.
define i32 @f14(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f14:
; CHECK: sra %r2, 0(%r3)
; CHECK-NEXT: blhr %r14
; CHECK: br %r14
entry:
%res = ashr i32 %a, %b
%cmp = icmp ne i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and SLT.
define i32 @f15(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f15:
; CHECK: sra %r2, 0(%r3)
; CHECK-NEXT: blr %r14
; CHECK: br %r14
entry:
%res = ashr i32 %a, %b
%cmp = icmp slt i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and SLE.
define i32 @f16(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f16:
; CHECK: sra %r2, 0(%r3)
; CHECK-NEXT: bler %r14
; CHECK: br %r14
entry:
%res = ashr i32 %a, %b
%cmp = icmp sle i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and SGT.
define i32 @f17(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f17:
; CHECK: sra %r2, 0(%r3)
; CHECK-NEXT: bhr %r14
; CHECK: br %r14
entry:
%res = ashr i32 %a, %b
%cmp = icmp sgt i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and SGE.
define i32 @f18(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f18:
; CHECK: sra %r2, 0(%r3)
; CHECK-NEXT: bher %r14
; CHECK: br %r14
entry:
%res = ashr i32 %a, %b
%cmp = icmp sge i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; RISBG provides the same result as a comparison against zero.
; Test the EQ case.
define i64 @f19(i64 %a, i64 %b, i64 *%dest) {
; CHECK-LABEL: f19:
; CHECK: risbg %r2, %r3, 0, 190, 0
; CHECK-NEXT: ber %r14
; CHECK: br %r14
entry:
%res = and i64 %b, -2
%cmp = icmp eq i64 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %b, i64 *%dest
br label %exit
exit:
ret i64 %res
}
; ...and the SLT case.
define i64 @f20(i64 %a, i64 %b, i64 *%dest) {
; CHECK-LABEL: f20:
; CHECK: risbg %r2, %r3, 0, 190, 0
; CHECK-NEXT: blr %r14
; CHECK: br %r14
entry:
%res = and i64 %b, -2
%cmp = icmp slt i64 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %b, i64 *%dest
br label %exit
exit:
ret i64 %res
}
; Test a case where the register we're testing is set by a non-CC-clobbering
; instruction.
define i32 @f21(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f21:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r2
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: cibe %r2, 0, 0(%r14)
; CHECK: br %r14
entry:
%add = add i32 %a, 1000000
%res = call i32 asm "blah $0", "=r,0" (i32 %add)
%cmp = icmp eq i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; ...and again with a CC-clobbering instruction.
define i32 @f22(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f22:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r2
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: cibe %r2, 0, 0(%r14)
; CHECK: br %r14
entry:
%add = add i32 %a, 1000000
%res = call i32 asm "blah $0", "=r,0,~{cc}" (i32 %add)
%cmp = icmp eq i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; Check that stores do not interfere.
define i32 @f23(i32 %a, i32 %b, i32 *%dest1, i32 *%dest2) {
; CHECK-LABEL: f23:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: st %r2, 0(%r4)
; CHECK-NEXT: blhr %r14
; CHECK: br %r14
entry:
%res = add nsw i32 %a, 1000000
store i32 %res, i32 *%dest1
%cmp = icmp ne i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest2
br label %exit
exit:
ret i32 %res
}
; Check that calls do interfere.
define void @f24(i32 *%ptr) {
; CHECK-LABEL: f24:
; CHECK: afi [[REG:%r[0-9]+]], 1000000
; CHECK-NEXT: brasl %r14, foo@PLT
; CHECK-NEXT: cijlh [[REG]], 0, .L{{.*}}
; CHECK: br %r14
entry:
%val = load i32, i32 *%ptr
%xor = xor i32 %val, 1
%add = add i32 %xor, 1000000
call void @foo()
%cmp = icmp eq i32 %add, 0
br i1 %cmp, label %store, label %exit, !prof !1
store:
store i32 %add, i32 *%ptr
br label %exit
exit:
ret void
}
; Check that inline asms don't interfere if they don't clobber CC.
define void @f25(i32 %a, i32 *%ptr) {
; CHECK-LABEL: f25:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: #APP
; CHECK-NEXT: blah
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: blhr %r14
; CHECK: br %r14
entry:
%add = add nsw i32 %a, 1000000
call void asm sideeffect "blah", "r"(i32 %add)
%cmp = icmp ne i32 %add, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %add, i32 *%ptr
br label %exit
exit:
ret void
}
; ...but do interfere if they do clobber CC.
define void @f26(i32 %a, i32 *%ptr) {
; CHECK-LABEL: f26:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: #APP
; CHECK-NEXT: blah
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: ciblh %r2, 0, 0(%r14)
; CHECK: br %r14
entry:
%add = add i32 %a, 1000000
call void asm sideeffect "blah", "r,~{cc}"(i32 %add)
%cmp = icmp ne i32 %add, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %add, i32 *%ptr
br label %exit
exit:
ret void
}
; Test a case where CC is set based on a different register from the
; compare input.
define i32 @f27(i32 %a, i32 %b, i32 *%dest1, i32 *%dest2) {
; CHECK-LABEL: f27:
; CHECK: afi %r2, 1000000
; CHECK-NEXT: sr %r3, %r2
; CHECK-NEXT: st %r3, 0(%r4)
; CHECK-NEXT: cibe %r2, 0, 0(%r14)
; CHECK: br %r14
entry:
%add = add nsw i32 %a, 1000000
%sub = sub i32 %b, %add
store i32 %sub, i32 *%dest1
%cmp = icmp eq i32 %add, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %sub, i32 *%dest2
br label %exit
exit:
ret i32 %add
}
; Make sure that we don't confuse a base register for a destination.
define void @f28(i64 %a, i64 *%dest) {
; CHECK-LABEL: f28:
; CHECK: xi 0(%r2), 15
; CHECK: cgibe %r2, 0, 0(%r14)
; CHECK: br %r14
entry:
%ptr = inttoptr i64 %a to i8 *
%val = load i8, i8 *%ptr
%xor = xor i8 %val, 15
store i8 %xor, i8 *%ptr
%cmp = icmp eq i64 %a, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %a, i64 *%dest
br label %exit
exit:
ret void
}
; Test that L gets converted to LT where useful.
define i32 @f29(i64 %base, i64 %index, i32 *%dest) {
; CHECK-LABEL: f29:
; CHECK: lt %r2, 0({{%r2,%r3|%r3,%r2}})
; CHECK-NEXT: bler %r14
; CHECK: br %r14
entry:
%add = add i64 %base, %index
%ptr = inttoptr i64 %add to i32 *
%res = load i32, i32 *%ptr
%cmp = icmp sle i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %res, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; Test that LY gets converted to LT where useful.
define i32 @f30(i64 %base, i64 %index, i32 *%dest) {
; CHECK-LABEL: f30:
; CHECK: lt %r2, 100000({{%r2,%r3|%r3,%r2}})
; CHECK-NEXT: bler %r14
; CHECK: br %r14
entry:
%add1 = add i64 %base, %index
%add2 = add i64 %add1, 100000
%ptr = inttoptr i64 %add2 to i32 *
%res = load i32, i32 *%ptr
%cmp = icmp sle i32 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %res, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; Test that LG gets converted to LTG where useful.
define i64 @f31(i64 %base, i64 %index, i64 *%dest) {
; CHECK-LABEL: f31:
; CHECK: ltg %r2, 0({{%r2,%r3|%r3,%r2}})
; CHECK-NEXT: bher %r14
; CHECK: br %r14
entry:
%add = add i64 %base, %index
%ptr = inttoptr i64 %add to i64 *
%res = load i64, i64 *%ptr
%cmp = icmp sge i64 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %res, i64 *%dest
br label %exit
exit:
ret i64 %res
}
; Test that LGF gets converted to LTGF where useful.
define i64 @f32(i64 %base, i64 %index, i64 *%dest) {
; CHECK-LABEL: f32:
; CHECK: ltgf %r2, 0({{%r2,%r3|%r3,%r2}})
; CHECK-NEXT: bhr %r14
; CHECK: br %r14
entry:
%add = add i64 %base, %index
%ptr = inttoptr i64 %add to i32 *
%val = load i32, i32 *%ptr
%res = sext i32 %val to i64
%cmp = icmp sgt i64 %res, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %res, i64 *%dest
br label %exit
exit:
ret i64 %res
}
; Test that LR gets converted to LTR where useful.
define i32 @f33(i32 %dummy, i32 %val, i32 *%dest) {
; CHECK-LABEL: f33:
; CHECK: ltr %r2, %r3
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r2
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: blr %r14
; CHECK: br %r14
entry:
call void asm sideeffect "blah $0", "{r2}"(i32 %val)
%cmp = icmp slt i32 %val, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %val, i32 *%dest
br label %exit
exit:
ret i32 %val
}
; Test that LGR gets converted to LTGR where useful.
define i64 @f34(i64 %dummy, i64 %val, i64 *%dest) {
; CHECK-LABEL: f34:
; CHECK: ltgr %r2, %r3
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r2
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: bhr %r14
; CHECK: br %r14
entry:
call void asm sideeffect "blah $0", "{r2}"(i64 %val)
%cmp = icmp sgt i64 %val, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %val, i64 *%dest
br label %exit
exit:
ret i64 %val
}
; Test that LGFR gets converted to LTGFR where useful.
define i64 @f35(i64 %dummy, i32 %val, i64 *%dest) {
; CHECK-LABEL: f35:
; CHECK: ltgfr %r2, %r3
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r2
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: bhr %r14
; CHECK: br %r14
entry:
%ext = sext i32 %val to i64
call void asm sideeffect "blah $0", "{r2}"(i64 %ext)
%cmp = icmp sgt i64 %ext, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %ext, i64 *%dest
br label %exit
exit:
ret i64 %ext
}
; Test a case where it is the source rather than destination of LR that
; we need.
define i32 @f36(i32 %val, i32 %dummy, i32 *%dest) {
; CHECK-LABEL: f36:
; CHECK: ltr %r3, %r2
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r3
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: blr %r14
; CHECK: br %r14
entry:
call void asm sideeffect "blah $0", "{r3}"(i32 %val)
%cmp = icmp slt i32 %val, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %val, i32 *%dest
br label %exit
exit:
ret i32 %val
}
; Test a case where it is the source rather than destination of LGR that
; we need.
define i64 @f37(i64 %val, i64 %dummy, i64 *%dest) {
; CHECK-LABEL: f37:
; CHECK: ltgr %r3, %r2
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r3
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: blr %r14
; CHECK: br %r14
entry:
call void asm sideeffect "blah $0", "{r3}"(i64 %val)
%cmp = icmp slt i64 %val, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %val, i64 *%dest
br label %exit
exit:
ret i64 %val
}
; Test a case where it is the source rather than destination of LGFR that
; we need.
define i32 @f38(i32 %val, i64 %dummy, i32 *%dest) {
; CHECK-LABEL: f38:
; CHECK: ltgfr %r3, %r2
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r3
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: blr %r14
; CHECK: br %r14
entry:
%ext = sext i32 %val to i64
call void asm sideeffect "blah $0", "{r3}"(i64 %ext)
%cmp = icmp slt i32 %val, 0
br i1 %cmp, label %exit, label %store
store:
store i32 %val, i32 *%dest
br label %exit
exit:
ret i32 %val
}
; Test f35 for in-register extensions.
define i64 @f39(i64 %dummy, i64 %a, i64 *%dest) {
; CHECK-LABEL: f39:
; CHECK: ltgfr %r2, %r3
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r2
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: bhr %r14
; CHECK: br %r14
entry:
%val = trunc i64 %a to i32
%ext = sext i32 %val to i64
call void asm sideeffect "blah $0", "{r2}"(i64 %ext)
%cmp = icmp sgt i64 %ext, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %ext, i64 *%dest
br label %exit
exit:
ret i64 %ext
}
; ...and again with what InstCombine would produce for f40.
define i64 @f40(i64 %dummy, i64 %a, i64 *%dest) {
; CHECK-LABEL: f40:
; CHECK: ltgfr %r2, %r3
; CHECK-NEXT: #APP
; CHECK-NEXT: blah %r2
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: bhr %r14
; CHECK: br %r14
entry:
%shl = shl i64 %a, 32
%ext = ashr i64 %shl, 32
call void asm sideeffect "blah $0", "{r2}"(i64 %ext)
%cmp = icmp sgt i64 %shl, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %ext, i64 *%dest
br label %exit
exit:
ret i64 %ext
}
; Try a form of f7 in which the subtraction operands are compared directly.
define i32 @f41(i32 %a, i32 %b, i32 *%dest) {
; CHECK-LABEL: f41:
; CHECK: s %r2, 0(%r4)
; CHECK-NEXT: bner %r14
; CHECK: br %r14
entry:
%cur = load i32, i32 *%dest
%res = sub i32 %a, %cur
%cmp = icmp ne i32 %a, %cur
br i1 %cmp, label %exit, label %store
store:
store i32 %b, i32 *%dest
br label %exit
exit:
ret i32 %res
}
; A version of f32 that tests the unextended value.
define i64 @f42(i64 %base, i64 %index, i64 *%dest) {
; CHECK-LABEL: f42:
; CHECK: ltgf %r2, 0({{%r2,%r3|%r3,%r2}})
; CHECK-NEXT: bhr %r14
; CHECK: br %r14
entry:
%add = add i64 %base, %index
%ptr = inttoptr i64 %add to i32 *
%val = load i32, i32 *%ptr
%res = sext i32 %val to i64
%cmp = icmp sgt i32 %val, 0
br i1 %cmp, label %exit, label %store
store:
store i64 %res, i64 *%dest
br label %exit
exit:
ret i64 %res
}
!1 = !{!"branch_weights", i32 2, i32 1}