https://github.com/jhuber6 updated 
https://github.com/llvm/llvm-project/pull/160185

>From be8d1e84e11274f64f931c6c52278e9d3d2daa82 Mon Sep 17 00:00:00 2001
From: Joseph Huber <[email protected]>
Date: Mon, 22 Sep 2025 14:26:40 -0500
Subject: [PATCH 1/4] [Clang][FIX] Fix type qualifiers on vector builtins

Summary:
These were not stripping qualifiers when using them to infer the types,
leading to errors when mixiing const and non-const.
---
 clang/lib/Sema/SemaChecking.cpp  | 61 +++++++++++++++++++++++++-------
 clang/test/Sema/builtin-masked.c | 26 ++++++++++++++
 2 files changed, 75 insertions(+), 12 deletions(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 27e3456bc6681..88725806a9920 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2296,12 +2296,21 @@ static ExprResult BuiltinMaskedLoad(Sema &S, CallExpr 
*TheCall) {
   QualType PointeeTy = PtrTy->getPointeeType();
   const VectorType *MaskVecTy = MaskTy->getAs<VectorType>();
 
-  QualType RetTy =
-      S.Context.getExtVectorType(PointeeTy, MaskVecTy->getNumElements());
+  QualType RetTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
+                                              MaskVecTy->getNumElements());
+  if (PtrTy->getPointeeType().isVolatileQualified())
+    return ExprError(
+        S.Diag(PtrArg->getExprLoc(), diag::err_typecheck_convert_incompatible)
+        << PtrTy->getPointeeType()
+        << PtrTy->getPointeeType().getUnqualifiedType()
+        << 5 /* different qualifiers */ << 0 /* qualifier difference */
+        << 3                                 /* parameter mismatch */
+        << 2 << PtrTy->getPointeeType()
+        << PtrTy->getPointeeType().getUnqualifiedType());
   if (TheCall->getNumArgs() == 3) {
     Expr *PassThruArg = TheCall->getArg(2);
     QualType PassThruTy = PassThruArg->getType();
-    if (!S.Context.hasSameType(PassThruTy, RetTy))
+    if (!S.Context.hasSameType(PassThruTy, RetTy.getUnqualifiedType()))
       return S.Diag(PtrArg->getExprLoc(), diag::err_vec_masked_load_store_ptr)
              << /* third argument */ 3 << RetTy;
   }
@@ -2329,12 +2338,22 @@ static ExprResult BuiltinMaskedStore(Sema &S, CallExpr 
*TheCall) {
         S.Diag(ValArg->getExprLoc(), diag::err_vec_masked_load_store_ptr)
         << 2 << "vector");
 
+  if (PtrTy->getPointeeType().hasQualifiers())
+    return ExprError(
+        S.Diag(PtrArg->getExprLoc(), diag::err_typecheck_convert_incompatible)
+        << PtrTy->getPointeeType()
+        << PtrTy->getPointeeType().getUnqualifiedType()
+        << 5 /* different qualifiers */ << 0 /* qualifier difference */
+        << 3                                 /* parameter mismatch */
+        << 2 << PtrTy->getPointeeType()
+        << PtrTy->getPointeeType().getUnqualifiedType());
+
   QualType PointeeTy = PtrTy->getPointeeType();
   const VectorType *MaskVecTy = MaskTy->getAs<VectorType>();
-  QualType RetTy =
-      S.Context.getExtVectorType(PointeeTy, MaskVecTy->getNumElements());
+  QualType RetTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
+                                              MaskVecTy->getNumElements());
 
-  if (!S.Context.hasSameType(ValTy, RetTy))
+  if (!S.Context.hasSameType(ValTy.getUnqualifiedType(), RetTy))
     return ExprError(S.Diag(TheCall->getBeginLoc(),
                             diag::err_vec_builtin_incompatible_vector)
                      << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ 2
@@ -2366,6 +2385,15 @@ static ExprResult BuiltinMaskedGather(Sema &S, CallExpr 
*TheCall) {
   QualType PtrTy = PtrArg->getType();
   QualType PointeeTy = PtrTy->getPointeeType();
   const VectorType *MaskVecTy = MaskTy->getAs<VectorType>();
+  if (PtrTy->getPointeeType().isVolatileQualified())
+    return ExprError(
+        S.Diag(PtrArg->getExprLoc(), diag::err_typecheck_convert_incompatible)
+        << PtrTy->getPointeeType()
+        << PtrTy->getPointeeType().getUnqualifiedType()
+        << 5 /* different qualifiers */ << 0 /* qualifier difference */
+        << 3                                 /* parameter mismatch */
+        << 2 << PtrTy->getPointeeType()
+        << PtrTy->getPointeeType().getUnqualifiedType());
   if (MaskVecTy->getNumElements() != IdxVecTy->getNumElements())
     return ExprError(
         S.Diag(TheCall->getBeginLoc(), diag::err_vec_masked_load_store_size)
@@ -2373,12 +2401,12 @@ static ExprResult BuiltinMaskedGather(Sema &S, CallExpr 
*TheCall) {
                TheCall->getBuiltinCallee())
         << MaskTy << IdxTy);
 
-  QualType RetTy =
-      S.Context.getExtVectorType(PointeeTy, MaskVecTy->getNumElements());
+  QualType RetTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
+                                              MaskVecTy->getNumElements());
   if (TheCall->getNumArgs() == 4) {
     Expr *PassThruArg = TheCall->getArg(3);
     QualType PassThruTy = PassThruArg->getType();
-    if (!S.Context.hasSameType(PassThruTy, RetTy))
+    if (!S.Context.hasSameType(PassThruTy.getUnqualifiedType(), RetTy))
       return S.Diag(PassThruArg->getExprLoc(),
                     diag::err_vec_masked_load_store_ptr)
              << /* fourth argument */ 4 << RetTy;
@@ -2414,6 +2442,15 @@ static ExprResult BuiltinMaskedScatter(Sema &S, CallExpr 
*TheCall) {
 
   const VectorType *MaskVecTy = MaskTy->castAs<VectorType>();
   const VectorType *ValVecTy = ValTy->castAs<VectorType>();
+  if (PtrTy->getPointeeType().hasQualifiers())
+    return ExprError(
+        S.Diag(PtrArg->getExprLoc(), diag::err_typecheck_convert_incompatible)
+        << PtrTy->getPointeeType()
+        << PtrTy->getPointeeType().getUnqualifiedType()
+        << 5 /* different qualifiers */ << 0 /* qualifier difference */
+        << 3                                 /* parameter mismatch */
+        << 2 << PtrTy->getPointeeType()
+        << PtrTy->getPointeeType().getUnqualifiedType());
   if (MaskVecTy->getNumElements() != IdxVecTy->getNumElements())
     return ExprError(
         S.Diag(TheCall->getBeginLoc(), diag::err_vec_masked_load_store_size)
@@ -2427,9 +2464,9 @@ static ExprResult BuiltinMaskedScatter(Sema &S, CallExpr 
*TheCall) {
                TheCall->getBuiltinCallee())
         << MaskTy << ValTy);
 
-  QualType ArgTy =
-      S.Context.getExtVectorType(PointeeTy, MaskVecTy->getNumElements());
-  if (!S.Context.hasSameType(ValTy, ArgTy))
+  QualType ArgTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
+                                              MaskVecTy->getNumElements());
+  if (!S.Context.hasSameType(ValTy.getUnqualifiedType(), ArgTy))
     return ExprError(S.Diag(TheCall->getBeginLoc(),
                             diag::err_vec_builtin_incompatible_vector)
                      << TheCall->getDirectCallee() << /*isMoreThanTwoArgs*/ 2
diff --git a/clang/test/Sema/builtin-masked.c b/clang/test/Sema/builtin-masked.c
index e24648da57fb1..c010bfab2ec60 100644
--- a/clang/test/Sema/builtin-masked.c
+++ b/clang/test/Sema/builtin-masked.c
@@ -54,3 +54,29 @@ void test_masked_scatter(int *p, v8i idx, v8b mask, v2b 
mask2, v8i val) {
   __builtin_masked_scatter(mask, idx, val, idx); // expected-error {{3rd 
argument must be a scalar pointer}}
   __builtin_masked_scatter(mask, idx, val, &idx); // expected-error {{3rd 
argument must be a scalar pointer}}
 }
