Skip to content

Commit fa496ce

Browse files
committed
[Intrinsic] Give "is.constant" the "convergent" attribute
Summary: Code frequently relies upon the results of "is.constant" intrinsics to DCE invalid code paths. We don't want the intrinsic to be made control- dependent on any additional values. For instance, we can't split a PHI into a "constant" and "non-constant" part via jump threading in order to "optimize" the constant part, because the "is.constant" intrinsic is meant to return "false". Reviewers: wmi, kazu, MaskRay Reviewed By: kazu Subscribers: jdoerfert, efriedma, joerg, lebedev.ri, nikic, xbolva00, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D75799
1 parent 24485ae commit fa496ce

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,9 @@ def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
11511151
[], "llvm.clear_cache">;
11521152

11531153
// Intrinsic to detect whether its argument is a constant.
1154-
def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem, IntrWillReturn], "llvm.is.constant">;
1154+
def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty],
1155+
[IntrNoMem, IntrWillReturn, IntrConvergent],
1156+
"llvm.is.constant">;
11551157

11561158
// Intrinsic to mask out bits of a pointer.
11571159
def int_ptrmask: Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty, llvm_anyint_ty],
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; RUN: opt -jump-threading -S -verify < %s | FileCheck %s
2+
3+
; This is reduced from the Linux net/ipv4/tcp.c file built with ASAN. We
4+
; don't want jump threading to split up a basic block which has a PHI node with
5+
; at least one constant incoming value, whose value is used by an is.constant
6+
; intrinsic with non-local uses. It could lead to later passes no DCE'ing
7+
; invalid paths.
8+
9+
; CHECK-LABEL: define void @test1(
10+
; CHECK-LABEL: bb_cond:
11+
; CHECK-NOT: %sext = phi i64 [ %var, %entry ]
12+
; CHECK-NEXT: %sext = phi i64 [ 24, %bb_constant ], [ %var, %entry ]
13+
; CHECK-NEXT: %cond2 = icmp
14+
; CHECK-NEXT: call i1 @llvm.is.constant.i64(
15+
16+
define void @test1(i32 %a, i64 %var) {
17+
entry:
18+
%cond1 = icmp ugt i32 %a, 24
19+
br i1 %cond1, label %bb_constant, label %bb_cond
20+
21+
bb_constant:
22+
br label %bb_cond
23+
24+
bb_cond:
25+
%sext = phi i64 [ 24, %bb_constant ], [ %var, %entry ]
26+
%cond2 = icmp ugt i64 %sext, 24
27+
%is_constant = call i1 @llvm.is.constant.i64(i64 %sext)
28+
br i1 %cond2, label %bb_then, label %bb_else
29+
30+
bb_then:
31+
unreachable
32+
33+
bb_else:
34+
unreachable
35+
}
36+
37+
; Function Attrs: nounwind readnone willreturn
38+
declare i1 @llvm.is.constant.i64(i64) #0
39+
40+
attributes #0 = { convergent nounwind readnone willreturn }

0 commit comments

Comments
 (0)