================ @@ -22505,6 +22506,57 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, return nullptr; } +Value *CodeGenFunction::EmitRISCVCpuIs(const CallExpr *E) { + const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); + StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); + return EmitRISCVCpuIs(CPUStr); +} + +Value *CodeGenFunction::EmitRISCVCpuIs(StringRef CPUStr) { + llvm::Type *Int32Ty = Builder.getInt32Ty(); + llvm::Type *Int64Ty = Builder.getInt64Ty(); + llvm::Type *MXLenType = + CGM.getTarget().getTriple().isArch32Bit() ? Int32Ty : Int64Ty; + + llvm::Type *StructTy = llvm::StructType::get(Int32Ty, MXLenType, MXLenType); + llvm::Constant *RISCVCPUModel = + CGM.CreateRuntimeVariable(StructTy, "__riscv_cpu_model"); + cast<llvm::GlobalValue>(RISCVCPUModel)->setDSOLocal(true); + + auto loadRISCVCPUID = [&](unsigned Index, llvm::Type *ValueTy, + CGBuilderTy &Builder, CodeGenModule &CGM) { + llvm::Value *GEPIndices[] = {Builder.getInt32(0), + llvm::ConstantInt::get(Int32Ty, Index)}; + Value *Ptr = Builder.CreateInBoundsGEP(StructTy, RISCVCPUModel, GEPIndices); + Value *CPUID = Builder.CreateAlignedLoad( + ValueTy, Ptr, + CharUnits::fromQuantity(ValueTy->getScalarSizeInBits() / 8)); + return CPUID; + }; + + // Compare mvendorid. + Value *VendorID = loadRISCVCPUID(0, Int32Ty, Builder, CGM); + Value *Result = Builder.CreateICmpEQ( + VendorID, + llvm::ConstantInt::get(Int32Ty, llvm::RISCV::getVendorID(CPUStr))); + + // Compare marchid. + Value *ArchID = loadRISCVCPUID(1, MXLenType, Builder, CGM); + Result = Builder.CreateAnd( + Result, Builder.CreateICmpEQ( + ArchID, llvm::ConstantInt::get( + MXLenType, llvm::RISCV::getArchID(CPUStr)))); + + // Compare mimplid. + Value *ImplID = loadRISCVCPUID(2, MXLenType, Builder, CGM); + Result = Builder.CreateAnd( + Result, Builder.CreateICmpEQ( + ImplID, llvm::ConstantInt::get( + MXLenType, llvm::RISCV::getImplID(CPUStr)))); ---------------- lenary wrote:
Currently we are using `getVendorID`, `getArchID` or `getImplID` returning 0 to mean we have no IDs in LLVM for that CPU. On the CPU Core's side, the CSRs will also report 0 if they are not implemented (though I'm not sure what e.g. Linux reports to userspace in this case). When we have no IDs, what comparisons should we be doing? Maybe we should only support `__builtin_cpu_is(...)` for CPUs where we have non-zero values for any of the three items? Otherwise either emit a compile-time error, or return `false` because we don't have a way to actually know if we're on the CPU being asked for? I don't know the right answer here, but I think this implementation isn't handling these cases right. https://github.com/llvm/llvm-project/pull/116231 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits