https://github.com/nemanjai updated https://github.com/llvm/llvm-project/pull/68919
>From 71f1352bf00d6a9eefa3f199859d47d093f272f8 Mon Sep 17 00:00:00 2001 From: Nemanja Ivanovic <nemanjaivano...@nemanjas-air.kpn> Date: Thu, 12 Oct 2023 14:08:42 -0400 Subject: [PATCH 1/4] [PowerPC][X86] Make cpu id builtins target independent and lower for PPC Make __builtin_cpu_{init|supports|is} target independent and provide an opt-in query for targets that want to support it. Each target is still responsible for their specific lowering/code-gen. Also provide code-gen for PowerPC. --- clang/include/clang/Basic/Builtins.def | 5 + clang/include/clang/Basic/BuiltinsX86.def | 7 - clang/include/clang/Basic/TargetInfo.h | 6 + clang/lib/Basic/Targets/PPC.cpp | 14 ++ clang/lib/Basic/Targets/PPC.h | 7 + clang/lib/Basic/Targets/X86.h | 4 + clang/lib/CodeGen/CGBuiltin.cpp | 42 +++++- clang/lib/Sema/SemaChecking.cpp | 124 +++++++++++------- clang/test/CodeGen/builtin-cpu-supports.c | 68 ++++++---- clang/test/Sema/builtin-cpu-supports.c | 8 +- llvm/include/llvm/IR/IntrinsicsPowerPC.td | 6 + .../llvm/TargetParser/PPCTargetParser.def | 80 +++++++++++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 4 + llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 33 +++++ llvm/lib/Target/PowerPC/PPCInstrInfo.td | 3 + llvm/lib/Target/PowerPC/PPCTargetMachine.h | 3 + llvm/test/CodeGen/PowerPC/cpu-supports.ll | 111 ++++++++++++++++ 17 files changed, 443 insertions(+), 82 deletions(-) create mode 100644 llvm/include/llvm/TargetParser/PPCTargetParser.def create mode 100644 llvm/test/CodeGen/PowerPC/cpu-supports.ll diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 6ea8484606cfd5..5e1f4088ff63f8 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -118,6 +118,11 @@ # define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) #endif +// Builtins for checking CPU features based on the GCC builtins. +BUILTIN(__builtin_cpu_supports, "bcC*", "nc") +BUILTIN(__builtin_cpu_is, "bcC*", "nc") +BUILTIN(__builtin_cpu_init, "v", "n") + // Standard libc/libm functions: BUILTIN(__builtin_atan2 , "ddd" , "Fne") BUILTIN(__builtin_atan2f, "fff" , "Fne") diff --git a/clang/include/clang/Basic/BuiltinsX86.def b/clang/include/clang/Basic/BuiltinsX86.def index e4802f8ab1c156..2acc5ce0f4a365 100644 --- a/clang/include/clang/Basic/BuiltinsX86.def +++ b/clang/include/clang/Basic/BuiltinsX86.def @@ -26,13 +26,6 @@ # define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS) #endif -// Miscellaneous builtin for checking x86 cpu features. -// TODO: Make this somewhat generic so that other backends -// can use it? -BUILTIN(__builtin_cpu_init, "v", "n") -BUILTIN(__builtin_cpu_supports, "bcC*", "nc") -BUILTIN(__builtin_cpu_is, "bcC*", "nc") - // Undefined Values // TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "ncV:128:", "") diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 9d56e97a3d4bb8..3d83b387aac093 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1415,6 +1415,12 @@ class TargetInfo : public TransferrableTargetInfo, getTriple().isOSFreeBSD()); } + // Identify whether this target supports __builtin_cpu_supports and + // __builtin_cpu_is. + virtual bool supportsCpuSupports() const { return false; } + virtual bool supportsCpuIs() const { return false; } + virtual bool supportsCpuInit() const { return false; } + // Validate the contents of the __builtin_cpu_supports(const char*) // argument. virtual bool validateCpuSupports(StringRef Name) const { return false; } diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index 0d87a3a4e8c20f..d8759c86c9932c 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -873,3 +873,17 @@ ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const { return llvm::ArrayRef(BuiltinInfo, clang::PPC::LastTSBuiltin - Builtin::FirstTSBuiltin); } + +bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const { +#define PPC_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) .Case(NAME, true) + return llvm::StringSwitch<bool>(FeatureStr) +#include "llvm/TargetParser/PPCTargetParser.def" + .Default(false); +} + +bool PPCTargetInfo::validateCpuIs(StringRef CPUName) const { +#define PPC_CPU(NAME, NUM) .Case(NAME, true) + return llvm::StringSwitch<bool>(CPUName) +#include "llvm/TargetParser/PPCTargetParser.def" + .Default(false); +} diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index 4d62673ba7fb8c..f700b625b79030 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -359,6 +359,13 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { bool isSPRegName(StringRef RegName) const override { return RegName.equals("r1") || RegName.equals("x1"); } + + // We support __builtin_cpu_supports/__builtin_cpu_is on targets that + // have GLIBC since it is GLIBC that provides the HWCAP[2] in the auxv. + bool supportsCpuSupports() const override { return getTriple().isOSGlibc(); } + bool supportsCpuIs() const override { return getTriple().isOSGlibc(); } + bool validateCpuSupports(StringRef Feature) const override; + bool validateCpuIs(StringRef Name) const override; }; class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo { diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 4fdc94de1e0cb4..3b379715163a8a 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -211,6 +211,10 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { return RegName.equals("esp") || RegName.equals("rsp"); } + bool supportsCpuSupports() const override { return true; } + bool supportsCpuIs() const override { return true; } + bool supportsCpuInit() const override { return true; } + bool validateCpuSupports(StringRef FeatureStr) const override; bool validateCpuIs(StringRef FeatureStr) const override; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 8cb7943df9a782..583b2be69ba166 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -13585,11 +13585,11 @@ CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) { Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { - if (BuiltinID == X86::BI__builtin_cpu_is) + if (BuiltinID == Builtin::BI__builtin_cpu_is) return EmitX86CpuIs(E); - if (BuiltinID == X86::BI__builtin_cpu_supports) + if (BuiltinID == Builtin::BI__builtin_cpu_supports) return EmitX86CpuSupports(E); - if (BuiltinID == X86::BI__builtin_cpu_init) + if (BuiltinID == Builtin::BI__builtin_cpu_init) return EmitX86CpuInit(); // Handle MSVC intrinsics before argument evaluation to prevent double @@ -16086,6 +16086,42 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, switch (BuiltinID) { default: return nullptr; + case Builtin::BI__builtin_cpu_is: { + const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); + StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); + unsigned NumCPUID = StringSwitch<unsigned>(CPUStr) +#define PPC_CPU(Name, NumericID) .Case(Name, NumericID) +#include "llvm/TargetParser/PPCTargetParser.def" + .Default(-1U); + Value *Op0 = + llvm::ConstantInt::get(Int32Ty, PPC_FAWORD_CPUID); + llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld); + Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_is"); + return Builder.CreateICmpEQ(TheCall, + llvm::ConstantInt::get(Int32Ty, NumCPUID)); + } + case Builtin::BI__builtin_cpu_supports: { + unsigned FeatureWord; + unsigned BitMask; + const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); + StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); + std::tie(FeatureWord, BitMask) = + StringSwitch<std::pair<unsigned, unsigned>>(CPUStr) +#define PPC_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD) \ + .Case(Name, {FA_WORD, Bitmask}) +#include "llvm/TargetParser/PPCTargetParser.def" + .Default({0, 0}); + Value *Op0 = llvm::ConstantInt::get(Int32Ty, FeatureWord); + llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld); + Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_supports"); + Value *Mask = + Builder.CreateAnd(TheCall, llvm::ConstantInt::get(Int32Ty, BitMask)); + return Builder.CreateICmpNE(Mask, llvm::Constant::getNullValue(Int32Ty)); +#undef PPC_FAWORD_HWCAP +#undef PPC_FAWORD_HWCAP2 +#undef PPC_FAWORD_CPUID + } + // __builtin_ppc_get_timebase is GCC 4.8+'s PowerPC-specific name for what we // call __builtin_readcyclecounter. case PPC::BI__builtin_ppc_get_timebase: diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2594a8f97f7d94..6e67f4edc9da32 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2110,6 +2110,66 @@ static bool checkFPMathBuiltinElementType(Sema &S, SourceLocation Loc, return false; } +/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *). +/// This checks that the target supports __builtin_cpu_supports and +/// that the string argument is constant and valid. +static bool SemaBuiltinCpuSupports(Sema &S, const TargetInfo &TI, + const TargetInfo *AuxTI, CallExpr *TheCall) { + Expr *Arg = TheCall->getArg(0); + + const TargetInfo *TheTI = nullptr; + if (TI.supportsCpuSupports()) + TheTI = &TI; + else if (AuxTI && AuxTI->supportsCpuSupports()) + TheTI = AuxTI; + else + return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) + << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); + + // Check if the argument is a string literal. + if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) + return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) + << Arg->getSourceRange(); + + // Check the contents of the string. + StringRef Feature = + cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); + if (!TheTI->validateCpuSupports(Feature)) + return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports) + << Arg->getSourceRange(); + return false; +} + +/// SemaBuiltinCpuIs - Handle __builtin_cpu_is(char *). +/// This checks that the target supports __builtin_cpu_is and +/// that the string argument is constant and valid. +static bool SemaBuiltinCpuIs(Sema &S, const TargetInfo &TI, + const TargetInfo *AuxTI, CallExpr *TheCall) { + Expr *Arg = TheCall->getArg(0); + + const TargetInfo *TheTI = nullptr; + if (TI.supportsCpuIs()) + TheTI = &TI; + else if (AuxTI && AuxTI->supportsCpuIs()) + TheTI = AuxTI; + else + return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) + << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); + + // Check if the argument is a string literal. + if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) + return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) + << Arg->getSourceRange(); + + // Check the contents of the string. + StringRef Feature = + cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); + if (!TheTI->validateCpuIs(Feature)) + return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is) + << Arg->getSourceRange(); + return false; +} + ExprResult Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall) { @@ -2137,6 +2197,23 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } switch (BuiltinID) { + case Builtin::BI__builtin_cpu_supports: + if (SemaBuiltinCpuSupports(*this, Context.getTargetInfo(), + Context.getAuxTargetInfo(), TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_cpu_is: + if (SemaBuiltinCpuIs(*this, Context.getTargetInfo(), + Context.getAuxTargetInfo(), TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_cpu_init: + if (!Context.getTargetInfo().supportsCpuInit()) { + Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) + << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); + return ExprError(); + } + break; case Builtin::BI__builtin___CFStringMakeConstantString: // CFStringMakeConstantString is currently not implemented for GOFF (i.e., // on z/OS) and for XCOFF (i.e., on AIX). Emit unsupported @@ -5582,47 +5659,6 @@ bool Sema::CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, return false; } -/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *). -/// This checks that the target supports __builtin_cpu_supports and -/// that the string argument is constant and valid. -static bool SemaBuiltinCpuSupports(Sema &S, const TargetInfo &TI, - CallExpr *TheCall) { - Expr *Arg = TheCall->getArg(0); - - // Check if the argument is a string literal. - if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) - return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) - << Arg->getSourceRange(); - - // Check the contents of the string. - StringRef Feature = - cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); - if (!TI.validateCpuSupports(Feature)) - return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports) - << Arg->getSourceRange(); - return false; -} - -/// SemaBuiltinCpuIs - Handle __builtin_cpu_is(char *). -/// This checks that the target supports __builtin_cpu_is and -/// that the string argument is constant and valid. -static bool SemaBuiltinCpuIs(Sema &S, const TargetInfo &TI, CallExpr *TheCall) { - Expr *Arg = TheCall->getArg(0); - - // Check if the argument is a string literal. - if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) - return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) - << Arg->getSourceRange(); - - // Check the contents of the string. - StringRef Feature = - cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); - if (!TI.validateCpuIs(Feature)) - return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is) - << Arg->getSourceRange(); - return false; -} - // Check if the rounding mode is legal. bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { // Indicates if this instruction has rounding control or just SAE. @@ -6097,12 +6133,6 @@ static bool isX86_32Builtin(unsigned BuiltinID) { bool Sema::CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { - if (BuiltinID == X86::BI__builtin_cpu_supports) - return SemaBuiltinCpuSupports(*this, TI, TheCall); - - if (BuiltinID == X86::BI__builtin_cpu_is) - return SemaBuiltinCpuIs(*this, TI, TheCall); - // Check for 32-bit only builtins on a 64-bit target. const llvm::Triple &TT = TI.getTriple(); if (TT.getArch() != llvm::Triple::x86 && isX86_32Builtin(BuiltinID)) diff --git a/clang/test/CodeGen/builtin-cpu-supports.c b/clang/test/CodeGen/builtin-cpu-supports.c index 796611c1fcd9af..42497d8845437a 100644 --- a/clang/test/CodeGen/builtin-cpu-supports.c +++ b/clang/test/CodeGen/builtin-cpu-supports.c @@ -1,11 +1,16 @@ -// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm < %s| FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm < %s | FileCheck %s \ +// RUN: --check-prefix=CHECK-X86 +// RUN: %clang_cc1 -triple ppc64le-linux-gnu -emit-llvm < %s | FileCheck %s \ +// RUN: --check-prefix=CHECK-PPC + +#ifndef __PPC__ // Test that we have the structure definition, the gep offsets, the name of the // global, the bit grab, and the icmp correct. extern void a(const char *); -// CHECK: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] } -// CHECK: @__cpu_features2 = external dso_local global [3 x i32] +// CHECK-X86: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] } +// CHECK-X86: @__cpu_features2 = external dso_local global [3 x i32] int main(void) { __builtin_cpu_init(); @@ -15,38 +20,57 @@ int main(void) { if (__builtin_cpu_supports("sse4.2")) a("sse4.2"); - // CHECK: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0) - // CHECK: [[AND:%[^ ]+]] = and i32 [[LOAD]], 256 - // CHECK: = icmp eq i32 [[AND]], 256 + // CHECK-X86: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0) + // CHECK-X86: [[AND:%[^ ]+]] = and i32 [[LOAD]], 256 + // CHECK-X86: = icmp eq i32 [[AND]], 256 if (__builtin_cpu_supports("gfni")) a("gfni"); - // CHECK: [[LOAD:%[^ ]+]] = load i32, ptr @__cpu_features2 - // CHECK: [[AND:%[^ ]+]] = and i32 [[LOAD]], 1 - // CHECK: = icmp eq i32 [[AND]], 1 + // CHECK-X86: [[LOAD:%[^ ]+]] = load i32, ptr @__cpu_features2 + // CHECK-X86: [[AND:%[^ ]+]] = and i32 [[LOAD]], 1 + // CHECK-X86: = icmp eq i32 [[AND]], 1 return 0; } -// CHECK: declare dso_local void @__cpu_indicator_init() +// CHECK-X86: declare dso_local void @__cpu_indicator_init() -// CHECK-LABEL: define{{.*}} @baseline( -// CHECK: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 1) -// CHECK-NEXT: and i32 [[LOAD]], -2147483648 +// CHECK-X86-LABEL: define{{.*}} @baseline( +// CHECK-X86: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 1) +// CHECK-X86-NEXT: and i32 [[LOAD]], -2147483648 int baseline() { return __builtin_cpu_supports("x86-64"); } -// CHECK-LABEL: define{{.*}} @v2( -// CHECK: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) -// CHECK-NEXT: and i32 [[LOAD]], 1 +// CHECK-X86-LABEL: define{{.*}} @v2( +// CHECK-X86: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) +// CHECK-X86-NEXT: and i32 [[LOAD]], 1 int v2() { return __builtin_cpu_supports("x86-64-v2"); } -// CHECK-LABEL: define{{.*}} @v3( -// CHECK: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) -// CHECK-NEXT: and i32 [[LOAD]], 2 +// CHECK-X86-LABEL: define{{.*}} @v3( +// CHECK-X86: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) +// CHECK-X86-NEXT: and i32 [[LOAD]], 2 int v3() { return __builtin_cpu_supports("x86-64-v3"); } -// CHECK-LABEL: define{{.*}} @v4( -// CHECK: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) -// CHECK-NEXT: and i32 [[LOAD]], 4 +// CHECK-X86-LABEL: define{{.*}} @v4( +// CHECK-X86: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) +// CHECK-X86-NEXT: and i32 [[LOAD]], 4 int v4() { return __builtin_cpu_supports("x86-64-v4"); } +#else +int test(int a) { +// CHECK-PPC: [[CPUSUP:%[^ ]+]] = call i32 @llvm.ppc.fixed.addr.ld(i32 2) +// CHECK-PPC: [[AND:%[^ ]+]] = and i32 [[CPUSUP]], 8388608 +// CHECK-PPC: icmp ne i32 [[AND]], 0 +// CHECK-PPC: [[CPUSUP2:%[^ ]+]] = call i32 @llvm.ppc.fixed.addr.ld(i32 1) +// CHECK-PPC: [[AND2:%[^ ]+]] = and i32 [[CPUSUP2]], 67108864 +// CHECK-PPC: icmp ne i32 [[AND2]], 0 +// CHECK-PPC: [[CPUID:%[^ ]+]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) +// CHECK-PPC: icmp eq i32 [[CPUID]], 39 + if (__builtin_cpu_supports("arch_3_00")) // HWCAP2 + return a; + else if (__builtin_cpu_supports("mmu")) // HWCAP + return a - 5; + else if (__builtin_cpu_is("power7")) // CPUID + return a + a; + return a + 5; +} +#endif diff --git a/clang/test/Sema/builtin-cpu-supports.c b/clang/test/Sema/builtin-cpu-supports.c index ad310128fecebf..cc6f1beb5d8a7c 100644 --- a/clang/test/Sema/builtin-cpu-supports.c +++ b/clang/test/Sema/builtin-cpu-supports.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux-gnu -verify %s -// RUN: %clang_cc1 -fsyntax-only -triple powerpc64le-linux-gnu -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple aarch64-linux-gnu -verify %s extern void a(const char *); @@ -27,11 +27,13 @@ int main(void) { (void)__builtin_cpu_supports("x86-64-v4"); (void)__builtin_cpu_supports("x86-64-v5"); // expected-error {{invalid cpu feature string for builtin}} #else - if (__builtin_cpu_supports("vsx")) // expected-error {{use of unknown builtin}} + if (__builtin_cpu_supports("aes")) // expected-error {{builtin is not supported on this target}} a("vsx"); - if (__builtin_cpu_is("pwr9")) // expected-error {{use of unknown builtin}} + if (__builtin_cpu_is("cortex-x3")) // expected-error {{builtin is not supported on this target}} a("pwr9"); + + __builtin_cpu_init(); // expected-error {{builtin is not supported on this target}} #endif return 0; diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td index 3ede2a3736bf30..f4e64764b4d1cc 100644 --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -210,6 +210,12 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". [llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_vararg_ty], [IntrNoMem]>; + // Load of a value provided by the system library at a fixed address. Used for + // accessing things like HWCAP word provided by GLIBC. + def int_ppc_fixed_addr_ld + : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], + [IntrInaccessibleMemOnly, ImmArg<ArgIndex<0>>]>; + } let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". diff --git a/llvm/include/llvm/TargetParser/PPCTargetParser.def b/llvm/include/llvm/TargetParser/PPCTargetParser.def new file mode 100644 index 00000000000000..e935e0112956fe --- /dev/null +++ b/llvm/include/llvm/TargetParser/PPCTargetParser.def @@ -0,0 +1,80 @@ +#ifndef PPC_FEATURE +#define PPC_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) +#endif +#ifndef PPC_CPU +#define PPC_CPU(NAME, NUM) +#endif +#ifndef PPC_FAWORD_HWCAP +#define PPC_FAWORD_HWCAP 1 +#endif +#ifndef PPC_FAWORD_HWCAP2 +#define PPC_FAWORD_HWCAP2 2 +#endif +#ifndef PPC_FAWORD_CPUID +#define PPC_FAWORD_CPUID 3 +#endif + +// PPC_FEATURE(Name, Description, EnumName, BitMask, PPC_FAWORD_WORD) +PPC_FEATURE("4xxmac","4xx CPU has a Multiply Accumulator",PPCF_4XXMAC,0x02000000,PPC_FAWORD_HWCAP) +PPC_FEATURE("altivec","CPU has a SIMD/Vector Unit",PPCF_ALTIVEC,0x10000000,PPC_FAWORD_HWCAP) +PPC_FEATURE("arch_2_05","CPU supports ISA 205 (eg, POWER6)",PPCF_ARCH205,0x00001000,PPC_FAWORD_HWCAP) +PPC_FEATURE("arch_2_06","CPU supports ISA 206 (eg, POWER7)",PPCF_ARCH206,0x00000100,PPC_FAWORD_HWCAP) +PPC_FEATURE("arch_2_07","CPU supports ISA 207 (eg, POWER8)",PPCF_ARCH207,0x80000000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("arch_3_00","CPU supports ISA 30 (eg, POWER9)",PPCF_ARCH30,0x00800000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("arch_3_1","CPU supports ISA 31 (eg, POWER10)",PPCF_ARCH31,0x00040000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("archpmu","CPU supports the set of compatible performance monitoring events",PPCF_ARCHPMU,0x00000040,PPC_FAWORD_HWCAP) +PPC_FEATURE("booke","CPU supports the Embedded ISA category",PPCF_BOOKE,0x00008000,PPC_FAWORD_HWCAP) +PPC_FEATURE("cellbe","CPU has a CELL broadband engine",PPCF_CELLBE,0x00010000,PPC_FAWORD_HWCAP) +PPC_FEATURE("darn","CPU supports the darn (deliver a random number) instruction",PPCF_DARN,0x00200000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("dfp","CPU has a decimal floating point unit",PPCF_DFP,0x00000400,PPC_FAWORD_HWCAP) +PPC_FEATURE("dscr","CPU supports the data stream control register",PPCF_DSCR,0x20000000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("ebb","CPU supports event base branching",PPCF_EBB,0x10000000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("efpdouble","CPU has a SPE double precision floating point unit",PPCF_EFPDOUBLE,0x00200000,PPC_FAWORD_HWCAP) +PPC_FEATURE("efpsingle","CPU has a SPE single precision floating point unit",PPCF_EFPSINGLE,0x00400000,PPC_FAWORD_HWCAP) +PPC_FEATURE("fpu","CPU has a floating point unit",PPCF_FPU,0x08000000,PPC_FAWORD_HWCAP) +PPC_FEATURE("htm","CPU has hardware transaction memory instructions",PPCF_HTM,0x40000000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("htm-nosc","Kernel aborts hardware transactions when a syscall is made",PPCF_HTM_NOSC,0x01000000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("htm-no-suspend","CPU supports hardware transaction memory but does not support the tsuspend instruction.",PPCF_HTM_NO_SUSPEND,0x00080000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("ic_snoop","CPU supports icache snooping capabilities",PPCF_IC_SNOOP,0x00002000,PPC_FAWORD_HWCAP) +PPC_FEATURE("ieee128","CPU supports 128-bit IEEE binary floating point instructions",PPCF_IEEE128,0x00400000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("isel","CPU supports the integer select instruction",PPCF_ISEL,0x08000000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("mma","CPU supports the matrix-multiply assist instructions",PPCF_MMA,0x00020000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("mmu","CPU has a memory management unit",PPCF_MMU,0x04000000,PPC_FAWORD_HWCAP) +PPC_FEATURE("notb","CPU does not have a timebase (eg, 601 and 403gx)",PPCF_NOTB,0x00100000,PPC_FAWORD_HWCAP) +PPC_FEATURE("pa6t","CPU supports the PA Semi 6T CORE ISA",PPCF_PA6T,0x00000800,PPC_FAWORD_HWCAP) +PPC_FEATURE("power4","CPU supports ISA 200 (eg, POWER4)",PPCF_POWER4,0x00080000,PPC_FAWORD_HWCAP) +PPC_FEATURE("power5","CPU supports ISA 202 (eg, POWER5)",PPCF_POWER5,0x00040000,PPC_FAWORD_HWCAP) +PPC_FEATURE("power5+","CPU supports ISA 203 (eg, POWER5+)",PPCF_POWER5P,0x00020000,PPC_FAWORD_HWCAP) +PPC_FEATURE("power6x","CPU supports ISA 205 (eg, POWER6) extended opcodes mffgpr and mftgpr.",PPCF_POWER6X,0x00000200,PPC_FAWORD_HWCAP) +PPC_FEATURE("ppc32","CPU supports 32-bit mode execution",PPCF_PPC32,0x80000000,PPC_FAWORD_HWCAP) +PPC_FEATURE("ppc601","CPU supports the old POWER ISA (eg, 601)",PPCF_PPC601,0x20000000,PPC_FAWORD_HWCAP) +PPC_FEATURE("ppc64","CPU supports 64-bit mode execution",PPCF_PPC64,0x40000000,PPC_FAWORD_HWCAP) +PPC_FEATURE("ppcle","CPU supports a little-endian mode that uses address swizzling",PPCF_PPCLE,0x00000001,PPC_FAWORD_HWCAP) +PPC_FEATURE("scv","Kernel supports system call vectored",PPCF_SCV,0x00100000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("smt","CPU support simultaneous multi-threading",PPCF_SMT,0x00004000,PPC_FAWORD_HWCAP) +PPC_FEATURE("spe","CPU has a signal processing extension unit",PPCF_SPE,0x00800000,PPC_FAWORD_HWCAP) +PPC_FEATURE("tar","CPU supports the target address register",PPCF_TAR,0x04000000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("true_le","CPU supports true little-endian mode",PPCF_TRUE_LE,0x00000002,PPC_FAWORD_HWCAP) +PPC_FEATURE("ucache","CPU has unified I/D cache",PPCF_UCACHE,0x01000000,PPC_FAWORD_HWCAP) +PPC_FEATURE("vcrypto","CPU supports the vector cryptography instructions",PPCF_VCRYPTO,0x02000000,PPC_FAWORD_HWCAP2) +PPC_FEATURE("vsx","CPU supports the vector-scalar extension",PPCF_VSX,0x00000080,PPC_FAWORD_HWCAP) + +// PPC_CPU(Name, NumericID) +PPC_CPU("power4",32) +PPC_CPU("ppc970",33) +PPC_CPU("power5",34) +PPC_CPU("power5+",35) +PPC_CPU("power6",36) +PPC_CPU("ppc-cell-be",37) +PPC_CPU("power6x",38) +PPC_CPU("power7",39) +PPC_CPU("ppca2",40) +PPC_CPU("ppc405",41) +PPC_CPU("ppc440",42) +PPC_CPU("ppc464",43) +PPC_CPU("ppc476",44) +PPC_CPU("power8",45) +PPC_CPU("power9",46) +PPC_CPU("power10",47) +#undef PPC_FEATURE +#undef PPC_CPU diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 4f15ba497d84c4..e8e20610d67bcf 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1830,6 +1830,10 @@ void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) { PPCTargetStreamer *TS = static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer()); + if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess()) + OutStreamer->emitSymbolValue( + GetExternalSymbolSymbol("__parse_hwcap_and_convert_at_platform"), + MAI->getCodePointerSize()); emitGNUAttributes(M); if (!TOC.empty()) { diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 75c6399fe7e16b..7d4cdd8be4a4a7 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1103,6 +1103,7 @@ bool PPCInstrInfo::isReallyTriviallyReMaterializable( case PPC::ADDIStocHA8: case PPC::ADDItocL: case PPC::LOAD_STACK_GUARD: + case PPC::PPCLdFixedAddr: case PPC::XXLXORz: case PPC::XXLXORspz: case PPC::XXLXORdpz: @@ -3124,6 +3125,38 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { .addReg(Reg); return true; } + case PPC::PPCLdFixedAddr: { + assert(Subtarget.isTargetLinux() && + "Only Linux target is expected to contain PPCLdFixedAddr"); + int64_t Offset = 0; + const unsigned Reg = Subtarget.isPPC64() ? PPC::X13 : PPC::R2; + MI.setDesc(get(PPC::LWZ)); + uint64_t FAType = MI.getOperand(1).getImm(); +#undef PPC_FEATURE +#undef PPC_CPU +#include "llvm/TargetParser/PPCTargetParser.def" + // The HWCAP and HWCAP2 word offsets are reversed on big endian Linux. + if ((FAType == PPC_FAWORD_HWCAP && Subtarget.isLittleEndian()) || + (FAType == PPC_FAWORD_HWCAP2 && !Subtarget.isLittleEndian())) + Offset = Subtarget.isPPC64() ? -0x7064 : -0x703C; + else if ((FAType == PPC_FAWORD_HWCAP2 && + Subtarget.isLittleEndian()) || + (FAType == PPC_FAWORD_HWCAP && + !Subtarget.isLittleEndian())) + Offset = Subtarget.isPPC64() ? -0x7068 : -0x7040; + else if (FAType == PPC_FAWORD_CPUID) + Offset = Subtarget.isPPC64() ? -0x705C : -0x7034; + assert(Offset && "Do not know the offset for this fixed addr load"); + MI.removeOperand(1); + Subtarget.getTargetMachine().setGlibcHWCAPAccess(); + MachineInstrBuilder(*MI.getParent()->getParent(), MI) + .addImm(Offset) + .addReg(Reg); + return true; +#undef PPC_FAWORD_HWCAP +#undef PPC_FAWORD_HWCAP2 +#undef PPC_FAWORD_CPUID + } case PPC::DFLOADf32: case PPC::DFLOADf64: case PPC::DFSTOREf32: diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index a97062e0c643fb..56fff50e6fb9b9 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -4826,6 +4826,9 @@ def RLWNMbm : PPCAsmPseudo<"rlwnm $rA, $rS, $n, $b", (ins g8rc:$rA, g8rc:$rS, u5imm:$n, i32imm:$b)>; def RLWNMbm_rec : PPCAsmPseudo<"rlwnm. $rA, $rS, $n, $b", (ins g8rc:$rA, g8rc:$rS, u5imm:$n, i32imm:$b)>; +def PPCLdFixedAddr : + PPCPostRAExpPseudo<(outs gprc:$rT), (ins i32imm:$imm), "#FA_LOAD", + [(set i32:$rT, (int_ppc_fixed_addr_ld timm:$imm))]>; // These generic branch instruction forms are used for the assembler parser only. // Defs and Uses are conservative, since we don't know the BO value. diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.h b/llvm/lib/Target/PowerPC/PPCTargetMachine.h index 56145a2eb39ce4..9d0d3e727170a3 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.h +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.h @@ -32,6 +32,7 @@ class PPCTargetMachine final : public LLVMTargetMachine { std::unique_ptr<TargetLoweringObjectFile> TLOF; PPCABI TargetABI; Endian Endianness = Endian::NOT_DETECTED; + mutable bool HasGlibcHWCAPAccess = false; mutable StringMap<std::unique_ptr<PPCSubtarget>> SubtargetMap; @@ -64,6 +65,8 @@ class PPCTargetMachine final : public LLVMTargetMachine { const TargetSubtargetInfo *STI) const override; bool isELFv2ABI() const { return TargetABI == PPC_ABI_ELFv2; } + bool hasGlibcHWCAPAccess() const { return HasGlibcHWCAPAccess; } + void setGlibcHWCAPAccess(bool Val = true) const { HasGlibcHWCAPAccess = Val; } bool isPPC64() const { const Triple &TT = getTargetTriple(); return (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le); diff --git a/llvm/test/CodeGen/PowerPC/cpu-supports.ll b/llvm/test/CodeGen/PowerPC/cpu-supports.ll new file mode 100644 index 00000000000000..912d67e5c555e6 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/cpu-supports.ll @@ -0,0 +1,111 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mcpu=pwr9 -ppc-asm-full-reg-names \ +; RUN: -mtriple=powerpc64-linux-gnu < %s | FileCheck %s \ +; RUN: -check-prefix=BE64 +; RUN: llc -mcpu=pwr9 -ppc-asm-full-reg-names \ +; RUN: -mtriple=powerpc-linux-gnu < %s | FileCheck %s \ +; RUN: -check-prefix=BE32 +; RUN: llc -mcpu=pwr9 -ppc-asm-full-reg-names \ +; RUN: -mtriple=powerpc64le-linux-gnu < %s | FileCheck %s \ +; RUN: -check-prefix=LE +define dso_local signext i32 @test(i32 noundef signext %a) local_unnamed_addr #0 { +; BE64-LABEL: test: +; BE64: # %bb.0: # %entry +; BE64-NEXT: lwz r4, -28772(r13) +; BE64-NEXT: andis. r4, r4, 128 +; BE64-NEXT: bne cr0, .LBB0_3 +; BE64-NEXT: # %bb.1: # %if.else +; BE64-NEXT: lwz r4, -28776(r13) +; BE64-NEXT: andis. r4, r4, 1024 +; BE64-NEXT: bne cr0, .LBB0_4 +; BE64-NEXT: # %bb.2: # %if.else3 +; BE64-NEXT: lwz r4, -28764(r13) +; BE64-NEXT: cmplwi r4, 39 +; BE64-NEXT: addi r4, r3, 5 +; BE64-NEXT: slwi r3, r3, 1 +; BE64-NEXT: iseleq r3, r3, r4 +; BE64-NEXT: .LBB0_3: # %return +; BE64-NEXT: extsw r3, r3 +; BE64-NEXT: blr +; BE64-NEXT: .LBB0_4: # %if.then2 +; BE64-NEXT: addi r3, r3, -5 +; BE64-NEXT: extsw r3, r3 +; BE64-NEXT: blr +; +; BE32-LABEL: test: +; BE32: # %bb.0: # %entry +; BE32-NEXT: lwz r4, -28732(r2) +; BE32-NEXT: andis. r4, r4, 128 +; BE32-NEXT: bnelr cr0 +; BE32-NEXT: # %bb.1: # %if.else +; BE32-NEXT: lwz r4, -28736(r2) +; BE32-NEXT: andis. r4, r4, 1024 +; BE32-NEXT: bne cr0, .LBB0_3 +; BE32-NEXT: # %bb.2: # %if.else3 +; BE32-NEXT: lwz r4, -28724(r2) +; BE32-NEXT: cmplwi r4, 39 +; BE32-NEXT: addi r4, r3, 5 +; BE32-NEXT: slwi r3, r3, 1 +; BE32-NEXT: iseleq r3, r3, r4 +; BE32-NEXT: blr +; BE32-NEXT: .LBB0_3: # %if.then2 +; BE32-NEXT: addi r3, r3, -5 +; BE32-NEXT: blr +; +; LE-LABEL: test: +; LE: # %bb.0: # %entry +; LE-NEXT: lwz r4, -28776(r13) +; LE-NEXT: andis. r4, r4, 128 +; LE-NEXT: bne cr0, .LBB0_3 +; LE-NEXT: # %bb.1: # %if.else +; LE-NEXT: lwz r4, -28772(r13) +; LE-NEXT: andis. r4, r4, 1024 +; LE-NEXT: bne cr0, .LBB0_4 +; LE-NEXT: # %bb.2: # %if.else3 +; LE-NEXT: lwz r4, -28764(r13) +; LE-NEXT: cmplwi r4, 39 +; LE-NEXT: addi r4, r3, 5 +; LE-NEXT: slwi r3, r3, 1 +; LE-NEXT: iseleq r3, r3, r4 +; LE-NEXT: .LBB0_3: # %return +; LE-NEXT: extsw r3, r3 +; LE-NEXT: blr +; LE-NEXT: .LBB0_4: # %if.then2 +; LE-NEXT: addi r3, r3, -5 +; LE-NEXT: extsw r3, r3 +; LE-NEXT: blr +entry: + %cpu_supports = tail call i32 @llvm.ppc.fixed.addr.ld(i32 2) + %0 = and i32 %cpu_supports, 8388608 + %.not = icmp eq i32 %0, 0 + br i1 %.not, label %if.else, label %return + +if.else: ; preds = %entry + %cpu_supports1 = tail call i32 @llvm.ppc.fixed.addr.ld(i32 1) + %1 = and i32 %cpu_supports1, 67108864 + %.not12 = icmp eq i32 %1, 0 + br i1 %.not12, label %if.else3, label %if.then2 + +if.then2: ; preds = %if.else + %sub = add nsw i32 %a, -5 + br label %return + +if.else3: ; preds = %if.else + %cpu_is = tail call i32 @llvm.ppc.fixed.addr.ld(i32 3) + %2 = icmp eq i32 %cpu_is, 39 + br i1 %2, label %if.then4, label %if.end6 + +if.then4: ; preds = %if.else3 + %add = shl nsw i32 %a, 1 + br label %return + +if.end6: ; preds = %if.else3 + %add7 = add nsw i32 %a, 5 + br label %return + +return: ; preds = %entry, %if.end6, %if.then4, %if.then2 + %retval.0 = phi i32 [ %sub, %if.then2 ], [ %add, %if.then4 ], [ %add7, %if.end6 ], [ %a, %entry ] + ret i32 %retval.0 +} + +declare i32 @llvm.ppc.fixed.addr.ld(i32 immarg) #1 >From b817566af1db72697cfdfd738a1e432687d7c8b9 Mon Sep 17 00:00:00 2001 From: Nemanja Ivanovic <nemanjaivano...@nemanjas-air.kpn> Date: Thu, 12 Oct 2023 14:32:07 -0400 Subject: [PATCH 2/4] Run clang-format which I appear to have forgotten to run --- clang/lib/CodeGen/CGBuiltin.cpp | 3 +-- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 583b2be69ba166..c5920216e307de 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -16093,8 +16093,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, #define PPC_CPU(Name, NumericID) .Case(Name, NumericID) #include "llvm/TargetParser/PPCTargetParser.def" .Default(-1U); - Value *Op0 = - llvm::ConstantInt::get(Int32Ty, PPC_FAWORD_CPUID); + Value *Op0 = llvm::ConstantInt::get(Int32Ty, PPC_FAWORD_CPUID); llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld); Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_is"); return Builder.CreateICmpEQ(TheCall, diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 7d4cdd8be4a4a7..79123cedda071d 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -3139,10 +3139,8 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { if ((FAType == PPC_FAWORD_HWCAP && Subtarget.isLittleEndian()) || (FAType == PPC_FAWORD_HWCAP2 && !Subtarget.isLittleEndian())) Offset = Subtarget.isPPC64() ? -0x7064 : -0x703C; - else if ((FAType == PPC_FAWORD_HWCAP2 && - Subtarget.isLittleEndian()) || - (FAType == PPC_FAWORD_HWCAP && - !Subtarget.isLittleEndian())) + else if ((FAType == PPC_FAWORD_HWCAP2 && Subtarget.isLittleEndian()) || + (FAType == PPC_FAWORD_HWCAP && !Subtarget.isLittleEndian())) Offset = Subtarget.isPPC64() ? -0x7068 : -0x7040; else if (FAType == PPC_FAWORD_CPUID) Offset = Subtarget.isPPC64() ? -0x705C : -0x7034; >From 89479473b07bb85bb94eea9b7d268c529dfe1eff Mon Sep 17 00:00:00 2001 From: Nemanja Ivanovic <nema...@synopsys.com> Date: Thu, 11 Jan 2024 13:23:28 +0100 Subject: [PATCH 3/4] Address comments - Use script for generating test checks - Clean up code and rename macros for clarity - Remove magic number offsets - Get rid of auxiliary targets in Sema checking - Clarify some comments and add missing ones - Add check for undefined symbol added for safety --- clang/lib/Basic/Targets/PPC.cpp | 4 +- clang/lib/CodeGen/CGBuiltin.cpp | 4 +- clang/lib/Sema/SemaChecking.cpp | 71 ++----- clang/test/CodeGen/builtin-cpu-supports.c | 149 +++++++++++--- llvm/include/llvm/IR/IntrinsicsPowerPC.td | 5 +- .../llvm/TargetParser/PPCTargetParser.def | 183 +++++++++++------- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 4 + llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 42 ++-- llvm/test/CodeGen/PowerPC/cpu-supports.ll | 3 + 9 files changed, 294 insertions(+), 171 deletions(-) diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index d8759c86c9932c..411a3c810a2e3a 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -875,14 +875,14 @@ ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const { } bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const { -#define PPC_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) .Case(NAME, true) +#define PPC_LNX_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) .Case(NAME, true) return llvm::StringSwitch<bool>(FeatureStr) #include "llvm/TargetParser/PPCTargetParser.def" .Default(false); } bool PPCTargetInfo::validateCpuIs(StringRef CPUName) const { -#define PPC_CPU(NAME, NUM) .Case(NAME, true) +#define PPC_LNX_CPU(NAME, NUM) .Case(NAME, true) return llvm::StringSwitch<bool>(CPUName) #include "llvm/TargetParser/PPCTargetParser.def" .Default(false); diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c5920216e307de..33f300905ac10a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -16090,7 +16090,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); unsigned NumCPUID = StringSwitch<unsigned>(CPUStr) -#define PPC_CPU(Name, NumericID) .Case(Name, NumericID) +#define PPC_LNX_CPU(Name, NumericID) .Case(Name, NumericID) #include "llvm/TargetParser/PPCTargetParser.def" .Default(-1U); Value *Op0 = llvm::ConstantInt::get(Int32Ty, PPC_FAWORD_CPUID); @@ -16106,7 +16106,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); std::tie(FeatureWord, BitMask) = StringSwitch<std::pair<unsigned, unsigned>>(CPUStr) -#define PPC_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD) \ +#define PPC_LNX_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD) \ .Case(Name, {FA_WORD, Bitmask}) #include "llvm/TargetParser/PPCTargetParser.def" .Default({0, 0}); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 6e67f4edc9da32..b5868c1349fb1f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2110,61 +2110,35 @@ static bool checkFPMathBuiltinElementType(Sema &S, SourceLocation Loc, return false; } -/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *). -/// This checks that the target supports __builtin_cpu_supports and -/// that the string argument is constant and valid. -static bool SemaBuiltinCpuSupports(Sema &S, const TargetInfo &TI, - const TargetInfo *AuxTI, CallExpr *TheCall) { - Expr *Arg = TheCall->getArg(0); - - const TargetInfo *TheTI = nullptr; - if (TI.supportsCpuSupports()) - TheTI = &TI; - else if (AuxTI && AuxTI->supportsCpuSupports()) - TheTI = AuxTI; - else +/// SemaBuiltinCpu{Supports|Is} - Handle __builtin_cpu_{supports|is}(char *). +/// This checks that the target supports the builtin and that the string +/// argument is constant and valid. +static bool SemaBuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall, + unsigned BuiltinID) { + assert((BuiltinID == Builtin::BI__builtin_cpu_supports || + BuiltinID == Builtin::BI__builtin_cpu_is) && + "Expecting __builtin_cpu_..."); + + bool IsCPUSupports = BuiltinID == Builtin::BI__builtin_cpu_supports; + if (IsCPUSupports && !TI.supportsCpuSupports()) return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); - - // Check if the argument is a string literal. - if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) - return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) - << Arg->getSourceRange(); - - // Check the contents of the string. - StringRef Feature = - cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); - if (!TheTI->validateCpuSupports(Feature)) - return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports) - << Arg->getSourceRange(); - return false; -} - -/// SemaBuiltinCpuIs - Handle __builtin_cpu_is(char *). -/// This checks that the target supports __builtin_cpu_is and -/// that the string argument is constant and valid. -static bool SemaBuiltinCpuIs(Sema &S, const TargetInfo &TI, - const TargetInfo *AuxTI, CallExpr *TheCall) { - Expr *Arg = TheCall->getArg(0); - - const TargetInfo *TheTI = nullptr; - if (TI.supportsCpuIs()) - TheTI = &TI; - else if (AuxTI && AuxTI->supportsCpuIs()) - TheTI = AuxTI; - else + if (!IsCPUSupports && !TI.supportsCpuIs()) return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); + Expr *Arg = TheCall->getArg(0)->IgnoreParenImpCasts(); // Check if the argument is a string literal. - if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) + if (!isa<StringLiteral>(Arg)) return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) << Arg->getSourceRange(); // Check the contents of the string. - StringRef Feature = - cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); - if (!TheTI->validateCpuIs(Feature)) + StringRef Feature = cast<StringLiteral>(Arg)->getString(); + if (IsCPUSupports && !TI.validateCpuSupports(Feature)) + return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports) + << Arg->getSourceRange(); + if (!IsCPUSupports && !TI.validateCpuIs(Feature)) return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is) << Arg->getSourceRange(); return false; @@ -2198,13 +2172,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, switch (BuiltinID) { case Builtin::BI__builtin_cpu_supports: - if (SemaBuiltinCpuSupports(*this, Context.getTargetInfo(), - Context.getAuxTargetInfo(), TheCall)) - return ExprError(); - break; case Builtin::BI__builtin_cpu_is: - if (SemaBuiltinCpuIs(*this, Context.getTargetInfo(), - Context.getAuxTargetInfo(), TheCall)) + if (SemaBuiltinCpu(*this, Context.getTargetInfo(), TheCall, BuiltinID)) return ExprError(); break; case Builtin::BI__builtin_cpu_init: diff --git a/clang/test/CodeGen/builtin-cpu-supports.c b/clang/test/CodeGen/builtin-cpu-supports.c index 42497d8845437a..88eb7b0fa786e5 100644 --- a/clang/test/CodeGen/builtin-cpu-supports.c +++ b/clang/test/CodeGen/builtin-cpu-supports.c @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm < %s | FileCheck %s \ -// RUN: --check-prefix=CHECK-X86 -// RUN: %clang_cc1 -triple ppc64le-linux-gnu -emit-llvm < %s | FileCheck %s \ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefix=CHECK-X86 +// RUN: %clang_cc1 -triple ppc64le-linux-gnu -emit-llvm -o - %s | FileCheck %s \ // RUN: --check-prefix=CHECK-PPC #ifndef __PPC__ @@ -9,9 +10,33 @@ // global, the bit grab, and the icmp correct. extern void a(const char *); -// CHECK-X86: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] } -// CHECK-X86: @__cpu_features2 = external dso_local global [3 x i32] +// CHECK-X86-LABEL: define dso_local i32 @main( +// CHECK-X86-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-X86-NEXT: entry: +// CHECK-X86-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-X86-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-X86-NEXT: call void @__cpu_indicator_init() +// CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 4 +// CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 256 +// CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 256 +// CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-X86-NEXT: br i1 [[TMP3]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +// CHECK-X86: if.then: +// CHECK-X86-NEXT: call void @a(ptr noundef @.str) +// CHECK-X86-NEXT: br label [[IF_END]] +// CHECK-X86: if.end: +// CHECK-X86-NEXT: [[TMP4:%.*]] = load i32, ptr @__cpu_features2, align 4 +// CHECK-X86-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 1 +// CHECK-X86-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 1 +// CHECK-X86-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-X86-NEXT: br i1 [[TMP7]], label [[IF_THEN1:%.*]], label [[IF_END2:%.*]] +// CHECK-X86: if.then1: +// CHECK-X86-NEXT: call void @a(ptr noundef @.str.1) +// CHECK-X86-NEXT: br label [[IF_END2]] +// CHECK-X86: if.end2: +// CHECK-X86-NEXT: ret i32 0 +// int main(void) { __builtin_cpu_init(); @@ -20,51 +45,111 @@ int main(void) { if (__builtin_cpu_supports("sse4.2")) a("sse4.2"); - // CHECK-X86: [[LOAD:%[^ ]+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0) - // CHECK-X86: [[AND:%[^ ]+]] = and i32 [[LOAD]], 256 - // CHECK-X86: = icmp eq i32 [[AND]], 256 if (__builtin_cpu_supports("gfni")) a("gfni"); - // CHECK-X86: [[LOAD:%[^ ]+]] = load i32, ptr @__cpu_features2 - // CHECK-X86: [[AND:%[^ ]+]] = and i32 [[LOAD]], 1 - // CHECK-X86: = icmp eq i32 [[AND]], 1 return 0; } -// CHECK-X86: declare dso_local void @__cpu_indicator_init() -// CHECK-X86-LABEL: define{{.*}} @baseline( -// CHECK-X86: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 1) -// CHECK-X86-NEXT: and i32 [[LOAD]], -2147483648 +// CHECK-X86-LABEL: define dso_local i32 @baseline( +// CHECK-X86-SAME: ) #[[ATTR0]] { +// CHECK-X86-NEXT: entry: +// CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 1), align 4 +// CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], -2147483648 +// CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], -2147483648 +// CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-X86-NEXT: [[CONV:%.*]] = zext i1 [[TMP3]] to i32 +// CHECK-X86-NEXT: ret i32 [[CONV]] +// int baseline() { return __builtin_cpu_supports("x86-64"); } -// CHECK-X86-LABEL: define{{.*}} @v2( -// CHECK-X86: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) -// CHECK-X86-NEXT: and i32 [[LOAD]], 1 +// CHECK-X86-LABEL: define dso_local i32 @v2( +// CHECK-X86-SAME: ) #[[ATTR0]] { +// CHECK-X86-NEXT: entry: +// CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2), align 4 +// CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 1 +// CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 +// CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-X86-NEXT: [[CONV:%.*]] = zext i1 [[TMP3]] to i32 +// CHECK-X86-NEXT: ret i32 [[CONV]] +// int v2() { return __builtin_cpu_supports("x86-64-v2"); } -// CHECK-X86-LABEL: define{{.*}} @v3( -// CHECK-X86: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) -// CHECK-X86-NEXT: and i32 [[LOAD]], 2 +// CHECK-X86-LABEL: define dso_local i32 @v3( +// CHECK-X86-SAME: ) #[[ATTR0]] { +// CHECK-X86-NEXT: entry: +// CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2), align 4 +// CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 2 +// CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 2 +// CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-X86-NEXT: [[CONV:%.*]] = zext i1 [[TMP3]] to i32 +// CHECK-X86-NEXT: ret i32 [[CONV]] +// int v3() { return __builtin_cpu_supports("x86-64-v3"); } -// CHECK-X86-LABEL: define{{.*}} @v4( -// CHECK-X86: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2) -// CHECK-X86-NEXT: and i32 [[LOAD]], 4 +// CHECK-X86-LABEL: define dso_local i32 @v4( +// CHECK-X86-SAME: ) #[[ATTR0]] { +// CHECK-X86-NEXT: entry: +// CHECK-X86-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2), align 4 +// CHECK-X86-NEXT: [[TMP1:%.*]] = and i32 [[TMP0]], 4 +// CHECK-X86-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 4 +// CHECK-X86-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-X86-NEXT: [[CONV:%.*]] = zext i1 [[TMP3]] to i32 +// CHECK-X86-NEXT: ret i32 [[CONV]] +// int v4() { return __builtin_cpu_supports("x86-64-v4"); } #else +// CHECK-PPC-LABEL: define dso_local signext i32 @test( +// CHECK-PPC-SAME: i32 noundef signext [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-PPC-NEXT: entry: +// CHECK-PPC-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-PPC-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-PPC-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK-PPC-NEXT: [[CPU_SUPPORTS:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 2) +// CHECK-PPC-NEXT: [[TMP0:%.*]] = and i32 [[CPU_SUPPORTS]], 8388608 +// CHECK-PPC-NEXT: [[TMP1:%.*]] = icmp ne i32 [[TMP0]], 0 +// CHECK-PPC-NEXT: br i1 [[TMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +// CHECK-PPC: if.then: +// CHECK-PPC-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-PPC-NEXT: store i32 [[TMP2]], ptr [[RETVAL]], align 4 +// CHECK-PPC-NEXT: br label [[RETURN:%.*]] +// CHECK-PPC: if.else: +// CHECK-PPC-NEXT: [[CPU_SUPPORTS1:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 1) +// CHECK-PPC-NEXT: [[TMP3:%.*]] = and i32 [[CPU_SUPPORTS1]], 67108864 +// CHECK-PPC-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], 0 +// CHECK-PPC-NEXT: br i1 [[TMP4]], label [[IF_THEN2:%.*]], label [[IF_ELSE3:%.*]] +// CHECK-PPC: if.then2: +// CHECK-PPC-NEXT: [[TMP5:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-PPC-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP5]], 5 +// CHECK-PPC-NEXT: store i32 [[SUB]], ptr [[RETVAL]], align 4 +// CHECK-PPC-NEXT: br label [[RETURN]] +// CHECK-PPC: if.else3: +// CHECK-PPC-NEXT: [[CPU_IS:%.*]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) +// CHECK-PPC-NEXT: [[TMP6:%.*]] = icmp eq i32 [[CPU_IS]], 39 +// CHECK-PPC-NEXT: br i1 [[TMP6]], label [[IF_THEN4:%.*]], label [[IF_END:%.*]] +// CHECK-PPC: if.then4: +// CHECK-PPC-NEXT: [[TMP7:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-PPC-NEXT: [[TMP8:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-PPC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP7]], [[TMP8]] +// CHECK-PPC-NEXT: store i32 [[ADD]], ptr [[RETVAL]], align 4 +// CHECK-PPC-NEXT: br label [[RETURN]] +// CHECK-PPC: if.end: +// CHECK-PPC-NEXT: br label [[IF_END5:%.*]] +// CHECK-PPC: if.end5: +// CHECK-PPC-NEXT: br label [[IF_END6:%.*]] +// CHECK-PPC: if.end6: +// CHECK-PPC-NEXT: [[TMP9:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-PPC-NEXT: [[ADD7:%.*]] = add nsw i32 [[TMP9]], 5 +// CHECK-PPC-NEXT: store i32 [[ADD7]], ptr [[RETVAL]], align 4 +// CHECK-PPC-NEXT: br label [[RETURN]] +// CHECK-PPC: return: +// CHECK-PPC-NEXT: [[TMP10:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK-PPC-NEXT: ret i32 [[TMP10]] +// int test(int a) { -// CHECK-PPC: [[CPUSUP:%[^ ]+]] = call i32 @llvm.ppc.fixed.addr.ld(i32 2) -// CHECK-PPC: [[AND:%[^ ]+]] = and i32 [[CPUSUP]], 8388608 -// CHECK-PPC: icmp ne i32 [[AND]], 0 -// CHECK-PPC: [[CPUSUP2:%[^ ]+]] = call i32 @llvm.ppc.fixed.addr.ld(i32 1) -// CHECK-PPC: [[AND2:%[^ ]+]] = and i32 [[CPUSUP2]], 67108864 -// CHECK-PPC: icmp ne i32 [[AND2]], 0 -// CHECK-PPC: [[CPUID:%[^ ]+]] = call i32 @llvm.ppc.fixed.addr.ld(i32 3) -// CHECK-PPC: icmp eq i32 [[CPUID]], 39 if (__builtin_cpu_supports("arch_3_00")) // HWCAP2 return a; else if (__builtin_cpu_supports("mmu")) // HWCAP diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td index f4e64764b4d1cc..4ca56b3d1a6749 100644 --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -211,7 +211,10 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_vararg_ty], [IntrNoMem]>; // Load of a value provided by the system library at a fixed address. Used for - // accessing things like HWCAP word provided by GLIBC. + // accessing things like HWCAP word provided by GLIBC. The immediate argument + // is not an address but a value defined in + // include/llvm/TargetParser/PPCTargetParser.def. Each of the values provided + // by Glibc is a 32-bit word. def int_ppc_fixed_addr_ld : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrInaccessibleMemOnly, ImmArg<ArgIndex<0>>]>; diff --git a/llvm/include/llvm/TargetParser/PPCTargetParser.def b/llvm/include/llvm/TargetParser/PPCTargetParser.def index e935e0112956fe..f2c44b46fa6730 100644 --- a/llvm/include/llvm/TargetParser/PPCTargetParser.def +++ b/llvm/include/llvm/TargetParser/PPCTargetParser.def @@ -1,8 +1,41 @@ -#ifndef PPC_FEATURE -#define PPC_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) +//===- PPCTargetParser.def - PPC target parsing defines ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides defines to build up the PPC target parser's logic. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifdef PPC_TGT_PARSER_UNDEF_MACROS +#undef PPC_LNX_FEATURE +#undef PPC_LNX_CPU +#undef PPC_FAWORD_HWCAP +#undef PPC_FAWORD_HWCAP2 +#undef PPC_FAWORD_CPUID +#undef PPC_HWCAP_OFFSET_LE32 +#undef PPC_HWCAP_OFFSET_LE64 +#undef PPC_HWCAP_OFFSET_BE32 +#undef PPC_HWCAP_OFFSET_BE64 +#undef PPC_HWCAP2_OFFSET_LE32 +#undef PPC_HWCAP2_OFFSET_LE64 +#undef PPC_HWCAP2_OFFSET_BE32 +#undef PPC_HWCAP2_OFFSET_BE64 +#undef PPC_CPUID_OFFSET_LE32 +#undef PPC_CPUID_OFFSET_LE64 +#undef PPC_CPUID_OFFSET_BE32 +#undef PPC_CPUID_OFFSET_BE64 +#else +#ifndef PPC_LNX_FEATURE +#define PPC_LNX_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) #endif -#ifndef PPC_CPU -#define PPC_CPU(NAME, NUM) +#ifndef PPC_LNX_CPU +#define PPC_LNX_CPU(NAME, NUM) #endif #ifndef PPC_FAWORD_HWCAP #define PPC_FAWORD_HWCAP 1 @@ -14,67 +47,83 @@ #define PPC_FAWORD_CPUID 3 #endif -// PPC_FEATURE(Name, Description, EnumName, BitMask, PPC_FAWORD_WORD) -PPC_FEATURE("4xxmac","4xx CPU has a Multiply Accumulator",PPCF_4XXMAC,0x02000000,PPC_FAWORD_HWCAP) -PPC_FEATURE("altivec","CPU has a SIMD/Vector Unit",PPCF_ALTIVEC,0x10000000,PPC_FAWORD_HWCAP) -PPC_FEATURE("arch_2_05","CPU supports ISA 205 (eg, POWER6)",PPCF_ARCH205,0x00001000,PPC_FAWORD_HWCAP) -PPC_FEATURE("arch_2_06","CPU supports ISA 206 (eg, POWER7)",PPCF_ARCH206,0x00000100,PPC_FAWORD_HWCAP) -PPC_FEATURE("arch_2_07","CPU supports ISA 207 (eg, POWER8)",PPCF_ARCH207,0x80000000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("arch_3_00","CPU supports ISA 30 (eg, POWER9)",PPCF_ARCH30,0x00800000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("arch_3_1","CPU supports ISA 31 (eg, POWER10)",PPCF_ARCH31,0x00040000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("archpmu","CPU supports the set of compatible performance monitoring events",PPCF_ARCHPMU,0x00000040,PPC_FAWORD_HWCAP) -PPC_FEATURE("booke","CPU supports the Embedded ISA category",PPCF_BOOKE,0x00008000,PPC_FAWORD_HWCAP) -PPC_FEATURE("cellbe","CPU has a CELL broadband engine",PPCF_CELLBE,0x00010000,PPC_FAWORD_HWCAP) -PPC_FEATURE("darn","CPU supports the darn (deliver a random number) instruction",PPCF_DARN,0x00200000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("dfp","CPU has a decimal floating point unit",PPCF_DFP,0x00000400,PPC_FAWORD_HWCAP) -PPC_FEATURE("dscr","CPU supports the data stream control register",PPCF_DSCR,0x20000000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("ebb","CPU supports event base branching",PPCF_EBB,0x10000000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("efpdouble","CPU has a SPE double precision floating point unit",PPCF_EFPDOUBLE,0x00200000,PPC_FAWORD_HWCAP) -PPC_FEATURE("efpsingle","CPU has a SPE single precision floating point unit",PPCF_EFPSINGLE,0x00400000,PPC_FAWORD_HWCAP) -PPC_FEATURE("fpu","CPU has a floating point unit",PPCF_FPU,0x08000000,PPC_FAWORD_HWCAP) -PPC_FEATURE("htm","CPU has hardware transaction memory instructions",PPCF_HTM,0x40000000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("htm-nosc","Kernel aborts hardware transactions when a syscall is made",PPCF_HTM_NOSC,0x01000000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("htm-no-suspend","CPU supports hardware transaction memory but does not support the tsuspend instruction.",PPCF_HTM_NO_SUSPEND,0x00080000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("ic_snoop","CPU supports icache snooping capabilities",PPCF_IC_SNOOP,0x00002000,PPC_FAWORD_HWCAP) -PPC_FEATURE("ieee128","CPU supports 128-bit IEEE binary floating point instructions",PPCF_IEEE128,0x00400000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("isel","CPU supports the integer select instruction",PPCF_ISEL,0x08000000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("mma","CPU supports the matrix-multiply assist instructions",PPCF_MMA,0x00020000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("mmu","CPU has a memory management unit",PPCF_MMU,0x04000000,PPC_FAWORD_HWCAP) -PPC_FEATURE("notb","CPU does not have a timebase (eg, 601 and 403gx)",PPCF_NOTB,0x00100000,PPC_FAWORD_HWCAP) -PPC_FEATURE("pa6t","CPU supports the PA Semi 6T CORE ISA",PPCF_PA6T,0x00000800,PPC_FAWORD_HWCAP) -PPC_FEATURE("power4","CPU supports ISA 200 (eg, POWER4)",PPCF_POWER4,0x00080000,PPC_FAWORD_HWCAP) -PPC_FEATURE("power5","CPU supports ISA 202 (eg, POWER5)",PPCF_POWER5,0x00040000,PPC_FAWORD_HWCAP) -PPC_FEATURE("power5+","CPU supports ISA 203 (eg, POWER5+)",PPCF_POWER5P,0x00020000,PPC_FAWORD_HWCAP) -PPC_FEATURE("power6x","CPU supports ISA 205 (eg, POWER6) extended opcodes mffgpr and mftgpr.",PPCF_POWER6X,0x00000200,PPC_FAWORD_HWCAP) -PPC_FEATURE("ppc32","CPU supports 32-bit mode execution",PPCF_PPC32,0x80000000,PPC_FAWORD_HWCAP) -PPC_FEATURE("ppc601","CPU supports the old POWER ISA (eg, 601)",PPCF_PPC601,0x20000000,PPC_FAWORD_HWCAP) -PPC_FEATURE("ppc64","CPU supports 64-bit mode execution",PPCF_PPC64,0x40000000,PPC_FAWORD_HWCAP) -PPC_FEATURE("ppcle","CPU supports a little-endian mode that uses address swizzling",PPCF_PPCLE,0x00000001,PPC_FAWORD_HWCAP) -PPC_FEATURE("scv","Kernel supports system call vectored",PPCF_SCV,0x00100000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("smt","CPU support simultaneous multi-threading",PPCF_SMT,0x00004000,PPC_FAWORD_HWCAP) -PPC_FEATURE("spe","CPU has a signal processing extension unit",PPCF_SPE,0x00800000,PPC_FAWORD_HWCAP) -PPC_FEATURE("tar","CPU supports the target address register",PPCF_TAR,0x04000000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("true_le","CPU supports true little-endian mode",PPCF_TRUE_LE,0x00000002,PPC_FAWORD_HWCAP) -PPC_FEATURE("ucache","CPU has unified I/D cache",PPCF_UCACHE,0x01000000,PPC_FAWORD_HWCAP) -PPC_FEATURE("vcrypto","CPU supports the vector cryptography instructions",PPCF_VCRYPTO,0x02000000,PPC_FAWORD_HWCAP2) -PPC_FEATURE("vsx","CPU supports the vector-scalar extension",PPCF_VSX,0x00000080,PPC_FAWORD_HWCAP) +// PPC_LNX_FEATURE(Name, Description, EnumName, BitMask, PPC_FAWORD_WORD) +PPC_LNX_FEATURE("4xxmac","4xx CPU has a Multiply Accumulator",PPCF_4XXMAC,0x02000000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("altivec","CPU has a SIMD/Vector Unit",PPCF_ALTIVEC,0x10000000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("arch_2_05","CPU supports ISA 205 (eg, POWER6)",PPCF_ARCH205,0x00001000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("arch_2_06","CPU supports ISA 206 (eg, POWER7)",PPCF_ARCH206,0x00000100,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("arch_2_07","CPU supports ISA 207 (eg, POWER8)",PPCF_ARCH207,0x80000000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("arch_3_00","CPU supports ISA 30 (eg, POWER9)",PPCF_ARCH30,0x00800000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("arch_3_1","CPU supports ISA 31 (eg, POWER10)",PPCF_ARCH31,0x00040000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("archpmu","CPU supports the set of compatible performance monitoring events",PPCF_ARCHPMU,0x00000040,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("booke","CPU supports the Embedded ISA category",PPCF_BOOKE,0x00008000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("cellbe","CPU has a CELL broadband engine",PPCF_CELLBE,0x00010000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("darn","CPU supports the darn (deliver a random number) instruction",PPCF_DARN,0x00200000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("dfp","CPU has a decimal floating point unit",PPCF_DFP,0x00000400,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("dscr","CPU supports the data stream control register",PPCF_DSCR,0x20000000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("ebb","CPU supports event base branching",PPCF_EBB,0x10000000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("efpdouble","CPU has a SPE double precision floating point unit",PPCF_EFPDOUBLE,0x00200000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("efpsingle","CPU has a SPE single precision floating point unit",PPCF_EFPSINGLE,0x00400000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("fpu","CPU has a floating point unit",PPCF_FPU,0x08000000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("htm","CPU has hardware transaction memory instructions",PPCF_HTM,0x40000000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("htm-nosc","Kernel aborts hardware transactions when a syscall is made",PPCF_HTM_NOSC,0x01000000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("htm-no-suspend","CPU supports hardware transaction memory but does not support the tsuspend instruction.",PPCF_HTM_NO_SUSPEND,0x00080000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("ic_snoop","CPU supports icache snooping capabilities",PPCF_IC_SNOOP,0x00002000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("ieee128","CPU supports 128-bit IEEE binary floating point instructions",PPCF_IEEE128,0x00400000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("isel","CPU supports the integer select instruction",PPCF_ISEL,0x08000000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("mma","CPU supports the matrix-multiply assist instructions",PPCF_MMA,0x00020000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("mmu","CPU has a memory management unit",PPCF_MMU,0x04000000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("notb","CPU does not have a timebase (eg, 601 and 403gx)",PPCF_NOTB,0x00100000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("pa6t","CPU supports the PA Semi 6T CORE ISA",PPCF_PA6T,0x00000800,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("power4","CPU supports ISA 200 (eg, POWER4)",PPCF_POWER4,0x00080000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("power5","CPU supports ISA 202 (eg, POWER5)",PPCF_POWER5,0x00040000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("power5+","CPU supports ISA 203 (eg, POWER5+)",PPCF_POWER5P,0x00020000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("power6x","CPU supports ISA 205 (eg, POWER6) extended opcodes mffgpr and mftgpr.",PPCF_POWER6X,0x00000200,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("ppc32","CPU supports 32-bit mode execution",PPCF_PPC32,0x80000000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("ppc601","CPU supports the old POWER ISA (eg, 601)",PPCF_PPC601,0x20000000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("ppc64","CPU supports 64-bit mode execution",PPCF_PPC64,0x40000000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("ppcle","CPU supports a little-endian mode that uses address swizzling",PPCF_PPCLE,0x00000001,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("scv","Kernel supports system call vectored",PPCF_SCV,0x00100000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("smt","CPU support simultaneous multi-threading",PPCF_SMT,0x00004000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("spe","CPU has a signal processing extension unit",PPCF_SPE,0x00800000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("tar","CPU supports the target address register",PPCF_TAR,0x04000000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("true_le","CPU supports true little-endian mode",PPCF_TRUE_LE,0x00000002,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("ucache","CPU has unified I/D cache",PPCF_UCACHE,0x01000000,PPC_FAWORD_HWCAP) +PPC_LNX_FEATURE("vcrypto","CPU supports the vector cryptography instructions",PPCF_VCRYPTO,0x02000000,PPC_FAWORD_HWCAP2) +PPC_LNX_FEATURE("vsx","CPU supports the vector-scalar extension",PPCF_VSX,0x00000080,PPC_FAWORD_HWCAP) -// PPC_CPU(Name, NumericID) -PPC_CPU("power4",32) -PPC_CPU("ppc970",33) -PPC_CPU("power5",34) -PPC_CPU("power5+",35) -PPC_CPU("power6",36) -PPC_CPU("ppc-cell-be",37) -PPC_CPU("power6x",38) -PPC_CPU("power7",39) -PPC_CPU("ppca2",40) -PPC_CPU("ppc405",41) -PPC_CPU("ppc440",42) -PPC_CPU("ppc464",43) -PPC_CPU("ppc476",44) -PPC_CPU("power8",45) -PPC_CPU("power9",46) -PPC_CPU("power10",47) -#undef PPC_FEATURE -#undef PPC_CPU +// PPC_LNX_CPU(Name, NumericID) +PPC_LNX_CPU("power4",32) +PPC_LNX_CPU("ppc970",33) +PPC_LNX_CPU("power5",34) +PPC_LNX_CPU("power5+",35) +PPC_LNX_CPU("power6",36) +PPC_LNX_CPU("ppc-cell-be",37) +PPC_LNX_CPU("power6x",38) +PPC_LNX_CPU("power7",39) +PPC_LNX_CPU("ppca2",40) +PPC_LNX_CPU("ppc405",41) +PPC_LNX_CPU("ppc440",42) +PPC_LNX_CPU("ppc464",43) +PPC_LNX_CPU("ppc476",44) +PPC_LNX_CPU("power8",45) +PPC_LNX_CPU("power9",46) +PPC_LNX_CPU("power10",47) +#ifdef PPC_LNX_DEFINE_OFFSETS +# define PPC_HWCAP_OFFSET_LE32 -0x703C +# define PPC_HWCAP_OFFSET_LE64 -0x7064 +# define PPC_HWCAP_OFFSET_BE32 -0x7040 +# define PPC_HWCAP_OFFSET_BE64 -0x7068 +# define PPC_HWCAP2_OFFSET_LE32 -0x7040 +# define PPC_HWCAP2_OFFSET_LE64 -0x7068 +# define PPC_HWCAP2_OFFSET_BE32 -0x703C +# define PPC_HWCAP2_OFFSET_BE64 -0x7064 +# define PPC_CPUID_OFFSET_LE32 -0x7034 +# define PPC_CPUID_OFFSET_LE64 -0x705C +# define PPC_CPUID_OFFSET_BE32 -0x7034 +# define PPC_CPUID_OFFSET_BE64 -0x705C +#endif +#undef PPC_LNX_DEFINE_OFFSETS +#undef PPC_LNX_FEATURE +#undef PPC_LNX_CPU +#endif // !PPC_TGT_PARSER_UNDEF_MACROS diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index e8e20610d67bcf..2291d4a0045aae 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1830,6 +1830,10 @@ void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) { PPCTargetStreamer *TS = static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer()); + // If we are using any values provided by Glibc at fixed addresses, + // we need to ensure that the Glibc used at link time actually provides + // those values. All versions of Glibc that do will define the symbol + // named "__parse_hwcap_and_convert_at_platform". if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess()) OutStreamer->emitSymbolValue( GetExternalSymbolSymbol("__parse_hwcap_and_convert_at_platform"), diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 79123cedda071d..016503c9483e00 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -3126,24 +3126,34 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { return true; } case PPC::PPCLdFixedAddr: { - assert(Subtarget.isTargetLinux() && - "Only Linux target is expected to contain PPCLdFixedAddr"); + assert(Subtarget.getTargetTriple().isOSGlibc() && + "Only targets with Glibc expected to contain PPCLdFixedAddr"); int64_t Offset = 0; const unsigned Reg = Subtarget.isPPC64() ? PPC::X13 : PPC::R2; MI.setDesc(get(PPC::LWZ)); uint64_t FAType = MI.getOperand(1).getImm(); -#undef PPC_FEATURE -#undef PPC_CPU +#undef PPC_LNX_FEATURE +#undef PPC_LNX_CPU +#define PPC_LNX_DEFINE_OFFSETS #include "llvm/TargetParser/PPCTargetParser.def" - // The HWCAP and HWCAP2 word offsets are reversed on big endian Linux. - if ((FAType == PPC_FAWORD_HWCAP && Subtarget.isLittleEndian()) || - (FAType == PPC_FAWORD_HWCAP2 && !Subtarget.isLittleEndian())) - Offset = Subtarget.isPPC64() ? -0x7064 : -0x703C; - else if ((FAType == PPC_FAWORD_HWCAP2 && Subtarget.isLittleEndian()) || - (FAType == PPC_FAWORD_HWCAP && !Subtarget.isLittleEndian())) - Offset = Subtarget.isPPC64() ? -0x7068 : -0x7040; - else if (FAType == PPC_FAWORD_CPUID) - Offset = Subtarget.isPPC64() ? -0x705C : -0x7034; + bool IsLE = Subtarget.isLittleEndian(); + bool Is64 = Subtarget.isPPC64(); + if (FAType == PPC_FAWORD_HWCAP) { + if (IsLE) + Offset = Is64 ? PPC_HWCAP_OFFSET_LE64 : PPC_HWCAP_OFFSET_LE32; + else + Offset = Is64 ? PPC_HWCAP_OFFSET_BE64 : PPC_HWCAP_OFFSET_BE32; + } else if (FAType == PPC_FAWORD_HWCAP2) { + if (IsLE) + Offset = Is64 ? PPC_HWCAP2_OFFSET_LE64 : PPC_HWCAP2_OFFSET_LE32; + else + Offset = Is64 ? PPC_HWCAP2_OFFSET_BE64 : PPC_HWCAP2_OFFSET_BE32; + } else if (FAType == PPC_FAWORD_CPUID) { + if (IsLE) + Offset = Is64 ? PPC_CPUID_OFFSET_LE64 : PPC_CPUID_OFFSET_LE32; + else + Offset = Is64 ? PPC_CPUID_OFFSET_BE64 : PPC_CPUID_OFFSET_BE32; + } assert(Offset && "Do not know the offset for this fixed addr load"); MI.removeOperand(1); Subtarget.getTargetMachine().setGlibcHWCAPAccess(); @@ -3151,9 +3161,9 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { .addImm(Offset) .addReg(Reg); return true; -#undef PPC_FAWORD_HWCAP -#undef PPC_FAWORD_HWCAP2 -#undef PPC_FAWORD_CPUID +#define PPC_TGT_PARSER_UNDEF_MACROS +#include "llvm/TargetParser/PPCTargetParser.def" +#undef PPC_TGT_PARSER_UNDEF_MACROS } case PPC::DFLOADf32: case PPC::DFLOADf64: diff --git a/llvm/test/CodeGen/PowerPC/cpu-supports.ll b/llvm/test/CodeGen/PowerPC/cpu-supports.ll index 912d67e5c555e6..82ceb15084f07b 100644 --- a/llvm/test/CodeGen/PowerPC/cpu-supports.ll +++ b/llvm/test/CodeGen/PowerPC/cpu-supports.ll @@ -31,6 +31,7 @@ define dso_local signext i32 @test(i32 noundef signext %a) local_unnamed_addr #0 ; BE64-NEXT: addi r3, r3, -5 ; BE64-NEXT: extsw r3, r3 ; BE64-NEXT: blr +; BE64: .quad __parse_hwcap_and_convert_at_platform ; ; BE32-LABEL: test: ; BE32: # %bb.0: # %entry @@ -51,6 +52,7 @@ define dso_local signext i32 @test(i32 noundef signext %a) local_unnamed_addr #0 ; BE32-NEXT: .LBB0_3: # %if.then2 ; BE32-NEXT: addi r3, r3, -5 ; BE32-NEXT: blr +; BE32: .long __parse_hwcap_and_convert_at_platform ; ; LE-LABEL: test: ; LE: # %bb.0: # %entry @@ -74,6 +76,7 @@ define dso_local signext i32 @test(i32 noundef signext %a) local_unnamed_addr #0 ; LE-NEXT: addi r3, r3, -5 ; LE-NEXT: extsw r3, r3 ; LE-NEXT: blr +; LE: .quad __parse_hwcap_and_convert_at_platform entry: %cpu_supports = tail call i32 @llvm.ppc.fixed.addr.ld(i32 2) %0 = and i32 %cpu_supports, 8388608 >From 4253c52ea766e0e31dcc9b658889f32af5212cb7 Mon Sep 17 00:00:00 2001 From: Nemanja Ivanovic <nema...@synopsys.com> Date: Thu, 11 Jan 2024 21:56:12 +0100 Subject: [PATCH 4/4] Add the Auxiliary target checks back in for Sema. --- clang/lib/Sema/SemaChecking.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b5868c1349fb1f..21ecae2417a6ce 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2114,16 +2114,24 @@ static bool checkFPMathBuiltinElementType(Sema &S, SourceLocation Loc, /// This checks that the target supports the builtin and that the string /// argument is constant and valid. static bool SemaBuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall, - unsigned BuiltinID) { + const TargetInfo *AuxTI, unsigned BuiltinID) { assert((BuiltinID == Builtin::BI__builtin_cpu_supports || BuiltinID == Builtin::BI__builtin_cpu_is) && "Expecting __builtin_cpu_..."); bool IsCPUSupports = BuiltinID == Builtin::BI__builtin_cpu_supports; - if (IsCPUSupports && !TI.supportsCpuSupports()) + const TargetInfo *TheTI = &TI; + auto SupportsBI = [=](const TargetInfo *TInfo) { + return TInfo && ((IsCPUSupports && TInfo->supportsCpuSupports()) || + (!IsCPUSupports && TInfo->supportsCpuIs())); + }; + if (!SupportsBI(&TI) && SupportsBI(AuxTI)) + TheTI = AuxTI; + + if (IsCPUSupports && !TheTI->supportsCpuSupports()) return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); - if (!IsCPUSupports && !TI.supportsCpuIs()) + if (!IsCPUSupports && !TheTI->supportsCpuIs()) return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc()); @@ -2135,10 +2143,10 @@ static bool SemaBuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall, // Check the contents of the string. StringRef Feature = cast<StringLiteral>(Arg)->getString(); - if (IsCPUSupports && !TI.validateCpuSupports(Feature)) + if (IsCPUSupports && !TheTI->validateCpuSupports(Feature)) return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports) << Arg->getSourceRange(); - if (!IsCPUSupports && !TI.validateCpuIs(Feature)) + if (!IsCPUSupports && !TheTI->validateCpuIs(Feature)) return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is) << Arg->getSourceRange(); return false; @@ -2173,7 +2181,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, switch (BuiltinID) { case Builtin::BI__builtin_cpu_supports: case Builtin::BI__builtin_cpu_is: - if (SemaBuiltinCpu(*this, Context.getTargetInfo(), TheCall, BuiltinID)) + if (SemaBuiltinCpu(*this, Context.getTargetInfo(), TheCall, + Context.getAuxTargetInfo(), BuiltinID)) return ExprError(); break; case Builtin::BI__builtin_cpu_init: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits