From af839a96187e3538d63ad57571e4bdf01e2b15c5 Mon Sep 17 00:00:00 2001 From: David Green Date: Thu, 9 Jul 2020 13:06:51 +0100 Subject: [PATCH 01/11] [BasicAA] Enable -basic-aa-recphi by default This option was added a while back, to help improve AA around pointer phi loops. It looks for phi(gep(phi, const), x) loops, checking if x can then prove more precise aliasing info. Differential Revision: https://reviews.llvm.org/D82998 --- llvm/lib/Analysis/BasicAliasAnalysis.cpp | 2 +- llvm/test/Analysis/BasicAA/phi-loop.ll | 2 +- llvm/test/Analysis/BasicAA/recphi.ll | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp index 74664098ce1d40..5574d3f5db6a0e 100644 --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -66,7 +66,7 @@ using namespace llvm; /// Enable analysis of recursive PHI nodes. static cl::opt EnableRecPhiAnalysis("basic-aa-recphi", cl::Hidden, - cl::init(false)); + cl::init(true)); /// By default, even on 32-bit architectures we use 64-bit integers for /// calculations. This will allow us to more-aggressively decompose indexing diff --git a/llvm/test/Analysis/BasicAA/phi-loop.ll b/llvm/test/Analysis/BasicAA/phi-loop.ll index db3023c6560d06..e54752a9223f75 100644 --- a/llvm/test/Analysis/BasicAA/phi-loop.ll +++ b/llvm/test/Analysis/BasicAA/phi-loop.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basic-aa -basic-aa-recphi=1 -gvn -S | FileCheck %s +; RUN: opt < %s -basic-aa -gvn -S | FileCheck %s ; ; Check that section->word_ofs doesn't get reloaded in every iteration of the ; for loop. diff --git a/llvm/test/Analysis/BasicAA/recphi.ll b/llvm/test/Analysis/BasicAA/recphi.ll index 130058c745604c..bdd85c8f0e6ceb 100644 --- a/llvm/test/Analysis/BasicAA/recphi.ll +++ b/llvm/test/Analysis/BasicAA/recphi.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basic-aa -aa-eval -print-all-alias-modref-info -basic-aa-recphi -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -basic-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s ; CHECK-LABEL: Function: simple: 5 pointers, 0 call sites ; CHECK: NoAlias: float* %src1, float* %src2 From 3514f58fbea5967a967468633c901e9b2f241594 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 9 Jul 2020 15:00:57 +0100 Subject: [PATCH 02/11] Fix MSVC "not all control paths return a value" warning. NFC. --- llvm/tools/llvm-objdump/llvm-objdump.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 7d282074efa6a5..320bbb5d358b9d 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -811,6 +811,7 @@ class LiveVariablePrinter { case LineChar::LabelHoriz: return IsASCII ? "-" : u8"\u2500"; } + llvm_unreachable("Unhandled LineChar enum"); } /// Print live ranges to the right of an existing line. This assumes the From fdde69aac9b99a5cda49c5b738dc8dc67ea4cbbd Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 9 Jul 2020 10:22:22 -0400 Subject: [PATCH 03/11] AMDGPU/GlobalISel: Work around verifier error in test The unfortunate split between finalizeLowering and the selector pass means there's a point where the verifier fails. The DAG selector pass skips the verifier, but this seems to not work when using the GlobalISel fallback. --- .../CodeGen/AMDGPU/GlobalISel/dynamic-alloca-divergent.ll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/dynamic-alloca-divergent.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/dynamic-alloca-divergent.ll index df536962e1b267..256b95d222beab 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/dynamic-alloca-divergent.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/dynamic-alloca-divergent.ll @@ -1,4 +1,4 @@ -; RUN: not llc -global-isel -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -global-isel-abort=2 -pass-remarks-missed="gisel.*" -o /dev/null 2>&1 %s | FileCheck -check-prefix=ERR %s +; RUN: not llc -global-isel -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -global-isel-abort=2 -pass-remarks-missed="gisel.*" -verify-machineinstrs -o /dev/null 2>&1 %s | FileCheck -check-prefix=ERR %s ; ERR: remark: :0:0: cannot select: %{{[0-9]+}}:sreg_32(p5) = G_DYN_STACKALLOC %{{[0-9]+}}:vgpr(s32), 1 (in function: kernel_dynamic_stackalloc_vgpr_align4) ; ERR-NEXT: warning: Instruction selection used fallback path for kernel_dynamic_stackalloc_vgpr_align4 @@ -13,13 +13,13 @@ define amdgpu_kernel void @kernel_dynamic_stackalloc_vgpr_align4(i32 addrspace(1 %gep = getelementptr i32, i32 addrspace(1)* %ptr, i32 %id %n = load i32, i32 addrspace(1)* %gep %alloca = alloca i32, i32 %n, align 4, addrspace(5) - store volatile i32 0, i32 addrspace(5)* %alloca + store volatile i32 addrspace(5)* %alloca, i32 addrspace(5)* addrspace(1)* undef ret void } define void @func_dynamic_stackalloc_vgpr_align4(i32 %n) { %alloca = alloca i32, i32 %n, align 4, addrspace(5) - store volatile i32 0, i32 addrspace(5)* %alloca + store volatile i32 addrspace(5)* %alloca, i32 addrspace(5)* addrspace(1)* undef ret void } From a0e981c190ffa0ad6b521222bc2fba504c9750ec Mon Sep 17 00:00:00 2001 From: Diogo Sampaio Date: Thu, 9 Jul 2020 15:30:24 +0100 Subject: [PATCH 04/11] [NFC] Add SExt multiuses test --- llvm/test/Transforms/BDCE/sext_multi_uses.ll | 111 +++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 llvm/test/Transforms/BDCE/sext_multi_uses.ll diff --git a/llvm/test/Transforms/BDCE/sext_multi_uses.ll b/llvm/test/Transforms/BDCE/sext_multi_uses.ll new file mode 100644 index 00000000000000..97709357919e9e --- /dev/null +++ b/llvm/test/Transforms/BDCE/sext_multi_uses.ll @@ -0,0 +1,111 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -o - -bdce -S %s | FileCheck %s +define i32 @ZEXT_0(i16 %a) { +; CHECK-LABEL: @ZEXT_0( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT]], 65280 +; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 8 +; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]] +; CHECK-NEXT: ret i32 [[OR]] +; +entry: + %ext = sext i16 %a to i32 + %and = and i32 %ext, 65280 + %lsr = lshr i32 %ext, 8 + %and2 = and i32 %lsr, 255 + %or = or i32 %and, %and2 + ret i32 %or +} + +define i32 @ZEXT_1(i16 %a) { +; CHECK-LABEL: @ZEXT_1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 8 +; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255 +; CHECK-NEXT: [[AND:%.*]] = or i32 [[EXT]], -65536 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]] +; CHECK-NEXT: ret i32 [[OR]] +; +entry: + %ext = sext i16 %a to i32 + %lsr = lshr i32 %ext, 8 + %and2 = and i32 %lsr, 255 + %and = or i32 %ext, 4294901760 + %or = or i32 %and, %and2 + ret i32 %or +} + +define i16 @NOT_ZEXT_0(i16 %a) { +; CHECK-LABEL: @NOT_ZEXT_0( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT]], 65280 +; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 9 +; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]] +; CHECK-NEXT: [[RET:%.*]] = trunc i32 [[OR]] to i16 +; CHECK-NEXT: ret i16 [[RET]] +; +entry: + %ext = sext i16 %a to i32 + %and = and i32 %ext, 65280 + %lsr = lshr i32 %ext, 9 + %and2 = and i32 %lsr, 255 + %or = or i32 %and, %and2 + %ret = trunc i32 %or to i16 + ret i16 %ret +} + +define i32 @NOT_ZEXT_1(i16 %a) { +; CHECK-LABEL: @NOT_ZEXT_1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT]], 85280 +; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 8 +; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]] +; CHECK-NEXT: ret i32 [[OR]] +; +entry: + %ext = sext i16 %a to i32 + %and = and i32 %ext, 85280 + %lsr = lshr i32 %ext, 8 + %and2 = and i32 %lsr, 255 + %or = or i32 %and, %and2 + ret i32 %or +} + +define i32 @NOT_ZEXT_2(i16 %a) { +; CHECK-LABEL: @NOT_ZEXT_2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 8 +; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255 +; CHECK-NEXT: [[AND:%.*]] = xor i32 [[EXT]], -65536 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]] +; CHECK-NEXT: ret i32 [[OR]] +; +entry: + %ext = sext i16 %a to i32 + %lsr = lshr i32 %ext, 8 + %and2 = and i32 %lsr, 255 + %and = xor i32 %ext, 4294901760 + %or = or i32 %and, %and2 + ret i32 %or +} + +define i16 @clear_assumptions(i8 %x, i16 %y) { +; CHECK-LABEL: @clear_assumptions( +; CHECK-NEXT: [[EXT:%.*]] = sext i8 [[X:%.*]] to i16 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[EXT]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i16 [[ADD]], 255 +; CHECK-NEXT: ret i16 [[AND]] +; + %ext = sext i8 %x to i16 + %add = add nsw i16 %ext, %y + %and = and i16 %add, 255 + ret i16 %and +} From 7cd1b0ff347d7aa4864624501efbe2ac609e67d7 Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Thu, 9 Jul 2020 07:39:44 -0700 Subject: [PATCH 05/11] [flang] partially revert upstreamed code to support complex values in runtime support to avoid warnings. --- flang/lib/Evaluate/intrinsics-library.cpp | 11 ------ flang/runtime/pgmath.h.inc | 41 ----------------------- 2 files changed, 52 deletions(-) diff --git a/flang/lib/Evaluate/intrinsics-library.cpp b/flang/lib/Evaluate/intrinsics-library.cpp index 184dc0555d7bd8..c81ad4f34563a5 100644 --- a/flang/lib/Evaluate/intrinsics-library.cpp +++ b/flang/lib/Evaluate/intrinsics-library.cpp @@ -248,17 +248,6 @@ template struct ToStdComplex { using AType = Type; }; -template <> struct ToStdComplex { - using Type = std::complex; - // Complex arguments are passed by reference in C++ std math functions. - using AType = Type &; -}; - -template <> struct ToStdComplex { - using Type = std::complex; - using AType = Type &; -}; - template struct CComplexFunc {}; template func> struct CComplexFunc, func> { diff --git a/flang/runtime/pgmath.h.inc b/flang/runtime/pgmath.h.inc index 32e1e5cfd070ac..061a47431e6d4c 100644 --- a/flang/runtime/pgmath.h.inc +++ b/flang/runtime/pgmath.h.inc @@ -33,8 +33,6 @@ #ifdef PGMATH_USE_ALL_TYPES #define PGMATH_USE_S(name, func) PGMATH_USE_ALL_TYPES(name, func) #define PGMATH_USE_D(name, func) PGMATH_USE_ALL_TYPES(name, func) -#define PGMATH_USE_C(name, func) PGMATH_USE_ALL_TYPES(name, func) -#define PGMATH_USE_Z(name, func) PGMATH_USE_ALL_TYPES(name, func) #define PGMATH_USE_OTHER(name, func) PGMATH_USE_ALL_TYPES(name, func) #endif @@ -64,15 +62,8 @@ PGMATH_USE_S(func, __##impl##s_##func##_1) \ PGMATH_USE_D(func, __##impl##d_##func##_1) -#define PGMATH_COMPLEX_IMPL(impl, func) \ - PGMATH_DECLARE(float _Complex __##impl##c_##func##_1(float _Complex)) \ - PGMATH_DECLARE(double _Complex __##impl##z_##func##_1(double _Complex)) \ - PGMATH_USE_C(func, __##impl##c_##func##_1) \ - PGMATH_USE_Z(func, __##impl##z_##func##_1) - #define PGMATH_ALL_FP_IMPL(impl, func) \ PGMATH_REAL_IMPL(impl, func) \ - PGMATH_FAST_COMPLEX_IMPL(impl, func) #define PGMATH_REAL2_IMPL(impl, func) \ PGMATH_DECLARE(float __##impl##s_##func##_1(float, float)) \ @@ -80,17 +71,8 @@ PGMATH_USE_S(func, __##impl##s_##func##_1) \ PGMATH_USE_D(func, __##impl##d_##func##_1) -#define PGMATH_COMPLEX2_IMPL(impl, func) \ - PGMATH_DECLARE( \ - float _Complex __##impl##c_##func##_1(float _Complex, float _Complex)) \ - PGMATH_DECLARE(double _Complex __##impl##z_##func##_1( \ - double _Complex, double _Complex)) \ - PGMATH_USE_C(func, __##impl##c_##func##_1) \ - PGMATH_USE_Z(func, __##impl##z_##func##_1) - #define PGMATH_ALL_FP2_IMPL(impl, func) \ PGMATH_REAL2_IMPL(func) \ - PGMATH_COMPLEX2_IMPL(func) #undef PGMATH_FAST_REAL #undef PGMATH_FAST_COMPLEX @@ -100,10 +82,8 @@ #undef PGMATH_FAST_ALL_FP2 #ifdef PGMATH_FAST #define PGMATH_FAST_REAL(func) PGMATH_REAL_IMPL(f, func) -#define PGMATH_FAST_COMPLEX(func) PGMATH_COMPLEX_IMPL(f, func) #define PGMATH_FAST_ALL_FP(func) PGMATH_ALL_IMPL(f, func) #define PGMATH_FAST_REAL2(func) PGMATH_REAL2_IMPL(f, func) -#define PGMATH_FAST_COMPLEX2(func) PGMATH_COMPLEX2_IMPL(f, func) #define PGMATH_FAST_ALL_FP2(func) PGMATH_ALL_FP2_IMPL(f, func) #else #define PGMATH_FAST_REAL(func) @@ -122,10 +102,8 @@ #undef PGMATH_RELAXED_ALL_FP2 #ifdef PGMATH_RELAXED #define PGMATH_RELAXED_REAL(func) PGMATH_REAL_IMPL(r, func) -#define PGMATH_RELAXED_COMPLEX(func) PGMATH_COMPLEX_IMPL(r, func) #define PGMATH_RELAXED_ALL_FP(func) PGMATH_ALL_IMPL(r, func) #define PGMATH_RELAXED_REAL2(func) PGMATH_REAL2_IMPL(r, func) -#define PGMATH_RELAXED_COMPLEX2(func) PGMATH_COMPLEX2_IMPL(r, func) #define PGMATH_RELAXED_ALL_FP2(func) PGMATH_ALL_FP2_IMPL(r, func) #else #define PGMATH_RELAXED_REAL(func) @@ -144,10 +122,8 @@ #undef PGMATH_PRECISE_ALL_FP2 #ifdef PGMATH_PRECISE #define PGMATH_PRECISE_REAL(func) PGMATH_REAL_IMPL(p, func) -#define PGMATH_PRECISE_COMPLEX(func) PGMATH_COMPLEX_IMPL(p, func) #define PGMATH_PRECISE_ALL_FP(func) PGMATH_ALL_IMPL(p, func) #define PGMATH_PRECISE_REAL2(func) PGMATH_REAL2_IMPL(p, func) -#define PGMATH_PRECISE_COMPLEX2(func) PGMATH_COMPLEX2_IMPL(p, func) #define PGMATH_PRECISE_ALL_FP2(func) PGMATH_ALL_FP2_IMPL(p, func) #else #define PGMATH_PRECISE_REAL(func) @@ -163,28 +139,16 @@ PGMATH_PRECISE_REAL(func) \ PGMATH_RELAXED_REAL(func) -#define PGMATH_COMPLEX(func) \ - PGMATH_FAST_COMPLEX(func) \ - PGMATH_PRECISE_COMPLEX(func) \ - PGMATH_RELAXED_COMPLEX(func) - #define PGMATH_ALL(func) \ PGMATH_REAL(func) \ - PGMATH_COMPLEX(func) #define PGMATH_REAL2(func) \ PGMATH_FAST_REAL2(func) \ PGMATH_PRECISE_REAL2(func) \ PGMATH_RELAXED_REAL2(func) -#define PGMATH_COMPLEX2(func) \ - PGMATH_FAST_COMPLEX2(func) \ - PGMATH_PRECISE_COMPLEX2(func) \ - PGMATH_RELAXED_COMPLEX2(func) - #define PGMATH_ALL2(func) \ PGMATH_REAL2(func) \ - PGMATH_COMPLEX2(func) // Marcos to declare __mth_i libpgmath variants #define PGMATH_MTH_VERSION_REAL(func) \ @@ -243,16 +207,12 @@ PGMATH_ALL2(pow) #define PGMATH_DELCARE_POW(impl) \ PGMATH_DECLARE(float __##impl##s_powi_1(float, int)) \ PGMATH_DECLARE(double __##impl##d_powi_1(double, int)) \ - PGMATH_DECLARE(float _Complex __##impl##c_powi_1(float _Complex, int)) \ - PGMATH_DECLARE(double _Complex __##impl##z_powi_1(double _Complex, int)) \ PGMATH_USE_S(pow, __##impl##s_powi_1) \ PGMATH_USE_D(pow, __##impl##d_powi_1) \ PGMATH_USE_C(pow, __##impl##c_powi_1) \ PGMATH_USE_Z(pow, __##impl##z_powi_1) \ PGMATH_DECLARE(float __##impl##s_powk_1(float, int64_t)) \ PGMATH_DECLARE(double __##impl##d_powk_1(double, int64_t)) \ - PGMATH_DECLARE(float _Complex __##impl##c_powk_1(float _Complex, int64_t)) \ - PGMATH_DECLARE(double _Complex __##impl##z_powk_1(double _Complex, int64_t)) \ PGMATH_USE_S(pow, __##impl##s_powk_1) \ PGMATH_USE_D(pow, __##impl##d_powk_1) \ PGMATH_USE_C(pow, __##impl##c_powk_1) \ @@ -277,7 +237,6 @@ PGMATH_USE_OTHER(pow, __mth_i_kpowk) PGMATH_ALL(sin) PGMATH_ALL(sinh) PGMATH_MTH_VERSION_REAL(sqrt) -PGMATH_COMPLEX(sqrt) // real versions are __mth_i... PGMATH_ALL(tan) PGMATH_ALL(tanh) From 5d075beae73f3d9570230c0780e74dc32dda39a9 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Thu, 9 Jul 2020 17:20:38 +0300 Subject: [PATCH 06/11] [MLIR][SPIRVToLLVM] SPIR-V types size in bytes function Added `getSizeInBytes()` function as a class member to several SPIR-V types: `ScalarType`, `ArrayType` and `VectorType`. This function aims at exposing the functionality of `getTypeNumBytes()` from `SPIRVLowering.cpp`. Support of more types will be added on demand. Reviewed By: antiagainst Differential Revision: https://reviews.llvm.org/D83285 --- mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h | 13 ++++++ mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp | 47 ++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h b/mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h index 91ad96fed7b048..b13d3c7892be59 100644 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h @@ -109,6 +109,11 @@ class SPIRVType : public Type { /// times. void getCapabilities(CapabilityArrayRefVector &capabilities, Optional storage = llvm::None); + + /// Returns the size in bytes for each type. If no size can be calculated, + /// returns `llvm::None`. Note that if the type has explicit layout, it is + /// also taken into account in calculation. + Optional getSizeInBytes(); }; // SPIR-V scalar type: bool type, integer type, floating point type. @@ -127,6 +132,8 @@ class ScalarType : public SPIRVType { Optional storage = llvm::None); void getCapabilities(SPIRVType::CapabilityArrayRefVector &capabilities, Optional storage = llvm::None); + + Optional getSizeInBytes(); }; // SPIR-V composite type: VectorType, SPIR-V ArrayType, or SPIR-V StructType. @@ -153,6 +160,8 @@ class CompositeType : public SPIRVType { Optional storage = llvm::None); void getCapabilities(SPIRVType::CapabilityArrayRefVector &capabilities, Optional storage = llvm::None); + + Optional getSizeInBytes(); }; // SPIR-V array type @@ -181,6 +190,10 @@ class ArrayType : public Type::TypeBase storage = llvm::None); void getCapabilities(SPIRVType::CapabilityArrayRefVector &capabilities, Optional storage = llvm::None); + + /// Returns the array size in bytes. Since array type may have an explicit + /// stride declaration (in bytes), we also include it in the calculation. + Optional getSizeInBytes(); }; // SPIR-V image type diff --git a/mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp b/mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp index 07ffe40464837e..93d0c43d669fb1 100644 --- a/mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp +++ b/mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp @@ -151,6 +151,14 @@ void ArrayType::getCapabilities( getElementType().cast().getCapabilities(capabilities, storage); } +Optional ArrayType::getSizeInBytes() { + auto elementType = getElementType().cast(); + Optional size = elementType.getSizeInBytes(); + if (!size) + return llvm::None; + return (*size + getArrayStride()) * getNumElements(); +} + //===----------------------------------------------------------------------===// // CompositeType //===----------------------------------------------------------------------===// @@ -281,6 +289,24 @@ void CompositeType::getCapabilities( } } +Optional CompositeType::getSizeInBytes() { + switch (getKind()) { + case spirv::TypeKind::Array: + return cast().getSizeInBytes(); + case spirv::TypeKind::Struct: + return cast().getSizeInBytes(); + case StandardTypes::Vector: { + auto elementSize = + cast().getElementType().cast().getSizeInBytes(); + if (!elementSize) + return llvm::None; + return *elementSize * cast().getNumElements(); + } + default: + return llvm::None; + } +} + //===----------------------------------------------------------------------===// // CooperativeMatrixType //===----------------------------------------------------------------------===// @@ -806,6 +832,19 @@ void ScalarType::getCapabilities( #undef WIDTH_CASE } +Optional ScalarType::getSizeInBytes() { + auto bitWidth = getIntOrFloatBitWidth(); + // According to the SPIR-V spec: + // "There is no physical size or bit pattern defined for values with boolean + // type. If they are stored (in conjunction with OpVariable), they can only + // be used with logical addressing operations, not physical, and only with + // non-externally visible shader Storage Classes: Workgroup, CrossWorkgroup, + // Private, Function, Input, and Output." + if (bitWidth == 1) + return llvm::None; + return bitWidth / 8; +} + //===----------------------------------------------------------------------===// // SPIRVType //===----------------------------------------------------------------------===// @@ -861,6 +900,14 @@ void SPIRVType::getCapabilities( } } +Optional SPIRVType::getSizeInBytes() { + if (auto scalarType = dyn_cast()) + return scalarType.getSizeInBytes(); + if (auto compositeType = dyn_cast()) + return compositeType.getSizeInBytes(); + return llvm::None; +} + //===----------------------------------------------------------------------===// // StructType //===----------------------------------------------------------------------===// From beb52b12cb175d0df9bf168837d153f857f69eda Mon Sep 17 00:00:00 2001 From: Stefan Pintilie Date: Thu, 9 Jul 2020 09:50:19 -0500 Subject: [PATCH 07/11] [PowerPC] Support PCRelative Callees for R_PPC64_REL24 Relocation The R_PPC64_REL24 is used in function calls when the caller requires a valid TOC pointer. If the callee shares the same TOC or does not clobber the TOC pointer then a direct call can be made. If the callee does not share the TOC a thunk must be added to save the TOC pointer for the caller. Up until PC Relative was introduced all local calls on medium and large code models were assumed to share a TOC. This is no longer the case because if the caller requires a TOC and the callee is PC Relative then the callee can clobber the TOC even if it is in the same DSO. This patch is to add support for a TOC caller calling a PC Relative callee that clobbers the TOC. Reviewed By: sfertile, MaskRay Differential Revision: https://reviews.llvm.org/D82950 --- lld/ELF/Arch/PPC64.cpp | 5 ++ lld/ELF/Thunks.cpp | 34 +++++++++ lld/test/ELF/ppc64-error-toc-local-call.s | 32 ++++++++ .../ELF/ppc64-toc-call-to-pcrel-long-jump.s | 33 +++++++++ lld/test/ELF/ppc64-toc-call-to-pcrel.s | 74 +++++++++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 lld/test/ELF/ppc64-error-toc-local-call.s create mode 100644 lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s create mode 100644 lld/test/ELF/ppc64-toc-call-to-pcrel.s diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 0764dabe45f86f..cf58b322bb3a24 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -1039,6 +1039,11 @@ bool PPC64::needsThunk(RelExpr expr, RelType type, const InputFile *file, if (s.isInPlt()) return true; + // This check looks at the st_other bits of the callee. If the value is 1 + // then the callee clobbers the TOC and we need an R2 save stub. + if ((s.stOther >> 5) == 1) + return true; + // If a symbol is a weak undefined and we are compiling an executable // it doesn't need a range-extending thunk since it can't be called. if (s.isUndefWeak() && !config->shared) diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp index 744ceaf725cf6e..ea74d343ebb266 100644 --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -279,6 +279,20 @@ class PPC64PltCallStub final : public Thunk { void addSymbols(ThunkSection &isec) override; }; +// PPC64 R2 Save Stub +// When the caller requires a valid R2 TOC pointer but the callee does not +// require a TOC pointer and the callee cannot guarantee that it doesn't +// clobber R2 then we need to save R2. This stub: +// 1) Saves the TOC pointer to the stack. +// 2) Tail calls the callee. +class PPC64R2SaveStub final : public Thunk { +public: + PPC64R2SaveStub(Symbol &dest) : Thunk(dest, 0) {} + uint32_t size() override { return 8; } + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; +}; + // A bl instruction uses a signed 24 bit offset, with an implicit 4 byte // alignment. This gives a possible 26 bits of 'reach'. If the call offset is // larger then that we need to emit a long-branch thunk. The target address @@ -822,6 +836,21 @@ void PPC64PltCallStub::addSymbols(ThunkSection &isec) { s->file = destination.file; } +void PPC64R2SaveStub::writeTo(uint8_t *buf) { + int64_t offset = destination.getVA() - (getThunkTargetSym()->getVA() + 4); + // The branch offset needs to fit in 26 bits. + if (!isInt<26>(offset)) + fatal("R2 save stub branch offset is too large: " + Twine(offset)); + write32(buf + 0, 0xf8410018); // std r2,24(r1) + write32(buf + 4, 0x48000000 | (offset & 0x03fffffc)); // b +} + +void PPC64R2SaveStub::addSymbols(ThunkSection &isec) { + Defined *s = addSymbol(saver.save("__toc_save_" + destination.getName()), + STT_FUNC, 0, isec); + s->needsTocRestore = true; +} + void PPC64LongBranchThunk::writeTo(uint8_t *buf) { int64_t offset = in.ppc64LongBranchTarget->getEntryVA(&destination, addend) - getPPC64TocBase(); @@ -950,6 +979,11 @@ static Thunk *addThunkPPC64(RelType type, Symbol &s, int64_t a) { if (s.isInPlt()) return make(s); + // This check looks at the st_other bits of the callee. If the value is 1 + // then the callee clobbers the TOC and we need an R2 save stub. + if ((s.stOther >> 5) == 1) + return make(s); + if (config->picThunk) return make(s, a); diff --git a/lld/test/ELF/ppc64-error-toc-local-call.s b/lld/test/ELF/ppc64-error-toc-local-call.s new file mode 100644 index 00000000000000..f23eba1012097d --- /dev/null +++ b/lld/test/ELF/ppc64-error-toc-local-call.s @@ -0,0 +1,32 @@ +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o +# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s + +# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o +# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s + +## This test checks that the linker produces errors when it is missing the nop +## after a local call to a callee with st_other=1. + +# CHECK: (.text+0xC): call to save_callee lacks nop, can't restore toc +# CHECK: (.text+0x1C): call to save_callee lacks nop, can't restore toc + +callee: + .localentry callee, 1 + blr # 0x0 + +caller: +.Lfunc_gep1: + addis 2, 12, .TOC.-.Lfunc_gep1@ha + addi 2, 2, .TOC.-.Lfunc_gep1@l +.Lfunc_lep1: + .localentry caller, .Lfunc_lep1-.Lfunc_gep1 + bl callee # 0xC + blr + +caller_tail: +.Lfunc_gep2: + addis 2, 12, .TOC.-.Lfunc_gep2@ha + addi 2, 2, .TOC.-.Lfunc_gep2@l +.Lfunc_lep2: + .localentry caller_tail, .Lfunc_lep2-.Lfunc_gep2 + b callee # 0x1C diff --git a/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s b/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s new file mode 100644 index 00000000000000..89f62c7de7ce38 --- /dev/null +++ b/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s @@ -0,0 +1,33 @@ +# REQUIRES: ppc +# RUN: echo 'SECTIONS { \ +# RUN: .text_callee 0x10010000 : { *(.text_callee) } \ +# RUN: .text_caller 0x20020000 : { *(.text_caller) } \ +# RUN: }' > %t.script + +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o +# RUN: not ld.lld -T %t.script %t.o -o %t 2>&1 >/dev/null | FileCheck %s + +# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o +# RUN: not ld.lld -T %t.script %t.o -o %t 2>&1 >/dev/null | FileCheck %s + +# CHECK: error: R2 save stub branch offset is too large: -268501028 + +.section .text_callee, "ax", %progbits +callee: + .localentry callee, 1 + blr + +.section .text_caller, "ax", %progbits +caller: +.Lfunc_gep1: + addis 2, 12, .TOC.-.Lfunc_gep1@ha + addi 2, 2, .TOC.-.Lfunc_gep1@l +.Lfunc_lep1: + .localentry caller, .Lfunc_lep1-.Lfunc_gep1 + addis 30, 2, global@toc@ha + lwz 3, global@toc@l(30) + bl callee + nop + blr +global: + .long 0 diff --git a/lld/test/ELF/ppc64-toc-call-to-pcrel.s b/lld/test/ELF/ppc64-toc-call-to-pcrel.s new file mode 100644 index 00000000000000..1807895a1914b7 --- /dev/null +++ b/lld/test/ELF/ppc64-toc-call-to-pcrel.s @@ -0,0 +1,74 @@ +# REQUIRES: ppc +# RUN: echo 'SECTIONS { \ +# RUN: .text_callee 0x10010000 : { *(.text_callee) } \ +# RUN: .text_caller 0x10020000 : { *(.text_caller) } \ +# RUN: }' > %t.script + +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o +# RUN: ld.lld -T %t.script %t.o -o %t +# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL +# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=future %t | FileCheck %s + +# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o +# RUN: ld.lld -T %t.script %t.o -o %t +# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYMBOL +# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=future %t | FileCheck %s + +# The point of this test is to make sure that when a function with TOC access +# a local function with st_other=1, a TOC save stub is inserted. + +# SYMBOL: Symbol table '.symtab' contains 7 entries +# SYMBOL: 10010000 0 NOTYPE LOCAL DEFAULT [] 1 callee +# SYMBOL: 10020000 0 NOTYPE LOCAL DEFAULT [] 2 caller +# SYMBOL: 10020020 0 NOTYPE LOCAL DEFAULT [] 2 caller_14 +# SYMBOL: 1002003c 8 FUNC LOCAL DEFAULT 2 __toc_save_callee + +# CHECK-LABEL: callee +# CHECK: blr + +# CHECK-LABEL: caller +# CHECK: bl 0x1002003c +# CHECK-NEXT: ld 2, 24(1) +# CHECK-NEXT: blr + +# CHECK-LABEL: caller_14 +# CHECK: bfl 0, 0x1002003c +# CHECK-NEXT: ld 2, 24(1) +# CHECK-NEXT: blr + +# CHECK-LABEL: __toc_save_callee +# CHECK-NEXT: std 2, 24(1) +# CHECK-NEXT: b 0x10010000 + + +.section .text_callee, "ax", %progbits +callee: + .localentry callee, 1 + blr + +.section .text_caller, "ax", %progbits +caller: +.Lfunc_gep1: + addis 2, 12, .TOC.-.Lfunc_gep1@ha + addi 2, 2, .TOC.-.Lfunc_gep1@l +.Lfunc_lep1: + .localentry caller, .Lfunc_lep1-.Lfunc_gep1 + addis 30, 2, global@toc@ha + lwz 3, global@toc@l(30) + bl callee + nop + blr +global: + .long 0 + +caller_14: +.Lfunc_gep2: + addis 2, 12, .TOC.-.Lfunc_gep1@ha + addi 2, 2, .TOC.-.Lfunc_gep1@l +.Lfunc_lep2: + .localentry caller_14, .Lfunc_lep2-.Lfunc_gep2 + addis 30, 2, global@toc@ha + lwz 3, global@toc@l(30) + bcl 4, 0, callee + nop + blr From 4d4d9037670a3537c14092807a717284ea0c4f92 Mon Sep 17 00:00:00 2001 From: Zhi Zhuang Date: Thu, 9 Jul 2020 07:10:14 -0700 Subject: [PATCH 08/11] Fix warning caused by __builtin_expect_with_probability was not handled in places such as constant folding Previously some places that should have handled __builtin_expect_with_probability is missing, so in some case it acts differently than __builtin_expect. For example it was not handled in constant folding, thus in the following program, the "if" condition should be constantly true and folded, but previously it was not handled and cause warning "control may reach end of non-void function" (while __builtin_expect does not): __attribute__((noreturn)) extern void bar(); int foo(int x, int y) { if (y) { if (__builtin_expect_with_probability(1, 1, 1)) bar(); } else return 0; } Now it's fixed. Differential Revisions: https://reviews.llvm.org/D83362 --- clang/lib/AST/ExprConstant.cpp | 1 + .../Checkers/BuiltinFunctionChecker.cpp | 6 +++-- .../Sema/builtin-expect-with-probability.cpp | 26 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index d6dbfb14e60b32..a4dc0ccad1e0f5 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11231,6 +11231,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, } case Builtin::BI__builtin_expect: + case Builtin::BI__builtin_expect_with_probability: return Visit(E->getArg(0)); case Builtin::BI__builtin_ffs: diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 3eeb1e9a3502e6..233ce57c3ac9f8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -64,10 +64,12 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call, case Builtin::BI__builtin_unpredictable: case Builtin::BI__builtin_expect: + case Builtin::BI__builtin_expect_with_probability: case Builtin::BI__builtin_assume_aligned: case Builtin::BI__builtin_addressof: { - // For __builtin_unpredictable, __builtin_expect, and - // __builtin_assume_aligned, just return the value of the subexpression. + // For __builtin_unpredictable, __builtin_expect, + // __builtin_expect_with_probability and __builtin_assume_aligned, + // just return the value of the subexpression. // __builtin_addressof is going from a reference to a pointer, but those // are represented the same way in the analyzer. assert (Call.getNumArgs() > 0); diff --git a/clang/test/Sema/builtin-expect-with-probability.cpp b/clang/test/Sema/builtin-expect-with-probability.cpp index 4a5b62a55bbc69..3aa20cb0e6dd7c 100644 --- a/clang/test/Sema/builtin-expect-with-probability.cpp +++ b/clang/test/Sema/builtin-expect-with-probability.cpp @@ -1,4 +1,30 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s + +__attribute__((noreturn)) extern void bar(); + +int test_no_warn(int x) { + if (x) { + if (__builtin_expect_with_probability(1, 1, 1)) + bar(); + } else { + return 0; + } +} // should not emit warn "control may reach end of non-void function" here since expr is constantly true, so the "if(__bui..)" should be constantly true condition and be ignored + +template void tempf() { + static_assert(b == 1, "should be evaluated as 1"); // should not have error here +} + +constexpr int constf() { + return __builtin_expect_with_probability(1, 1, 1); +} + +void foo() { + tempf<__builtin_expect_with_probability(1, 1, 1)>(); + constexpr int f = constf(); + static_assert(f == 1, "should be evaluated as 1"); // should not have error here +} + extern int global; struct S { From 28cd3cbc12577fa44f9b15c2ffaf9fb1bc280590 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Thu, 9 Jul 2020 17:48:50 +0300 Subject: [PATCH 09/11] [MLIR][SPIRVToLLVM] Conversion of SPIR-V array, runtime array, and pointer types This patch adds type conversion for 4 SPIR-V types: array, runtime array, pointer and struct. This conversion is integrated using a separate function `populateSPIRVToLLVMTypeConversion()` that adds new type conversions. At the moment, this is a basic skeleton that allows to perfom conversion from SPIR-V array, runtime array and pointer types to LLVM typesystem. There is no support of array strides or storage classes. These will be supported on the case by case basis. Reviewed By: antiagainst Differential Revision: https://reviews.llvm.org/D83399 --- .../SPIRVToLLVM/ConvertSPIRVToLLVM.h | 3 ++ .../SPIRVToLLVM/ConvertSPIRVToLLVM.cpp | 51 +++++++++++++++++++ .../SPIRVToLLVM/ConvertSPIRVToLLVMPass.cpp | 3 ++ .../SPIRVToLLVM/cast-ops-to-llvm.mlir | 6 +++ .../spirv-types-to-llvm.invalid.mlir | 6 +++ .../SPIRVToLLVM/spirv-types-to-llvm.mlir | 28 ++++++++++ 6 files changed, 97 insertions(+) create mode 100644 mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir create mode 100644 mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir diff --git a/mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h b/mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h index 17537232cc0350..4092083f260772 100644 --- a/mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h +++ b/mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h @@ -32,6 +32,9 @@ class SPIRVToLLVMConversion : public OpConversionPattern { LLVMTypeConverter &typeConverter; }; +/// Populates type conversions with additional SPIR-V types. +void populateSPIRVToLLVMTypeConversion(LLVMTypeConverter &typeConverter); + /// Populates the given list with patterns that convert from SPIR-V to LLVM. void populateSPIRVToLLVMConversionPatterns(MLIRContext *context, LLVMTypeConverter &typeConverter, diff --git a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp index 6d0028b38ec24c..7755656ea3b861 100644 --- a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp +++ b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp @@ -165,6 +165,43 @@ static Value processCountOrOffset(Location loc, Value value, Type srcType, return optionallyTruncateOrExtend(loc, broadcasted, dstType, rewriter); } +//===----------------------------------------------------------------------===// +// Type conversion +//===----------------------------------------------------------------------===// + +/// Converts SPIR-V array type to LLVM array. There is no modelling of array +/// stride at the moment. +static Optional convertArrayType(spirv::ArrayType type, + TypeConverter &converter) { + if (type.getArrayStride() != 0) + return llvm::None; + auto elementType = + converter.convertType(type.getElementType()).cast(); + unsigned numElements = type.getNumElements(); + return LLVM::LLVMType::getArrayTy(elementType, numElements); +} + +/// Converts SPIR-V pointer type to LLVM pointer. Pointer's storage class is not +/// modelled at the moment. +static Type convertPointerType(spirv::PointerType type, + TypeConverter &converter) { + auto pointeeType = + converter.convertType(type.getPointeeType()).cast(); + return pointeeType.getPointerTo(); +} + +/// Converts SPIR-V runtime array to LLVM array. Since LLVM allows indexing over +/// the bounds, the runtime array is converted to a 0-sized LLVM array. There is +/// no modelling of array stride at the moment. +static Optional convertRuntimeArrayType(spirv::RuntimeArrayType type, + TypeConverter &converter) { + if (type.getArrayStride() != 0) + return llvm::None; + auto elementType = + converter.convertType(type.getElementType()).cast(); + return LLVM::LLVMType::getArrayTy(elementType, 0); +} + //===----------------------------------------------------------------------===// // Operation conversion //===----------------------------------------------------------------------===// @@ -581,6 +618,8 @@ class FuncConversionPattern : public SPIRVToLLVMConversion { funcType.getNumInputs()); auto llvmType = this->typeConverter.convertFunctionSignature( funcOp.getType(), /*isVariadic=*/false, signatureConverter); + if (!llvmType) + return failure(); // Create a new `LLVMFuncOp` Location loc = funcOp.getLoc(); @@ -662,6 +701,18 @@ class ModuleEndConversionPattern // Pattern population //===----------------------------------------------------------------------===// +void mlir::populateSPIRVToLLVMTypeConversion(LLVMTypeConverter &typeConverter) { + typeConverter.addConversion([&](spirv::ArrayType type) { + return convertArrayType(type, typeConverter); + }); + typeConverter.addConversion([&](spirv::PointerType type) { + return convertPointerType(type, typeConverter); + }); + typeConverter.addConversion([&](spirv::RuntimeArrayType type) { + return convertRuntimeArrayType(type, typeConverter); + }); +} + void mlir::populateSPIRVToLLVMConversionPatterns( MLIRContext *context, LLVMTypeConverter &typeConverter, OwningRewritePatternList &patterns) { diff --git a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.cpp b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.cpp index c5128782034c8e..1a806d04d9fc07 100644 --- a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.cpp +++ b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.cpp @@ -34,6 +34,9 @@ void ConvertSPIRVToLLVMPass::runOnOperation() { LLVMTypeConverter converter(&getContext()); OwningRewritePatternList patterns; + + populateSPIRVToLLVMTypeConversion(converter); + populateSPIRVToLLVMModuleConversionPatterns(context, converter, patterns); populateSPIRVToLLVMConversionPatterns(context, converter, patterns); populateSPIRVToLLVMFunctionConversionPatterns(context, converter, patterns); diff --git a/mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir index 0d101f348a9f42..29f43fadf933c9 100644 --- a/mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir +++ b/mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir @@ -34,6 +34,12 @@ func @bitcast_vector_to_vector(%arg0 : vector<4xf32>) { return } +func @bitcast_pointer(%arg0: !spv.ptr) { + // CHECK: %{{.*}} = llvm.bitcast %{{.*}} : !llvm<"float*"> to !llvm<"i32*"> + %0 = spv.Bitcast %arg0 : !spv.ptr to !spv.ptr + return +} + //===----------------------------------------------------------------------===// // spv.ConvertFToS //===----------------------------------------------------------------------===// diff --git a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir new file mode 100644 index 00000000000000..8115b973507bd7 --- /dev/null +++ b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir @@ -0,0 +1,6 @@ +// RUN: mlir-opt %s -convert-spirv-to-llvm -verify-diagnostics -split-input-file + +// expected-error@+1 {{failed to legalize operation 'spv.func' that was explicitly marked illegal}} +spv.func @array_with_stride(%arg: !spv.array<4 x f32, stride=4>) -> () "None" { + spv.Return +} diff --git a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir new file mode 100644 index 00000000000000..d2bfdcd4c33dc9 --- /dev/null +++ b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir @@ -0,0 +1,28 @@ +// RUN: mlir-opt -split-input-file -convert-spirv-to-llvm -verify-diagnostics %s | FileCheck %s + +//===----------------------------------------------------------------------===// +// Array type +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @array(!llvm<"[16 x float]">, !llvm<"[32 x <4 x float>]">) +func @array(!spv.array<16xf32>, !spv.array< 32 x vector<4xf32> >) -> () + +//===----------------------------------------------------------------------===// +// Pointer type +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @pointer_scalar(!llvm<"i1*">, !llvm<"float*">) +func @pointer_scalar(!spv.ptr, !spv.ptr) -> () + +// CHECK-LABEL: @pointer_vector(!llvm<"<4 x i32>*">) +func @pointer_vector(!spv.ptr, Function>) -> () + +//===----------------------------------------------------------------------===// +// Runtime array type +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @runtime_array_vector(!llvm<"[0 x <4 x float>]">) +func @runtime_array_vector(!spv.rtarray< vector<4xf32> >) -> () + +// CHECK-LABEL: @runtime_array_scalar(!llvm<"[0 x float]">) +func @runtime_array_scalar(!spv.rtarray) -> () From 67422e4294754e08f277b1ba22820487eb76b918 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Thu, 9 Jul 2020 17:25:32 +0300 Subject: [PATCH 10/11] [MSP430] Align the _Complex ABI with current msp430-gcc Assembler output is checked against msp430-gcc 9.2.0.50 from TI. Reviewed By: asl Differential Revision: https://reviews.llvm.org/D82646 --- clang/lib/CodeGen/TargetInfo.cpp | 41 ++++- clang/test/CodeGen/msp430-abi-complex.c | 226 ++++++++++++++++++++++++ 2 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/msp430-abi-complex.c diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 801adc29acd146..b83267dec6f029 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -7475,10 +7475,49 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { namespace { +class MSP430ABIInfo : public DefaultABIInfo { + static ABIArgInfo complexArgInfo() { + ABIArgInfo Info = ABIArgInfo::getDirect(); + Info.setCanBeFlattened(false); + return Info; + } + +public: + MSP430ABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} + + ABIArgInfo classifyReturnType(QualType RetTy) const { + if (RetTy->isAnyComplexType()) + return complexArgInfo(); + + return DefaultABIInfo::classifyReturnType(RetTy); + } + + ABIArgInfo classifyArgumentType(QualType RetTy) const { + if (RetTy->isAnyComplexType()) + return complexArgInfo(); + + return DefaultABIInfo::classifyArgumentType(RetTy); + } + + // Just copy the original implementations because + // DefaultABIInfo::classify{Return,Argument}Type() are not virtual + void computeInfo(CGFunctionInfo &FI) const override { + if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (auto &I : FI.arguments()) + I.info = classifyArgumentType(I.type); + } + + Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, + QualType Ty) const override { + return EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty)); + } +}; + class MSP430TargetCodeGenInfo : public TargetCodeGenInfo { public: MSP430TargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(std::make_unique(CGT)) {} + : TargetCodeGenInfo(std::make_unique(CGT)) {} void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const override; }; diff --git a/clang/test/CodeGen/msp430-abi-complex.c b/clang/test/CodeGen/msp430-abi-complex.c new file mode 100644 index 00000000000000..faafcd2cde3f8c --- /dev/null +++ b/clang/test/CodeGen/msp430-abi-complex.c @@ -0,0 +1,226 @@ +// REQUIRES: msp430-registered-target +// RUN: %clang -target msp430 -Os -S -o- %s | FileCheck %s + +volatile int N; +volatile int i16_1, i16_2; +volatile long i32_1, i32_2; +volatile long long i64_1, i64_2; +volatile float f1, f2; +volatile double d1, d2; + +_Static_assert(sizeof(int) == 2, "Assumption failed"); +_Static_assert(sizeof(long) == 4, "Assumption failed"); +_Static_assert(sizeof(long long) == 8, "Assumption failed"); + +void complex_i16_arg_first(int _Complex x, int n) { +// CHECK-LABEL: @complex_i16_arg_first + i16_1 = __real__ x; +// CHECK-DAG: mov r12, &i16_1 + i16_2 = __imag__ x; +// CHECK-DAG: mov r13, &i16_2 + N = n; +// CHECK-DAG: mov r14, &N +// CHECK: ret +} + +void complex_i16_arg_second(int n, int _Complex x) { +// CHECK-LABEL: @complex_i16_arg_second + N = n; +// CHECK-DAG: mov r12, &N + i16_1 = __real__ x; +// CHECK-DAG: mov r13, &i16_1 + i16_2 = __imag__ x; +// CHECK-DAG: mov r14, &i16_2 +// CHECK: ret +} + +void complex_i32_arg_first(long _Complex x, int n) { +// CHECK-LABEL: @complex_i32_arg_first + i32_1 = __real__ x; +// CHECK-DAG: mov r12, &i32_1 +// CHECK-DAG: mov r13, &i32_1+2 + i32_2 = __imag__ x; +// CHECK-DAG: mov r14, &i32_2 +// CHECK-DAG: mov r15, &i32_2+2 + N = n; +// CHECK-DAG: mov 2(r1), &N +// CHECK: ret +} + +void complex_i32_arg_second(int n, long _Complex x) { +// CHECK-LABEL: @complex_i32_arg_second + N = n; +// CHECK-DAG: mov r12, &N + i32_1 = __real__ x; +// CHECK-DAG: mov 2(r1), &i32_1 +// CHECK-DAG: mov 4(r1), &i32_1+2 + i32_2 = __imag__ x; +// CHECK-DAG: mov 6(r1), &i32_2 +// CHECK-DAG: mov 8(r1), &i32_2+2 +// CHECK: ret +} + +void complex_i64_arg_first(long long _Complex x, int n) { +// CHECK-LABEL: @complex_i64_arg_first + i64_1 = __real__ x; +// CHECK-DAG: mov 2(r1), &i64_1 +// CHECK-DAG: mov 4(r1), &i64_1+2 +// CHECK-DAG: mov 6(r1), &i64_1+4 +// CHECK-DAG: mov 8(r1), &i64_1+6 + i64_2 = __imag__ x; +// CHECK-DAG: mov 10(r1), &i64_2 +// CHECK-DAG: mov 12(r1), &i64_2+2 +// CHECK-DAG: mov 14(r1), &i64_2+4 +// CHECK-DAG: mov 16(r1), &i64_2+6 + N = n; +// CHECK-DAG: mov r12, &N +// CHECK: ret +} + +void complex_i64_arg_second(int n, long long _Complex x) { +// CHECK-LABEL: @complex_i64_arg_second + N = n; +// CHECK-DAG: mov r12, &N + i64_1 = __real__ x; +// CHECK-DAG: mov 2(r1), &i64_1 +// CHECK-DAG: mov 4(r1), &i64_1+2 +// CHECK-DAG: mov 6(r1), &i64_1+4 +// CHECK-DAG: mov 8(r1), &i64_1+6 + i64_2 = __imag__ x; +// CHECK-DAG: mov 10(r1), &i64_2 +// CHECK-DAG: mov 12(r1), &i64_2+2 +// CHECK-DAG: mov 14(r1), &i64_2+4 +// CHECK-DAG: mov 16(r1), &i64_2+6 +// CHECK: ret +} + +void complex_float_arg_first(float _Complex x, int n) { +// CHECK-LABEL: @complex_float_arg_first + f1 = __real__ x; +// CHECK-DAG: mov r12, &f1 +// CHECK-DAG: mov r13, &f1+2 + f2 = __imag__ x; +// CHECK-DAG: mov r14, &f2 +// CHECK-DAG: mov r15, &f2+2 + N = n; +// CHECK-DAG: mov 2(r1), &N +// CHECK: ret +} + +void complex_float_arg_second(int n, float _Complex x) { +// CHECK-LABEL: @complex_float_arg_second + N = n; +// CHECK-DAG: mov r12, &N + f1 = __real__ x; +// CHECK-DAG: mov 2(r1), &f1 +// CHECK-DAG: mov 4(r1), &f1+2 + f2 = __imag__ x; +// CHECK-DAG: mov 6(r1), &f2 +// CHECK-DAG: mov 8(r1), &f2+2 +// CHECK: ret +} + +void complex_double_arg_first(double _Complex x, int n) { +// CHECK-LABEL: @complex_double_arg_first + d1 = __real__ x; +// CHECK-DAG: mov 2(r1), &d1 +// CHECK-DAG: mov 4(r1), &d1+2 +// CHECK-DAG: mov 6(r1), &d1+4 +// CHECK-DAG: mov 8(r1), &d1+6 + d2 = __imag__ x; +// CHECK-DAG: mov 10(r1), &d2 +// CHECK-DAG: mov 12(r1), &d2+2 +// CHECK-DAG: mov 14(r1), &d2+4 +// CHECK-DAG: mov 16(r1), &d2+6 + N = n; +// CHECK-DAG: mov r12, &N +// CHECK: ret +} + +void complex_double_arg_second(int n, double _Complex x) { +// CHECK-LABEL: @complex_double_arg_second + d1 = __real__ x; +// CHECK-DAG: mov 2(r1), &d1 +// CHECK-DAG: mov 4(r1), &d1+2 +// CHECK-DAG: mov 6(r1), &d1+4 +// CHECK-DAG: mov 8(r1), &d1+6 + d2 = __imag__ x; +// CHECK-DAG: mov 10(r1), &d2 +// CHECK-DAG: mov 12(r1), &d2+2 +// CHECK-DAG: mov 14(r1), &d2+4 +// CHECK-DAG: mov 16(r1), &d2+6 + N = n; +// CHECK-DAG: mov r12, &N +// CHECK: ret +} + +int _Complex complex_i16_res(void) { +// CHECK-LABEL: @complex_i16_res + int _Complex res; + __real__ res = 0x1122; +// CHECK-DAG: mov #4386, r12 + __imag__ res = 0x3344; +// CHECK-DAG: mov #13124, r13 + return res; +// CHECK: ret +} + +long _Complex complex_i32_res(void) { +// CHECK-LABEL: @complex_i32_res + long _Complex res; + __real__ res = 0x11223344; +// CHECK-DAG: mov #13124, r12 +// CHECK-DAG: mov #4386, r13 + __imag__ res = 0x55667788; +// CHECK-DAG: mov #30600, r14 +// CHECK-DAG: mov #21862, r15 + return res; +// CHECK: ret +} + +long long _Complex complex_i64_res(void) { +// CHECK-LABEL: @complex_i64_res + long long _Complex res; + __real__ res = 0x1122334455667788; +// CHECK-DAG: mov #30600, 0(r12) +// CHECK-DAG: mov #21862, 2(r12) +// CHECK-DAG: mov #13124, 4(r12) +// CHECK-DAG: mov #4386, 6(r12) + __imag__ res = 0x99aabbccddeeff00; +// CHECK-DAG: mov #-256, 8(r12) +// CHECK-DAG: mov #-8722, 10(r12) +// CHECK-DAG: mov #-17460, 12(r12) +// CHECK-DAG: mov #-26198, 14(r12) + return res; +// CHECK: ret +} + +float _Complex complex_float_res(void) { +// CHECK-LABEL: @complex_float_res + float _Complex res; + __real__ res = 1; +// CHECK-DAG: clr r12 +// CHECK-DAG: mov #16256, r13 + __imag__ res = -1; +// CHECK-DAG: clr r14 +// CHECK-DAG: mov #-16512, r15 + return res; +// CHECK: ret +} + +double _Complex complex_double_res(void) { +// CHECK-LABEL: @complex_double_res + double _Complex res; + __real__ res = 1; +// CHECK-DAG: clr 0(r12) +// CHECK-DAG: clr 2(r12) +// CHECK-DAG: clr 4(r12) +// CHECK-DAG: mov #16368, 6(r12) + __imag__ res = -1; +// CHECK-DAG: clr 8(r12) +// CHECK-DAG: clr 10(r12) +// CHECK-DAG: clr 12(r12) +// CHECK-DAG: mov #-16400, 14(r12) + return res; +// CHECK: ret +} From 3cca818efabbccdde36b06609cf75ee7caa8e012 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Thu, 9 Jul 2020 17:09:57 +0200 Subject: [PATCH 11/11] Refactored NumericLiteralParser to not require a Preprocessor Summary: We would like to use NumericLiteralParser in the implementation of the syntax tree builder, and plumbing a preprocessor there seems inconvenient and superfluous. Reviewers: eduucaldas Reviewed By: eduucaldas Subscribers: gribozavr2, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D83480 --- clang/include/clang/Lex/LiteralSupport.h | 10 ++- clang/lib/Lex/LiteralSupport.cpp | 104 +++++++++++++---------- clang/lib/Lex/PPExpressions.cpp | 4 +- clang/lib/Lex/Preprocessor.cpp | 4 +- clang/lib/Sema/SemaExpr.cpp | 4 +- 5 files changed, 74 insertions(+), 52 deletions(-) diff --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h index 6829771b283088..0c4f0fe277b7c6 100644 --- a/clang/include/clang/Lex/LiteralSupport.h +++ b/clang/include/clang/Lex/LiteralSupport.h @@ -40,7 +40,9 @@ void expandUCNs(SmallVectorImpl &Buf, StringRef Input); /// of a ppnumber, classifying it as either integer, floating, or erroneous, /// determines the radix of the value and can convert it to a useful value. class NumericLiteralParser { - Preprocessor &PP; // needed for diagnostics + const SourceManager &SM; + const LangOptions &LangOpts; + DiagnosticsEngine &Diags; const char *const ThisTokBegin; const char *const ThisTokEnd; @@ -54,9 +56,9 @@ class NumericLiteralParser { SmallString<32> UDSuffixBuf; public: - NumericLiteralParser(StringRef TokSpelling, - SourceLocation TokLoc, - Preprocessor &PP); + NumericLiteralParser(StringRef TokSpelling, SourceLocation TokLoc, + const SourceManager &SM, const LangOptions &LangOpts, + const TargetInfo &Target, DiagnosticsEngine &Diags); bool hadError : 1; bool isUnsigned : 1; bool isLong : 1; // This is *not* set for long long. diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index f44614b4bec466..eb16bc8c7da2d0 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -525,8 +525,12 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, /// NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, SourceLocation TokLoc, - Preprocessor &PP) - : PP(PP), ThisTokBegin(TokSpelling.begin()), ThisTokEnd(TokSpelling.end()) { + const SourceManager &SM, + const LangOptions &LangOpts, + const TargetInfo &Target, + DiagnosticsEngine &Diags) + : SM(SM), LangOpts(LangOpts), Diags(Diags), + ThisTokBegin(TokSpelling.begin()), ThisTokEnd(TokSpelling.end()) { // This routine assumes that the range begin/end matches the regex for integer // and FP constants (specifically, the 'pp-number' regex), and assumes that @@ -572,7 +576,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, checkSeparator(TokLoc, s, CSK_AfterDigits); // Initial scan to lookahead for fixed point suffix. - if (PP.getLangOpts().FixedPoint) { + if (LangOpts.FixedPoint) { for (const char *c = s; c != ThisTokEnd; ++c) { if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') { saw_fixed_point_suffix = true; @@ -592,14 +596,16 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, switch (*s) { case 'R': case 'r': - if (!PP.getLangOpts().FixedPoint) break; + if (!LangOpts.FixedPoint) + break; if (isFract || isAccum) break; if (!(saw_period || saw_exponent)) break; isFract = true; continue; case 'K': case 'k': - if (!PP.getLangOpts().FixedPoint) break; + if (!LangOpts.FixedPoint) + break; if (isFract || isAccum) break; if (!(saw_period || saw_exponent)) break; isAccum = true; @@ -607,7 +613,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, case 'h': // FP Suffix for "half". case 'H': // OpenCL Extension v1.2 s9.5 - h or H suffix for half type. - if (!(PP.getLangOpts().Half || PP.getLangOpts().FixedPoint)) break; + if (!(LangOpts.Half || LangOpts.FixedPoint)) + break; if (isIntegerLiteral()) break; // Error for integer constant. if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid. isHalf = true; @@ -621,8 +628,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, // CUDA host and device may have different _Float16 support, therefore // allows f16 literals to avoid false alarm. // ToDo: more precise check for CUDA. - if ((PP.getTargetInfo().hasFloat16Type() || PP.getLangOpts().CUDA) && - s + 2 < ThisTokEnd && s[1] == '1' && s[2] == '6') { + if ((Target.hasFloat16Type() || LangOpts.CUDA) && s + 2 < ThisTokEnd && + s[1] == '1' && s[2] == '6') { s += 2; // success, eat up 2 characters. isFloat16 = true; continue; @@ -657,10 +664,10 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, } else { isLong = true; } - continue; // Success. + continue; // Success. case 'i': case 'I': - if (PP.getLangOpts().MicrosoftExt) { + if (LangOpts.MicrosoftExt) { if (isLong || isLongLong || MicrosoftInteger) break; @@ -713,7 +720,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, if (s != ThisTokEnd || isImaginary) { // FIXME: Don't bother expanding UCNs if !tok.hasUCN(). expandUCNs(UDSuffixBuf, StringRef(SuffixBegin, ThisTokEnd - SuffixBegin)); - if (isValidUDSuffix(PP.getLangOpts(), UDSuffixBuf)) { + if (isValidUDSuffix(LangOpts, UDSuffixBuf)) { if (!isImaginary) { // Any suffix pieces we might have parsed are actually part of the // ud-suffix. @@ -736,8 +743,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, if (s != ThisTokEnd) { // Report an error if there are any. - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin), - diag::err_invalid_suffix_constant) + Diags.Report(Lexer::AdvanceToTokenCharacter( + TokLoc, SuffixBegin - ThisTokBegin, SM, LangOpts), + diag::err_invalid_suffix_constant) << StringRef(SuffixBegin, ThisTokEnd - SuffixBegin) << (isFixedPointConstant ? 2 : isFPConstant); hadError = true; @@ -758,9 +766,11 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){ // If we have a hex digit other than 'e' (which denotes a FP exponent) then // the code is using an incorrect base. if (isHexDigit(*s) && *s != 'e' && *s != 'E' && - !isValidUDSuffix(PP.getLangOpts(), StringRef(s, ThisTokEnd - s))) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_invalid_digit) << StringRef(s, 1) << (radix == 8 ? 1 : 0); + !isValidUDSuffix(LangOpts, StringRef(s, ThisTokEnd - s))) { + Diags.Report( + Lexer::AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin, SM, LangOpts), + diag::err_invalid_digit) + << StringRef(s, 1) << (radix == 8 ? 1 : 0); hadError = true; return; } @@ -786,8 +796,9 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){ s = first_non_digit; } else { if (!hadError) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), - diag::err_exponent_has_no_digits); + Diags.Report(Lexer::AdvanceToTokenCharacter( + TokLoc, Exponent - ThisTokBegin, SM, LangOpts), + diag::err_exponent_has_no_digits); hadError = true; } return; @@ -833,9 +844,10 @@ void NumericLiteralParser::checkSeparator(SourceLocation TokLoc, return; if (isDigitSeparator(*Pos)) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Pos - ThisTokBegin), - diag::err_digit_separator_not_between_digits) - << IsAfterDigits; + Diags.Report(Lexer::AdvanceToTokenCharacter(TokLoc, Pos - ThisTokBegin, SM, + LangOpts), + diag::err_digit_separator_not_between_digits) + << IsAfterDigits; hadError = true; } } @@ -873,9 +885,10 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { } if (!HasSignificandDigits) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), - diag::err_hex_constant_requires) - << PP.getLangOpts().CPlusPlus << 1; + Diags.Report(Lexer::AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin, SM, + LangOpts), + diag::err_hex_constant_requires) + << LangOpts.CPlusPlus << 1; hadError = true; return; } @@ -891,8 +904,9 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { const char *first_non_digit = SkipDigits(s); if (!containsDigits(s, first_non_digit)) { if (!hadError) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin), - diag::err_exponent_has_no_digits); + Diags.Report(Lexer::AdvanceToTokenCharacter( + TokLoc, Exponent - ThisTokBegin, SM, LangOpts), + diag::err_exponent_has_no_digits); hadError = true; } return; @@ -900,16 +914,17 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { checkSeparator(TokLoc, s, CSK_BeforeDigits); s = first_non_digit; - if (!PP.getLangOpts().HexFloats) - PP.Diag(TokLoc, PP.getLangOpts().CPlusPlus - ? diag::ext_hex_literal_invalid - : diag::ext_hex_constant_invalid); - else if (PP.getLangOpts().CPlusPlus17) - PP.Diag(TokLoc, diag::warn_cxx17_hex_literal); + if (!LangOpts.HexFloats) + Diags.Report(TokLoc, LangOpts.CPlusPlus + ? diag::ext_hex_literal_invalid + : diag::ext_hex_constant_invalid); + else if (LangOpts.CPlusPlus17) + Diags.Report(TokLoc, diag::warn_cxx17_hex_literal); } else if (saw_period) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin), - diag::err_hex_constant_requires) - << PP.getLangOpts().CPlusPlus << 0; + Diags.Report(Lexer::AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin, SM, + LangOpts), + diag::err_hex_constant_requires) + << LangOpts.CPlusPlus << 0; hadError = true; } return; @@ -918,12 +933,10 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { // Handle simple binary numbers 0b01010 if ((c1 == 'b' || c1 == 'B') && (s[1] == '0' || s[1] == '1')) { // 0b101010 is a C++1y / GCC extension. - PP.Diag(TokLoc, - PP.getLangOpts().CPlusPlus14 - ? diag::warn_cxx11_compat_binary_literal - : PP.getLangOpts().CPlusPlus - ? diag::ext_binary_literal_cxx14 - : diag::ext_binary_literal); + Diags.Report(TokLoc, LangOpts.CPlusPlus14 + ? diag::warn_cxx11_compat_binary_literal + : LangOpts.CPlusPlus ? diag::ext_binary_literal_cxx14 + : diag::ext_binary_literal); ++s; assert(s < ThisTokEnd && "didn't maximally munch?"); radix = 2; @@ -932,10 +945,11 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { if (s == ThisTokEnd) { // Done. } else if (isHexDigit(*s) && - !isValidUDSuffix(PP.getLangOpts(), - StringRef(s, ThisTokEnd - s))) { - PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin), - diag::err_invalid_digit) << StringRef(s, 1) << 2; + !isValidUDSuffix(LangOpts, StringRef(s, ThisTokEnd - s))) { + Diags.Report(Lexer::AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin, SM, + LangOpts), + diag::err_invalid_digit) + << StringRef(s, 1) << 2; hadError = true; } // Other suffixes will be diagnosed by the caller. diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp index 7a158a31490d29..8c120c13d7d26e 100644 --- a/clang/lib/Lex/PPExpressions.cpp +++ b/clang/lib/Lex/PPExpressions.cpp @@ -295,7 +295,9 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, if (NumberInvalid) return true; // a diagnostic was already reported - NumericLiteralParser Literal(Spelling, PeekTok.getLocation(), PP); + NumericLiteralParser Literal(Spelling, PeekTok.getLocation(), + PP.getSourceManager(), PP.getLangOpts(), + PP.getTargetInfo(), PP.getDiagnostics()); if (Literal.hadError) return true; // a diagnostic was already reported. diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 105aa6683c8b56..160e2b6ed88463 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -1370,7 +1370,9 @@ bool Preprocessor::parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value) { StringRef Spelling = getSpelling(Tok, IntegerBuffer, &NumberInvalid); if (NumberInvalid) return false; - NumericLiteralParser Literal(Spelling, Tok.getLocation(), *this); + NumericLiteralParser Literal(Spelling, Tok.getLocation(), getSourceManager(), + getLangOpts(), getTargetInfo(), + getDiagnostics()); if (Literal.hadError || !Literal.isIntegerLiteral() || Literal.hasUDSuffix()) return false; llvm::APInt APVal(64, 0); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e1433d293286ec..986c03bb872b8a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3634,7 +3634,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { if (Invalid) return ExprError(); - NumericLiteralParser Literal(TokSpelling, Tok.getLocation(), PP); + NumericLiteralParser Literal(TokSpelling, Tok.getLocation(), + PP.getSourceManager(), PP.getLangOpts(), + PP.getTargetInfo(), PP.getDiagnostics()); if (Literal.hadError) return ExprError();