diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -17395,7 +17395,7 @@ ``idx`` are overwritten with ``subvec``. Elements ``idx`` through (``idx`` + num_elements(``subvec``) - 1) must be valid ``vec`` indices. If this condition cannot be determined statically but is false at runtime, then the result vector -is undefined. +is a :ref:`poison value `. '``llvm.vector.extract``' Intrinsic @@ -17439,9 +17439,9 @@ ``idx`` is first scaled by the result type's runtime scaling factor. Elements ``idx`` through (``idx`` + num_elements(result_type) - 1) must be valid vector indices. If this condition cannot be determined statically but is false at -runtime, then the result vector is undefined. The ``idx`` parameter must be a -vector index constant type (for most targets this will be an integer pointer -type). +runtime, then the result vector is a :ref:`poison value `. The +``idx`` parameter must be a vector index constant type (for most targets this +will be an integer pointer type). '``llvm.experimental.vector.reverse``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1963,11 +1963,11 @@ //===---------- Intrinsics to perform subvector insertion/extraction ------===// def int_vector_insert : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; + [IntrNoMem, IntrSpeculatable, ImmArg>]>; def int_vector_extract : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i64_ty], - [IntrNoMem, ImmArg>]>; + [IntrNoMem, IntrSpeculatable, ImmArg>]>; //===----------------- Pointer Authentication Intrinsics ------------------===// // diff --git a/llvm/test/Transforms/SimplifyCFG/speculate-vector-insert-extract.ll b/llvm/test/Transforms/SimplifyCFG/speculate-vector-insert-extract.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/speculate-vector-insert-extract.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +declare @llvm.vector.insert.nxv4i32.v4i32(, <4 x i32>, i64 immarg) +declare <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(, i64 immarg) + +define @speculate_vector_insert(i32 %c, <4 x i32> %v1, <4 x i32> %v2) { +; CHECK-LABEL: @speculate_vector_insert( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C:%.*]], 0 +; CHECK-NEXT: [[T1:%.*]] = tail call @llvm.vector.insert.nxv4i32.v4i32( zeroinitializer, <4 x i32> [[V1:%.*]], i64 0) +; CHECK-NEXT: [[T2:%.*]] = tail call @llvm.vector.insert.nxv4i32.v4i32( zeroinitializer, <4 x i32> [[V2:%.*]], i64 0) +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], [[T2]], [[T1]] +; CHECK-NEXT: ret [[COND]] +; +entry: + %tobool = icmp eq i32 %c, 0 + br i1 %tobool, label %cond.else, label %cond.then + +cond.then: ; preds = %entry + %t1 = tail call @llvm.vector.insert.nxv4i32.v4i32( zeroinitializer, <4 x i32> %v1, i64 0) + br label %cond.end + +cond.else: ; preds = %entry + %t2 = tail call @llvm.vector.insert.nxv4i32.v4i32( zeroinitializer, <4 x i32> %v2, i64 0) + br label %cond.end + +cond.end: ; preds = %cond.else, %cond.then + %cond = phi [ %t1, %cond.then ], [ %t2, %cond.else ] + br label %return + +return: ; preds = %cond.end + ret %cond +} + +define <4 x i32> @speculate_vector_extract(i32 %c, %v1, %v2) { +; CHECK-LABEL: @speculate_vector_extract( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C:%.*]], 0 +; CHECK-NEXT: [[T1:%.*]] = tail call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32( [[V1:%.*]], i64 0) +; CHECK-NEXT: [[T2:%.*]] = tail call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32( [[V2:%.*]], i64 0) +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], <4 x i32> [[T2]], <4 x i32> [[T1]] +; CHECK-NEXT: ret <4 x i32> [[COND]] +; +entry: + %tobool = icmp eq i32 %c, 0 + br i1 %tobool, label %cond.else, label %cond.then + +cond.then: ; preds = %entry + %t1 = tail call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32( %v1, i64 0) + br label %cond.end + +cond.else: ; preds = %entry + %t2 = tail call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32( %v2, i64 0) + br label %cond.end + +cond.end: ; preds = %cond.else, %cond.then + %cond = phi <4 x i32> [ %t1, %cond.then ], [ %t2, %cond.else ] + br label %return + +return: ; preds = %cond.end + ret <4 x i32> %cond +} diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir --- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir @@ -808,9 +808,9 @@ // CHECK-DAG: declare <8 x i64> @llvm.vp.fptosi.v8i64.v8f64(<8 x double>, <8 x i1>, i32) #2 // CHECK-DAG: declare <8 x i64> @llvm.vp.ptrtoint.v8i64.v8p0(<8 x ptr>, <8 x i1>, i32) #2 // CHECK-DAG: declare <8 x ptr> @llvm.vp.inttoptr.v8p0.v8i64(<8 x i64>, <8 x i1>, i32) #2 -// CHECK-DAG: declare @llvm.vector.insert.nxv4i32.v8i32(, <8 x i32>, i64 immarg) #2 -// CHECK-DAG: declare @llvm.vector.insert.nxv4i32.v4i32(, <4 x i32>, i64 immarg) #2 -// CHECK-DAG: declare <8 x i32> @llvm.vector.insert.v8i32.v4i32(<8 x i32>, <4 x i32>, i64 immarg) #2 -// CHECK-DAG: declare <8 x i32> @llvm.vector.extract.v8i32.nxv4i32(, i64 immarg) #2 -// CHECK-DAG: declare <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(, i64 immarg) #2 -// CHECK-DAG: declare <2 x i32> @llvm.vector.extract.v2i32.v8i32(<8 x i32>, i64 immarg) #2 +// CHECK-DAG: declare @llvm.vector.insert.nxv4i32.v8i32(, <8 x i32>, i64 immarg) #0 +// CHECK-DAG: declare @llvm.vector.insert.nxv4i32.v4i32(, <4 x i32>, i64 immarg) #0 +// CHECK-DAG: declare <8 x i32> @llvm.vector.insert.v8i32.v4i32(<8 x i32>, <4 x i32>, i64 immarg) #0 +// CHECK-DAG: declare <8 x i32> @llvm.vector.extract.v8i32.nxv4i32(, i64 immarg) #0 +// CHECK-DAG: declare <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(, i64 immarg) #0 +// CHECK-DAG: declare <2 x i32> @llvm.vector.extract.v2i32.v8i32(<8 x i32>, i64 immarg) #0