+
+void a(v8b mask, v8i val, const int *ptr) {
+  __builtin_masked_load(mask, ptr, val);
+  (void)__builtin_masked_load(mask, (volatile int *)ptr, val); // 
expected-error {{sending 'volatile int' to parameter of incompatible type 
'int': type mismatch at 2nd parameter ('volatile int' vs 'int')}}
+}
+
+void b(v8b mask, v8i idx, const int *ptr) {
+  (void)__builtin_masked_gather(mask, idx, ptr);
+  (void)__builtin_masked_gather(mask, idx, (volatile int *)ptr); // 
expected-error {{sending 'volatile int' to parameter of incompatible type 
'int': type mismatch at 2nd parameter ('volatile int' vs 'int')}}
+}
+
+void c(v8b mask, const v8i val, int *ptr) {
+  __builtin_masked_store(mask, val, ptr);
+}
+
+void readonly(v8b mask, v8i val, const int *ptr, const int *s) {
+  __builtin_masked_store(mask, val, ptr); // expected-error {{sending 'const 
int' to parameter of incompatible type 'int': type mismatch at 2nd parameter 
('const int' vs 'int')}}
+  __builtin_masked_compress_store(mask, val, ptr); // expected-error {{sending 
'const int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('const int' vs 'int')}}
+  __builtin_masked_scatter(mask, val, val, s); // expected-error {{sending 
'const int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('const int' vs 'int')}}
+}
+
+void vol(v8b mask, v8i val, volatile int *ptr, volatile int *s) {
+  __builtin_masked_store(mask, val, ptr); // expected-error {{sending 
'volatile int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('volatile int' vs 'int')}}
+  __builtin_masked_compress_store(mask, val, ptr); // expected-error {{sending 
'volatile int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('volatile int' vs 'int')}}
+  __builtin_masked_scatter(mask, val, val, s); // expected-error {{sending 
'volatile int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('volatile int' vs 'int')}}
+}

>From cd0ff843ac23e1c1a6af51f18189d06b7831f957 Mon Sep 17 00:00:00 2001
From: Joseph Huber <[email protected]>
Date: Thu, 25 Sep 2025 14:22:58 -0500
Subject: [PATCH 2/4] Update qualifiers

---
 clang/lib/CodeGen/CGBuiltin.cpp     |   7 +-
 clang/lib/Sema/SemaChecking.cpp     | 100 +++++++++++++---------------
 clang/test/CodeGen/builtin-masked.c |  49 ++++++++++++++
 clang/test/Sema/builtin-masked.c    |  37 +++++++---
 4 files changed, 128 insertions(+), 65 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 1cff1e0de71b7..9ee810c9d5775 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4289,7 +4289,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
     llvm::Value *Result;
     if (BuiltinID == Builtin::BI__builtin_masked_load) {
       Function *F =
-          CGM.getIntrinsic(Intrinsic::masked_load, {RetTy, UnqualPtrTy});
+          CGM.getIntrinsic(Intrinsic::masked_load, {RetTy, Ptr->getType()});
       Result =
           Builder.CreateCall(F, {Ptr, AlignVal, Mask, PassThru}, 
"masked_load");
     } else {
@@ -4334,7 +4334,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
     QualType ValTy = E->getArg(1)->getType();
     llvm::Type *ValLLTy = CGM.getTypes().ConvertType(ValTy);
-    llvm::Type *PtrTy = Ptr->getType();
 
     CharUnits Align = CGM.getNaturalTypeAlignment(
         E->getArg(1)->getType()->getAs<VectorType>()->getElementType(),
@@ -4343,8 +4342,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
         llvm::ConstantInt::get(Int32Ty, Align.getQuantity());
 
     if (BuiltinID == Builtin::BI__builtin_masked_store) {
-      llvm::Function *F =
-          CGM.getIntrinsic(llvm::Intrinsic::masked_store, {ValLLTy, PtrTy});
+      llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::masked_store,
+                                           {ValLLTy, Ptr->getType()});
       Builder.CreateCall(F, {Val, Ptr, AlignVal, Mask});
     } else {
       llvm::Function *F =
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 88725806a9920..0272ad31231cc 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2268,7 +2268,8 @@ static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr 
*TheCall) {
 }
 
 static bool CheckMaskedBuiltinArgs(Sema &S, Expr *MaskArg, Expr *PtrArg,
-                                   unsigned Pos) {
+                                   unsigned Pos, bool AllowConst,
+                                   bool AllowAS) {
   QualType MaskTy = MaskArg->getType();
   if (!MaskTy->isExtVectorBoolType())
     return S.Diag(MaskArg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
@@ -2279,6 +2280,20 @@ static bool CheckMaskedBuiltinArgs(Sema &S, Expr 
*MaskArg, Expr *PtrArg,
   if (!PtrTy->isPointerType() || PtrTy->getPointeeType()->isVectorType())
     return S.Diag(PtrArg->getExprLoc(), diag::err_vec_masked_load_store_ptr)
            << Pos << "scalar pointer";
+
+  QualType PointeeTy = PtrTy->getPointeeType();
+  if (PointeeTy.isVolatileQualified() || PointeeTy->isAtomicType() ||
+      (!AllowConst && PointeeTy.isConstQualified()) ||
+      (!AllowAS && PointeeTy.hasAddressSpace())) {
+    QualType Target = S.Context.getPointerType(PointeeTy.getUnqualifiedType());
+    if (const auto *AT = dyn_cast<AtomicType>(PointeeTy))
+      Target = S.Context.getPointerType(AT->getValueType());
+    return S.Diag(PtrArg->getExprLoc(),
+                  diag::err_typecheck_convert_incompatible)
+           << PtrTy << Target << /*different qualifiers=*/5
+           << /*qualifier difference=*/0 << /*parameter mismatch=*/3 << 2
+           << PtrTy << Target;
+  }
   return false;
 }
 
@@ -2288,7 +2303,9 @@ static ExprResult BuiltinMaskedLoad(Sema &S, CallExpr 
*TheCall) {
 
   Expr *MaskArg = TheCall->getArg(0);
   Expr *PtrArg = TheCall->getArg(1);
-  if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 2))
+  if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 2, /*AllowConst=*/true,
+                             TheCall->getBuiltinCallee() ==
+                                 Builtin::BI__builtin_masked_load))
     return ExprError();
 
   QualType MaskTy = MaskArg->getType();
@@ -2298,19 +2315,15 @@ static ExprResult BuiltinMaskedLoad(Sema &S, CallExpr 
*TheCall) {
 
   QualType RetTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
                                               MaskVecTy->getNumElements());
-  if (PtrTy->getPointeeType().isVolatileQualified())
-    return ExprError(
-        S.Diag(PtrArg->getExprLoc(), diag::err_typecheck_convert_incompatible)
-        << PtrTy->getPointeeType()
-        << PtrTy->getPointeeType().getUnqualifiedType()
-        << 5 /* different qualifiers */ << 0 /* qualifier difference */
-        << 3                                 /* parameter mismatch */
-        << 2 << PtrTy->getPointeeType()
-        << PtrTy->getPointeeType().getUnqualifiedType());
+  Qualifiers Qs = PointeeTy.getQualifiers();
+  Qs.removeConst();
+  if (Qs.hasAddressSpace())
+    RetTy = S.Context.getQualifiedType(RetTy, Qs);
+
   if (TheCall->getNumArgs() == 3) {
     Expr *PassThruArg = TheCall->getArg(2);
     QualType PassThruTy = PassThruArg->getType();
-    if (!S.Context.hasSameType(PassThruTy, RetTy.getUnqualifiedType()))
+    if (!S.Context.hasSameType(PassThruTy, RetTy))
       return S.Diag(PtrArg->getExprLoc(), diag::err_vec_masked_load_store_ptr)
              << /* third argument */ 3 << RetTy;
   }
@@ -2327,7 +2340,9 @@ static ExprResult BuiltinMaskedStore(Sema &S, CallExpr 
*TheCall) {
   Expr *ValArg = TheCall->getArg(1);
   Expr *PtrArg = TheCall->getArg(2);
 
-  if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3))
+  if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3, /*AllowConst=*/false,
+                             TheCall->getBuiltinCallee() ==
+                                 Builtin::BI__builtin_masked_store))
     return ExprError();
 
   QualType MaskTy = MaskArg->getType();
@@ -2338,22 +2353,16 @@ static ExprResult BuiltinMaskedStore(Sema &S, CallExpr 
*TheCall) {
         S.Diag(ValArg->getExprLoc(), diag::err_vec_masked_load_store_ptr)
         << 2 << "vector");
 
-  if (PtrTy->getPointeeType().hasQualifiers())
-    return ExprError(
-        S.Diag(PtrArg->getExprLoc(), diag::err_typecheck_convert_incompatible)
-        << PtrTy->getPointeeType()
-        << PtrTy->getPointeeType().getUnqualifiedType()
-        << 5 /* different qualifiers */ << 0 /* qualifier difference */
-        << 3                                 /* parameter mismatch */
-        << 2 << PtrTy->getPointeeType()
-        << PtrTy->getPointeeType().getUnqualifiedType());
-
   QualType PointeeTy = PtrTy->getPointeeType();
   const VectorType *MaskVecTy = MaskTy->getAs<VectorType>();
-  QualType RetTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
-                                              MaskVecTy->getNumElements());
-
-  if (!S.Context.hasSameType(ValTy.getUnqualifiedType(), RetTy))
+  QualType MemoryTy = 
S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
+                                                 MaskVecTy->getNumElements());
+  Qualifiers Qs = PointeeTy.getQualifiers();
+  if (Qs.hasAddressSpace())
+    MemoryTy = S.Context.getQualifiedType(MemoryTy, Qs);
+
+  if (!S.Context.hasSameType(ValTy.getUnqualifiedType(),
+                             MemoryTy.getUnqualifiedType()))
     return ExprError(S.Diag(TheCall->getBeginLoc(),
                             diag::err_vec_builtin_incompatible_vector)
                      << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ 2
@@ -2371,7 +2380,8 @@ static ExprResult BuiltinMaskedGather(Sema &S, CallExpr 
*TheCall) {
   Expr *MaskArg = TheCall->getArg(0);
   Expr *IdxArg = TheCall->getArg(1);
   Expr *PtrArg = TheCall->getArg(2);
-  if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3))
+  if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3, /*AllowConst=*/true,
+                             /*AllowAS=*/false))
     return ExprError();
 
   QualType IdxTy = IdxArg->getType();
@@ -2385,15 +2395,6 @@ static ExprResult BuiltinMaskedGather(Sema &S, CallExpr 
*TheCall) {
   QualType PtrTy = PtrArg->getType();
   QualType PointeeTy = PtrTy->getPointeeType();
   const VectorType *MaskVecTy = MaskTy->getAs<VectorType>();
-  if (PtrTy->getPointeeType().isVolatileQualified())
-    return ExprError(
-        S.Diag(PtrArg->getExprLoc(), diag::err_typecheck_convert_incompatible)
-        << PtrTy->getPointeeType()
-        << PtrTy->getPointeeType().getUnqualifiedType()
-        << 5 /* different qualifiers */ << 0 /* qualifier difference */
-        << 3                                 /* parameter mismatch */
-        << 2 << PtrTy->getPointeeType()
-        << PtrTy->getPointeeType().getUnqualifiedType());
   if (MaskVecTy->getNumElements() != IdxVecTy->getNumElements())
     return ExprError(
         S.Diag(TheCall->getBeginLoc(), diag::err_vec_masked_load_store_size)
@@ -2401,12 +2402,13 @@ static ExprResult BuiltinMaskedGather(Sema &S, CallExpr 
*TheCall) {
                TheCall->getBuiltinCallee())
         << MaskTy << IdxTy);
 
-  QualType RetTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
-                                              MaskVecTy->getNumElements());
+  PointeeTy.removeLocalConst();
+  QualType RetTy =
+      S.Context.getExtVectorType(PointeeTy, MaskVecTy->getNumElements());
   if (TheCall->getNumArgs() == 4) {
     Expr *PassThruArg = TheCall->getArg(3);
     QualType PassThruTy = PassThruArg->getType();
-    if (!S.Context.hasSameType(PassThruTy.getUnqualifiedType(), RetTy))
+    if (!S.Context.hasSameType(PassThruTy, RetTy))
       return S.Diag(PassThruArg->getExprLoc(),
                     diag::err_vec_masked_load_store_ptr)
              << /* fourth argument */ 4 << RetTy;
@@ -2425,7 +2427,8 @@ static ExprResult BuiltinMaskedScatter(Sema &S, CallExpr 
*TheCall) {
   Expr *ValArg = TheCall->getArg(2);
   Expr *PtrArg = TheCall->getArg(3);
 
-  if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3))
+  if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3, /*AllowConst=*/false,
+                             /*AllowAS=*/false))
     return ExprError();
 
   QualType IdxTy = IdxArg->getType();
