Skip to content
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
MPM.addPass(SYCLPropagateJointMatrixUsagePass());
// Lowers static/dynamic local memory builtin calls.
MPM.addPass(SYCLLowerWGLocalMemoryPass());
// Compile-time properties pass must create standard metadata as early
// as possible to make them available for other passes.
MPM.addPass(CompileTimePropertiesPass());
});
else if (LangOpts.SYCLIsHost && !LangOpts.SYCLESIMDBuildHostCode)
PB.registerPipelineStartEPCallback(
Expand Down Expand Up @@ -1271,9 +1274,6 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
MPM.addPass(SPIRITTAnnotationsPass());
}

// Process properties and annotations
MPM.addPass(CompileTimePropertiesPass());

// Record SYCL aspect names (this should come after propagating aspects
// and before cleaning up metadata)
MPM.addPass(RecordSYCLAspectNamesPass());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// CHECK: SYCLPropagateAspectsUsagePass
// CHECK: SYCLPropagateJointMatrixUsagePass
// CHECK: SYCLLowerWGLocalMemoryPass
// CHECK: CompileTimePropertiesPass
// CHECK: InferFunctionAttrsPass
// CHECK: AlwaysInlinerPass
// CHECK: ModuleInlinerWrapperPass
Expand All @@ -17,7 +18,6 @@
// CHECK: SYCLMutatePrintfAddrspacePass
// CHECK: SYCLPropagateAspectsUsagePass
// CHECK: SYCLAddOptLevelAttributePass
// CHECK: CompileTimePropertiesPass
// CHECK: RecordSYCLAspectNamesPass
// CHECK: CleanupSYCLMetadataPass
//
Expand Down
28 changes: 20 additions & 8 deletions llvm/lib/SYCLLowerIR/CompileTimePropertiesPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -943,16 +943,28 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
LLVMContext &Ctx = M.getContext();
unsigned MDKindID = Ctx.getMDKindID(SpirvDecorMdKind);
if (!FPGAProp && llvm::isa<llvm::Instruction>(IntrInst->getArgOperand(0))) {
// If there are no annotations other than cache controls we can apply the
// controls to the pointer and remove the intrinsic.
// Find all load/store instructions using the pointer being annotated and
// apply the cache control metadata to them.
SmallVector<std::pair<Instruction *, int>, 8> TargetedInstList;
getUserListIgnoringCast<LoadInst>(IntrInst, TargetedInstList);
getUserListIgnoringCast<StoreInst>(IntrInst, TargetedInstList);
getUserListIgnoringCast<MemTransferInst>(IntrInst, TargetedInstList);
for (const auto &[Inst, MDVal] : TargetedInstList) {
// Merge with existing metadata if present.
SmallVector<Metadata *, 8> MDOps;
if (MDNode *CurrentMD = Inst->getMetadata(MDKindID))
for (Metadata *Op : CurrentMD->operands())
MDOps.push_back(Op);
for (Metadata *Op : MDOpsCacheProp)
MDOps.push_back(Op);
MDOps.push_back(ConstantAsMetadata::get(Constant::getIntegerValue(
Type::getInt32Ty(Ctx), APInt(32, MDVal))));
Inst->setMetadata(MDKindID, MDTuple::get(Ctx, MDOps));
}
// Replace all uses of ptr.annotations intrinsic with first operand and
// delete the original intrinsic.
Instruction *PtrInstr = cast<Instruction>(IntrInst->getArgOperand(0));
if (MDNode *CurrentMD = PtrInstr->getMetadata(MDKindID))
for (Metadata *Op : CurrentMD->operands())
MDOpsCacheProp.push_back(Op);
PtrInstr->setMetadata(MDKindID, MDTuple::get(Ctx, MDOpsCacheProp));
// Replace all uses of IntrInst with first operand
IntrInst->replaceAllUsesWith(PtrInstr);
// Delete the original IntrInst
RemovableAnnotations.push_back(IntrInst);
} else {
// If there were FPGA annotations then we retain the original intrinsic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,57 +171,62 @@ SYCL_EXTERNAL void annotated_ptr_func_param_test(float *p) {
}

// CHECK: spir_func{{.*}}annotated_ptr_func_param_test
// CHECK: {{.*}}call ptr addrspace(4) @llvm.ptr.annotation.p4.p1{{.*}}!spirv.Decorations [[WHINT:.*]]
// CHECK: store float 4.200000e+01, ptr addrspace(4) %{{.*}}, !spirv.Decorations ![[WHINT:[0-9]+]]
// CHECK: ret void

// CHECK: spir_kernel{{.*}}cache_control_read_hint_func
// CHECK: {{.*}}addrspacecast ptr addrspace(1){{.*}}!spirv.Decorations [[RHINT:.*]]
// CHECK: store float 5.500000e+01, ptr addrspace(1) %{{.*}}, !spirv.Decorations ![[RHINT:[0-9]+]]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: There is a bug in the test, which I reported here: #20718.
RHINT must be applied to load instructions.

// CHECK: ret void

// CHECK: spir_kernel{{.*}}cache_control_read_assertion_func
// CHECK: {{.*}}addrspacecast ptr addrspace(1){{.*}}!spirv.Decorations [[RASSERT:.*]]
// CHECK: store i32 66, ptr addrspace(1) %{{.*}}, !spirv.Decorations ![[RASSERT:[0-9]+]]
// CHECK: ret void

// CHECK: spir_kernel{{.*}}cache_control_write_hint_func
// CHECK: {{.*}}addrspacecast ptr addrspace(1){{.*}}!spirv.Decorations [[WHINT]]
// CHECK: store float 7.700000e+01, ptr addrspace(1) %{{.*}}, !spirv.Decorations ![[WHINT]]
// CHECK: ret void

// CHECK: spir_kernel{{.*}}cache_control_read_write_func
// CHECK: {{.*}}addrspacecast ptr addrspace(1){{.*}}!spirv.Decorations [[RWHINT:.*]]
// CHECK: store float 7.700000e+01, ptr addrspace(1) %{{.*}}, !spirv.Decorations ![[RWHINT:[0-9]+]]
// CHECK: ret void

// CHECK: spir_kernel{{.*}}cache_control_load_store_func
// CHECK: {{.*}}getelementptr{{.*}}addrspace(4){{.*}}!spirv.Decorations [[LDSTHINT_A:.*]]
// CHECK: {{.*}}getelementptr{{.*}}addrspace(4){{.*}}!spirv.Decorations [[LDSTHINT_B:.*]]
// CHECK: store double 1.000000e+00, ptr addrspace(1) %[[PTR_A:.*]], align 8{{.*}}, !spirv.Decorations ![[STHINT_A:[0-9]+]]
// CHECK: store double 1.000000e+00, ptr addrspace(1) %[[PTR_B:.*]], align 8{{.*}}, !spirv.Decorations ![[STHINT_B:[0-9]+]]
// CHECK: load double, ptr addrspace(1) %[[PTR_A]], align 8{{.*}}, !spirv.Decorations ![[LDHINT_A:[0-9]+]]
// CHECK: load double, ptr addrspace(1) %[[PTR_B]], align 8{{.*}}, !spirv.Decorations ![[LDHINT_B:[0-9]+]]
// CHECK: ret void

// CHECK: [[WHINT]] = !{[[WHINT1:.*]], [[WHINT2:.*]], [[WHINT3:.*]], [[WHINT4:.*]]}
// CHECK: [[WHINT]] = !{[[WHINT1:.*]], [[WHINT2:.*]], [[WHINT3:.*]], [[WHINT4:.*]], i32 1}
// CHECK: [[WHINT1]] = !{i32 6443, i32 3, i32 3}
// CHECK: [[WHINT2]] = !{i32 6443, i32 0, i32 1}
// CHECK: [[WHINT3]] = !{i32 6443, i32 1, i32 2}
// CHECK: [[WHINT4]] = !{i32 6443, i32 2, i32 2}

