================
@@ -1476,6 +1476,127 @@ static bool shouldExtendLifetime(const ASTContext
&Context,
return true;
}
+/// Adds metadata for restrict-qualified pointers at any nesting level.
+///
+/// This function processes pointer types recursively to generate metadata
+/// for restrict-qualified pointers. The metadata encodes which pointer levels
+/// are restrict qualified and assigns unique identifiers to each restrict
+/// qualification level.
+///
+/// For example, consider the type `int * restrict * restrict` in foo():
+/// - First level: pointer to restrict pointer (gets unique code 1)
+/// - Second level: restrict pointer to int (gets another unique code 1)
+///
+/// The metadata structure is attached to the alloca instruction and consists
+/// of:
+/// 1. Full variable name (function name + scope encoding)
+/// 2. List of restrict codes for each pointer level:
+/// - Non-zero: unique identifier for restrict-qualified pointer
+/// - Zero: non-restrict qualified pointer at that level
+///
+/// For example, consider function `foo` with variable declarations:
+/// void foo() {
+/// int * restrict p1; // Single-level restrict pointer
+/// int * restrict *p2; // restrict at first level, non-restrict at
+/// second int * restrict * restrict p3; // restrict at both levels
+/// }
+///
+/// Generated metadata would be:
+/// p1: !{!"foo_1", !{1}} // One restrict level, code 1
+/// p2: !{!"foo_1", !{2, 0}} // First level restrict (1), second
+/// non-restrict (0) p3: !{!"foo_1", !{3, 1}} // First level restrict
+/// (1), second restrict (2)
+///
+/// The unique codes allow distinguishing different restrict pointers at the
+/// same nesting level within the same function and scope.
+///
+void CodeGenFunction::AddPointerMetodataForRestrict(RawAddress AllocaAddr,
+ QualType Ty,
+ llvm::StringRef FullName) {
+ auto *AllocaInst = cast<llvm::AllocaInst>(AllocaAddr.getPointer());
+
+ unsigned RestictNesting = 0;
+
+ llvm::SmallVector<llvm::Metadata *, 8> RestrictMDs;
+ llvm::LLVMContext &Ctx = AllocaInst->getContext();
+
+ while (const PointerType *PT = Ty->getAs<PointerType>()) {
+ if (Ty.isRestrictQualified()) {
+ if (RestictNesting >= RestrictCodes.size())
+ RestrictCodes.push_back(1);
+ unsigned Code = RestrictCodes[RestictNesting];
+ llvm::Constant *C =
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), Code);
+ RestrictMDs.push_back(llvm::ConstantAsMetadata::get(C));
+ RestrictCodes[RestictNesting]++;
+ } else {
+ if (PT->getPointeeType()->getAs<RecordType>())
+ AddMetodataForRestrict(AllocaAddr, PT->getPointeeType(), FullName);
+ llvm::Constant *C =
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), 0);
+ RestrictMDs.push_back(llvm::ConstantAsMetadata::get(C));
+ }
+ RestictNesting++;
+ Ty = PT->getPointeeType();
+ }
+ llvm::MDNode *RestrictList = llvm::MDNode::get(Ctx, RestrictMDs);
+ llvm::MDString *NameMD = llvm::MDString::get(Ctx, FullName.str());
+ llvm::MDNode *Node = llvm::MDNode::get(Ctx, {NameMD, RestrictList});
+ AllocaInst->setMetadata(llvm::LLVMContext::MD_scope, Node);
+}
+
+bool CodeGenFunction::IsRestrictExperimentalSupportEnabled() const {
+ return (getLangOpts().IsCLanguageOnly() &&
+ (CGM.getCodeGenOpts().RestrictExperimental));
+}
+
+/// Constructs metadata for variables in the current lexical scope.
+///
+/// This function builds a unique name for each variable by combining the
----------------
AnastasiyaChernikova wrote:
In this case, a separate method is used for a class of variables (all variables
in one scope have the same prefix, and then only the variables designated as
restriction differ)
Example:
```
void test() {
for (int i = 0; i < 3; i++) {
int * restrict p;
int *m;
int *n;
if (i % 2 == 0) {
int *q;
} else {
int * restrict r;
int *l;
}
}
}
```
After After the frontend work phase:
```
define dso_local void @test() #0 {
entry:
%i = alloca i32, align 4
%p = alloca ptr, align 8, !scope !9
%m = alloca ptr, align 8, !scope !11
%n = alloca ptr, align 8, !scope !11
%q = alloca ptr, align 8, !scope !13
%r = alloca ptr, align 8, !scope !14
%l = alloca ptr, align 8, !scope !16
call void @llvm.lifetime.start.p0(ptr %i) #2
store i32 0, ptr %i, align 4, !tbaa !5
br label %for.cond
...
}
!9 = !{!"test_10", !10}
!10 = !{i64 1}
!11 = !{!"test_10", !12}
!12 = !{i64 0}
!13 = !{!"test_100", !12}
!14 = !{!"test_1001", !15}
!15 = !{i64 2}
!16 = !{!"test_1001", !12}
```
https://github.com/llvm/llvm-project/pull/173394
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits