Skip to content

Commit b396921

Browse files
authored
[SCCP] Handle llvm.vscale intrinsic calls (#114033)
Teach SCCP to compute a constant range for calls to llvm.vscale intrinsics.
1 parent b185e92 commit b396921

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

llvm/lib/Transforms/Utils/SCCPSolver.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1923,6 +1923,12 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {
19231923
return (void)mergeInValue(IV, &CB, CopyOfVal);
19241924
}
19251925

1926+
if (II->getIntrinsicID() == Intrinsic::vscale) {
1927+
unsigned BitWidth = CB.getType()->getScalarSizeInBits();
1928+
const ConstantRange Result = getVScaleRange(II->getFunction(), BitWidth);
1929+
return (void)mergeInValue(II, ValueLatticeElement::getRange(Result));
1930+
}
1931+
19261932
if (ConstantRange::isIntrinsicSupported(II->getIntrinsicID())) {
19271933
// Compute result range for intrinsics supported by ConstantRange.
19281934
// Do this even if we don't know a range for all operands, as we may
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=sccp -S | FileCheck %s
3+
4+
define i1 @vscale_i32_noattr() {
5+
; CHECK-LABEL: define i1 @vscale_i32_noattr() {
6+
; CHECK-NEXT: [[SCALE:%.*]] = call i32 @llvm.vscale.i32()
7+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[SCALE]], 16
8+
; CHECK-NEXT: [[RES:%.*]] = and i1 true, [[CMP2]]
9+
; CHECK-NEXT: ret i1 [[RES]]
10+
;
11+
%scale = call i32 @llvm.vscale.i32()
12+
%cmp1 = icmp uge i32 %scale, 1
13+
%cmp2 = icmp ule i32 %scale, 16
14+
%res = and i1 %cmp1, %cmp2
15+
ret i1 %res
16+
}
17+
18+
define i1 @vscale_i32_attr() vscale_range(1, 16) {
19+
; CHECK-LABEL: define i1 @vscale_i32_attr(
20+
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
21+
; CHECK-NEXT: [[SCALE:%.*]] = call i32 @llvm.vscale.i32()
22+
; CHECK-NEXT: ret i1 true
23+
;
24+
%scale = call i32 @llvm.vscale.i32()
25+
%cmp1 = icmp uge i32 %scale, 1
26+
%cmp2 = icmp ule i32 %scale, 16
27+
%res = and i1 %cmp1, %cmp2
28+
ret i1 %res
29+
}
30+
31+
define i1 @vscale_i64_noattr() {
32+
; CHECK-LABEL: define i1 @vscale_i64_noattr() {
33+
; CHECK-NEXT: [[SCALE:%.*]] = call i64 @llvm.vscale.i64()
34+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i64 [[SCALE]], 16
35+
; CHECK-NEXT: [[RES:%.*]] = and i1 true, [[CMP2]]
36+
; CHECK-NEXT: ret i1 [[RES]]
37+
;
38+
%scale = call i64 @llvm.vscale.i64()
39+
%cmp1 = icmp uge i64 %scale, 1
40+
%cmp2 = icmp ule i64 %scale, 16
41+
%res = and i1 %cmp1, %cmp2
42+
ret i1 %res
43+
}
44+
45+
define i1 @vscale_i64_attr() vscale_range(1, 16) {
46+
; CHECK-LABEL: define i1 @vscale_i64_attr(
47+
; CHECK-SAME: ) #[[ATTR0]] {
48+
; CHECK-NEXT: [[SCALE:%.*]] = call i64 @llvm.vscale.i64()
49+
; CHECK-NEXT: ret i1 true
50+
;
51+
%scale = call i64 @llvm.vscale.i64()
52+
%cmp1 = icmp uge i64 %scale, 1
53+
%cmp2 = icmp ule i64 %scale, 16
54+
%res = and i1 %cmp1, %cmp2
55+
ret i1 %res
56+
}
57+
58+
define i32 @vscale_branch_elim(i32 %x) vscale_range(1, 16) {
59+
; CHECK-LABEL: define i32 @vscale_branch_elim(
60+
; CHECK-SAME: i32 [[X:%.*]]) #[[ATTR0]] {
61+
; CHECK-NEXT: [[ENTRY:.*:]]
62+
; CHECK-NEXT: [[SCALE:%.*]] = call i32 @llvm.vscale.i32()
63+
; CHECK-NEXT: [[BOUND:%.*]] = shl nuw nsw i32 [[SCALE]], 3
64+
; CHECK-NEXT: br label %[[IF_END:.*]]
65+
; CHECK: [[IF_END]]:
66+
; CHECK-NEXT: ret i32 [[X]]
67+
;
68+
entry:
69+
%scale = call i32 @llvm.vscale.i32()
70+
%bound = shl nsw nuw i32 %scale, 3
71+
%cmp = icmp uge i32 1, %bound
72+
br i1 %cmp, label %if.then, label %if.end
73+
74+
if.then:
75+
%double = mul i32 %x, 2
76+
br label %if.end
77+
78+
if.end:
79+
%res = phi i32 [ %x, %entry ], [ %double, %if.then]
80+
ret i32 %res
81+
}

0 commit comments

Comments
 (0)