mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
c7933992b4
Summary: If we have e.g.: ``` %t = icmp ult i32 %x, 65536 %r = select i1 %t, i32 %y, i32 65535 ``` the constants `65535` and `65536` are suspiciously close. We could perform a transformation to deduplicate them: ``` Name: ult %t = icmp ult i32 %x, 65536 %r = select i1 %t, i32 %y, i32 65535 => %t.inv = icmp ugt i32 %x, 65535 %r = select i1 %t.inv, i32 65535, i32 %y ``` https://rise4fun.com/Alive/avb While this may seem esoteric, this should certainly be good for vectors (less constant pool usage) and for opt-for-size - need to have only one constant. But the real fun part here is that it allows further transformation, in particular it finishes cleaning up the `clamp` folding, see e.g. `canonicalize-clamp-with-select-of-constant-threshold-pattern.ll`. We start with e.g. ``` %dont_need_to_clamp_positive = icmp sle i32 %X, 32767 %dont_need_to_clamp_negative = icmp sge i32 %X, -32768 %clamp_limit = select i1 %dont_need_to_clamp_positive, i32 -32768, i32 32767 %dont_need_to_clamp = and i1 %dont_need_to_clamp_positive, %dont_need_to_clamp_negative %R = select i1 %dont_need_to_clamp, i32 %X, i32 %clamp_limit ``` without this patch we currently produce ``` %1 = icmp slt i32 %X, 32768 %2 = icmp sgt i32 %X, -32768 %3 = select i1 %2, i32 %X, i32 -32768 %R = select i1 %1, i32 %3, i32 32767 ``` which isn't really a `clamp` - both comparisons are performed on the original value, this patch changes it into ``` %1.inv = icmp sgt i32 %X, 32767 %2 = icmp sgt i32 %X, -32768 %3 = select i1 %2, i32 %X, i32 -32768 %R = select i1 %1.inv, i32 32767, i32 %3 ``` and then the magic happens! Some further transform finishes polishing it and we finally get: ``` %t1 = icmp sgt i32 %X, -32768 %t2 = select i1 %t1, i32 %X, i32 -32768 %t3 = icmp slt i32 %t2, 32767 %R = select i1 %t3, i32 %t2, i32 32767 ``` which is beautiful and just what we want. Proofs for `getFlippedStrictnessPredicateAndConstant()` for de-canonicalization: https://rise4fun.com/Alive/THl Proofs for the fold itself: https://rise4fun.com/Alive/THl Reviewers: spatel, dmgreen, nikic, xbolva00 Reviewed By: spatel Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66232 llvm-svn: 369840
337 lines
12 KiB
LLVM
337 lines
12 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
; If we have a relational comparison with a constant, and said comparison is
|
|
; used in a select, and there is a constant in select, see if we can make
|
|
; those constants match.
|
|
|
|
; We can't ever get non-canonical scalar predicates.
|
|
|
|
; Likewise, while we can get non-canonical vector predicates, there must be an
|
|
; extra use on that `icmp`, which precludes the fold from happening.
|
|
|
|
;------------------------------------------------------------------------------;
|
|
; Canonical scalar predicates
|
|
;------------------------------------------------------------------------------;
|
|
|
|
!0 = !{!"branch_weights", i32 2000, i32 1}
|
|
|
|
define i32 @p0_ult_65536(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @p0_ult_65536(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]], !prof !0
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i32 %x, 65536
|
|
%r = select i1 %t, i32 %y, i32 65535, !prof !0
|
|
ret i32 %r
|
|
}
|
|
define i32 @p1_ugt(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @p1_ugt(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ult i32 [[X:%.*]], 65535
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ugt i32 %x, 65534
|
|
%r = select i1 %t, i32 %y, i32 65535
|
|
ret i32 %r
|
|
}
|
|
define i32 @p2_slt_65536(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @p2_slt_65536(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt i32 [[X:%.*]], 65535
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp slt i32 %x, 65536
|
|
%r = select i1 %t, i32 %y, i32 65535
|
|
ret i32 %r
|
|
}
|
|
define i32 @p3_sgt(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @p3_sgt(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp slt i32 [[X:%.*]], 65535
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp sgt i32 %x, 65534
|
|
%r = select i1 %t, i32 %y, i32 65535
|
|
ret i32 %r
|
|
}
|
|
|
|
;------------------------------------------------------------------------------;
|
|
; Vectors
|
|
;------------------------------------------------------------------------------;
|
|
|
|
define <2 x i32> @p4_vec_splat_ult_65536(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @p4_vec_splat_ult_65536(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp ult <2 x i32> %x, <i32 65536, i32 65536>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
|
|
ret <2 x i32> %r
|
|
}
|
|
define <2 x i32> @p5_vec_splat_ugt(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @p5_vec_splat_ugt(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp ugt <2 x i32> %x, <i32 65534, i32 65534>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
|
|
ret <2 x i32> %r
|
|
}
|
|
define <2 x i32> @p6_vec_splat_slt_65536(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @p6_vec_splat_slt_65536(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp slt <2 x i32> %x, <i32 65536, i32 65536>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
|
|
ret <2 x i32> %r
|
|
}
|
|
define <2 x i32> @p7_vec_splat_sgt(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @p7_vec_splat_sgt(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp sgt <2 x i32> %x, <i32 65534, i32 65534>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
|
|
ret <2 x i32> %r
|
|
}
|
|
|
|
; Vectors with undef
|
|
|
|
define <2 x i32> @p8_vec_nonsplat_undef0(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @p8_vec_nonsplat_undef0(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 undef>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 65535>, <2 x i32> [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp ult <2 x i32> %x, <i32 65536, i32 undef>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 65535>
|
|
ret <2 x i32> %r
|
|
}
|
|
define <2 x i32> @p9_vec_nonsplat_undef1(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @p9_vec_nonsplat_undef1(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 65535>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 undef>, <2 x i32> [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp ult <2 x i32> %x, <i32 65536, i32 65536>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 undef>
|
|
ret <2 x i32> %r
|
|
}
|
|
define <2 x i32> @p10_vec_nonsplat_undef2(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @p10_vec_nonsplat_undef2(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 undef>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 undef>, <2 x i32> [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp ult <2 x i32> %x, <i32 65536, i32 undef>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 undef>
|
|
ret <2 x i32> %r
|
|
}
|
|
|
|
; Non-splat vectors
|
|
|
|
define <2 x i32> @p11_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @p11_vec_nonsplat(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65535, i32 32767>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> <i32 65535, i32 32767>, <2 x i32> [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp ult <2 x i32> %x, <i32 65536, i32 32768>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 32767>
|
|
ret <2 x i32> %r
|
|
}
|
|
|
|
;------------------------------------------------------------------------------;
|
|
; Extra uses prevent the fold.
|
|
;------------------------------------------------------------------------------;
|
|
|
|
declare void @use1(i1)
|
|
|
|
define i32 @n12_extrause(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @n12_extrause(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
|
|
; CHECK-NEXT: call void @use1(i1 [[T]])
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i32 %x, 65536
|
|
call void @use1(i1 %t)
|
|
%r = select i1 %t, i32 %y, i32 65535
|
|
ret i32 %r
|
|
}
|
|
|
|
;------------------------------------------------------------------------------;
|
|
; Commutativity
|
|
;------------------------------------------------------------------------------;
|
|
|
|
; We don't care if the constant in select is true value or false value
|
|
define i32 @p13_commutativity0(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @p13_commutativity0(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 65535
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i32 %x, 65536
|
|
%r = select i1 %t, i32 65535, i32 %y
|
|
ret i32 %r
|
|
}
|
|
|
|
; Which means, if both possibilities are constants, we must check both of them.
|
|
define i32 @p14_commutativity1(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @p14_commutativity1(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 42, i32 65535
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i32 %x, 65536
|
|
%r = select i1 %t, i32 65535, i32 42
|
|
ret i32 %r
|
|
}
|
|
define i32 @p15_commutativity2(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @p15_commutativity2(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 42
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i32 %x, 65536
|
|
%r = select i1 %t, i32 42, i32 65535
|
|
ret i32 %r
|
|
}
|
|
|
|
;------------------------------------------------------------------------------;
|
|
; Negative tests
|
|
;------------------------------------------------------------------------------;
|
|
|
|
; For vectors, make sure we handle edge cases correctly
|
|
define <2 x i32> @n17_ult_zero(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @n17_ult_zero(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> [[X:%.*]], <i32 65536, i32 0>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 -1>
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp ult <2 x i32> %x, <i32 65536, i32 0>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 -1>
|
|
ret <2 x i32> %r
|
|
}
|
|
define <2 x i32> @n18_ugt_allones(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @n18_ugt_allones(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> [[X:%.*]], <i32 65534, i32 -1>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 0>
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp ugt <2 x i32> %x, <i32 65534, i32 -1>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 0>
|
|
ret <2 x i32> %r
|
|
}
|
|
define <2 x i32> @n19_slt_int_min(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @n19_slt_int_min(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 65536, i32 -2147483648>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 2147483647>
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp slt <2 x i32> %x, <i32 65536, i32 -2147483648>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 2147483647>
|
|
ret <2 x i32> %r
|
|
}
|
|
define <2 x i32> @n20_sgt_int_max(<2 x i32> %x, <2 x i32> %y) {
|
|
; CHECK-LABEL: @n20_sgt_int_max(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 65534, i32 2147483647>
|
|
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 65535, i32 -2147483648>
|
|
; CHECK-NEXT: ret <2 x i32> [[R]]
|
|
;
|
|
%t = icmp sgt <2 x i32> %x, <i32 65534, i32 2147483647>
|
|
%r = select <2 x i1> %t, <2 x i32> %y, <2 x i32> <i32 65535, i32 -2147483648>
|
|
ret <2 x i32> %r
|
|
}
|
|
|
|
; We don't do anything for non-relational comparisons.
|
|
define i32 @n21_equality(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @n21_equality(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp eq i32 [[X:%.*]], -2147483648
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 2147483647, i32 [[Y:%.*]]
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp eq i32 %x, -2147483648
|
|
%r = select i1 %t, i32 2147483647, i32 %y
|
|
ret i32 %r
|
|
}
|
|
|
|
; There is nothing special about sign-bit-tests, we can fold them.
|
|
define i32 @t22_sign_check(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @t22_sign_check(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt i32 [[X:%.*]], -1
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 -1
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp slt i32 %x, 0
|
|
%r = select i1 %t, i32 -1, i32 %y
|
|
ret i32 %r
|
|
}
|
|
define i32 @t22_sign_check2(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @t22_sign_check2(
|
|
; CHECK-NEXT: [[T_INV:%.*]] = icmp slt i32 [[X:%.*]], 0
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 0
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp sgt i32 %x, -1
|
|
%r = select i1 %t, i32 0, i32 %y
|
|
ret i32 %r
|
|
}
|
|
|
|
; If the types don't match we currently don't do anything.
|
|
define i32 @n23_type_mismatch(i64 %x, i32 %y) {
|
|
; CHECK-LABEL: @n23_type_mismatch(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp ult i64 [[X:%.*]], 65536
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i64 %x, 65536
|
|
%r = select i1 %t, i32 %y, i32 65535
|
|
ret i32 %r
|
|
}
|
|
|
|
; Don't do wrong tranform
|
|
define i32 @n24_ult_65534(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @n24_ult_65534(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65534
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i32 %x, 65534
|
|
%r = select i1 %t, i32 %y, i32 65535
|
|
ret i32 %r
|
|
}
|
|
|
|
; If we already have a match, it's good enough.
|
|
define i32 @n25_all_good0(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @n25_all_good0(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 65535, i32 65536
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i32 %x, 65536
|
|
%r = select i1 %t, i32 65535, i32 65536
|
|
ret i32 %r
|
|
}
|
|
define i32 @n26_all_good1(i32 %x, i32 %y) {
|
|
; CHECK-LABEL: @n26_all_good1(
|
|
; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
|
|
; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 65536, i32 65535
|
|
; CHECK-NEXT: ret i32 [[R]]
|
|
;
|
|
%t = icmp ult i32 %x, 65536
|
|
%r = select i1 %t, i32 65536, i32 65535
|
|
ret i32 %r
|
|
}
|
|
|
|
|
|
|
|
; CHECK: !0 = !{!"branch_weights", i32 1, i32 2000}
|