[llvm] 8c2d462 - [Verifier] Support masked load/store with opaque pointers

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 26 09:14:36 PDT 2021


Author: Nikita Popov
Date: 2021-06-26T18:11:59+02:00
New Revision: 8c2d4621d94ede43fd2309249556b96bf7400fe7

URL: https://github.com/llvm/llvm-project/commit/8c2d4621d94ede43fd2309249556b96bf7400fe7
DIFF: https://github.com/llvm/llvm-project/commit/8c2d4621d94ede43fd2309249556b96bf7400fe7.diff

LOG: [Verifier] Support masked load/store with opaque pointers

Added: 
    

Modified: 
    llvm/lib/IR/Verifier.cpp
    llvm/test/Verifier/opaque-ptr.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 76341082a01e2..468c935e3bbf2 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5066,15 +5066,14 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
     Assert(Alignment->getValue().isPowerOf2(),
            "masked_load: alignment must be a power of 2", Call);
 
-    // DataTy is the overloaded type
-    Type *DataTy = cast<PointerType>(Ptr->getType())->getElementType();
-    Assert(DataTy == Call.getType(),
+    PointerType *PtrTy = cast<PointerType>(Ptr->getType());
+    Assert(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType()),
            "masked_load: return must match pointer type", Call);
-    Assert(PassThru->getType() == DataTy,
-           "masked_load: pass through and data type must match", Call);
+    Assert(PassThru->getType() == Call.getType(),
+           "masked_load: pass through and return type must match", Call);
     Assert(cast<VectorType>(Mask->getType())->getElementCount() ==
-               cast<VectorType>(DataTy)->getElementCount(),
-           "masked_load: vector mask must be same length as data", Call);
+               cast<VectorType>(Call.getType())->getElementCount(),
+           "masked_load: vector mask must be same length as return", Call);
     break;
   }
   case Intrinsic::masked_store: {
@@ -5087,13 +5086,12 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
     Assert(Alignment->getValue().isPowerOf2(),
            "masked_store: alignment must be a power of 2", Call);
 
-    // DataTy is the overloaded type
-    Type *DataTy = cast<PointerType>(Ptr->getType())->getElementType();
-    Assert(DataTy == Val->getType(),
+    PointerType *PtrTy = cast<PointerType>(Ptr->getType());
+    Assert(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType()),
            "masked_store: storee must match pointer type", Call);
     Assert(cast<VectorType>(Mask->getType())->getElementCount() ==
-               cast<VectorType>(DataTy)->getElementCount(),
-           "masked_store: vector mask must be same length as data", Call);
+               cast<VectorType>(Val->getType())->getElementCount(),
+           "masked_store: vector mask must be same length as value", Call);
     break;
   }
 

diff  --git a/llvm/test/Verifier/opaque-ptr.ll b/llvm/test/Verifier/opaque-ptr.ll
index 3cdcb306a9442..944b24cd652b3 100644
--- a/llvm/test/Verifier/opaque-ptr.ll
+++ b/llvm/test/Verifier/opaque-ptr.ll
@@ -1,36 +1,68 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -passes=verify -S < %s | FileCheck %s
 
-; CHECK: @load
 define i32 @load(ptr %a) {
-    %i = load i32, ptr %a
-    ret i32 %i
+; CHECK-LABEL: @load(
+; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[A:%.*]], align 4
+; CHECK-NEXT:    ret i32 [[I]]
+;
+  %i = load i32, ptr %a
+  ret i32 %i
 }
 
-; CHECK: @store
 define void @store(ptr %a, i32 %i) {
-    store i32 %i, ptr %a
-    ret void
+; CHECK-LABEL: @store(
+; CHECK-NEXT:    store i32 [[I:%.*]], ptr [[A:%.*]], align 4
+; CHECK-NEXT:    ret void
+;
+  store i32 %i, ptr %a
+  ret void
 }
 
-; CHECK: @cmpxchg
 define void @cmpxchg(ptr %p, i32 %a, i32 %b) {
-    %val_success = cmpxchg ptr %p, i32 %a, i32 %b acq_rel monotonic
-    ret void
+; CHECK-LABEL: @cmpxchg(
+; CHECK-NEXT:    [[VAL_SUCCESS:%.*]] = cmpxchg ptr [[P:%.*]], i32 [[A:%.*]], i32 [[B:%.*]] acq_rel monotonic, align 4
+; CHECK-NEXT:    ret void
+;
+  %val_success = cmpxchg ptr %p, i32 %a, i32 %b acq_rel monotonic
+  ret void
 }
 
-; CHECK: @atomicrmw
 define void @atomicrmw(ptr %a, i32 %i) {
-    %b = atomicrmw add ptr %a, i32 %i acquire
-    ret void
+; CHECK-LABEL: @atomicrmw(
+; CHECK-NEXT:    [[B:%.*]] = atomicrmw add ptr [[A:%.*]], i32 [[I:%.*]] acquire, align 4
+; CHECK-NEXT:    ret void
+;
+  %b = atomicrmw add ptr %a, i32 %i acquire
+  ret void
 }
 
 define void @opaque_mangle(ptr %a) {
-    call void @llvm.lifetime.start.p0(i64 8, ptr %a)
-    call void @llvm.lifetime.end.p0(i64 8, ptr %a)
-    ret void
+; CHECK-LABEL: @opaque_mangle(
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[A:%.*]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[A]])
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.lifetime.start.p0(i64 8, ptr %a)
+  call void @llvm.lifetime.end.p0(i64 8, ptr %a)
+  ret void
+}
+
+define void @intrinsic_calls(ptr %a) {
+; CHECK-LABEL: @intrinsic_calls(
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr [[A:%.*]], i32 4, <2 x i1> zeroinitializer, <2 x i32> zeroinitializer)
+; CHECK-NEXT:    call void @llvm.masked.store.v2i32.p0(<2 x i32> zeroinitializer, ptr [[A]], i32 4, <2 x i1> zeroinitializer)
+; CHECK-NEXT:    ret void
+;
+  call <2 x i32> @llvm.masked.load.v2i32.p0(ptr %a, i32 4, <2 x i1> zeroinitializer, <2 x i32> zeroinitializer)
+  call void @llvm.masked.store.v2i32.p0(<2 x i32> zeroinitializer, ptr %a, i32 4, <2 x i1> zeroinitializer)
+  ret void
 }
 
 ; CHECK: @llvm.lifetime.start.p0
 ; CHECK: @llvm.lifetime.end.p0
 declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
 declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
+
+declare <2 x i32> @llvm.masked.load.v2i32.p0(ptr, i32, <2 x i1>, <2 x i32>)
+declare void @llvm.masked.store.v2i32.p0(<2 x i32>, ptr, i32, <2 x i1>)


        


More information about the llvm-commits mailing list