// CHECK: [[RHINT]] = !{[[RHINT1:.*]], [[RHINT2:.*]], [[RHINT3:.*]]}
// CHECK: [[RHINT]] = !{[[RHINT1:.*]], [[RHINT2:.*]], [[RHINT3:.*]], i32 1}
// CHECK: [[RHINT1]] = !{i32 6442, i32 1, i32 0}
// CHECK: [[RHINT2]] = !{i32 6442, i32 2, i32 0}
// CHECK: [[RHINT3]] = !{i32 6442, i32 0, i32 1}

// CHECK: [[RASSERT]] = !{[[RASSERT1:.*]], [[RASSERT2:.*]], [[RASSERT3:.*]]}
// CHECK: [[RASSERT]] = !{[[RASSERT1:.*]], [[RASSERT2:.*]], [[RASSERT3:.*]], i32 1}
// CHECK: [[RASSERT1]] = !{i32 6442, i32 1, i32 3}
// CHECK: [[RASSERT2]] = !{i32 6442, i32 2, i32 3}
// CHECK: [[RASSERT3]] = !{i32 6442, i32 0, i32 4}

// CHECK: [[RWHINT]] = !{[[RWHINT1:.*]], [[RWHINT2:.*]], [[RWHINT3:.*]]}
// CHECK: [[RWHINT]] = !{[[RWHINT1:.*]], [[RWHINT2:.*]], [[RWHINT3:.*]], i32 1}
// CHECK: [[RWHINT1]] = !{i32 6442, i32 2, i32 1}
// CHECK: [[RWHINT2]] = !{i32 6442, i32 3, i32 4}
// CHECK: [[RWHINT3]] = !{i32 6443, i32 3, i32 1}

// CHECK: [[LDSTHINT_A]] = !{[[RHINT1]], [[RHINT2]], [[RHINT3]], [[LDSTHINT_A1:.*]], [[LDSTHINT_A2:.*]], [[LDSTHINT_A3:.*]]}
// CHECK: [[LDSTHINT_A1]] = !{i32 6443, i32 0, i32 0}
// CHECK: [[LDSTHINT_A2]] = !{i32 6443, i32 1, i32 0}
// CHECK: [[LDSTHINT_A3]] = !{i32 6443, i32 2, i32 0}
// CHECK: [[STHINT_A]] = !{[[STHINT_A1:.*]], [[STHINT_A2:.*]], [[STHINT_A3:.*]], i32 1}
// CHECK: [[STHINT_A1]] = !{i32 6443, i32 0, i32 0}
// CHECK: [[STHINT_A2]] = !{i32 6443, i32 1, i32 0}
// CHECK: [[STHINT_A3]] = !{i32 6443, i32 2, i32 0}

// CHECK: [[LDSTHINT_B]] = !{[[LDSTHINT_B1:.*]], [[RWHINT1]], [[LDSTHINT_B2:.*]], [[LDSTHINT_A2]], [[LDSTHINT_A3]], [[LDSTHINT_B3:.*]]}
// CHECK: [[LDSTHINT_B1]] = !{i32 6442, i32 1, i32 1}
// CHECK: [[LDSTHINT_B2]] = !{i32 6442, i32 0, i32 2}
// CHECK: [[LDSTHINT_B3]] = !{i32 6443, i32 0, i32 2}
// CHECK: [[STHINT_B]] = !{[[STHINT_A2]], [[STHINT_A3]], [[STHINT_B1:.*]], i32 1}
// CHECK: [[STHINT_B1]] = !{i32 6443, i32 0, i32 2}

// CHECK: [[LDHINT_A]] = !{[[RHINT1]], [[RHINT2]], [[RHINT3]], i32 0}
// CHECK: [[LDHINT_B]] = !{[[LDHINT_B1:.*]], [[RWHINT1]], [[LDHINT_B2:.*]], i32 0}
// CHECK: [[LDHINT_B1]] = !{i32 6442, i32 1, i32 1}
// CHECK: [[LDHINT_B2]] = !{i32 6442, i32 0, i32 2}
Loading