@@ -2442,15 +2445,6 @@ static ExprResult BuiltinMaskedScatter(Sema &S, CallExpr 
*TheCall) {
 
   const VectorType *MaskVecTy = MaskTy->castAs<VectorType>();
   const VectorType *ValVecTy = ValTy->castAs<VectorType>();
-  if (PtrTy->getPointeeType().hasQualifiers())
-    return ExprError(
-        S.Diag(PtrArg->getExprLoc(), diag::err_typecheck_convert_incompatible)
-        << PtrTy->getPointeeType()
-        << PtrTy->getPointeeType().getUnqualifiedType()
-        << 5 /* different qualifiers */ << 0 /* qualifier difference */
-        << 3                                 /* parameter mismatch */
-        << 2 << PtrTy->getPointeeType()
-        << PtrTy->getPointeeType().getUnqualifiedType());
   if (MaskVecTy->getNumElements() != IdxVecTy->getNumElements())
     return ExprError(
         S.Diag(TheCall->getBeginLoc(), diag::err_vec_masked_load_store_size)
@@ -2464,9 +2458,9 @@ static ExprResult BuiltinMaskedScatter(Sema &S, CallExpr 
*TheCall) {
                TheCall->getBuiltinCallee())
         << MaskTy << ValTy);
 
-  QualType ArgTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
-                                              MaskVecTy->getNumElements());
-  if (!S.Context.hasSameType(ValTy.getUnqualifiedType(), ArgTy))
+  QualType ArgTy =
+      S.Context.getExtVectorType(PointeeTy, MaskVecTy->getNumElements());
+  if (!S.Context.hasSameType(ValTy, ArgTy))
     return ExprError(S.Diag(TheCall->getBeginLoc(),
                             diag::err_vec_builtin_incompatible_vector)
                      << TheCall->getDirectCallee() << /*isMoreThanTwoArgs*/ 2
diff --git a/clang/test/CodeGen/builtin-masked.c 
b/clang/test/CodeGen/builtin-masked.c
index 2ac05fac219fe..c8fc7c03b4f1d 100644
--- a/clang/test/CodeGen/builtin-masked.c
+++ b/clang/test/CodeGen/builtin-masked.c
@@ -187,3 +187,52 @@ v8i test_gather(v8b mask, v8i idx, int *ptr) {
 void test_scatter(v8b mask, v8i val, v8i idx, int *ptr) {
   __builtin_masked_scatter(mask, val, idx, ptr);
 }
+
+// CHECK-LABEL: define dso_local <8 x i32> @test_load_as(
+// CHECK-SAME: i8 noundef [[MASK_COERCE:%.*]], ptr addrspace(42) noundef 
[[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[MASK:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[MASK_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr addrspace(42), align 8
+// CHECK-NEXT:    store i8 [[MASK_COERCE]], ptr [[MASK]], align 1
+// CHECK-NEXT:    [[LOAD_BITS:%.*]] = load i8, ptr [[MASK]], align 1
+// CHECK-NEXT:    [[MASK1:%.*]] = bitcast i8 [[LOAD_BITS]] to <8 x i1>
+// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <8 x i1> [[MASK1]] to i8
+// CHECK-NEXT:    store i8 [[TMP0]], ptr [[MASK_ADDR]], align 1
+// CHECK-NEXT:    store ptr addrspace(42) [[PTR]], ptr [[PTR_ADDR]], align 8
+// CHECK-NEXT:    [[LOAD_BITS2:%.*]] = load i8, ptr [[MASK_ADDR]], align 1
+// CHECK-NEXT:    [[TMP1:%.*]] = bitcast i8 [[LOAD_BITS2]] to <8 x i1>
+// CHECK-NEXT:    [[TMP2:%.*]] = load ptr addrspace(42), ptr [[PTR_ADDR]], 
align 8
+// CHECK-NEXT:    [[MASKED_LOAD:%.*]] = call <8 x i32> 
@llvm.masked.load.v8i32.p42(ptr addrspace(42) [[TMP2]], i32 4, <8 x i1> 
[[TMP1]], <8 x i32> poison)
+// CHECK-NEXT:    ret <8 x i32> [[MASKED_LOAD]]
+//
+v8i __attribute__((address_space(42))) test_load_as(v8b mask, int
+    __attribute__((address_space(42))) * ptr) {
+  return __builtin_masked_load(mask, ptr);
+}
+
+// CHECK-LABEL: define dso_local void @test_store_as(
+// CHECK-SAME: i8 noundef [[M_COERCE:%.*]], ptr noundef byval(<8 x i32>) align 
32 [[TMP0:%.*]], ptr addrspace(42) noundef [[P:%.*]]) #[[ATTR3]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[V_ADDR:%.*]] = alloca <8 x i32>, align 32
+// CHECK-NEXT:    [[P_ADDR:%.*]] = alloca ptr addrspace(42), align 8
+// CHECK-NEXT:    store i8 [[M_COERCE]], ptr [[M]], align 1
+// CHECK-NEXT:    [[LOAD_BITS:%.*]] = load i8, ptr [[M]], align 1
+// CHECK-NEXT:    [[M1:%.*]] = bitcast i8 [[LOAD_BITS]] to <8 x i1>
+// CHECK-NEXT:    [[V:%.*]] = load <8 x i32>, ptr [[TMP0]], align 32
+// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i1> [[M1]] to i8
+// CHECK-NEXT:    store i8 [[TMP1]], ptr [[M_ADDR]], align 1
+// CHECK-NEXT:    store <8 x i32> [[V]], ptr [[V_ADDR]], align 32
+// CHECK-NEXT:    store ptr addrspace(42) [[P]], ptr [[P_ADDR]], align 8
+// CHECK-NEXT:    [[LOAD_BITS2:%.*]] = load i8, ptr [[M_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8 [[LOAD_BITS2]] to <8 x i1>
+// CHECK-NEXT:    [[TMP3:%.*]] = load <8 x i32>, ptr [[V_ADDR]], align 32
+// CHECK-NEXT:    [[TMP4:%.*]] = load ptr addrspace(42), ptr [[P_ADDR]], align 
8
+// CHECK-NEXT:    call void @llvm.masked.store.v8i32.p42(<8 x i32> [[TMP3]], 
ptr addrspace(42) [[TMP4]], i32 4, <8 x i1> [[TMP2]])
+// CHECK-NEXT:    ret void
+//
+void test_store_as(v8b m, v8i v, int __attribute__((address_space(42))) *p) {
+  __builtin_masked_store(m, v, p);
+}
diff --git a/clang/test/Sema/builtin-masked.c b/clang/test/Sema/builtin-masked.c
index c010bfab2ec60..f809a77bca5de 100644
--- a/clang/test/Sema/builtin-masked.c
+++ b/clang/test/Sema/builtin-masked.c
@@ -57,12 +57,12 @@ void test_masked_scatter(int *p, v8i idx, v8b mask, v2b 
mask2, v8i val) {
 
 void a(v8b mask, v8i val, const int *ptr) {
   __builtin_masked_load(mask, ptr, val);
-  (void)__builtin_masked_load(mask, (volatile int *)ptr, val); // 
expected-error {{sending 'volatile int' to parameter of incompatible type 
'int': type mismatch at 2nd parameter ('volatile int' vs 'int')}}
+  (void)__builtin_masked_load(mask, (volatile int *)ptr, val); // 
expected-error {{sending 'volatile int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('volatile int *' vs 'int *')}}
 }
 
 void b(v8b mask, v8i idx, const int *ptr) {
   (void)__builtin_masked_gather(mask, idx, ptr);
-  (void)__builtin_masked_gather(mask, idx, (volatile int *)ptr); // 
expected-error {{sending 'volatile int' to parameter of incompatible type 
'int': type mismatch at 2nd parameter ('volatile int' vs 'int')}}
+  (void)__builtin_masked_gather(mask, idx, (volatile int *)ptr); // 
expected-error {{sending 'volatile int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('volatile int *' vs 'int *')}}
 }
 
 void c(v8b mask, const v8i val, int *ptr) {
@@ -70,13 +70,34 @@ void c(v8b mask, const v8i val, int *ptr) {
 }
 
 void readonly(v8b mask, v8i val, const int *ptr, const int *s) {
-  __builtin_masked_store(mask, val, ptr); // expected-error {{sending 'const 
int' to parameter of incompatible type 'int': type mismatch at 2nd parameter 
('const int' vs 'int')}}
-  __builtin_masked_compress_store(mask, val, ptr); // expected-error {{sending 
'const int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('const int' vs 'int')}}
-  __builtin_masked_scatter(mask, val, val, s); // expected-error {{sending 
'const int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('const int' vs 'int')}}
+  __builtin_masked_store(mask, val, ptr); // expected-error {{sending 'const 
int *' to parameter of incompatible type 'int *': type mismatch at 2nd 
parameter ('const int *' vs 'int *')}}
+  __builtin_masked_compress_store(mask, val, ptr); // expected-error {{sending 
'const int *' to parameter of incompatible type 'int *': type mismatch at 2nd 
parameter ('const int *' vs 'int *')}}
+  __builtin_masked_scatter(mask, val, val, s); // expected-error {{sending 
'const int *' to parameter of incompatible type 'int *': type mismatch at 2nd 
parameter ('const int *' vs 'int *')}}
 }
 
 void vol(v8b mask, v8i val, volatile int *ptr, volatile int *s) {
-  __builtin_masked_store(mask, val, ptr); // expected-error {{sending 
'volatile int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('volatile int' vs 'int')}}
-  __builtin_masked_compress_store(mask, val, ptr); // expected-error {{sending 
'volatile int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('volatile int' vs 'int')}}
-  __builtin_masked_scatter(mask, val, val, s); // expected-error {{sending 
'volatile int' to parameter of incompatible type 'int': type mismatch at 2nd 
parameter ('volatile int' vs 'int')}}
+  __builtin_masked_store(mask, val, ptr); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
+  __builtin_masked_compress_store(mask, val, ptr); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
+  __builtin_masked_scatter(mask, val, val, s); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
+}
+
+v8i [[clang::address_space(999)]] load(v8b mask, int 
[[clang::address_space(999)]] * ptr) {
+}
+
+void as(v8b mask, int [[clang::address_space(999)]] * ptr, v8i v) {
+  (void)__builtin_masked_load(mask, ptr);
+  (void)__builtin_masked_store(mask, v, ptr);
+  (void)__builtin_masked_expand_load(mask, ptr); // expected-error {{sending 
'__attribute__((address_space(999))) int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('__attribute__((address_space(999))) 
int *' vs 'int *')}}
+  (void)__builtin_masked_compress_store(mask, v, ptr); // expected-error 
{{sending '__attribute__((address_space(999))) int *' to parameter of 
incompatible type 'int *': type mismatch at 2nd parameter 
('__attribute__((address_space(999))) int *' vs 'int *')}}
+  (void)__builtin_masked_gather(mask, v, ptr); // expected-error {{sending 
'__attribute__((address_space(999))) int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('__attribute__((address_space(999))) 
int *' vs 'int *')}}
+  (void)__builtin_masked_scatter(mask, v, v, ptr); // expected-error {{sending 
'__attribute__((address_space(999))) int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('__attribute__((address_space(999))) 
int *' vs 'int *')}}
+}
+
+void atom(v8b mask, _Atomic int * ptr, v8i v) {
+  (void)__builtin_masked_load(mask, ptr); // expected-error {{'_Atomic(int) *' 
to parameter of incompatible type 'int *': type mismatch at 2nd parameter 
('_Atomic(int) *' vs 'int *')}}
+  (void)__builtin_masked_store(mask, v, ptr); // expected-error 
{{'_Atomic(int) *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('_Atomic(int) *' vs 'int *')}}
+  (void)__builtin_masked_expand_load(mask, ptr); // expected-error 
{{'_Atomic(int) *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('_Atomic(int) *' vs 'int *')}}
+  (void)__builtin_masked_compress_store(mask, v, ptr); // expected-error 
{{'_Atomic(int) *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('_Atomic(int) *' vs 'int *')}}
+  (void)__builtin_masked_gather(mask, v, ptr); // expected-error 
{{'_Atomic(int) *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('_Atomic(int) *' vs 'int *')}}
+  (void)__builtin_masked_scatter(mask, v, v, ptr); // expected-error 
{{'_Atomic(int) *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('_Atomic(int) *' vs 'int *')}}
 }

>From d9b5d5ea818ef7663d130022c5e95ad414507205 Mon Sep 17 00:00:00 2001
From: Joseph Huber <[email protected]>
Date: Thu, 25 Sep 2025 15:44:57 -0500
Subject: [PATCH 3/4] Update

---
 clang/lib/Sema/SemaChecking.cpp     | 58 +++++++++++++++++++--------
 clang/test/CodeGen/builtin-masked.c | 61 ++++++++++++++++++++++++++++-
 clang/test/Sema/builtin-masked.c    | 36 ++++++++---------
 3 files changed, 118 insertions(+), 37 deletions(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0272ad31231cc..03c3378ca06ef 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2297,12 +2297,30 @@ static bool CheckMaskedBuiltinArgs(Sema &S, Expr 
*MaskArg, Expr *PtrArg,
   return false;
 }
 
+static bool CheckMaskedBuiltinPtr(Sema &S, CallExpr *TheCall, unsigned ArgNum) 
{
+  ExprResult ConvertedPtr =
+      S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(ArgNum));
+  if (ConvertedPtr.isInvalid())
+    return true;
+  TheCall->setArg(ArgNum, ConvertedPtr.get());
+
+  if (ConvertedPtr.get()->isTypeDependent())
+    TheCall->setType(S.Context.DependentTy);
+  return false;
+}
+
 static ExprResult BuiltinMaskedLoad(Sema &S, CallExpr *TheCall) {
   if (S.checkArgCountRange(TheCall, 2, 3))
     return ExprError();
 
+  if (CheckMaskedBuiltinPtr(S, TheCall, /*PtrArg=*/1))
+    return ExprError();
+
   Expr *MaskArg = TheCall->getArg(0);
   Expr *PtrArg = TheCall->getArg(1);
+  if (PtrArg->isTypeDependent())
+    return TheCall;
+
   if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 2, /*AllowConst=*/true,
                              TheCall->getBuiltinCallee() ==
                                  Builtin::BI__builtin_masked_load))
@@ -2315,11 +2333,6 @@ static ExprResult BuiltinMaskedLoad(Sema &S, CallExpr 
*TheCall) {
 
   QualType RetTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
                                               MaskVecTy->getNumElements());
-  Qualifiers Qs = PointeeTy.getQualifiers();
-  Qs.removeConst();
-  if (Qs.hasAddressSpace())
-    RetTy = S.Context.getQualifiedType(RetTy, Qs);
-
   if (TheCall->getNumArgs() == 3) {
     Expr *PassThruArg = TheCall->getArg(2);
     QualType PassThruTy = PassThruArg->getType();
@@ -2336,9 +2349,14 @@ static ExprResult BuiltinMaskedStore(Sema &S, CallExpr 
*TheCall) {
   if (S.checkArgCount(TheCall, 3))
     return ExprError();
 
+  if (CheckMaskedBuiltinPtr(S, TheCall, /*PtrArg=*/2))
+    return ExprError();
+
   Expr *MaskArg = TheCall->getArg(0);
   Expr *ValArg = TheCall->getArg(1);
   Expr *PtrArg = TheCall->getArg(2);
+  if (PtrArg->isTypeDependent())
+    return TheCall;
 
   if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3, /*AllowConst=*/false,
                              TheCall->getBuiltinCallee() ==
@@ -2357,10 +2375,6 @@ static ExprResult BuiltinMaskedStore(Sema &S, CallExpr 
*TheCall) {
   const VectorType *MaskVecTy = MaskTy->getAs<VectorType>();
   QualType MemoryTy = 
S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
                                                  MaskVecTy->getNumElements());
-  Qualifiers Qs = PointeeTy.getQualifiers();
-  if (Qs.hasAddressSpace())
-    MemoryTy = S.Context.getQualifiedType(MemoryTy, Qs);
-
   if (!S.Context.hasSameType(ValTy.getUnqualifiedType(),
                              MemoryTy.getUnqualifiedType()))
     return ExprError(S.Diag(TheCall->getBeginLoc(),
@@ -2377,11 +2391,17 @@ static ExprResult BuiltinMaskedGather(Sema &S, CallExpr 
*TheCall) {
   if (S.checkArgCountRange(TheCall, 3, 4))
     return ExprError();
 
+  if (CheckMaskedBuiltinPtr(S, TheCall, /*PtrArg=*/2))
+    return ExprError();
+
   Expr *MaskArg = TheCall->getArg(0);
   Expr *IdxArg = TheCall->getArg(1);
   Expr *PtrArg = TheCall->getArg(2);
+  if (PtrArg->isTypeDependent())
+    return TheCall;
+
   if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3, /*AllowConst=*/true,
-                             /*AllowAS=*/false))
+                             /*AllowAS=*/true))
     return ExprError();
 
   QualType IdxTy = IdxArg->getType();
@@ -2402,9 +2422,8 @@ static ExprResult BuiltinMaskedGather(Sema &S, CallExpr 
*TheCall) {
                TheCall->getBuiltinCallee())
         << MaskTy << IdxTy);
 
-  PointeeTy.removeLocalConst();
-  QualType RetTy =
-      S.Context.getExtVectorType(PointeeTy, MaskVecTy->getNumElements());
+  QualType RetTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
+                                              MaskVecTy->getNumElements());
   if (TheCall->getNumArgs() == 4) {
     Expr *PassThruArg = TheCall->getArg(3);
     QualType PassThruTy = PassThruArg->getType();
@@ -2422,13 +2441,18 @@ static ExprResult BuiltinMaskedScatter(Sema &S, 
CallExpr *TheCall) {
   if (S.checkArgCount(TheCall, 4))
     return ExprError();
 
+  if (CheckMaskedBuiltinPtr(S, TheCall, /*PtrArg=*/3))
+    return ExprError();
+
   Expr *MaskArg = TheCall->getArg(0);
   Expr *IdxArg = TheCall->getArg(1);
   Expr *ValArg = TheCall->getArg(2);
   Expr *PtrArg = TheCall->getArg(3);
+  if (PtrArg->isTypeDependent())
+    return TheCall;
 
   if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3, /*AllowConst=*/false,
-                             /*AllowAS=*/false))
+                             /*AllowAS=*/true))
     return ExprError();
 
   QualType IdxTy = IdxArg->getType();
@@ -2458,9 +2482,9 @@ static ExprResult BuiltinMaskedScatter(Sema &S, CallExpr 
*TheCall) {
                TheCall->getBuiltinCallee())
         << MaskTy << ValTy);
 
-  QualType ArgTy =
-      S.Context.getExtVectorType(PointeeTy, MaskVecTy->getNumElements());
-  if (!S.Context.hasSameType(ValTy, ArgTy))
+  QualType ArgTy = S.Context.getExtVectorType(PointeeTy.getUnqualifiedType(),
+                                              MaskVecTy->getNumElements());
+  if (!S.Context.hasSameType(ValTy.getUnqualifiedType(), ArgTy))
     return ExprError(S.Diag(TheCall->getBeginLoc(),
                             diag::err_vec_builtin_incompatible_vector)
                      << TheCall->getDirectCallee() << /*isMoreThanTwoArgs*/ 2
diff --git a/clang/test/CodeGen/builtin-masked.c 
b/clang/test/CodeGen/builtin-masked.c
index c8fc7c03b4f1d..e2b5e099a4ba9 100644
--- a/clang/test/CodeGen/builtin-masked.c
+++ b/clang/test/CodeGen/builtin-masked.c
@@ -206,8 +206,7 @@ void test_scatter(v8b mask, v8i val, v8i idx, int *ptr) {
 // CHECK-NEXT:    [[MASKED_LOAD:%.*]] = call <8 x i32> 
@llvm.masked.load.v8i32.p42(ptr addrspace(42) [[TMP2]], i32 4, <8 x i1> 
[[TMP1]], <8 x i32> poison)
 // CHECK-NEXT:    ret <8 x i32> [[MASKED_LOAD]]
 //
-v8i __attribute__((address_space(42))) test_load_as(v8b mask, int
-    __attribute__((address_space(42))) * ptr) {
+v8i test_load_as(v8b mask, int __attribute__((address_space(42))) * ptr) {
   return __builtin_masked_load(mask, ptr);
 }
 
@@ -236,3 +235,61 @@ v8i __attribute__((address_space(42))) test_load_as(v8b 
mask, int
 void test_store_as(v8b m, v8i v, int __attribute__((address_space(42))) *p) {
   __builtin_masked_store(m, v, p);
 }
+
+// CHECK-LABEL: define dso_local <8 x i32> @test_gather_as(
+// CHECK-SAME: i8 noundef [[MASK_COERCE:%.*]], ptr noundef byval(<8 x i32>) 
align 32 [[TMP0:%.*]], ptr addrspace(42) noundef [[PTR:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[MASK:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[MASK_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[IDX_ADDR:%.*]] = alloca <8 x i32>, align 32
+// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr addrspace(42), align 8
+// CHECK-NEXT:    store i8 [[MASK_COERCE]], ptr [[MASK]], align 1
+// CHECK-NEXT:    [[LOAD_BITS:%.*]] = load i8, ptr [[MASK]], align 1
+// CHECK-NEXT:    [[MASK1:%.*]] = bitcast i8 [[LOAD_BITS]] to <8 x i1>
+// CHECK-NEXT:    [[IDX:%.*]] = load <8 x i32>, ptr [[TMP0]], align 32
+// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i1> [[MASK1]] to i8
+// CHECK-NEXT:    store i8 [[TMP1]], ptr [[MASK_ADDR]], align 1
+// CHECK-NEXT:    store <8 x i32> [[IDX]], ptr [[IDX_ADDR]], align 32
+// CHECK-NEXT:    store ptr addrspace(42) [[PTR]], ptr [[PTR_ADDR]], align 8
+// CHECK-NEXT:    [[LOAD_BITS2:%.*]] = load i8, ptr [[MASK_ADDR]], align 1
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8 [[LOAD_BITS2]] to <8 x i1>
+// CHECK-NEXT:    [[TMP3:%.*]] = load <8 x i32>, ptr [[IDX_ADDR]], align 32
+// CHECK-NEXT:    [[TMP4:%.*]] = load ptr addrspace(42), ptr [[PTR_ADDR]], 
align 8
+// CHECK-NEXT:    [[TMP5:%.*]] = getelementptr i32, ptr addrspace(42) 
[[TMP4]], <8 x i32> [[TMP3]]
+// CHECK-NEXT:    [[MASKED_GATHER:%.*]] = call <8 x i32> 
@llvm.masked.gather.v8i32.v8p42(<8 x ptr addrspace(42)> [[TMP5]], i32 4, <8 x 
i1> [[TMP2]], <8 x i32> poison)
+// CHECK-NEXT:    ret <8 x i32> [[MASKED_GATHER]]
+//
+v8i test_gather_as(v8b mask, v8i idx, int __attribute__((address_space(42))) 
*ptr) {
+  return __builtin_masked_gather(mask, idx, ptr);
+}
+
+// CHECK-LABEL: define dso_local void @test_scatter_as(
+// CHECK-SAME: i8 noundef [[MASK_COERCE:%.*]], ptr noundef byval(<8 x i32>) 
align 32 [[TMP0:%.*]], ptr noundef byval(<8 x i32>) align 32 [[TMP1:%.*]], ptr 
addrspace(42) noundef [[PTR:%.*]]) #[[ATTR3]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[MASK:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[MASK_ADDR:%.*]] = alloca i8, align 1
+// CHECK-NEXT:    [[VAL_ADDR:%.*]] = alloca <8 x i32>, align 32
+// CHECK-NEXT:    [[IDX_ADDR:%.*]] = alloca <8 x i32>, align 32
+// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr addrspace(42), align 8
+// CHECK-NEXT:    store i8 [[MASK_COERCE]], ptr [[MASK]], align 1
+// CHECK-NEXT:    [[LOAD_BITS:%.*]] = load i8, ptr [[MASK]], align 1
+// CHECK-NEXT:    [[MASK1:%.*]] = bitcast i8 [[LOAD_BITS]] to <8 x i1>
+// CHECK-NEXT:    [[VAL:%.*]] = load <8 x i32>, ptr [[TMP0]], align 32
+// CHECK-NEXT:    [[IDX:%.*]] = load <8 x i32>, ptr [[TMP1]], align 32
+// CHECK-NEXT:    [[TMP2:%.*]] = bitcast <8 x i1> [[MASK1]] to i8
+// CHECK-NEXT:    store i8 [[TMP2]], ptr [[MASK_ADDR]], align 1
+// CHECK-NEXT:    store <8 x i32> [[VAL]], ptr [[VAL_ADDR]], align 32
+// CHECK-NEXT:    store <8 x i32> [[IDX]], ptr [[IDX_ADDR]], align 32
+// CHECK-NEXT:    store ptr addrspace(42) [[PTR]], ptr [[PTR_ADDR]], align 8
+// CHECK-NEXT:    [[LOAD_BITS2:%.*]] = load i8, ptr [[MASK_ADDR]], align 1
+// CHECK-NEXT:    [[TMP3:%.*]] = bitcast i8 [[LOAD_BITS2]] to <8 x i1>
+// CHECK-NEXT:    [[TMP4:%.*]] = load <8 x i32>, ptr [[VAL_ADDR]], align 32
+// CHECK-NEXT:    [[TMP5:%.*]] = load <8 x i32>, ptr [[IDX_ADDR]], align 32
+// CHECK-NEXT:    [[TMP6:%.*]] = load ptr addrspace(42), ptr [[PTR_ADDR]], 
align 8
+// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr i32, ptr addrspace(42) 
[[TMP6]], <8 x i32> [[TMP4]]
+// CHECK-NEXT:    call void @llvm.masked.scatter.v8i32.v8p42(<8 x i32> 
[[TMP5]], <8 x ptr addrspace(42)> [[TMP7]], i32 4, <8 x i1> [[TMP3]])
+// CHECK-NEXT:    ret void
+//
+void test_scatter_as(v8b mask, v8i val, v8i idx, int 
__attribute__((address_space(42))) *ptr) {
+  __builtin_masked_scatter(mask, val, idx, ptr);
+}
diff --git a/clang/test/Sema/builtin-masked.c b/clang/test/Sema/builtin-masked.c
index f809a77bca5de..cacaefc911c9a 100644
--- a/clang/test/Sema/builtin-masked.c
+++ b/clang/test/Sema/builtin-masked.c
@@ -55,9 +55,9 @@ void test_masked_scatter(int *p, v8i idx, v8b mask, v2b 
mask2, v8i val) {
   __builtin_masked_scatter(mask, idx, val, &idx); // expected-error {{3rd 
argument must be a scalar pointer}}
 }
 
-void a(v8b mask, v8i val, const int *ptr) {
-  __builtin_masked_load(mask, ptr, val);
-  (void)__builtin_masked_load(mask, (volatile int *)ptr, val); // 
expected-error {{sending 'volatile int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('volatile int *' vs 'int *')}}
+void a(v8b mask, v8i v, const int *ptr) {
+  __builtin_masked_load(mask, ptr, v);
+  (void)__builtin_masked_load(mask, (volatile int *)ptr, v); // expected-error 
{{sending 'volatile int *' to parameter of incompatible type 'int *': type 
mismatch at 2nd parameter ('volatile int *' vs 'int *')}}
 }
 
 void b(v8b mask, v8i idx, const int *ptr) {
@@ -65,23 +65,23 @@ void b(v8b mask, v8i idx, const int *ptr) {
   (void)__builtin_masked_gather(mask, idx, (volatile int *)ptr); // 
expected-error {{sending 'volatile int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('volatile int *' vs 'int *')}}
 }
 
-void c(v8b mask, const v8i val, int *ptr) {
-  __builtin_masked_store(mask, val, ptr);
+void c(v8b mask, const v8i v, int *ptr) {
+  __builtin_masked_store(mask, v, ptr);
 }
 
-void readonly(v8b mask, v8i val, const int *ptr, const int *s) {
-  __builtin_masked_store(mask, val, ptr); // expected-error {{sending 'const 
int *' to parameter of incompatible type 'int *': type mismatch at 2nd 
parameter ('const int *' vs 'int *')}}
-  __builtin_masked_compress_store(mask, val, ptr); // expected-error {{sending 
'const int *' to parameter of incompatible type 'int *': type mismatch at 2nd 
parameter ('const int *' vs 'int *')}}
-  __builtin_masked_scatter(mask, val, val, s); // expected-error {{sending 
'const int *' to parameter of incompatible type 'int *': type mismatch at 2nd 
parameter ('const int *' vs 'int *')}}
+void readonly(v8b mask, v8i v, const int *ptr, const int *s) {
+  (void)__builtin_masked_store(mask, v, ptr); // expected-error {{sending 
'const int *' to parameter of incompatible type 'int *': type mismatch at 2nd 
parameter ('const int *' vs 'int *')}}
+  (void)__builtin_masked_compress_store(mask, v, ptr); // expected-error 
{{sending 'const int *' to parameter of incompatible type 'int *': type 
mismatch at 2nd parameter ('const int *' vs 'int *')}}
+  (void)__builtin_masked_scatter(mask, v, v, s); // expected-error {{sending 
'const int *' to parameter of incompatible type 'int *': type mismatch at 2nd 
parameter ('const int *' vs 'int *')}}
 }
 
-void vol(v8b mask, v8i val, volatile int *ptr, volatile int *s) {
-  __builtin_masked_store(mask, val, ptr); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
-  __builtin_masked_compress_store(mask, val, ptr); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
-  __builtin_masked_scatter(mask, val, val, s); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
-}
-
-v8i [[clang::address_space(999)]] load(v8b mask, int 
[[clang::address_space(999)]] * ptr) {
+void vol(v8b mask, v8i v, volatile int *ptr, volatile int *s) {
+  (void)__builtin_masked_load(mask, ptr); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
+  (void)__builtin_masked_store(mask, v, ptr); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
+  (void)__builtin_masked_expand_load(mask, ptr); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
+  (void)__builtin_masked_compress_store(mask, v, ptr); // expected-error 
{{sending 'volatile int *' to parameter of incompatible type 'int *': type 
mismatch at 2nd parameter ('volatile int *' vs 'int *')}}
+  (void)__builtin_masked_gather(mask, v, ptr);// expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
+  (void)__builtin_masked_scatter(mask, v, v, s); // expected-error {{sending 
'volatile int *' to parameter of incompatible type 'int *': type mismatch at 
2nd parameter ('volatile int *' vs 'int *')}}
 }
 
 void as(v8b mask, int [[clang::address_space(999)]] * ptr, v8i v) {
@@ -89,8 +89,8 @@ void as(v8b mask, int [[clang::address_space(999)]] * ptr, 
v8i v) {
   (void)__builtin_masked_store(mask, v, ptr);
   (void)__builtin_masked_expand_load(mask, ptr); // expected-error {{sending 
'__attribute__((address_space(999))) int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('__attribute__((address_space(999))) 
int *' vs 'int *')}}
   (void)__builtin_masked_compress_store(mask, v, ptr); // expected-error 
{{sending '__attribute__((address_space(999))) int *' to parameter of 
incompatible type 'int *': type mismatch at 2nd parameter 
('__attribute__((address_space(999))) int *' vs 'int *')}}
-  (void)__builtin_masked_gather(mask, v, ptr); // expected-error {{sending 
'__attribute__((address_space(999))) int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('__attribute__((address_space(999))) 
int *' vs 'int *')}}
-  (void)__builtin_masked_scatter(mask, v, v, ptr); // expected-error {{sending 
'__attribute__((address_space(999))) int *' to parameter of incompatible type 
'int *': type mismatch at 2nd parameter ('__attribute__((address_space(999))) 
int *' vs 'int *')}}
+  (void)__builtin_masked_gather(mask, v, ptr);
+  (void)__builtin_masked_scatter(mask, v, v, ptr);
 }
 
 void atom(v8b mask, _Atomic int * ptr, v8i v) {

>From 29e4a474d7728141f8d3d5916e1c59fd7ac1e3af Mon Sep 17 00:00:00 2001
From: Joseph Huber <[email protected]>
Date: Thu, 25 Sep 2025 15:45:53 -0500
Subject: [PATCH 4/4] Simplify atomic

---
 clang/lib/Sema/SemaChecking.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 03c3378ca06ef..8c3e47698cd21 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2285,9 +2285,8 @@ static bool CheckMaskedBuiltinArgs(Sema &S, Expr 
*MaskArg, Expr *PtrArg,
   if (PointeeTy.isVolatileQualified() || PointeeTy->isAtomicType() ||
       (!AllowConst && PointeeTy.isConstQualified()) ||
       (!AllowAS && PointeeTy.hasAddressSpace())) {
-    QualType Target = S.Context.getPointerType(PointeeTy.getUnqualifiedType());
-    if (const auto *AT = dyn_cast<AtomicType>(PointeeTy))
-      Target = S.Context.getPointerType(AT->getValueType());
+    QualType Target =
+        S.Context.getPointerType(PointeeTy.getAtomicUnqualifiedType());
     return S.Diag(PtrArg->getExprLoc(),
                   diag::err_typecheck_convert_incompatible)
            << PtrTy << Target << /*different qualifiers=*/5

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to