[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
Long5hot wrote: ping!! @nemanjai https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin approved this pull request. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
diggerlin wrote: > @diggerlin , > > > > can we implement -fcomplex-ppc-gnu-abi as "-msoft-float" ? what is your > > > opinion ? > > > that was not the intent here and we need to consultant ABI reference > > > regrading the same ,before we decide on implementation . I think I do not express comment clearly, My comment is that "can we implement ` -fcomplex-ppc-gnu-abi` in llc ? , as `-msoft-float` which was implemented in the llc . I went through the code which implement of the `-msoft-float` today , I am OK to implement ` -fcomplex-ppc-gnu-abi` as it is. I do not have comment on the PR, I approved it, but please wait other several days to see whether there is other comment from other reviewer before you merge. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
UmeshKalappa0 wrote: @diggerlin , >>can we implement -fcomplex-ppc-gnu-abi as "-msoft-float" ? what is your >>opinion ? that was not the intent here and we need to consultant ABI reference regrading the same ,before we decide on implementation . https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
diggerlin wrote: I do not further comment on the PR, but I have worry about that , the PR have different mechanism with "-msoft-float" , the -msoft-float pass "use-soft-float"="true" in the IR, the llc will l put float parameter in the GPR, but the PR implement `-fcomplex-ppc-gnu-abi` in the frontend , can we implement `-fcomplex-ppc-gnu-abi` as "-msoft-float" ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From cc5fe4a6aa4762040077ab39edb6677f42638673 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Sun, 28 Apr 2024 14:18:42 +0530 Subject: [PATCH 1/2] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. Following up with this patch : https://reviews.llvm.org/D146942 --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 87 +++- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 394 ++ .../ppc32-complex-soft-float-gnu-abi.c| 286 + .../test/Driver/ppc32-fcomplex-ppc-gnu-abi.c | 15 + 9 files changed, 805 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-soft-float-gnu-abi.c create mode 100644 clang/test/Driver/ppc32-fcomplex-ppc-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 086aedefc11878..e35ac8ea36d727 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2601,6 +2601,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlaghttps://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + bool IsComplex = Ty->isAnyComplexType(); + + if ((getCodeGenOpts().getComplexInRegABI() != CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft || (!IsComplex && Ty->isFloatingType() && !IsSoftFloatABI)) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + // For complex type or any other primitive types. + if (IsComplex || !isAggregateTypeForABI(Ty)) { +// If gr is even set gr = gr + 1 for
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,286 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-DEF +// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-SOFT-FLOAT + +// CHECK-GNU-DEF-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-DEF-SAME: (float noundef [[F:%.*]], [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 +// CHECK-GNU-DEF-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-DEF-NEXT:ret [8 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-SOFT-FLOAT-SAME: (float noundef [[F:%.*]], ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 [[X:%.*]]) #[[ATTR0:[0-9]+]] { Long5hot wrote: Below assembly's generated with -fcomplex-ppc-gnu-abi -O1 --target=ppc32 -S -msoft-float "use-soft-float"="true" get's passed in IR in attributes ``` _Complex double testComplexDouble(float w, _Complex float x, _Complex double z) { return z; } testComplexDouble: # @testComplexDouble .Lfunc_begin2: .cfi_startproc # %bb.0: mr 6, 10 mr 5, 9 mr 4, 8 mr 3, 7 blr .Lfunc_end2: .size testComplexDouble, .Lfunc_end2-.Lfunc_begin2 .cfi_endproc # -- End function ``` ``` _Complex double checkComplexDoubleOnStack(float x1, _Complex float cf, float x2, _Complex double cd) { return testComplexDouble(x2, cf, cd); } .globl checkComplexDoubleOnStack # -- Begin function checkComplexDoubleOnStack .p2align2 .type checkComplexDoubleOnStack,@function checkComplexDoubleOnStack: # @checkComplexDoubleOnStack .Lfunc_begin3: .cfi_startproc # %bb.0: lwz 3, 0(8) lwz 4, 4(8) lwz 5, 8(8) lwz 6, 12(8) blr ``` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot deleted https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,286 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-DEF +// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-SOFT-FLOAT + +// CHECK-GNU-DEF-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-DEF-SAME: (float noundef [[F:%.*]], [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 +// CHECK-GNU-DEF-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-DEF-NEXT:ret [8 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-SOFT-FLOAT-SAME: (float noundef [[F:%.*]], ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-SOFT-FLOAT-NEXT: entry: +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-SOFT-FLOAT-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:ret [8 x i32] [[TMP0]] +// +_Complex long double _cldouble(float f, _Complex long double x) { + return x; +} + +// CHECK-GNU-DEF-LABEL: define dso_local [4 x i32] @testComplexDouble +// CHECK-GNU-DEF-SAME: (float noundef [[W:%.*]], [1 x i64] noundef [[X_COERCE:%.*]], [4 x i32] noundef [[Z_COERCE:%.*]]) #[[ATTR0]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { float, float }, align 4 +// CHECK-GNU-DEF-NEXT:[[Z:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[W_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [1 x i64] [[X_COERCE]], ptr [[X]], align 4 +// CHECK-GNU-DEF-NEXT:store [4 x i32] [[Z_COERCE]], ptr [[Z]], align 8 +// CHECK-GNU-DEF-NEXT:store float [[W]], ptr [[W_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[Z_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[Z]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[Z_REAL:%.*]] = load double, ptr [[Z_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:[[Z_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[Z]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[Z_IMAG:%.*]] = load double, ptr [[Z_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] =
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
diggerlin wrote: please do not merge the commit if possible, merging the commit make the review difficult, We want to compare what change between the two commit when we review. otherwise we have review the patch from scratch. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,15 @@ +// RUN: not %clang %s --target=x86_64 -fcomplex-ppc-gnu-abi 2>&1 \ +// RUN: | FileCheck %s -check-prefix=X86_64 +// X86_64: error: unsupported option '-fcomplex-ppc-gnu-abi' for target 'x86_64' + +// RUN: not %clang %s --target=ppc64 -fcomplex-ppc-gnu-abi 2>&1 \ diggerlin wrote: I think two test scenarios is enough , `if (!TC.getTriple().isPPC32() || !TC.getTriple().isOSBinFormatELF()) {` one for `!TC.getTriple().isPPC32()` , other for `!TC.getTriple().isOSBinFormatELF()` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,286 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-DEF +// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-SOFT-FLOAT + +// CHECK-GNU-DEF-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-DEF-SAME: (float noundef [[F:%.*]], [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 +// CHECK-GNU-DEF-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-DEF-NEXT:ret [8 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-SOFT-FLOAT-SAME: (float noundef [[F:%.*]], ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-SOFT-FLOAT-NEXT: entry: +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-SOFT-FLOAT-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:ret [8 x i32] [[TMP0]] +// +_Complex long double _cldouble(float f, _Complex long double x) { + return x; +} + +// CHECK-GNU-DEF-LABEL: define dso_local [4 x i32] @testComplexDouble +// CHECK-GNU-DEF-SAME: (float noundef [[W:%.*]], [1 x i64] noundef [[X_COERCE:%.*]], [4 x i32] noundef [[Z_COERCE:%.*]]) #[[ATTR0]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { float, float }, align 4 +// CHECK-GNU-DEF-NEXT:[[Z:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[W_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [1 x i64] [[X_COERCE]], ptr [[X]], align 4 +// CHECK-GNU-DEF-NEXT:store [4 x i32] [[Z_COERCE]], ptr [[Z]], align 8 +// CHECK-GNU-DEF-NEXT:store float [[W]], ptr [[W_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[Z_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[Z]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[Z_REAL:%.*]] = load double, ptr [[Z_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:[[Z_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[Z]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[Z_IMAG:%.*]] = load double, ptr [[Z_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] =
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,286 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-DEF +// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-SOFT-FLOAT + +// CHECK-GNU-DEF-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-DEF-SAME: (float noundef [[F:%.*]], [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 +// CHECK-GNU-DEF-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-DEF-NEXT:ret [8 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-SOFT-FLOAT-SAME: (float noundef [[F:%.*]], ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-SOFT-FLOAT-NEXT: entry: +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-SOFT-FLOAT-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-SOFT-FLOAT-NEXT:ret [8 x i32] [[TMP0]] +// +_Complex long double _cldouble(float f, _Complex long double x) { + return x; +} + +// CHECK-GNU-DEF-LABEL: define dso_local [4 x i32] @testComplexDouble +// CHECK-GNU-DEF-SAME: (float noundef [[W:%.*]], [1 x i64] noundef [[X_COERCE:%.*]], [4 x i32] noundef [[Z_COERCE:%.*]]) #[[ATTR0]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { float, float }, align 4 +// CHECK-GNU-DEF-NEXT:[[Z:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[W_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [1 x i64] [[X_COERCE]], ptr [[X]], align 4 +// CHECK-GNU-DEF-NEXT:store [4 x i32] [[Z_COERCE]], ptr [[Z]], align 8 +// CHECK-GNU-DEF-NEXT:store float [[W]], ptr [[W_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[Z_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[Z]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[Z_REAL:%.*]] = load double, ptr [[Z_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:[[Z_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[Z]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[Z_IMAG:%.*]] = load double, ptr [[Z_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] =
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,286 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-DEF +// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-SOFT-FLOAT + +// CHECK-GNU-DEF-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-DEF-SAME: (float noundef [[F:%.*]], [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 +// CHECK-GNU-DEF-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-DEF-NEXT:ret [8 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-SOFT-FLOAT-SAME: (float noundef [[F:%.*]], ptr noundef byval({ ppc_fp128, ppc_fp128 }) align 16 [[X:%.*]]) #[[ATTR0:[0-9]+]] { diggerlin wrote: I am curiously that option `-msoft-float` do not change the `float noundef [[F:%.*]]` to `i32 noundef [[F:%.*]]` , I do not read the code implement of the option `-msoft-float` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -330,8 +330,12 @@ namespace { class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + // Size of GPR in bits. + static const unsigned RegLen = 32; diggerlin wrote: suggest change RegLen to GPRBits as https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/Targets/PPC.cpp#L615 https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From cc5fe4a6aa4762040077ab39edb6677f42638673 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Sun, 28 Apr 2024 14:18:42 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. Following up with this patch : https://reviews.llvm.org/D146942 --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 87 +++- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 394 ++ .../ppc32-complex-soft-float-gnu-abi.c| 286 + .../test/Driver/ppc32-fcomplex-ppc-gnu-abi.c | 15 + 9 files changed, 805 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-soft-float-gnu-abi.c create mode 100644 clang/test/Driver/ppc32-fcomplex-ppc-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 086aedefc11878..e35ac8ea36d727 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2601,6 +2601,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlaghttps://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + bool IsComplex = Ty->isAnyComplexType(); + + if ((getCodeGenOpts().getComplexInRegABI() != CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft || (!IsComplex && Ty->isFloatingType() && !IsSoftFloatABI)) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + // For complex type or any other primitive types. + if (IsComplex || !isAggregateTypeForABI(Ty)) { +// If gr is even set gr = gr + 1 for TypeSize=64. +
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From 4cdfaf0a576d44a65484c61f5a572bed73ab0ce4 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Wed, 24 Apr 2024 19:06:23 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. Following up with this patch : https://reviews.llvm.org/D146942 --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 87 +++- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 415 ++ .../ppc32-complex-soft-float-gnu-abi.c| 310 + .../test/Driver/ppc32-fcomplex-ppc-gnu-abi.c | 15 + 9 files changed, 850 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-soft-float-gnu-abi.c create mode 100644 clang/test/Driver/ppc32-fcomplex-ppc-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 922bda721dc780..605440ed1c596d 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2601,6 +2601,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlaghttps://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + bool IsComplex = Ty->isAnyComplexType(); + + if ((getCodeGenOpts().getComplexInRegABI() != CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft || (!IsComplex && Ty->isFloatingType() && !IsSoftFloatABI)) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + // For complex type or any other primitive types. + if (IsComplex || !isAggregateTypeForABI(Ty)) { +// If gr is even set gr = gr + 1 for TypeSize=64. +
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,350 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-DEF +// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-SOFT-FLOAT + +// CHECK-GNU-DEF-LABEL: define dso_local [4 x i32] @_cdouble +// CHECK-GNU-DEF-SAME: ([4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// CHECK-GNU-DEF-NEXT:ret [4 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [4 x i32] @_cdouble +// CHECK-GNU-SOFT-FLOAT-SAME: ([4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-SOFT-FLOAT-NEXT: entry: +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:ret [4 x i32] [[TMP0]] +// +_Complex double _cdouble(_Complex double x) { + return x; +} + +// CHECK-GNU-DEF-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-DEF-SAME: (float noundef [[F:%.*]], [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 +// CHECK-GNU-DEF-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-DEF-NEXT:ret [8 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [8 x i32] @_cldouble +//
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From b5746d24130b9595762d85f4da7169d7b7a801f0 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Wed, 24 Apr 2024 18:01:23 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. Following up with this patch : https://reviews.llvm.org/D146942 --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 87 +++- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 415 ++ .../ppc32-complex-soft-float-gnu-abi.c| 310 + .../test/Driver/ppc32-fcomplex-ppc-gnu-abi.c | 15 + 9 files changed, 850 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-soft-float-gnu-abi.c create mode 100644 clang/test/Driver/ppc32-fcomplex-ppc-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 922bda721dc780..605440ed1c596d 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2601,6 +2601,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlaghttps://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if ((getCodeGenOpts().getComplexInRegABI() != CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft || + (!Ty->isAnyComplexType() && Ty->isFloatingType() && !IsSoftFloatABI)) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + // For complex type or any other primitive types. + if (bool IsComplex = Ty->isAnyComplexType() || !isAggregateTypeForABI(Ty)) { +// If gr is even set gr = gr + 1 for
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,350 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-DEF +// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-SOFT-FLOAT + +// CHECK-GNU-DEF-LABEL: define dso_local [4 x i32] @_cdouble +// CHECK-GNU-DEF-SAME: ([4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// CHECK-GNU-DEF-NEXT:ret [4 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [4 x i32] @_cdouble +// CHECK-GNU-SOFT-FLOAT-SAME: ([4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-SOFT-FLOAT-NEXT: entry: +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:ret [4 x i32] [[TMP0]] +// +_Complex double _cdouble(_Complex double x) { + return x; +} + +// CHECK-GNU-DEF-LABEL: define dso_local [8 x i32] @_cldouble +// CHECK-GNU-DEF-SAME: (float noundef [[F:%.*]], [8 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { ppc_fp128, ppc_fp128 }, align 16 +// CHECK-GNU-DEF-NEXT:[[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-GNU-DEF-NEXT:store [8 x i32] [[X_COERCE]], ptr [[X]], align 16 +// CHECK-GNU-DEF-NEXT:store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load ppc_fp128, ptr [[X_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load ppc_fp128, ptr [[X_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_REAL]], ptr [[RETVAL_REALP]], align 16 +// CHECK-GNU-DEF-NEXT:store ppc_fp128 [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 16 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [8 x i32], ptr [[RETVAL]], align 16 +// CHECK-GNU-DEF-NEXT:ret [8 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [8 x i32] @_cldouble +//
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -5585,6 +5585,15 @@ void Clang::ConstructJob(Compilation , const JobAction , } } + if (Arg *A = Args.getLastArg(options::OPT_fcomplex_ppc_gnu_abi)) { +if (!TC.getTriple().isPPC32() || !TC.getTriple().isOSBinFormatELF()) { + D.Diag(diag::err_drv_unsupported_opt_for_target) diggerlin wrote: I think we need a test case for this. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -396,12 +405,80 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + // Choice of using llvm::Type::getInt64Ty(getVMContext()) for complex + // single-precision floats is based on the ABI ATR-PASS-COMPLEX-IN-GPRS + // specification. According to the specification: + // - For complex single-precision floats: If the register (gr) is even, it's + // incremented by one, and the lower-addressed word of the argument is loaded + // into gr, while the higher-addressed word is loaded into gr + 1. Then, gr is + // incremented by 2. + // - For complex double-precision floats: The words of the argument are loaded + // in memory-address order into gr, gr + 1, gr + 2, and gr + 3, with gr being + // incremented by 4. Thus, to maintain even alignment and adhere to the ABI + // specification, llvm::Type::getInt64Ty(getVMContext()) is used when TypeSize + // is 64. Powerpc backend handles this alignment requirement. Specifically, + // you can refer to the CC_PPC32_SVR4_Custom_AlignArgRegs method from + // PPCCallingconvention.cpp. For more context, refer to the previous + // discussion: https://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) diggerlin wrote: ` if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || !ArgGPRsLeft)` --> ` if (getCodeGenOpts().getComplexInRegABI() != CodeGenOptions::CMPLX_InGPR || !ArgGPRsLeft)` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,350 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-DEF +// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU-SOFT-FLOAT + +// CHECK-GNU-DEF-LABEL: define dso_local [4 x i32] @_cdouble +// CHECK-GNU-DEF-SAME: ([4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-DEF-NEXT: entry: +// CHECK-GNU-DEF-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:[[X:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-DEF-NEXT:store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 +// CHECK-GNU-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:[[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-DEF-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-DEF-NEXT:store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 +// CHECK-GNU-DEF-NEXT:store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 +// CHECK-GNU-DEF-NEXT:[[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// CHECK-GNU-DEF-NEXT:ret [4 x i32] [[TMP0]] +// +// CHECK-GNU-SOFT-FLOAT-LABEL: define dso_local [4 x i32] @_cdouble +// CHECK-GNU-SOFT-FLOAT-SAME: ([4 x i32] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-SOFT-FLOAT-NEXT: entry: +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X:%.*]] = alloca { double, double }, align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:store [4 x i32] [[X_COERCE]], ptr [[X]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-SOFT-FLOAT-NEXT:store double [[X_REAL]], ptr [[RETVAL_REALP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:store double [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:[[TMP0:%.*]] = load [4 x i32], ptr [[RETVAL]], align 8 +// CHECK-GNU-SOFT-FLOAT-NEXT:ret [4 x i32] [[TMP0]] +// +_Complex double _cdouble(_Complex double x) { diggerlin wrote: there is not float or double as parameter in the test case , I think we have tested the scenario in the ppc32-complex-gnu-abi.c , do we still need it ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -396,12 +405,80 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + // Choice of using llvm::Type::getInt64Ty(getVMContext()) for complex + // single-precision floats is based on the ABI ATR-PASS-COMPLEX-IN-GPRS + // specification. According to the specification: + // - For complex single-precision floats: If the register (gr) is even, it's + // incremented by one, and the lower-addressed word of the argument is loaded + // into gr, while the higher-addressed word is loaded into gr + 1. Then, gr is + // incremented by 2. + // - For complex double-precision floats: The words of the argument are loaded + // in memory-address order into gr, gr + 1, gr + 2, and gr + 3, with gr being + // incremented by 4. Thus, to maintain even alignment and adhere to the ABI + // specification, llvm::Type::getInt64Ty(getVMContext()) is used when TypeSize + // is 64. Powerpc backend handles this alignment requirement. Specifically, + // you can refer to the CC_PPC32_SVR4_Custom_AlignArgRegs method from + // PPCCallingconvention.cpp. For more context, refer to the previous + // discussion: https://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { +// If gr is even set gr = gr + 1 for TypeSize=64. +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + +if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) +--ArgGPRsLeft; + else if (!Ty->isFloatingType() || (Ty->isFloatingType() && IsSoftFloatABI)) { +// For other primitive types. +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; // If gr is even set gr = gr + 1 for TypeSize=64. +if (TypeSize <= ArgGPRsLeft * RegLen) + ArgGPRsLeft -= TypeSize / RegLen; + } diggerlin wrote: the code line 467-472 is duplicated with the code 452-458 ,you rewrite the function as ``` ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, int ) const { Ty = useFirstFieldIfTransparentUnion(Ty); if ( getCodeGenOpts().getComplexInRegABI() != CodeGenOptions::CMPLX_InGPR || !ArgGPRsLeft || (Ty->isFloatingType() && !IsSoftFloatABI) return DefaultABIInfo::classifyArgumentType(Ty); assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); // Records with non-trivial destructors/copy-constructors should not be // passed by value. if (isAggregateTypeForABI(Ty)) --ArgGPRsLeft; ASTContext = getContext(); uint64_t TypeSize = Context.getTypeSize(Ty); // If gr is even set gr = gr + 1 for TypeSize=64. if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) --ArgGPRsLeft; if (TypeSize <= RegLen * ArgGPRsLeft) { ArgGPRsLeft -= TypeSize / RegLen; return handleComplex(TypeSize); } return DefaultABIInfo::classifyArgumentType(Ty); } ``` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From 3c5fcb03ee7871a93d3163beb51133c836f58ca6 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Thu, 28 Mar 2024 17:26:48 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 94 - clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 394 ++ .../ppc32-complex-soft-float-gnu-abi.c| 350 8 files changed, 861 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-soft-float-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 29066ea14280c2..4a5cfc988b8c18 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2577,6 +2577,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlaghttps://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { +// If gr is even set gr = gr + 1 for TypeSize=64. +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + +if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) +
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -396,12 +405,85 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + // Choice of using llvm::Type::getInt64Ty(getVMContext()) for complex + // single-precision floats is based on the ABI ATR-PASS-COMPLEX-IN-GPRS + // specification. According to the specification: + // - For complex single-precision floats: If the register (gr) is even, it's + // incremented by one, and the lower-addressed word of the argument is loaded + // into gr, while the higher-addressed word is loaded into gr + 1. Then, gr is + // incremented by 2. + // - For complex double-precision floats: The words of the argument are loaded + // in memory-address order into gr, gr + 1, gr + 2, and gr + 3, with gr being + // incremented by 4. Thus, to maintain even alignment and adhere to the ABI + // specification, llvm::Type::getInt64Ty(getVMContext()) is used when TypeSize + // is 64. Powerpc backend handles this alignment requirement. Specifically, + // you can refer to the CC_PPC32_SVR4_Custom_AlignArgRegs method from + // PPCCallingconvention.cpp. For more context, refer to the previous + // discussion: https://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { +// If gr is even set gr = gr + 1 for TypeSize=64. +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + +if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) +--ArgGPRsLeft; + else if (!Ty->isFloatingType()) { +// For other primitive types. +if (TypeSize == 64) { + // If gr is even set gr = gr + 1 for TypeSize=64. + if (ArgGPRsLeft % 2 == 1) +--ArgGPRsLeft; + if (TypeSize <= ArgGPRsLeft * RegLen) { +ArgGPRsLeft -= TypeSize / RegLen; + } +} else + --ArgGPRsLeft; diggerlin wrote: it is nice to have. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -396,12 +405,85 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + // Choice of using llvm::Type::getInt64Ty(getVMContext()) for complex + // single-precision floats is based on the ABI ATR-PASS-COMPLEX-IN-GPRS + // specification. According to the specification: + // - For complex single-precision floats: If the register (gr) is even, it's + // incremented by one, and the lower-addressed word of the argument is loaded + // into gr, while the higher-addressed word is loaded into gr + 1. Then, gr is + // incremented by 2. + // - For complex double-precision floats: The words of the argument are loaded + // in memory-address order into gr, gr + 1, gr + 2, and gr + 3, with gr being + // incremented by 4. Thus, to maintain even alignment and adhere to the ABI + // specification, llvm::Type::getInt64Ty(getVMContext()) is used when TypeSize + // is 64. Powerpc backend handles this alignment requirement. Specifically, + // you can refer to the CC_PPC32_SVR4_Custom_AlignArgRegs method from + // PPCCallingconvention.cpp. For more context, refer to the previous + // discussion: https://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { +// If gr is even set gr = gr + 1 for TypeSize=64. +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + +if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) +--ArgGPRsLeft; + else if (!Ty->isFloatingType()) { +// For other primitive types. +if (TypeSize == 64) { + // If gr is even set gr = gr + 1 for TypeSize=64. + if (ArgGPRsLeft % 2 == 1) +--ArgGPRsLeft; + if (TypeSize <= ArgGPRsLeft * RegLen) { +ArgGPRsLeft -= TypeSize / RegLen; + } +} else + --ArgGPRsLeft; Long5hot wrote: I missed the part for soft-float, for soft-float we pass long-double(128) in GPRs, Below change works. ``` else if (!Ty->isFloatingType() || (Ty->isFloatingType() && IsSoftFloatABI)) { if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) --ArgGPRsLeft; // If gr is even set gr = gr + 1 for TypeSize=64. if (TypeSize <= ArgGPRsLeft * RegLen) ArgGPRsLeft -= TypeSize / RegLen; } ``` I will update the review as your comments. Do i need to add the tests for soft-floats as well?? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -396,12 +405,85 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + // Choice of using llvm::Type::getInt64Ty(getVMContext()) for complex + // single-precision floats is based on the ABI ATR-PASS-COMPLEX-IN-GPRS + // specification. According to the specification: + // - For complex single-precision floats: If the register (gr) is even, it's + // incremented by one, and the lower-addressed word of the argument is loaded + // into gr, while the higher-addressed word is loaded into gr + 1. Then, gr is + // incremented by 2. + // - For complex double-precision floats: The words of the argument are loaded + // in memory-address order into gr, gr + 1, gr + 2, and gr + 3, with gr being + // incremented by 4. Thus, to maintain even alignment and adhere to the ABI + // specification, llvm::Type::getInt64Ty(getVMContext()) is used when TypeSize + // is 64. Powerpc backend handles this alignment requirement. Specifically, + // you can refer to the CC_PPC32_SVR4_Custom_AlignArgRegs method from + // PPCCallingconvention.cpp. For more context, refer to the previous + // discussion: https://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { +// If gr is even set gr = gr + 1 for TypeSize=64. +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + +if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) +--ArgGPRsLeft; + else if (!Ty->isFloatingType()) { +// For other primitive types. +if (TypeSize == 64) { + // If gr is even set gr = gr + 1 for TypeSize=64. + if (ArgGPRsLeft % 2 == 1) +--ArgGPRsLeft; + if (TypeSize <= ArgGPRsLeft * RegLen) { +ArgGPRsLeft -= TypeSize / RegLen; + } +} else + --ArgGPRsLeft; diggerlin wrote: it look that if TypeSize=128, you only do `--ArgGPRsLeft`, it pass by pointer ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -421,6 +503,11 @@ ABIArgInfo PPC32_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { } } + bool IsComplexInRegABI = + getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR; + if (IsComplexInRegABI && RetTy->isAnyComplexType()) diggerlin wrote: you do not need to introduce a new variable `IsComplexInRegABI` here since it only be used once. change to `if ((getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) && RetTy->isAnyComplexType())` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,306 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-DEF +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU + +// CHECK-DEF-LABEL: define dso_local void @foo1 +// CHECK-DEF-SAME: (ptr dead_on_unwind noalias writable sret({ float, float }) align 4 [[AGG_RESULT:%.*]], ptr noundef byval({ float, float }) align 4 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-DEF-NEXT: entry: +// CHECK-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[X]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[X_REAL:%.*]] = load float, ptr [[X_REALP]], align 4 +// CHECK-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[X]], i32 0, i32 1 +// CHECK-DEF-NEXT:[[X_IMAG:%.*]] = load float, ptr [[X_IMAGP]], align 4 +// CHECK-DEF-NEXT:[[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-DEF-NEXT:store float [[X_REAL]], ptr [[AGG_RESULT_REALP]], align 4 +// CHECK-DEF-NEXT:store float [[X_IMAG]], ptr [[AGG_RESULT_IMAGP]], align 4 +// CHECK-DEF-NEXT:[[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[AGG_RESULT_REAL:%.*]] = load float, ptr [[AGG_RESULT_REALP1]], align 4 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAG:%.*]] = load float, ptr [[AGG_RESULT_IMAGP2]], align 4 +// CHECK-DEF-NEXT:[[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-DEF-NEXT:store float [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 4 +// CHECK-DEF-NEXT:store float [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 4 +// CHECK-DEF-NEXT:ret void +// +// CHECK-GNU-LABEL: define dso_local [1 x i64] @foo1 +// CHECK-GNU-SAME: ([1 x i64] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-NEXT: entry: +// CHECK-GNU-NEXT:[[RETVAL:%.*]] = alloca { float, float }, align 4 +// CHECK-GNU-NEXT:[[X:%.*]] = alloca { float, float }, align 4 +// CHECK-GNU-NEXT:store [1 x i64] [[X_COERCE]], ptr [[X]], align 4 +// CHECK-GNU-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-NEXT:[[X_REAL:%.*]] = load float, ptr [[X_REALP]], align 4 +// CHECK-GNU-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-NEXT:[[X_IMAG:%.*]] = load float, ptr [[X_IMAGP]], align 4 +// CHECK-GNU-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-NEXT:store float [[X_REAL]], ptr [[RETVAL_REALP]], align 4 +// CHECK-GNU-NEXT:store float [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 4 +// CHECK-GNU-NEXT:[[TMP0:%.*]] = load [1 x i64], ptr [[RETVAL]], align 4 +// CHECK-GNU-NEXT:ret [1 x i64] [[TMP0]] +// +_Complex float foo1(_Complex float x) { diggerlin wrote: general question for all test scenario: can you add a caller function to call the function to check whether organize the call parameter and pass the parameter as called function need ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From 81d57b415738e4cea8fbbade990046271cb505a5 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Tue, 26 Mar 2024 17:08:25 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 100 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 306 ++ 7 files changed, 429 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 29066ea14280c2..4a5cfc988b8c18 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2577,6 +2577,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlaghttps://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { +// If gr is even set gr = gr + 1 for TypeSize=64. +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + +if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) +--ArgGPRsLeft; + else if (!Ty->isFloatingType()) { +// For other primitive types. +if (TypeSize == 64) { + // If gr is even set gr = gr + 1 for
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +ArgGPRsLeft -= TypeSize / RegLen; +return handleComplex(TypeSize); + } + + if (ArgGPRsLeft) { +// Records with non-trivial destructors/copy-constructors should not be +// passed by value. +if (isAggregateTypeForABI(Ty)) + ArgGPRsLeft -= 1; +else if (!Ty->isFloatingType()) { + // For other premitive types. + if (TypeSize > RegLen && TypeSize <= 2 * RegLen) +ArgGPRsLeft -= TypeSize / RegLen; Long5hot wrote: Yes, gcc passes the last arg in stack https://godbolt.org/z/EbPMK4jad https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From 59bd85681c590a5b3e259bfa93d87a80e5362878 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Tue, 26 Mar 2024 16:40:32 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 104 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 306 ++ 7 files changed, 431 insertions(+), 8 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 29066ea14280c2..4a5cfc988b8c18 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2577,6 +2577,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlaghttps://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { +// If gr is even set gr = gr + 1 for TypeSize=64. +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + +if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) +--ArgGPRsLeft; + else if (!Ty->isFloatingType()) { +// For other primitive types. +if (TypeSize == 64) { + // If gr is even set gr = gr + 1 for
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From 618762c79f5ec1ea9a945b81e182e3d8e1046baf Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Tue, 26 Mar 2024 16:21:10 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 103 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 306 ++ 7 files changed, 430 insertions(+), 8 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 29066ea14280c2..4a5cfc988b8c18 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2577,6 +2577,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlaghttps://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) +return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { +if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + +if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) +--ArgGPRsLeft; + else if (!Ty->isFloatingType()) { +// For other primitive types. +if (TypeSize == 64) { + if (ArgGPRsLeft % 2 == 1) +--ArgGPRsLeft; + if (TypeSize <= ArgGPRsLeft *
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +ArgGPRsLeft -= TypeSize / RegLen; +return handleComplex(TypeSize); + } + + if (ArgGPRsLeft) { +// Records with non-trivial destructors/copy-constructors should not be +// passed by value. +if (isAggregateTypeForABI(Ty)) + ArgGPRsLeft -= 1; +else if (!Ty->isFloatingType()) { + // For other premitive types. + if (TypeSize > RegLen && TypeSize <= 2 * RegLen) +ArgGPRsLeft -= TypeSize / RegLen; diggerlin wrote: for a test case `foo6(_Complex long double foo4(int x1, long long y1, int x2, _Complex double z,)` `int x1` will have r3, `long long y1` will have r5,r6 (skip r4 since it is even, for 64bit integer need to start start odd register.) `int x2` will have r7, ` _Complex double z` need to occupy 4 registers, there is no enough register , it can not pass `_Complex double z` in r8,r9,r10 , you have to pass ` _Complex double z` in by pointer (you can not call `handleComplex()`). but in your code, ArgGPRsLeft is 7 after int x1, ArgGPRsLeft is 5 after long long y1 ArgGPRsLeft is 4 after int x2 there is still have 4 registers left for ` _Complex double z`, you can call `handleComplex()`, you will pass ` _Complex double z` by value can you check how gcc deal with this case `foo6(_Complex long double foo4(int x1, long long y1, int x2, _Complex double z,)` ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +ArgGPRsLeft -= TypeSize / RegLen; +return handleComplex(TypeSize); + } + + if (ArgGPRsLeft) { +// Records with non-trivial destructors/copy-constructors should not be +// passed by value. +if (isAggregateTypeForABI(Ty)) + ArgGPRsLeft -= 1; +else if (!Ty->isFloatingType()) { + // For other premitive types. + if (TypeSize > RegLen && TypeSize <= 2 * RegLen) +ArgGPRsLeft -= TypeSize / RegLen; diggerlin wrote: for a test case `foo6(_Complex long double foo4(int x1, long long y1, int x2, _Complex double z,)` `int x1` will have r3, `long long y1` will have r5,r6 (skip r4 since it is even, for 64bit integer need to start start odd register.) `int x2` will have r7, ` _Complex double z` need to occupy 4 registers, there is no enough register , it can not pass `_Complex double z` in r8,r9,r10 , you have to pass ` _Complex double z` in by pointer (you can not call `handleComplex()`). but in your code, ArgGPRsLeft is 7 after int x1, ArgGPRsLeft is 5 after long long y1 ArgGPRsLeft is 4 after int x2 there is still have 4 registers left for ` _Complex double z`, you can call `handleComplex()`, you will pass ` _Complex double z` by value can you check how gcc deal with this case `foo6(_Complex long double foo4(int x1, long long y1, int x2, _Complex double z,)` ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin deleted https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin deleted https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -396,12 +407,77 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + // Choice of using llvm::Type::getInt64Ty(getVMContext()) for complex + // single-precision floats is based on the ABI ATR-PASS-COMPLEX-IN-GPRS + // specification. According to the specification: + // - For complex single-precision floats: If the register (gr) is even, it's + // incremented by one, and the lower-addressed word of the argument is loaded + // into gr, while the higher-addressed word is loaded into gr + 1. Then, gr is + // incremented by 2. + // - For complex double-precision floats: The words of the argument are loaded + // in memory-address order into gr, gr + 1, gr + 2, and gr + 3, with gr being + // incremented by 4. Thus, to maintain even alignment and adhere to the ABI + // specification, llvm::Type::getInt64Ty(getVMContext()) is used when TypeSize + // is 64. Powerpc backend handles this alignment requirement. Specifically, + // you can refer to the CC_PPC32_SVR4_Custom_AlignArgRegs method from + // PPCCallingconvention.cpp. For more context, refer to the previous + // discussion: https://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType() && TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +if (IsComplexInRegABI) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); +} else + ArgGPRsLeft--; diggerlin wrote: I do not think you care about the value of ArgGPRsLeft when IsComplexInRegABI is false. is it correct ? we can add following code in front of the function. ``` if (!IsComplexInRegABI ) return DefaultABIInfo::classifyArgumentType(Ty); ``` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); diggerlin wrote: do we need the assert here since there is `if (Ty->isAnyComplexType() && TypeSize <= RegLen * ArgGPRsLeft)` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -330,22 +330,33 @@ namespace { class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + bool IsComplexInRegABI; diggerlin wrote: do we need a new data member `IsComplexInRegABI` here ? (there are several place code be modified because we add the new data member `IsComplexInRegABI` ) we can add ``` bool IsComplexInRegABI = getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR ; ``` in the function `classifyArgumentType` and `classifyReturnType()` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -420,6 +496,10 @@ ABIArgInfo PPC32_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getDirect(CoerceTy); } } + if (IsComplexInRegABI && RetTy->isAnyComplexType()) { +assert(RetTy->isAnyComplexType() && "RetTy must be Complex type."); diggerlin wrote: you already has `if (IsComplexInRegABI && RetTy->isAnyComplexType())` as condition, is there any reason to keep the `assert(RetTy->isAnyComplexType() && "RetTy must be Complex type.");` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +ArgGPRsLeft -= TypeSize / RegLen; +return handleComplex(TypeSize); + } + + if (ArgGPRsLeft) { +// Records with non-trivial destructors/copy-constructors should not be +// passed by value. +if (isAggregateTypeForABI(Ty)) + ArgGPRsLeft -= 1; +else if (!Ty->isFloatingType()) { + // For other premitive types. + if (TypeSize > RegLen && TypeSize <= 2 * RegLen) +ArgGPRsLeft -= TypeSize / RegLen; diggerlin wrote: for a test case `foo(_Complex long double foo4(int x1, long long y1, int x2, _Complex double z,)` `int x1` will have r3, `long long y1` will have r5,r6 (skip r4 since re is even.) `int x2` will have r7, ` _Complex double z` need to occupy 4 registers, there is no enough register , it can not pass `_Complex double z` in r8,r9,r10 , you have to pass ` _Complex double z` in by pointer (you can not call `handleComplex()`). but in your code, ArgGPRsLeft is 7 after int x1, ArgGPRsLeft is 5 after int y1 ArgGPRsLeft is 4 after int x2 there is still have 4 registers left for ` _Complex double z`, you can call `handleComplex()`, you can pass ` _Complex double z by value https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,177 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-DEF +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU + +// CHECK-DEF-LABEL: define dso_local void @foo1 +// CHECK-DEF-SAME: (ptr dead_on_unwind noalias writable sret({ float, float }) align 4 [[AGG_RESULT:%.*]], ptr noundef byval({ float, float }) align 4 [[X:%.*]]) #[[ATTR0:[0-9]+]] { Long5hot wrote: I couldn't remove #[[ATTR0:[0-9]+]]1. Because testcase fails saying no missing attributes. llvm-lit(clang) generates IR with # attributes, so looks like Filecheck expects #attribute fields to be present. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From ac3e5526189f5d9e2abe739a21394a63f75567b5 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Fri, 15 Mar 2024 15:29:41 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. Following up with this patch : https://reviews.llvm.org/D146942 --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 107 +++- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 255 ++ 7 files changed, 379 insertions(+), 12 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 340b08dd7e2a33..f4845e9e424c67 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -225,6 +225,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb0..1c9424f65623dd 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index a7e43b4d179a4d..2128b87abe8ea6 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2578,6 +2578,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlag( -CGT, SoftFloatABI, RetSmallStructInRegABI)) {} +CGT, SoftFloatABI, RetSmallStructInRegABI, ComplexInRegABI)) {} static bool isStructReturnInRegABI(const llvm::Triple , const CodeGenOptions ); @@ -396,12 +407,77 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + // Choice of using llvm::Type::getInt64Ty(getVMContext()) for complex + // single-precision floats is based on the ABI ATR-PASS-COMPLEX-IN-GPRS + // specification. According to the specification: + // - For complex single-precision floats: If the register (gr) is even, it's + // incremented by one, and the lower-addressed word of the argument is loaded + // into gr, while the higher-addressed word is loaded into gr + 1. Then, gr is + // incremented by 2. + // - For complex double-precision floats: The words of the argument are loaded + // in memory-address order into gr, gr + 1, gr + 2, and gr + 3, with gr being + // incremented by 4. Thus, to maintain even alignment and adhere to the ABI + // specification, llvm::Type::getInt64Ty(getVMContext()) is used when TypeSize + // is 64. Powerpc backend handles this
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot deleted https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); Long5hot wrote: I apologize because, There's a bug here. for if not IsComplexInRegABI we need to --ArgGPRsLeft; Will test and update the review accordingly. Thank you. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +ArgGPRsLeft -= TypeSize / RegLen; +return handleComplex(TypeSize); + } + + if (ArgGPRsLeft) { +// Records with non-trivial destructors/copy-constructors should not be +// passed by value. +if (isAggregateTypeForABI(Ty)) + ArgGPRsLeft -= 1; +else if (!Ty->isFloatingType()) { + // For other premitive types. + if (TypeSize > RegLen && TypeSize <= 2 * RegLen) +ArgGPRsLeft -= TypeSize / RegLen; Long5hot wrote: llvm powerpc backend takes care of that. refer CC_PPC32_SVR4_Custom_AlignArgRegs method from PPCCallingconvention.cpp https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/PowerPC/PPCCallingConv.cpp#L80 https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +ArgGPRsLeft -= TypeSize / RegLen; +return handleComplex(TypeSize); + } + + if (ArgGPRsLeft) { +// Records with non-trivial destructors/copy-constructors should not be +// passed by value. +if (isAggregateTypeForABI(Ty)) + ArgGPRsLeft -= 1; +else if (!Ty->isFloatingType()) { + // For other premitive types. + if (TypeSize > RegLen && TypeSize <= 2 * RegLen) +ArgGPRsLeft -= TypeSize / RegLen; diggerlin wrote: and If I understand correct, the single precision floating point complex . and 64 bit integer (long long unsigned) also need a even alignment . `If gr > 9, go to OTHER. If gr is even, set gr = gr + 1. Load the lower-addressed word of the argument into gr and the higher-addressed word into gr + 1, set gr = gr + 2,` it looks the logic not express in your code when you calculate the `ArgGPRsLeft` ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,177 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-DEF +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU + +// CHECK-DEF-LABEL: define dso_local void @foo1 +// CHECK-DEF-SAME: (ptr dead_on_unwind noalias writable sret({ float, float }) align 4 [[AGG_RESULT:%.*]], ptr noundef byval({ float, float }) align 4 [[X:%.*]]) #[[ATTR0:[0-9]+]] { diggerlin wrote: nit, we can delete `#[[ATTR0:[0-9]+]]1` , and please delete other place as well. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); diggerlin wrote: and add assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; diggerlin wrote: do we need to add `+31` here , can we change to `RegsNeeded = TypeSize >> 5; ` ? and https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -271,22 +271,32 @@ namespace { class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + bool IsComplexInRegABI; + // Size of GPR in bits. + static const unsigned RegLen = 32; + static const int NumArgGPRs = 8; diggerlin wrote: change to `ArgGPRsNum` ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +350,77 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(QualType Ty, + uint64_t ) const { + + assert(Ty->isAnyComplexType()); + llvm::Type *ElemTy; + unsigned SizeRegs; + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +SizeRegs = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); diggerlin wrote: got it, thanks for explain. can you add your explain as comment ? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +ArgGPRsLeft -= TypeSize / RegLen; +return handleComplex(TypeSize); + } + + if (ArgGPRsLeft) { +// Records with non-trivial destructors/copy-constructors should not be +// passed by value. +if (isAggregateTypeForABI(Ty)) + ArgGPRsLeft -= 1; +else if (!Ty->isFloatingType()) { + // For other premitive types. + if (TypeSize > RegLen && TypeSize <= 2 * RegLen) +ArgGPRsLeft -= TypeSize / RegLen; diggerlin wrote: can we change ``` if (TypeSize > RegLen && TypeSize <= 2 * RegLen) ArgGPRsLeft -= TypeSize / RegLen; ``` and what if ArgGPRsLeft =1 and TypeSize == 2 * RegLen. after above code , the ArgGPRsLeft will be -1. is it correct ? it hit assert `assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");` when the `classifyArgumentType` is called next time. suggest change to ``` if (TypeSize > RegLen && && TypeSize <= RLen * ArgGPRsLeft) ArgGPRsLeft -= TypeSize / RegLen; ``` and add a test case which can make ArgGPRsLeft to zero; https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -271,22 +271,33 @@ namespace { class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + bool isComplexInRegABI; + // Size of GPR in bits + unsigned RLen; + static const int NumArgGPRs = 8; CharUnits getParamTypeAlignment(QualType Ty) const; + ABIArgInfo handleComplex(QualType Ty, uint64_t ) const; public: PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes , bool SoftFloatABI, - bool RetSmallStructInRegABI) + bool RetSmallStructInRegABI, unsigned RLen, + bool ComplexInRegABI) : DefaultABIInfo(CGT), IsSoftFloatABI(SoftFloatABI), -IsRetSmallStructInRegABI(RetSmallStructInRegABI) {} +IsRetSmallStructInRegABI(RetSmallStructInRegABI), +isComplexInRegABI(ComplexInRegABI), RLen(RLen) {} ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType Ty, int ) const; void computeInfo(CGFunctionInfo ) const override { + +int ArgGPRsLeft = NumArgGPRs; diggerlin wrote: put `int ArgGPRsLeft = NumArgGPRs;` in front of ` for (auto : FI.arguments()) I.info = classifyArgumentType(I.type, ArgGPRsLeft);` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -271,22 +271,32 @@ namespace { class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + bool IsComplexInRegABI; + // Size of GPR in bits. + static const unsigned RegLen = 32; + static const int NumArgGPRs = 8; Long5hot wrote: The purpose of NumArgGPRs or ArgGPRsLeft is limited to complex types. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -78,6 +78,13 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_Default, +CMPLX_OnStack, Long5hot wrote: This was for future reference, if any arch wants to use this. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +350,77 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(QualType Ty, + uint64_t ) const { + + assert(Ty->isAnyComplexType()); + llvm::Type *ElemTy; + unsigned SizeRegs; + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +SizeRegs = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); Long5hot wrote: > llvm::Type *ElemTy = llvm::Type::getInt64Ty(getVMContext()); > unsigned SizeRegs = TypeSize/64; Since Typesize will be 64, in if is it necessary to replace 1 to TypeSize/64? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +350,77 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(QualType Ty, + uint64_t ) const { + + assert(Ty->isAnyComplexType()); + llvm::Type *ElemTy; + unsigned SizeRegs; + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +SizeRegs = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); Long5hot wrote: Reason for using llvm::Type::getInt64Ty(getVMContext()) for floats here was to follow ABI ATR-PASS-COMPLEX-IN-GPRS > complex single-precision float : If gr is even, set gr = gr + 1. Load the > lower-addressed word of the > argument into gr and the higher-addressed word into gr + 1, set gr = gr + 2. > > complex double-precision float: Load the words of the argument, in > memory-address order, into gr, gr + 1, > gr + 2 and gr + 3, set gr = gr + 4. You can check the previous discussion here. : https://reviews.llvm.org/D146942 https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,177 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-DEF +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fcomplex-ppc-gnu-abi \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-GNU + +// CHECK-DEF-LABEL: define dso_local void @foo1 +// CHECK-DEF-SAME: (ptr dead_on_unwind noalias writable sret({ float, float }) align 4 [[AGG_RESULT:%.*]], ptr noundef byval({ float, float }) align 4 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-DEF-NEXT: entry: +// CHECK-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[X]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[X_REAL:%.*]] = load float, ptr [[X_REALP]], align 4 +// CHECK-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[X]], i32 0, i32 1 +// CHECK-DEF-NEXT:[[X_IMAG:%.*]] = load float, ptr [[X_IMAGP]], align 4 +// CHECK-DEF-NEXT:[[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-DEF-NEXT:store float [[X_REAL]], ptr [[AGG_RESULT_REALP]], align 4 +// CHECK-DEF-NEXT:store float [[X_IMAG]], ptr [[AGG_RESULT_IMAGP]], align 4 +// CHECK-DEF-NEXT:[[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[AGG_RESULT_REAL:%.*]] = load float, ptr [[AGG_RESULT_REALP1]], align 4 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAG:%.*]] = load float, ptr [[AGG_RESULT_IMAGP2]], align 4 +// CHECK-DEF-NEXT:[[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { float, float }, ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-DEF-NEXT:store float [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 4 +// CHECK-DEF-NEXT:store float [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 4 +// CHECK-DEF-NEXT:ret void +// +// CHECK-GNU-LABEL: define dso_local [1 x i64] @foo1 +// CHECK-GNU-SAME: ([1 x i64] noundef [[X_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-GNU-NEXT: entry: +// CHECK-GNU-NEXT:[[RETVAL:%.*]] = alloca { float, float }, align 4 +// CHECK-GNU-NEXT:[[X:%.*]] = alloca { float, float }, align 4 +// CHECK-GNU-NEXT:store [1 x i64] [[X_COERCE]], ptr [[X]], align 4 +// CHECK-GNU-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[X]], i32 0, i32 0 +// CHECK-GNU-NEXT:[[X_REAL:%.*]] = load float, ptr [[X_REALP]], align 4 +// CHECK-GNU-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[X]], i32 0, i32 1 +// CHECK-GNU-NEXT:[[X_IMAG:%.*]] = load float, ptr [[X_IMAGP]], align 4 +// CHECK-GNU-NEXT:[[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// CHECK-GNU-NEXT:[[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// CHECK-GNU-NEXT:store float [[X_REAL]], ptr [[RETVAL_REALP]], align 4 +// CHECK-GNU-NEXT:store float [[X_IMAG]], ptr [[RETVAL_IMAGP]], align 4 +// CHECK-GNU-NEXT:[[TMP0:%.*]] = load [1 x i64], ptr [[RETVAL]], align 4 +// CHECK-GNU-NEXT:ret [1 x i64] [[TMP0]] +// +_Complex float foo1(_Complex float x) { + return x; +} + +// CHECK-DEF-LABEL: define dso_local void @foo2 +// CHECK-DEF-SAME: (ptr dead_on_unwind noalias writable sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr noundef byval({ double, double }) align 8 [[X:%.*]]) #[[ATTR0]] { +// CHECK-DEF-NEXT: entry: +// CHECK-DEF-NEXT:[[X_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[X_REAL:%.*]] = load double, ptr [[X_REALP]], align 8 +// CHECK-DEF-NEXT:[[X_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[X]], i32 0, i32 1 +// CHECK-DEF-NEXT:[[X_IMAG:%.*]] = load double, ptr [[X_IMAGP]], align 8 +// CHECK-DEF-NEXT:[[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// CHECK-DEF-NEXT:store double [[X_REAL]], ptr [[AGG_RESULT_REALP]], align 8 +// CHECK-DEF-NEXT:store double [[X_IMAG]], ptr [[AGG_RESULT_IMAGP]], align 8 +// CHECK-DEF-NEXT:[[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// CHECK-DEF-NEXT:[[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 +// CHECK-DEF-NEXT:
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -271,22 +271,33 @@ namespace { class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + bool isComplexInRegABI; + // Size of GPR in bits + unsigned RLen; + static const int NumArgGPRs = 8; CharUnits getParamTypeAlignment(QualType Ty) const; + ABIArgInfo handleComplex(QualType Ty, uint64_t ) const; public: PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes , bool SoftFloatABI, - bool RetSmallStructInRegABI) + bool RetSmallStructInRegABI, unsigned RLen, + bool ComplexInRegABI) : DefaultABIInfo(CGT), IsSoftFloatABI(SoftFloatABI), -IsRetSmallStructInRegABI(RetSmallStructInRegABI) {} +IsRetSmallStructInRegABI(RetSmallStructInRegABI), +isComplexInRegABI(ComplexInRegABI), RLen(RLen) {} ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType Ty, int ) const; void computeInfo(CGFunctionInfo ) const override { + +int ArgGPRsLeft = NumArgGPRs; Long5hot wrote: Couldn't understand what you mean here.. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/Long5hot updated https://github.com/llvm/llvm-project/pull/77732 >From a89cd20615f3649e2a625eb8da851f9cbdd2d863 Mon Sep 17 00:00:00 2001 From: Kishan Parmar Date: Mon, 4 Mar 2024 18:04:20 +0530 Subject: [PATCH] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments Fixes : https://github.com/llvm/llvm-project/issues/56023 https://godbolt.org/z/1bsW1sKMs newFlag : -fcomplex-ppc-gnu-abi GNU uses GPRs for complex parameters and return values storing for PowerPC-32bit, which can be enabled which above flag. Intent of this patch is to make clang compatible with GNU libraries of complex. --- clang/include/clang/Basic/CodeGenOptions.def | 2 + clang/include/clang/Basic/CodeGenOptions.h| 6 + clang/include/clang/Driver/Options.td | 4 + clang/lib/CodeGen/Targets/PPC.cpp | 87 +++-- clang/lib/Driver/ToolChains/Clang.cpp | 9 + clang/lib/Frontend/CompilerInvocation.cpp | 8 + .../CodeGen/PowerPC/ppc32-complex-gnu-abi.c | 177 ++ 7 files changed, 281 insertions(+), 12 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/ppc32-complex-gnu-abi.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 6ad05031962562..64f938dd01 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -224,6 +224,8 @@ CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) + /// If -fcomplex-ppc-gnu-abi is specified on ppc32. +ENUM_CODEGENOPT(ComplexInRegABI, ComplexArgumentConventionKind, 2, CMPLX_OnStack) CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 3f8fe385fef3df..af22bc00797655 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -78,6 +78,12 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_OnStack, +CMPLX_InGPR, // If -fcomplex-ppc-gnu-abi is specified on ppc32 +CMPLX_InFPR + }; + enum ProfileInstrKind { ProfileNone, // Profile instrumentation is turned off. ProfileClangInstr, // Clang instrumentation to generate execution counts diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 3e857f4e6faf87..82d8ab087fe6a5 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2574,6 +2574,10 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group, HelpText<"Form fused FP ops (e.g. FMAs)">, Values<"fast,on,off,fast-honor-pragmas">; +def fcomplex_ppc_gnu_abi : Flag<["-"], "fcomplex-ppc-gnu-abi">, Group, Visibility<[ClangOption, CC1Option]>, + DocBrief<"Follow the GNU ABI, pass Complex values in GPRs instead of the stack for PowerPC-32">, + HelpText<"Pass Complex values in GPR instead of stack for PowerPC-32">; + defm strict_float_cast_overflow : BoolFOption<"strict-float-cast-overflow", CodeGenOpts<"StrictFloatCastOverflow">, DefaultTrue, NegFlag( -CGT, SoftFloatABI, RetSmallStructInRegABI)) {} +CGT, SoftFloatABI, RetSmallStructInRegABI, ComplexInRegABI)) {} static bool isStructReturnInRegABI(const llvm::Triple , const CodeGenOptions ); @@ -337,12 +347,58 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t ) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +RegsNeeded = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +RegsNeeded = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (IsComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RegLen * ArgGPRsLeft) { +assert(Ty->isAnyComplexType() && "Ty must be Complex type."); +ArgGPRsLeft -= TypeSize / RegLen; +return handleComplex(TypeSize); + } + + if (ArgGPRsLeft) { +//
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +350,77 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(QualType Ty, + uint64_t ) const { + + assert(Ty->isAnyComplexType()); + llvm::Type *ElemTy; + unsigned SizeRegs; + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +SizeRegs = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +SizeRegs = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, SizeRegs)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (isComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RLen * ArgGPRsLeft) { +ArgGPRsLeft -= TypeSize / RLen; +return handleComplex(Ty, TypeSize); + } + + if (isAggregateTypeForABI(Ty)) { diggerlin wrote: it look, you only has Complex as parameter in your test case .for example `_Complex float foo1(_Complex float x)` I think you need more test case with other parameters to test the functionality of function `classifyArgumentType()` https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,132 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -target-cpu pwr8 \ diggerlin wrote: do you really need `-target-cpu pwr8` since the test case only check generated IR? https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -0,0 +1,132 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 + +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -target-cpu pwr8 \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-DEF +// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -target-cpu pwr8 -fcomplex-ppc-gnu-abi \ diggerlin wrote: ditto https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin edited https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin deleted https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -271,22 +271,33 @@ namespace { class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; bool IsRetSmallStructInRegABI; + bool isComplexInRegABI; + // Size of GPR in bits + unsigned RLen; + static const int NumArgGPRs = 8; CharUnits getParamTypeAlignment(QualType Ty) const; + ABIArgInfo handleComplex(QualType Ty, uint64_t ) const; public: PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes , bool SoftFloatABI, - bool RetSmallStructInRegABI) + bool RetSmallStructInRegABI, unsigned RLen, + bool ComplexInRegABI) : DefaultABIInfo(CGT), IsSoftFloatABI(SoftFloatABI), -IsRetSmallStructInRegABI(RetSmallStructInRegABI) {} +IsRetSmallStructInRegABI(RetSmallStructInRegABI), +isComplexInRegABI(ComplexInRegABI), RLen(RLen) {} ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType Ty, int ) const; void computeInfo(CGFunctionInfo ) const override { + +int ArgGPRsLeft = NumArgGPRs; diggerlin wrote: nit: move the definition to the closest first be used. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -78,6 +78,13 @@ class CodeGenOptions : public CodeGenOptionsBase { SRCK_InRegs// Small structs in registers (-freg-struct-return). }; + enum ComplexArgumentConventionKind { +CMPLX_Default, +CMPLX_OnStack, diggerlin wrote: it looks you define the `CMPLX_Default` and ` CMPLX_OnStack` , but never use them. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin deleted https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
https://github.com/diggerlin deleted https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][PowerPC] Add flag to enable compatibility with GNU for complex arguments (PR #77732)
@@ -337,12 +350,77 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(QualType Ty, + uint64_t ) const { + + assert(Ty->isAnyComplexType()); + llvm::Type *ElemTy; + unsigned SizeRegs; + + if (TypeSize == 64) { +ElemTy = llvm::Type::getInt64Ty(getVMContext()); +SizeRegs = 1; + } else { +ElemTy = llvm::Type::getInt32Ty(getVMContext()); +SizeRegs = (TypeSize + 31) / 32; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, SizeRegs)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, +int ) const { + + assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); + Ty = useFirstFieldIfTransparentUnion(Ty); + + ASTContext = getContext(); + + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (isComplexInRegABI && Ty->isAnyComplexType() && + TypeSize <= RLen * ArgGPRsLeft) { +ArgGPRsLeft -= TypeSize / RLen; +return handleComplex(Ty, TypeSize); + } + + if (isAggregateTypeForABI(Ty)) { +if (ArgGPRsLeft) + ArgGPRsLeft -= 1; +// Records with non-trivial destructors/copy-constructors should not be +// passed by value. +if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { + return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); +} +return getNaturalAlignIndirect(Ty); + } + + if (!Ty->isFloatingType()) { +if (TypeSize > RLen && TypeSize <= 2 * RLen) + ArgGPRsLeft -= 2; +else + ArgGPRsLeft--; + } + + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = Ty->getAs()) +Ty = EnumTy->getDecl()->getIntegerType(); + + if (const auto *EIT = Ty->getAs()) +if (EIT->getNumBits() > +Context.getTypeSize(Context.getTargetInfo().hasInt128Type() +? Context.Int128Ty +: Context.LongLongTy)) + return getNaturalAlignIndirect(Ty); + + return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) diggerlin wrote: since most of the code is same as `DefaultABIInfo::classifyArgumentType(QualType Ty)` , I suggest rewrite the function `PPC32_SVR4_ABIInfo::classifyArgumentType` as ``` ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, int ) const { special functionality code of the function here . DefaultABIInfo::classifyArgumentType(Ty) } ``` duplication code is not a good idea. https://github.com/llvm/llvm-project/pull/77732 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits