3535#include " llvm/Support/Process.h"
3636#include " llvm/Support/Program.h"
3737#include " llvm/Support/TargetSelect.h"
38+ #include " llvm/Support/Timer.h"
3839#include " llvm/Support/raw_ostream.h"
3940
4041#include < cstdint>
4142#include < cstdlib>
43+ #include < optional>
4244
4345using namespace mlir ;
4446using namespace mlir ::NVVM;
@@ -220,6 +222,16 @@ class NVPTXSerializer : public SerializeGPUModuleBase {
220222 std::optional<SmallVector<char , 0 >>
221223 moduleToObject (llvm::Module &llvmModule) override ;
222224
225+ // / Get LLVMIR->ISA performance result.
226+ // / Return nullopt if moduleToObject has not been called or the target format
227+ // / is LLVMIR.
228+ std::optional<int64_t > getLLVMIRToISATimeInMs ();
229+
230+ // / Get ISA->Binary performance result.
231+ // / Return nullopt if moduleToObject has not been called or the target format
232+ // / is LLVMIR or ISA.
233+ std::optional<int64_t > getISAToBinaryTimeInMs ();
234+
223235private:
224236 using TmpFile = std::pair<llvm::SmallString<128 >, llvm::FileRemover>;
225237
@@ -235,13 +247,20 @@ class NVPTXSerializer : public SerializeGPUModuleBase {
235247
236248 // / Target options.
237249 gpu::TargetOptions targetOptions;
250+
251+ // / LLVMIR->ISA perf result.
252+ std::optional<int64_t > llvmToISATimeInMs;
253+
254+ // / ISA->Binary perf result.
255+ std::optional<int64_t > isaToBinaryTimeInMs;
238256};
239257} // namespace
240258
241259NVPTXSerializer::NVPTXSerializer (Operation &module , NVVMTargetAttr target,
242260 const gpu::TargetOptions &targetOptions)
243261 : SerializeGPUModuleBase(module , target, targetOptions),
244- targetOptions(targetOptions) {}
262+ targetOptions(targetOptions), llvmToISATimeInMs(std::nullopt ),
263+ isaToBinaryTimeInMs(std::nullopt ) {}
245264
246265std::optional<NVPTXSerializer::TmpFile>
247266NVPTXSerializer::createTemp (StringRef name, StringRef suffix) {
@@ -256,6 +275,14 @@ NVPTXSerializer::createTemp(StringRef name, StringRef suffix) {
256275 return TmpFile (filename, llvm::FileRemover (filename.c_str ()));
257276}
258277
278+ std::optional<int64_t > NVPTXSerializer::getLLVMIRToISATimeInMs () {
279+ return llvmToISATimeInMs;
280+ }
281+
282+ std::optional<int64_t > NVPTXSerializer::getISAToBinaryTimeInMs () {
283+ return isaToBinaryTimeInMs;
284+ }
285+
259286gpu::GPUModuleOp NVPTXSerializer::getOperation () {
260287 return dyn_cast<gpu::GPUModuleOp>(&SerializeGPUModuleBase::getOperation ());
261288}
@@ -618,6 +645,10 @@ NVPTXSerializer::compileToBinaryNVPTX(const std::string &ptxCode) {
618645
619646std::optional<SmallVector<char , 0 >>
620647NVPTXSerializer::moduleToObject (llvm::Module &llvmModule) {
648+ llvm::Timer moduleToObjectTimer (
649+ " moduleToObjectTimer" ,
650+ " Timer for perf llvm-ir -> isa and isa -> binary." );
651+ moduleToObjectTimer.startTimer ();
621652 // Return LLVM IR if the compilation target is `offload`.
622653#define DEBUG_TYPE " serialize-to-llvm"
623654 LLVM_DEBUG ({
@@ -650,6 +681,11 @@ NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
650681 getOperation ().emitError () << " Failed translating the module to ISA." ;
651682 return std::nullopt ;
652683 }
684+
685+ moduleToObjectTimer.stopTimer ();
686+ llvmToISATimeInMs = moduleToObjectTimer.getTotalTime ().getWallTime () * 1000 ;
687+ moduleToObjectTimer.clear ();
688+ moduleToObjectTimer.startTimer ();
653689 if (isaCallback)
654690 isaCallback (serializedISA.value ());
655691
@@ -669,17 +705,24 @@ NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
669705 return SmallVector<char , 0 >(bin.begin (), bin.end ());
670706 }
671707
708+ std::optional<SmallVector<char , 0 >> result;
672709 // Compile to binary.
673710#if MLIR_ENABLE_NVPTXCOMPILER
674- return compileToBinaryNVPTX (*serializedISA);
711+ result = compileToBinaryNVPTX (*serializedISA);
675712#else
676- return compileToBinary (*serializedISA);
713+ result = compileToBinary (*serializedISA);
677714#endif // MLIR_ENABLE_NVPTXCOMPILER
715+
716+ moduleToObjectTimer.stopTimer ();
717+ isaToBinaryTimeInMs = moduleToObjectTimer.getTotalTime ().getWallTime () * 1000 ;
718+ moduleToObjectTimer.clear ();
719+ return result;
678720}
679721
680722std::optional<SmallVector<char , 0 >>
681723NVVMTargetAttrImpl::serializeToObject (Attribute attribute, Operation *module ,
682724 const gpu::TargetOptions &options) const {
725+ Builder builder (attribute.getContext ());
683726 assert (module && " The module must be non null." );
684727 if (!module )
685728 return std::nullopt ;
@@ -689,7 +732,16 @@ NVVMTargetAttrImpl::serializeToObject(Attribute attribute, Operation *module,
689732 }
690733 NVPTXSerializer serializer (*module , cast<NVVMTargetAttr>(attribute), options);
691734 serializer.init ();
692- return serializer.run ();
735+ std::optional<SmallVector<char , 0 >> result = serializer.run ();
736+ auto llvmToISATimeInMs = serializer.getLLVMIRToISATimeInMs ();
737+ if (llvmToISATimeInMs.has_value ())
738+ module ->setAttr (" LLVMIRToISATimeInMs" ,
739+ builder.getI64IntegerAttr (*llvmToISATimeInMs));
740+ auto isaToBinaryTimeInMs = serializer.getISAToBinaryTimeInMs ();
741+ if (isaToBinaryTimeInMs.has_value ())
742+ module ->setAttr (" ISAToBinaryTimeInMs" ,
743+ builder.getI64IntegerAttr (*isaToBinaryTimeInMs));
744+ return result;
693745}
694746
695747Attribute
@@ -700,7 +752,7 @@ NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
700752 gpu::CompilationTarget format = options.getCompilationTarget ();
701753 DictionaryAttr objectProps;
702754 Builder builder (attribute.getContext ());
703- SmallVector<NamedAttribute, 2 > properties;
755+ SmallVector<NamedAttribute, 4 > properties;
704756 if (format == gpu::CompilationTarget::Assembly)
705757 properties.push_back (
706758 builder.getNamedAttr (" O" , builder.getI32IntegerAttr (target.getO ())));
@@ -709,6 +761,14 @@ NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
709761 properties.push_back (builder.getNamedAttr (gpu::elfSectionName,
710762 builder.getStringAttr (section)));
711763
764+ for (const auto *perfName : {" LLVMIRToISATimeInMs" , " ISAToBinaryTimeInMs" }) {
765+ if (module ->hasAttr (perfName)) {
766+ IntegerAttr attr = llvm::dyn_cast<IntegerAttr>(module ->getAttr (perfName));
767+ properties.push_back (builder.getNamedAttr (
768+ perfName, builder.getI64IntegerAttr (attr.getInt ())));
769+ }
770+ }
771+
712772 if (!properties.empty ())
713773 objectProps = builder.getDictionaryAttr (properties);
714774
0 commit comments