From fa496ce3c6774097080c8a9cb808da56f383b938 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Mon, 30 Mar 2020 11:45:58 -0700 Subject: [PATCH] [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 --- llvm/include/llvm/IR/Intrinsics.td | 4 ++- llvm/test/Transforms/JumpThreading/is_constant.ll | 40 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/JumpThreading/is_constant.ll diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 0812d70..eda69b3 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1151,7 +1151,9 @@ def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], "llvm.clear_cache">; // Intrinsic to detect whether its argument is a constant. -def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem, IntrWillReturn], "llvm.is.constant">; +def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], + [IntrNoMem, IntrWillReturn, IntrConvergent], + "llvm.is.constant">; // Intrinsic to mask out bits of a pointer. def int_ptrmask: Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty, llvm_anyint_ty], diff --git a/llvm/test/Transforms/JumpThreading/is_constant.ll b/llvm/test/Transforms/JumpThreading/is_constant.ll new file mode 100644 index 0000000..12d0451 --- /dev/null +++ b/llvm/test/Transforms/JumpThreading/is_constant.ll @@ -0,0 +1,40 @@ +; RUN: opt -jump-threading -S -verify < %s | FileCheck %s + +; This is reduced from the Linux net/ipv4/tcp.c file built with ASAN. We +; don't want jump threading to split up a basic block which has a PHI node with +; at least one constant incoming value, whose value is used by an is.constant +; intrinsic with non-local uses. It could lead to later passes no DCE'ing +; invalid paths. + +; CHECK-LABEL: define void @test1( +; CHECK-LABEL: bb_cond: +; CHECK-NOT: %sext = phi i64 [ %var, %entry ] +; CHECK-NEXT: %sext = phi i64 [ 24, %bb_constant ], [ %var, %entry ] +; CHECK-NEXT: %cond2 = icmp +; CHECK-NEXT: call i1 @llvm.is.constant.i64( + +define void @test1(i32 %a, i64 %var) { +entry: + %cond1 = icmp ugt i32 %a, 24 + br i1 %cond1, label %bb_constant, label %bb_cond + +bb_constant: + br label %bb_cond + +bb_cond: + %sext = phi i64 [ 24, %bb_constant ], [ %var, %entry ] + %cond2 = icmp ugt i64 %sext, 24 + %is_constant = call i1 @llvm.is.constant.i64(i64 %sext) + br i1 %cond2, label %bb_then, label %bb_else + +bb_then: + unreachable + +bb_else: + unreachable +} + +; Function Attrs: nounwind readnone willreturn +declare i1 @llvm.is.constant.i64(i64) #0 + +attributes #0 = { convergent nounwind readnone willreturn } -- 2.7.4