Clarify the behavior of the llvm.vector.insert/extract intrinsics when the index

is out of range. Both intrinsics return a poison value.

Consequently, mark the intrinsics speculatable.
Differential Revision: https://reviews.llvm.org/D129656
This commit is contained in:
David Kreitzer 2022-07-06 11:15:16 -07:00
parent 86d73c11cf
commit c720b6fddd
4 changed files with 75 additions and 12 deletions

View File

@ -17395,7 +17395,7 @@ the runtime scaling factor of ``subvec``. The elements of ``vec`` starting at
``idx`` are overwritten with ``subvec``. Elements ``idx`` through (``idx`` + ``idx`` are overwritten with ``subvec``. Elements ``idx`` through (``idx`` +
num_elements(``subvec``) - 1) must be valid ``vec`` indices. If this condition 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 cannot be determined statically but is false at runtime, then the result vector
is undefined. is a :ref:`poison value <poisonvalues>`.
'``llvm.vector.extract``' Intrinsic '``llvm.vector.extract``' Intrinsic
@ -17439,9 +17439,9 @@ vector length of the result type. If the result type is a scalable vector,
``idx`` is first scaled by the result type's runtime scaling factor. Elements ``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 ``idx`` through (``idx`` + num_elements(result_type) - 1) must be valid vector
indices. If this condition cannot be determined statically but is false at 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 runtime, then the result vector is a :ref:`poison value <poisonvalues>`. The
vector index constant type (for most targets this will be an integer pointer ``idx`` parameter must be a vector index constant type (for most targets this
type). will be an integer pointer type).
'``llvm.experimental.vector.reverse``' Intrinsic '``llvm.experimental.vector.reverse``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1963,11 +1963,11 @@ def int_vscale : DefaultAttrsIntrinsic<[llvm_anyint_ty], [], [IntrNoMem]>;
//===---------- Intrinsics to perform subvector insertion/extraction ------===// //===---------- Intrinsics to perform subvector insertion/extraction ------===//
def int_vector_insert : DefaultAttrsIntrinsic<[llvm_anyvector_ty], def int_vector_insert : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, llvm_anyvector_ty, llvm_i64_ty], [LLVMMatchType<0>, llvm_anyvector_ty, llvm_i64_ty],
[IntrNoMem, ImmArg<ArgIndex<2>>]>; [IntrNoMem, IntrSpeculatable, ImmArg<ArgIndex<2>>]>;
def int_vector_extract : DefaultAttrsIntrinsic<[llvm_anyvector_ty], def int_vector_extract : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
[llvm_anyvector_ty, llvm_i64_ty], [llvm_anyvector_ty, llvm_i64_ty],
[IntrNoMem, ImmArg<ArgIndex<1>>]>; [IntrNoMem, IntrSpeculatable, ImmArg<ArgIndex<1>>]>;
//===----------------- Pointer Authentication Intrinsics ------------------===// //===----------------- Pointer Authentication Intrinsics ------------------===//
// //

View File

@ -0,0 +1,63 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -simplifycfg -S | FileCheck %s
declare <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32>, <4 x i32>, i64 immarg)
declare <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(<vscale x 4 x i32>, i64 immarg)
define <vscale x 4 x i32> @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 <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> zeroinitializer, <4 x i32> [[V1:%.*]], i64 0)
; CHECK-NEXT: [[T2:%.*]] = tail call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> zeroinitializer, <4 x i32> [[V2:%.*]], i64 0)
; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], <vscale x 4 x i32> [[T2]], <vscale x 4 x i32> [[T1]]
; CHECK-NEXT: ret <vscale x 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 <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> zeroinitializer, <4 x i32> %v1, i64 0)
br label %cond.end
cond.else: ; preds = %entry
%t2 = tail call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32> zeroinitializer, <4 x i32> %v2, i64 0)
br label %cond.end
cond.end: ; preds = %cond.else, %cond.then
%cond = phi <vscale x 4 x i32> [ %t1, %cond.then ], [ %t2, %cond.else ]
br label %return
return: ; preds = %cond.end
ret <vscale x 4 x i32> %cond
}
define <4 x i32> @speculate_vector_extract(i32 %c, <vscale x 4 x i32> %v1, <vscale x 4 x i32> %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(<vscale x 4 x i32> [[V1:%.*]], i64 0)
; CHECK-NEXT: [[T2:%.*]] = tail call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(<vscale x 4 x i32> [[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(<vscale x 4 x i32> %v1, i64 0)
br label %cond.end
cond.else: ; preds = %entry
%t2 = tail call <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(<vscale x 4 x i32> %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
}

View File

@ -808,9 +808,9 @@ llvm.func @vector_insert_extract(%f256: vector<8xi32>, %f128: vector<4xi32>,
// 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.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 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 <8 x ptr> @llvm.vp.inttoptr.v8p0.v8i64(<8 x i64>, <8 x i1>, i32) #2
// CHECK-DAG: declare <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v8i32(<vscale x 4 x i32>, <8 x i32>, i64 immarg) #2 // CHECK-DAG: declare <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v8i32(<vscale x 4 x i32>, <8 x i32>, i64 immarg) #0
// CHECK-DAG: declare <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32>, <4 x i32>, i64 immarg) #2 // CHECK-DAG: declare <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v4i32(<vscale x 4 x i32>, <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) #2 // 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(<vscale x 4 x i32>, i64 immarg) #2 // CHECK-DAG: declare <8 x i32> @llvm.vector.extract.v8i32.nxv4i32(<vscale x 4 x i32>, i64 immarg) #0
// CHECK-DAG: declare <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(<vscale x 4 x i32>, i64 immarg) #2 // CHECK-DAG: declare <4 x i32> @llvm.vector.extract.v4i32.nxv4i32(<vscale x 4 x i32>, i64 immarg) #0
// CHECK-DAG: declare <2 x i32> @llvm.vector.extract.v2i32.v8i32(<8 x i32>, i64 immarg) #2 // CHECK-DAG: declare <2 x i32> @llvm.vector.extract.v2i32.v8i32(<8 x i32>, i64 immarg) #0