From be8c9e3e0554b69e18c23698443cd836e3a6cb69 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 13 Feb 2019 10:30:16 +0000 Subject: [PATCH 01/35] Merging r352707, r352714, r352886, r352892, r352895, r352908, r352917, r352935, r353213, r353733, and r353758 ------------------------------------------------------------------------ r352707 | evandro | 2019-01-31 01:49:27 +0100 (Thu, 31 Jan 2019) | 1 line [InstCombine] Simplify check clauses in test (NFC) ------------------------------------------------------------------------ ------------------------------------------------------------------------ r352714 | evandro | 2019-01-31 02:41:39 +0100 (Thu, 31 Jan 2019) | 3 lines [InstCombine] Expand testing for Windows (NFC) Added the checks to the existing cases when the target is Win64. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r352886 | evandro | 2019-02-01 17:57:53 +0100 (Fri, 01 Feb 2019) | 1 line [InstCombine] Refactor test checks (NFC) ------------------------------------------------------------------------ ------------------------------------------------------------------------ r352892 | evandro | 2019-02-01 18:39:48 +0100 (Fri, 01 Feb 2019) | 3 lines [InstCombine] Expand Windows test (NFC) Add checks for Win64 to existing cases. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r352895 | evandro | 2019-02-01 19:34:20 +0100 (Fri, 01 Feb 2019) | 1 line [InstCombine] Refactor test checks (NFC) ------------------------------------------------------------------------ ------------------------------------------------------------------------ r352908 | evandro | 2019-02-01 21:42:03 +0100 (Fri, 01 Feb 2019) | 3 lines [InstCombine] Expand Windows test (NFC) Run checks for Win64 as well. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r352917 | evandro | 2019-02-01 22:14:10 +0100 (Fri, 01 Feb 2019) | 3 lines [InstCombine] Expand Windows test (NFC) Run checks for Win32 as well. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r352935 | evandro | 2019-02-01 23:52:05 +0100 (Fri, 01 Feb 2019) | 1 line [InstCombine] Refactor test checks (NFC) ------------------------------------------------------------------------ ------------------------------------------------------------------------ r353213 | evandro | 2019-02-05 21:24:21 +0100 (Tue, 05 Feb 2019) | 3 lines [TargetLibraryInfo] Regroup run time functions for Windows (NFC) Regroup supported and unsupported functions by precision and C standard. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r353733 | evandro | 2019-02-11 20:02:28 +0100 (Mon, 11 Feb 2019) | 8 lines [TargetLibraryInfo] Update run time support for Windows It seems that the run time for Windows has changed and supports more math functions than it used to, especially on AArch64, ARM, and AMD64. Fixes PR40541. Differential revision: https://reviews.llvm.org/D57625 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r353758 | evandro | 2019-02-11 23:12:01 +0100 (Mon, 11 Feb 2019) | 6 lines [TargetLibraryInfo] Update run time support for Windows It seems that, since VC19, the `float` C99 math functions are supported for all targets, unlike the C89 ones. According to the discussion at https://reviews.llvm.org/D57625. ------------------------------------------------------------------------ llvm-svn: 353934 --- llvm/lib/Analysis/TargetLibraryInfo.cpp | 168 ++++--- .../InstCombine/double-float-shrink-1.ll | 128 +++-- .../InstCombine/double-float-shrink-2.ll | 446 ++++++++---------- llvm/test/Transforms/InstCombine/pow-1.ll | 306 +++++++----- llvm/test/Transforms/InstCombine/win-math.ll | 261 +++++----- 5 files changed, 724 insertions(+), 585 deletions(-) diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 4643f75da42d14..ae86ee3d365000 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -161,25 +161,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, } if (T.isOSWindows() && !T.isOSCygMing()) { - // Win32 does not support long double + // XXX: The earliest documentation available at the moment is for VS2015/VC19: + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support?view=vs-2015 + // XXX: In order to use an MSVCRT older than VC19, + // the specific library version must be explicit in the target triple, + // e.g., x86_64-pc-windows-msvc18. + bool hasPartialC99 = true; + if (T.isKnownWindowsMSVCEnvironment()) { + unsigned Major, Minor, Micro; + T.getEnvironmentVersion(Major, Minor, Micro); + hasPartialC99 = (Major == 0 || Major >= 19); + } + + // Latest targets support C89 math functions, in part. + bool isARM = (T.getArch() == Triple::aarch64 || + T.getArch() == Triple::arm); + bool hasPartialFloat = (isARM || + T.getArch() == Triple::x86_64); + + // Win32 does not support float C89 math functions, in general. + if (!hasPartialFloat) { + TLI.setUnavailable(LibFunc_acosf); + TLI.setUnavailable(LibFunc_asinf); + TLI.setUnavailable(LibFunc_atan2f); + TLI.setUnavailable(LibFunc_atanf); + TLI.setUnavailable(LibFunc_ceilf); + TLI.setUnavailable(LibFunc_cosf); + TLI.setUnavailable(LibFunc_coshf); + TLI.setUnavailable(LibFunc_expf); + TLI.setUnavailable(LibFunc_floorf); + TLI.setUnavailable(LibFunc_fmodf); + TLI.setUnavailable(LibFunc_log10f); + TLI.setUnavailable(LibFunc_logf); + TLI.setUnavailable(LibFunc_modff); + TLI.setUnavailable(LibFunc_powf); + TLI.setUnavailable(LibFunc_sinf); + TLI.setUnavailable(LibFunc_sinhf); + TLI.setUnavailable(LibFunc_sqrtf); + TLI.setUnavailable(LibFunc_tanf); + TLI.setUnavailable(LibFunc_tanhf); + } + if (!isARM) + TLI.setUnavailable(LibFunc_fabsf); + TLI.setUnavailable(LibFunc_frexpf); + TLI.setUnavailable(LibFunc_ldexpf); + + // Win32 does not support long double C89 math functions. TLI.setUnavailable(LibFunc_acosl); TLI.setUnavailable(LibFunc_asinl); - TLI.setUnavailable(LibFunc_atanl); TLI.setUnavailable(LibFunc_atan2l); + TLI.setUnavailable(LibFunc_atanl); TLI.setUnavailable(LibFunc_ceill); - TLI.setUnavailable(LibFunc_copysignl); TLI.setUnavailable(LibFunc_cosl); TLI.setUnavailable(LibFunc_coshl); TLI.setUnavailable(LibFunc_expl); - TLI.setUnavailable(LibFunc_fabsf); // Win32 and Win64 both lack fabsf TLI.setUnavailable(LibFunc_fabsl); TLI.setUnavailable(LibFunc_floorl); - TLI.setUnavailable(LibFunc_fmaxl); - TLI.setUnavailable(LibFunc_fminl); TLI.setUnavailable(LibFunc_fmodl); TLI.setUnavailable(LibFunc_frexpl); - TLI.setUnavailable(LibFunc_ldexpf); TLI.setUnavailable(LibFunc_ldexpl); + TLI.setUnavailable(LibFunc_log10l); TLI.setUnavailable(LibFunc_logl); TLI.setUnavailable(LibFunc_modfl); TLI.setUnavailable(LibFunc_powl); @@ -189,81 +230,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_tanl); TLI.setUnavailable(LibFunc_tanhl); - // Win32 only has C89 math - TLI.setUnavailable(LibFunc_acosh); - TLI.setUnavailable(LibFunc_acoshf); + // Win32 does not fully support C99 math functions. + if (!hasPartialC99) { + TLI.setUnavailable(LibFunc_acosh); + TLI.setUnavailable(LibFunc_acoshf); + TLI.setUnavailable(LibFunc_asinh); + TLI.setUnavailable(LibFunc_asinhf); + TLI.setUnavailable(LibFunc_atanh); + TLI.setUnavailable(LibFunc_atanhf); + TLI.setAvailableWithName(LibFunc_cabs, "_cabs"); + TLI.setUnavailable(LibFunc_cabsf); + TLI.setUnavailable(LibFunc_cbrt); + TLI.setUnavailable(LibFunc_cbrtf); + TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); + TLI.setAvailableWithName(LibFunc_copysignf, "_copysignf"); + TLI.setUnavailable(LibFunc_exp2); + TLI.setUnavailable(LibFunc_exp2f); + TLI.setUnavailable(LibFunc_expm1); + TLI.setUnavailable(LibFunc_expm1f); + TLI.setUnavailable(LibFunc_fmax); + TLI.setUnavailable(LibFunc_fmaxf); + TLI.setUnavailable(LibFunc_fmin); + TLI.setUnavailable(LibFunc_fminf); + TLI.setUnavailable(LibFunc_log1p); + TLI.setUnavailable(LibFunc_log1pf); + TLI.setUnavailable(LibFunc_log2); + TLI.setUnavailable(LibFunc_log2f); + TLI.setAvailableWithName(LibFunc_logb, "_logb"); + if (hasPartialFloat) + TLI.setAvailableWithName(LibFunc_logbf, "_logbf"); + else + TLI.setUnavailable(LibFunc_logbf); + TLI.setUnavailable(LibFunc_rint); + TLI.setUnavailable(LibFunc_rintf); + TLI.setUnavailable(LibFunc_round); + TLI.setUnavailable(LibFunc_roundf); + TLI.setUnavailable(LibFunc_trunc); + TLI.setUnavailable(LibFunc_truncf); + } + + // Win32 does not support long double C99 math functions. TLI.setUnavailable(LibFunc_acoshl); - TLI.setUnavailable(LibFunc_asinh); - TLI.setUnavailable(LibFunc_asinhf); TLI.setUnavailable(LibFunc_asinhl); - TLI.setUnavailable(LibFunc_atanh); - TLI.setUnavailable(LibFunc_atanhf); TLI.setUnavailable(LibFunc_atanhl); - TLI.setUnavailable(LibFunc_cabs); - TLI.setUnavailable(LibFunc_cabsf); TLI.setUnavailable(LibFunc_cabsl); - TLI.setUnavailable(LibFunc_cbrt); - TLI.setUnavailable(LibFunc_cbrtf); TLI.setUnavailable(LibFunc_cbrtl); - TLI.setUnavailable(LibFunc_exp2); - TLI.setUnavailable(LibFunc_exp2f); + TLI.setUnavailable(LibFunc_copysignl); TLI.setUnavailable(LibFunc_exp2l); - TLI.setUnavailable(LibFunc_expm1); - TLI.setUnavailable(LibFunc_expm1f); TLI.setUnavailable(LibFunc_expm1l); - TLI.setUnavailable(LibFunc_log2); - TLI.setUnavailable(LibFunc_log2f); - TLI.setUnavailable(LibFunc_log2l); - TLI.setUnavailable(LibFunc_log1p); - TLI.setUnavailable(LibFunc_log1pf); + TLI.setUnavailable(LibFunc_fmaxl); + TLI.setUnavailable(LibFunc_fminl); TLI.setUnavailable(LibFunc_log1pl); - TLI.setUnavailable(LibFunc_logb); - TLI.setUnavailable(LibFunc_logbf); + TLI.setUnavailable(LibFunc_log2l); TLI.setUnavailable(LibFunc_logbl); - TLI.setUnavailable(LibFunc_nearbyint); - TLI.setUnavailable(LibFunc_nearbyintf); TLI.setUnavailable(LibFunc_nearbyintl); - TLI.setUnavailable(LibFunc_rint); - TLI.setUnavailable(LibFunc_rintf); TLI.setUnavailable(LibFunc_rintl); - TLI.setUnavailable(LibFunc_round); - TLI.setUnavailable(LibFunc_roundf); TLI.setUnavailable(LibFunc_roundl); - TLI.setUnavailable(LibFunc_trunc); - TLI.setUnavailable(LibFunc_truncf); TLI.setUnavailable(LibFunc_truncl); - // Win32 provides some C99 math with mangled names - TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); - - if (T.getArch() == Triple::x86) { - // Win32 on x86 implements single-precision math functions as macros - TLI.setUnavailable(LibFunc_acosf); - TLI.setUnavailable(LibFunc_asinf); - TLI.setUnavailable(LibFunc_atanf); - TLI.setUnavailable(LibFunc_atan2f); - TLI.setUnavailable(LibFunc_ceilf); - TLI.setUnavailable(LibFunc_copysignf); - TLI.setUnavailable(LibFunc_cosf); - TLI.setUnavailable(LibFunc_coshf); - TLI.setUnavailable(LibFunc_expf); - TLI.setUnavailable(LibFunc_floorf); - TLI.setUnavailable(LibFunc_fminf); - TLI.setUnavailable(LibFunc_fmaxf); - TLI.setUnavailable(LibFunc_fmodf); - TLI.setUnavailable(LibFunc_logf); - TLI.setUnavailable(LibFunc_log10f); - TLI.setUnavailable(LibFunc_modff); - TLI.setUnavailable(LibFunc_powf); - TLI.setUnavailable(LibFunc_sinf); - TLI.setUnavailable(LibFunc_sinhf); - TLI.setUnavailable(LibFunc_sqrtf); - TLI.setUnavailable(LibFunc_tanf); - TLI.setUnavailable(LibFunc_tanhf); - } - - // Win32 does *not* provide these functions, but they are - // generally available on POSIX-compliant systems: + // Win32 does not support these functions, but + // they are generally available on POSIX-compliant systems. TLI.setUnavailable(LibFunc_access); TLI.setUnavailable(LibFunc_bcmp); TLI.setUnavailable(LibFunc_bcopy); @@ -318,12 +344,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_utime); TLI.setUnavailable(LibFunc_utimes); TLI.setUnavailable(LibFunc_write); - - // Win32 does *not* provide provide these functions, but they are - // specified by C99: - TLI.setUnavailable(LibFunc_atoll); - TLI.setUnavailable(LibFunc_frexpf); - TLI.setUnavailable(LibFunc_llabs); } switch (T.getOS()) { diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll index c170f2ca74ba6b..e8f7f720b15273 100644 --- a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll +++ b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll @@ -1,8 +1,8 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -instcombine -S | FileCheck %s - -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" +; RUN: opt < %s -instcombine -S -mtriple x86_64-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK,LINUX,ISC99 +; RUN: opt < %s -instcombine -S -mtriple x86_64-pc-win32 | FileCheck %s --check-prefixes=CHECK,ISC99 +; RUN: opt < %s -instcombine -S -mtriple x86_64-pc-windows-msvc16 | FileCheck %s --check-prefixes=CHECK,MS64,ISC89 +; RUN: opt < %s -instcombine -S -mtriple i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,ISC99 +; RUN: opt < %s -instcombine -S -mtriple i686-pc-windows-msvc17 | FileCheck %s --check-prefixes=CHECK,MS32,ISC89 ; Check for and against shrinkage when using the ; unsafe-fp-math function attribute on a math lib @@ -12,8 +12,10 @@ target triple = "x86_64-unknown-linux-gnu" define float @acos_test1(float %f) { ; CHECK-LABEL: @acos_test1( -; CHECK-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ACOSF]] +; LINUX-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ACOSF]] +; MS32: [[ACOSF:%.*]] = call fast double @acos(double [[F:%.*]]) +; MS64-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @acos(double %conv) @@ -34,8 +36,9 @@ define double @acos_test2(float %f) { define float @acosh_test1(float %f) { ; CHECK-LABEL: @acosh_test1( -; CHECK-NEXT: [[ACOSHF:%.*]] = call fast float @acoshf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ACOSHF]] +; ISC99-NEXT: [[ACOSHF:%.*]] = call fast float @acoshf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ACOSHF]] +; ISC89: [[ACOSHF:%.*]] = call fast double @acosh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @acosh(double %conv) @@ -56,8 +59,10 @@ define double @acosh_test2(float %f) { define float @asin_test1(float %f) { ; CHECK-LABEL: @asin_test1( -; CHECK-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ASINF]] +; LINUX-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ASINF]] +; MS32: [[ASINF:%.*]] = call fast double @asin(double [[F:%.*]]) +; MS64-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @asin(double %conv) @@ -78,8 +83,9 @@ define double @asin_test2(float %f) { define float @asinh_test1(float %f) { ; CHECK-LABEL: @asinh_test1( -; CHECK-NEXT: [[ASINHF:%.*]] = call fast float @asinhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ASINHF]] +; ISC99-NEXT: [[ASINHF:%.*]] = call fast float @asinhf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ASINHF]] +; ISC89: [[ASINHF:%.*]] = call fast double @asinh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @asinh(double %conv) @@ -100,8 +106,10 @@ define double @asinh_test2(float %f) { define float @atan_test1(float %f) { ; CHECK-LABEL: @atan_test1( -; CHECK-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ATANF]] +; LINUX-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ATANF]] +; MS32: [[ATANF:%.*]] = call fast double @atan(double [[F:%.*]]) +; MS64-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @atan(double %conv) @@ -122,8 +130,9 @@ define double @atan_test2(float %f) { define float @atanh_test1(float %f) { ; CHECK-LABEL: @atanh_test1( -; CHECK-NEXT: [[ATANHF:%.*]] = call fast float @atanhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ATANHF]] +; ISC99-NEXT: [[ATANHF:%.*]] = call fast float @atanhf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ATANHF]] +; ISC89: [[ATANHF:%.*]] = call fast double @atanh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @atanh(double %conv) @@ -144,8 +153,9 @@ define double @atanh_test2(float %f) { define float @cbrt_test1(float %f) { ; CHECK-LABEL: @cbrt_test1( -; CHECK-NEXT: [[CBRTF:%.*]] = call fast float @cbrtf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[CBRTF]] +; ISC99-NEXT: [[CBRTF:%.*]] = call fast float @cbrtf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[CBRTF]] +; ISC89: [[CBRTF:%.*]] = call fast double @cbrt(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @cbrt(double %conv) @@ -166,8 +176,10 @@ define double @cbrt_test2(float %f) { define float @exp_test1(float %f) { ; CHECK-LABEL: @exp_test1( -; CHECK-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[EXPF]] +; LINUX-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[EXPF]] +; MS32: [[EXPF:%.*]] = call fast double @exp(double [[F:%.*]]) +; MS64-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @exp(double %conv) @@ -188,8 +200,9 @@ define double @exp_test2(float %f) { define float @expm1_test1(float %f) { ; CHECK-LABEL: @expm1_test1( -; CHECK-NEXT: [[EXPM1F:%.*]] = call fast float @expm1f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[EXPM1F]] +; ISC99-NEXT: [[EXPM1F:%.*]] = call fast float @expm1f(float [[F:%.*]]) +; ISC99-NEXT: ret float [[EXPM1F]] +; ISC89: [[EXPM1F:%.*]] = call fast double @expm1(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @expm1(double %conv) @@ -236,8 +249,10 @@ define double @exp10_test2(float %f) { define float @log_test1(float %f) { ; CHECK-LABEL: @log_test1( -; CHECK-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOGF]] +; LINUX-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOGF]] +; MS32: [[LOGF:%.*]] = call fast double @log(double [[F:%.*]]) +; MS64-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log(double %conv) @@ -258,8 +273,10 @@ define double @log_test2(float %f) { define float @log10_test1(float %f) { ; CHECK-LABEL: @log10_test1( -; CHECK-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG10F]] +; LINUX-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOG10F]] +; MS32: [[LOG10F:%.*]] = call fast double @log10(double [[F:%.*]]) +; MS64-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log10(double %conv) @@ -280,8 +297,9 @@ define double @log10_test2(float %f) { define float @log1p_test1(float %f) { ; CHECK-LABEL: @log1p_test1( -; CHECK-NEXT: [[LOG1PF:%.*]] = call fast float @log1pf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG1PF]] +; ISC99-NEXT: [[LOG1PF:%.*]] = call fast float @log1pf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[LOG1PF]] +; ISC89: [[LOG1PF:%.*]] = call fast double @log1p(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log1p(double %conv) @@ -302,8 +320,9 @@ define double @log1p_test2(float %f) { define float @log2_test1(float %f) { ; CHECK-LABEL: @log2_test1( -; CHECK-NEXT: [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG2F]] +; ISC99-NEXT: [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]]) +; ISC99-NEXT: ret float [[LOG2F]] +; ISC89: [[LOG2F:%.*]] = call fast double @log2(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log2(double %conv) @@ -324,8 +343,10 @@ define double @log2_test2(float %f) { define float @logb_test1(float %f) { ; CHECK-LABEL: @logb_test1( -; CHECK-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOGBF]] +; LINUX-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOGBF]] +; MS32: [[POWF:%.*]] = call fast double @logb(double [[F:%.*]]) +; MS64-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @logb(double %conv) @@ -346,8 +367,10 @@ define double @logb_test2(float %f) { define float @pow_test1(float %f, float %g) { ; CHECK-LABEL: @pow_test1( -; CHECK-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) -; CHECK-NEXT: ret float [[POWF]] +; LINUX-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) +; LINUX-NEXT: ret float [[POWF]] +; MS32: [[POWF:%.*]] = call fast double @pow(double %df, double %dg) +; MS64-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) ; %df = fpext float %f to double %dg = fpext float %g to double @@ -369,8 +392,10 @@ define double @pow_test2(float %f, float %g) { define float @sin_test1(float %f) { ; CHECK-LABEL: @sin_test1( -; CHECK-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[SINF]] +; LINUX-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[SINF]] +; MS32: [[SINF:%.*]] = call fast double @sin(double [[F:%.*]]) +; MS64-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @sin(double %conv) @@ -391,8 +416,10 @@ define double @sin_test2(float %f) { define float @sqrt_test1(float %f) { ; CHECK-LABEL: @sqrt_test1( -; CHECK-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[SQRTF]] +; LINUX-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[SQRTF]] +; MS32: [[SQRTF:%.*]] = call double @sqrt(double [[F:%.*]]) +; MS64-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call double @sqrt(double %conv) @@ -413,8 +440,10 @@ define double @sqrt_test2(float %f) { define float @sqrt_int_test1(float %f) { ; CHECK-LABEL: @sqrt_int_test1( -; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TMP1]] +; LINUX-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TMP1]] +; MS32: [[TMP1:%.*]] = call double @llvm.sqrt.f64(double [[F:%.*]]) +; MS64-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call double @llvm.sqrt.f64(double %conv) @@ -435,8 +464,10 @@ define double @sqrt_int_test2(float %f) { define float @tan_test1(float %f) { ; CHECK-LABEL: @tan_test1( -; CHECK-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TANF]] +; LINUX-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TANF]] +; MS32: [[TANF:%.*]] = call fast double @tan(double [[F:%.*]]) +; MS64-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @tan(double %conv) @@ -456,8 +487,10 @@ define double @tan_test2(float %f) { } define float @tanh_test1(float %f) { ; CHECK-LABEL: @tanh_test1( -; CHECK-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TANHF]] +; LINUX-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TANHF]] +; MS32: [[TANHF:%.*]] = call fast double @tanh(double [[F:%.*]]) +; MS64-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @tanh(double %conv) @@ -480,8 +513,9 @@ define double @tanh_test2(float %f) { ; flags are propagated for shrunken *binary* double FP calls. define float @max1(float %a, float %b) { ; CHECK-LABEL: @max1( -; CHECK-NEXT: [[FMAXF:%.*]] = call arcp float @fmaxf(float [[A:%.*]], float [[B:%.*]]) -; CHECK-NEXT: ret float [[FMAXF]] +; ISC99-NEXT: [[FMAXF:%.*]] = call arcp float @fmaxf(float [[A:%.*]], float [[B:%.*]]) +; ISC99-NEXT: ret float [[FMAXF]] +; ISC89: [[FMAXF:%.*]] = call arcp double @fmax(double [[A:%.*]], double [[B:%.*]]) ; %c = fpext float %a to double %d = fpext float %b to double diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll index 5bdeaf7d9d7e0f..76e497bd68fc79 100644 --- a/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll +++ b/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll @@ -1,11 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-linux" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-win32" | FileCheck -check-prefix=ALL -check-prefix=DONT-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" | FileCheck -check-prefix=ALL -check-prefix=C89-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-mingw32" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-mingw32" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "sparc-sun-solaris" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -enable-debugify -instcombine -S -mtriple "x86_64-pc-win32" 2>&1 | FileCheck -check-prefix=DBG-VALID %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-linux" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-win32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-mingw32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-mingw32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "sparc-sun-solaris" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" -enable-debugify 2>&1 | FileCheck --check-prefix=DBG-VALID %s declare double @floor(double) declare double @ceil(double) @@ -36,9 +36,9 @@ declare double @llvm.trunc.f64(double) declare <2 x double> @llvm.trunc.v2f64(<2 x double>) define float @test_shrink_libcall_floor(float %C) { -; ALL-LABEL: @test_shrink_libcall_floor( -; ALL-NEXT: [[F:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_floor( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> floorf @@ -48,9 +48,9 @@ define float @test_shrink_libcall_floor(float %C) { } define float @test_shrink_libcall_ceil(float %C) { -; ALL-LABEL: @test_shrink_libcall_ceil( -; ALL-NEXT: [[F:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_ceil( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> ceilf @@ -60,21 +60,9 @@ define float @test_shrink_libcall_ceil(float %C) { } define float @test_shrink_libcall_round(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @round(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @round(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_round( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> roundf @@ -84,21 +72,9 @@ define float @test_shrink_libcall_round(float %C) { } define float @test_shrink_libcall_nearbyint(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @nearbyint(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @nearbyint(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_nearbyint( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> nearbyintf @@ -108,21 +84,9 @@ define float @test_shrink_libcall_nearbyint(float %C) { } define float @test_shrink_libcall_trunc(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @trunc(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @trunc(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_trunc( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> truncf @@ -132,11 +96,11 @@ define float @test_shrink_libcall_trunc(float %C) { } ; This is replaced with the intrinsic, which does the right thing on -; all platforms. +; CHECK platforms. define float @test_shrink_libcall_fabs(float %C) { -; ALL-LABEL: @test_shrink_libcall_fabs( -; ALL-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_fabs( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double %E = call double @fabs(double %D) @@ -146,9 +110,9 @@ define float @test_shrink_libcall_fabs(float %C) { ; Make sure fast math flags are preserved define float @test_shrink_libcall_fabs_fast(float %C) { -; ALL-LABEL: @test_shrink_libcall_fabs_fast( -; ALL-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_fabs_fast( +; CHECK-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double %E = call fast double @fabs(double %D) @@ -157,9 +121,9 @@ define float @test_shrink_libcall_fabs_fast(float %C) { } define float @test_shrink_intrin_ceil(float %C) { -; ALL-LABEL: @test_shrink_intrin_ceil( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_ceil( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.ceil.f64(double %D) @@ -168,9 +132,9 @@ define float @test_shrink_intrin_ceil(float %C) { } define float @test_shrink_intrin_fabs(float %C) { -; ALL-LABEL: @test_shrink_intrin_fabs( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.fabs.f64(double %D) @@ -179,9 +143,9 @@ define float @test_shrink_intrin_fabs(float %C) { } define float @test_shrink_intrin_floor(float %C) { -; ALL-LABEL: @test_shrink_intrin_floor( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_floor( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.floor.f64(double %D) @@ -190,9 +154,9 @@ define float @test_shrink_intrin_floor(float %C) { } define float @test_shrink_intrin_nearbyint(float %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.nearbyint.f64(double %D) @@ -201,9 +165,9 @@ define float @test_shrink_intrin_nearbyint(float %C) { } define half @test_shrink_intrin_rint(half %C) { -; ALL-LABEL: @test_shrink_intrin_rint( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.rint.f16(half [[C:%.*]]) -; ALL-NEXT: ret half [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_rint( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.rint.f16(half [[C:%.*]]) +; CHECK-NEXT: ret half [[TMP1]] ; %D = fpext half %C to float %E = call float @llvm.rint.f32(float %D) @@ -212,9 +176,9 @@ define half @test_shrink_intrin_rint(half %C) { } define float @test_shrink_intrin_round(float %C) { -; ALL-LABEL: @test_shrink_intrin_round( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_round( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.round.f64(double %D) @@ -223,9 +187,9 @@ define float @test_shrink_intrin_round(float %C) { } define float @test_shrink_intrin_trunc(float %C) { -; ALL-LABEL: @test_shrink_intrin_trunc( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_trunc( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.trunc.f64(double %D) @@ -237,12 +201,12 @@ declare void @use_v2f64(<2 x double>) declare void @use_v2f32(<2 x float>) define <2 x float> @test_shrink_intrin_ceil_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_ceil_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_ceil_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.ceil.v2f64(<2 x double> %D) @@ -252,11 +216,11 @@ define <2 x float> @test_shrink_intrin_ceil_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_fabs_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_multi_use( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs_multi_use( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[TMP1]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.fabs.v2f64(<2 x double> %D) @@ -266,13 +230,13 @@ define <2 x float> @test_shrink_intrin_fabs_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_floor_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_floor_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_floor_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.floor.v2f64(<2 x double> %D) @@ -283,12 +247,12 @@ define <2 x float> @test_shrink_intrin_floor_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_nearbyint_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %D) @@ -298,11 +262,11 @@ define <2 x float> @test_shrink_intrin_nearbyint_multi_use(<2 x float> %C) { } define <2 x half> @test_shrink_intrin_rint_multi_use(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_rint_multi_use( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.rint.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x float> -; ALL-NEXT: call void @use_v2f32(<2 x float> [[E]]) -; ALL-NEXT: ret <2 x half> [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_rint_multi_use( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.rint.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x float> +; CHECK-NEXT: call void @use_v2f32(<2 x float> [[E]]) +; CHECK-NEXT: ret <2 x half> [[TMP1]] ; %D = fpext <2 x half> %C to <2 x float> %E = call <2 x float> @llvm.rint.v2f32(<2 x float> %D) @@ -312,13 +276,13 @@ define <2 x half> @test_shrink_intrin_rint_multi_use(<2 x half> %C) { } define <2 x float> @test_shrink_intrin_round_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_round_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_round_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.round.v2f64(<2 x double> %D) @@ -329,12 +293,12 @@ define <2 x float> @test_shrink_intrin_round_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_trunc_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_trunc_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_trunc_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.trunc.v2f64(<2 x double> %D) @@ -345,9 +309,9 @@ define <2 x float> @test_shrink_intrin_trunc_multi_use(<2 x float> %C) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast(float %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast( -; ALL-NEXT: [[TMP1:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast( +; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call fast double @llvm.fabs.f64(double %D) @@ -356,10 +320,10 @@ define float @test_shrink_intrin_fabs_fast(float %C) { } define float @test_no_shrink_intrin_floor(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_floor( -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_floor( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.floor.f64(double %D) %F = fptrunc double %E to float @@ -367,10 +331,10 @@ define float @test_no_shrink_intrin_floor(double %D) { } define float @test_no_shrink_intrin_ceil(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_ceil( -; ALL-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_ceil( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.ceil.f64(double %D) %F = fptrunc double %E to float @@ -378,10 +342,10 @@ define float @test_no_shrink_intrin_ceil(double %D) { } define float @test_no_shrink_intrin_round(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_round( -; ALL-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_round( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.round.f64(double %D) %F = fptrunc double %E to float @@ -389,10 +353,10 @@ define float @test_no_shrink_intrin_round(double %D) { } define float @test_no_shrink_intrin_nearbyint(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_nearbyint( -; ALL-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_nearbyint( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.nearbyint.f64(double %D) %F = fptrunc double %E to float @@ -400,10 +364,10 @@ define float @test_no_shrink_intrin_nearbyint(double %D) { } define float @test_no_shrink_intrin_trunc(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_trunc( -; ALL-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_trunc( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.trunc.f64(double %D) %F = fptrunc double %E to float @@ -411,10 +375,10 @@ define float @test_no_shrink_intrin_trunc(double %D) { } define float @test_shrink_intrin_fabs_double_src(double %D) { -; ALL-LABEL: @test_shrink_intrin_fabs_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float -; ALL-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float +; CHECK-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.fabs.f64(double %D) %F = fptrunc double %E to float @@ -423,10 +387,10 @@ define float @test_shrink_intrin_fabs_double_src(double %D) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast_double_src(double %D) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float -; ALL-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[TMP1]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float +; CHECK-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[TMP1]]) +; CHECK-NEXT: ret float [[F]] ; %E = call fast double @llvm.fabs.f64(double %D) %F = fptrunc double %E to float @@ -434,8 +398,8 @@ define float @test_shrink_intrin_fabs_fast_double_src(double %D) { } define float @test_shrink_float_convertible_constant_intrin_floor() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_floor( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_floor( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.floor.f64(double 2.1) %F = fptrunc double %E to float @@ -443,8 +407,8 @@ define float @test_shrink_float_convertible_constant_intrin_floor() { } define float @test_shrink_float_convertible_constant_intrin_ceil() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_ceil( -; ALL-NEXT: ret float 3.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_ceil( +; CHECK-NEXT: ret float 3.000000e+00 ; %E = call double @llvm.ceil.f64(double 2.1) %F = fptrunc double %E to float @@ -452,8 +416,8 @@ define float @test_shrink_float_convertible_constant_intrin_ceil() { } define float @test_shrink_float_convertible_constant_intrin_round() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_round( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_round( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.round.f64(double 2.1) %F = fptrunc double %E to float @@ -461,8 +425,8 @@ define float @test_shrink_float_convertible_constant_intrin_round() { } define float @test_shrink_float_convertible_constant_intrin_nearbyint() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_nearbyint( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_nearbyint( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.nearbyint.f64(double 2.1) %F = fptrunc double %E to float @@ -470,8 +434,8 @@ define float @test_shrink_float_convertible_constant_intrin_nearbyint() { } define float @test_shrink_float_convertible_constant_intrin_trunc() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_trunc( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_trunc( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.trunc.f64(double 2.1) %F = fptrunc double %E to float @@ -479,8 +443,8 @@ define float @test_shrink_float_convertible_constant_intrin_trunc() { } define float @test_shrink_float_convertible_constant_intrin_fabs() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_fabs( -; ALL-NEXT: ret float 0x4000CCCCC0000000 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_fabs( +; CHECK-NEXT: ret float 0x4000CCCCC0000000 ; %E = call double @llvm.fabs.f64(double 2.1) %F = fptrunc double %E to float @@ -489,8 +453,8 @@ define float @test_shrink_float_convertible_constant_intrin_fabs() { ; Make sure fast math flags are preserved define float @test_shrink_float_convertible_constant_intrin_fabs_fast() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_fabs_fast( -; ALL-NEXT: ret float 0x4000CCCCC0000000 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_fabs_fast( +; CHECK-NEXT: ret float 0x4000CCCCC0000000 ; %E = call fast double @llvm.fabs.f64(double 2.1) %F = fptrunc double %E to float @@ -498,10 +462,10 @@ define float @test_shrink_float_convertible_constant_intrin_fabs_fast() { } define half @test_no_shrink_mismatched_type_intrin_floor(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_floor( -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_floor( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.floor.f64(double %D) %F = fptrunc double %E to half @@ -509,10 +473,10 @@ define half @test_no_shrink_mismatched_type_intrin_floor(double %D) { } define half @test_no_shrink_mismatched_type_intrin_ceil(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_ceil( -; ALL-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_ceil( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.ceil.f64(double %D) %F = fptrunc double %E to half @@ -520,10 +484,10 @@ define half @test_no_shrink_mismatched_type_intrin_ceil(double %D) { } define half @test_no_shrink_mismatched_type_intrin_round(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_round( -; ALL-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_round( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.round.f64(double %D) %F = fptrunc double %E to half @@ -531,10 +495,10 @@ define half @test_no_shrink_mismatched_type_intrin_round(double %D) { } define half @test_no_shrink_mismatched_type_intrin_nearbyint(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_nearbyint( -; ALL-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_nearbyint( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.nearbyint.f64(double %D) %F = fptrunc double %E to half @@ -542,10 +506,10 @@ define half @test_no_shrink_mismatched_type_intrin_nearbyint(double %D) { } define half @test_no_shrink_mismatched_type_intrin_trunc(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_trunc( -; ALL-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_trunc( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.trunc.f64(double %D) %F = fptrunc double %E to half @@ -553,10 +517,10 @@ define half @test_no_shrink_mismatched_type_intrin_trunc(double %D) { } define half @test_shrink_mismatched_type_intrin_fabs_double_src(double %D) { -; ALL-LABEL: @test_shrink_mismatched_type_intrin_fabs_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half -; ALL-NEXT: [[F:%.*]] = call half @llvm.fabs.f16(half [[TMP1]]) -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_shrink_mismatched_type_intrin_fabs_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half +; CHECK-NEXT: [[F:%.*]] = call half @llvm.fabs.f16(half [[TMP1]]) +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.fabs.f64(double %D) %F = fptrunc double %E to half @@ -565,10 +529,10 @@ define half @test_shrink_mismatched_type_intrin_fabs_double_src(double %D) { ; Make sure fast math flags are preserved define half @test_mismatched_type_intrin_fabs_fast_double_src(double %D) { -; ALL-LABEL: @test_mismatched_type_intrin_fabs_fast_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half -; ALL-NEXT: [[F:%.*]] = call fast half @llvm.fabs.f16(half [[TMP1]]) -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_mismatched_type_intrin_fabs_fast_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half +; CHECK-NEXT: [[F:%.*]] = call fast half @llvm.fabs.f16(half [[TMP1]]) +; CHECK-NEXT: ret half [[F]] ; %E = call fast double @llvm.fabs.f64(double %D) %F = fptrunc double %E to half @@ -576,10 +540,10 @@ define half @test_mismatched_type_intrin_fabs_fast_double_src(double %D) { } define <2 x double> @test_shrink_intrin_floor_fp16_vec(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_floor_fp16_vec( -; ALL-NEXT: [[TMP1:%.*]] = call arcp <2 x half> @llvm.floor.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_floor_fp16_vec( +; CHECK-NEXT: [[TMP1:%.*]] = call arcp <2 x half> @llvm.floor.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call arcp <2 x double> @llvm.floor.v2f64(<2 x double> %D) @@ -587,10 +551,10 @@ define <2 x double> @test_shrink_intrin_floor_fp16_vec(<2 x half> %C) { } define float @test_shrink_intrin_ceil_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_ceil_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.ceil.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_ceil_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.ceil.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.ceil.f64(double %D) @@ -599,10 +563,10 @@ define float @test_shrink_intrin_ceil_fp16_src(half %C) { } define <2 x double> @test_shrink_intrin_round_fp16_vec(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_round_fp16_vec( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.round.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_round_fp16_vec( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.round.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call <2 x double> @llvm.round.v2f64(<2 x double> %D) @@ -610,10 +574,10 @@ define <2 x double> @test_shrink_intrin_round_fp16_vec(<2 x half> %C) { } define float @test_shrink_intrin_nearbyint_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.nearbyint.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.nearbyint.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.nearbyint.f64(double %D) @@ -622,10 +586,10 @@ define float @test_shrink_intrin_nearbyint_fp16_src(half %C) { } define <2 x double> @test_shrink_intrin_trunc_fp16_src(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_trunc_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.trunc.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_trunc_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.trunc.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call <2 x double> @llvm.trunc.v2f64(<2 x double> %D) @@ -633,10 +597,10 @@ define <2 x double> @test_shrink_intrin_trunc_fp16_src(<2 x half> %C) { } define float @test_shrink_intrin_fabs_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.fabs.f64(double %D) @@ -646,10 +610,10 @@ define float @test_shrink_intrin_fabs_fp16_src(half %C) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call fast half @llvm.fabs.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call fast half @llvm.fabs.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call fast double @llvm.fabs.f64(double %D) @@ -658,12 +622,12 @@ define float @test_shrink_intrin_fabs_fast_fp16_src(half %C) { } define float @test_no_shrink_intrin_floor_multi_use_fpext(half %C) { -; ALL-LABEL: @test_no_shrink_intrin_floor_multi_use_fpext( -; ALL-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double -; ALL-NEXT: store volatile double [[D]], double* undef, align 8 -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_floor_multi_use_fpext( +; CHECK-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double +; CHECK-NEXT: store volatile double [[D]], double* undef, align 8 +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double store volatile double %D, double* undef @@ -673,12 +637,12 @@ define float @test_no_shrink_intrin_floor_multi_use_fpext(half %C) { } define float @test_no_shrink_intrin_fabs_multi_use_fpext(half %C) { -; ALL-LABEL: @test_no_shrink_intrin_fabs_multi_use_fpext( -; ALL-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double -; ALL-NEXT: store volatile double [[D]], double* undef, align 8 -; ALL-NEXT: [[E:%.*]] = call double @llvm.fabs.f64(double [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_fabs_multi_use_fpext( +; CHECK-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double +; CHECK-NEXT: store volatile double [[D]], double* undef, align 8 +; CHECK-NEXT: [[E:%.*]] = call double @llvm.fabs.f64(double [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double store volatile double %D, double* undef diff --git a/llvm/test/Transforms/InstCombine/pow-1.ll b/llvm/test/Transforms/InstCombine/pow-1.ll index 672ec70e71ec2a..957e2488b721b4 100644 --- a/llvm/test/Transforms/InstCombine/pow-1.ll +++ b/llvm/test/Transforms/InstCombine/pow-1.ll @@ -1,15 +1,18 @@ ; Test that the pow library call simplifier works correctly. ; -; RUN: opt -instcombine -S < %s | FileCheck %s --check-prefixes=ANY -; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios7.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.8 | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios6.0 | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-netbsd | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-tvos9.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-watchos2.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s | FileCheck %s --check-prefixes=CHECK,ANY +; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios7.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.8 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios6.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-netbsd | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-tvos9.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-watchos2.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 ; rdar://7251832 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK-WIN +; RUN: opt -instcombine -S < %s -mtriple=i386-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVC,VC32,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC,VC51,VC19,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVC,VC64,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC,VC83,VC19,CHECK-NO-EXP10 ; NOTE: The readonly attribute on the pow call should be preserved ; in the cases below where pow is transformed into another function call. @@ -23,32 +26,39 @@ declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) nounwind readon ; Check pow(1.0, x) -> 1.0. define float @test_simplify1(float %x) { -; ANY-LABEL: @test_simplify1( +; CHECK-LABEL: @test_simplify1( ; ANY-NEXT: ret float 1.000000e+00 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 1.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 1.000000e+00 ; %retval = call float @powf(float 1.0, float %x) ret float %retval } define <2 x float> @test_simplify1v(<2 x float> %x) { -; ANY-LABEL: @test_simplify1v( +; CHECK-LABEL: @test_simplify1v( ; ANY-NEXT: ret <2 x float> +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval } define double @test_simplify2(double %x) { -; ANY-LABEL: @test_simplify2( -; ANY-NEXT: ret double 1.000000e+00 +; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: ret double 1.000000e+00 ; %retval = call double @pow(double 1.0, double %x) ret double %retval } define <2 x double> @test_simplify2v(<2 x double> %x) { -; ANY-LABEL: @test_simplify2v( +; CHECK-LABEL: @test_simplify2v( ; ANY-NEXT: ret <2 x double> +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval @@ -57,104 +67,114 @@ define <2 x double> @test_simplify2v(<2 x double> %x) { ; Check pow(2.0 ** n, x) -> exp2(n * x). define float @test_simplify3(float %x) { -; ANY-LABEL: @test_simplify3( -; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) [[NUW_RO:#[0-9]+]] +; CHECK-LABEL: @test_simplify3( +; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) ; ANY-NEXT: ret float [[EXP2F]] -; -; CHECK-WIN-LABEL: @test_simplify3( -; CHECK-WIN-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) -; CHECK-WIN-NEXT: ret float [[POW]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC64-NEXT: ret float [[POW]] +; VC83-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) +; VC83-NEXT: ret float [[EXP2F]] ; %retval = call float @powf(float 2.0, float %x) ret float %retval } define double @test_simplify3n(double %x) { -; ANY-LABEL: @test_simplify3n( +; CHECK-LABEL: @test_simplify3n( ; ANY-NEXT: [[MUL:%.*]] = fmul double [[X:%.*]], -2.000000e+00 -; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) [[NUW_RO]] +; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) ; ANY-NEXT: ret double [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify3n( -; CHECK-WIN-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) -; CHECK-WIN-NEXT: ret double [[POW]] +; VC19-NEXT: [[MUL:%.*]] = fmul double [[X:%.*]], -2.000000e+00 +; VC19-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) +; VC19-NEXT: ret double [[EXP2]] +; VC32-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) +; VC32-NEXT: ret double [[POW]] +; VC64-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) +; VC64-NEXT: ret double [[POW]] ; %retval = call double @pow(double 0.25, double %x) ret double %retval } define <2 x float> @test_simplify3v(<2 x float> %x) { -; ANY-LABEL: @test_simplify3v( +; CHECK-LABEL: @test_simplify3v( ; ANY-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[X:%.*]]) ; ANY-NEXT: ret <2 x float> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify3v( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x float> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval } define <2 x double> @test_simplify3vn(<2 x double> %x) { -; ANY-LABEL: @test_simplify3vn( +; CHECK-LABEL: @test_simplify3vn( ; ANY-NEXT: [[MUL:%.*]] = fmul <2 x double> [[X:%.*]], ; ANY-NEXT: [[EXP2:%.*]] = call <2 x double> @llvm.exp2.v2f64(<2 x double> [[MUL]]) ; ANY-NEXT: ret <2 x double> [[EXP2]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval } define double @test_simplify4(double %x) { -; ANY-LABEL: @test_simplify4( -; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) [[NUW_RO]] +; CHECK-LABEL: @test_simplify4( +; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) ; ANY-NEXT: ret double [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4( -; CHECK-WIN-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) -; CHECK-WIN-NEXT: ret double [[POW]] +; VC19-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) +; VC19-NEXT: ret double [[EXP2]] +; VC32-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) +; VC32-NEXT: ret double [[POW]] +; VC64-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) +; VC64-NEXT: ret double [[POW]] ; %retval = call double @pow(double 2.0, double %x) ret double %retval } define float @test_simplify4n(float %x) { -; ANY-LABEL: @test_simplify4n( +; CHECK-LABEL: @test_simplify4n( ; ANY-NEXT: [[MUL:%.*]] = fmul float [[X:%.*]], 3.000000e+00 -; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) [[NUW_RO]] +; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) ; ANY-NEXT: ret float [[EXP2F]] -; -; CHECK-WIN-LABEL: @test_simplify4n( -; CHECK-WIN-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) -; CHECK-WIN-NEXT: ret float [[POW]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC64-NEXT: ret float [[POW]] +; VC83-NEXT: [[MUL:%.*]] = fmul float [[X:%.*]], 3.000000e+00 +; VC83-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) +; VC83-NEXT: ret float [[EXP2F]] ; %retval = call float @powf(float 8.0, float %x) ret float %retval } define <2 x double> @test_simplify4v(<2 x double> %x) { -; ANY-LABEL: @test_simplify4v( +; CHECK-LABEL: @test_simplify4v( ; ANY-NEXT: [[EXP2:%.*]] = call <2 x double> @llvm.exp2.v2f64(<2 x double> [[X:%.*]]) ; ANY-NEXT: ret <2 x double> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4v( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x double> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval } define <2 x float> @test_simplify4vn(<2 x float> %x) { -; ANY-LABEL: @test_simplify4vn( +; CHECK-LABEL: @test_simplify4vn( ; ANY-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[X:%.*]] ; ANY-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUL]]) ; ANY-NEXT: ret <2 x float> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4vn( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x float> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval @@ -163,32 +183,42 @@ define <2 x float> @test_simplify4vn(<2 x float> %x) { ; Check pow(x, 0.0) -> 1.0. define float @test_simplify5(float %x) { -; ANY-LABEL: @test_simplify5( +; CHECK-LABEL: @test_simplify5( ; ANY-NEXT: ret float 1.000000e+00 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 0.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 0.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 1.000000e+00 +; VC83-NEXT: ret float 1.000000e+00 ; %retval = call float @powf(float %x, float 0.0) ret float %retval } define <2 x float> @test_simplify5v(<2 x float> %x) { -; ANY-LABEL: @test_simplify5v( +; CHECK-LABEL: @test_simplify5v( ; ANY-NEXT: ret <2 x float> +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> zeroinitializer) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %retval } define double @test_simplify6(double %x) { -; ANY-LABEL: @test_simplify6( -; ANY-NEXT: ret double 1.000000e+00 +; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: ret double 1.000000e+00 ; %retval = call double @pow(double %x, double 0.0) ret double %retval } define <2 x double> @test_simplify6v(<2 x double> %x) { -; ANY-LABEL: @test_simplify6v( +; CHECK-LABEL: @test_simplify6v( ; ANY-NEXT: ret <2 x double> +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> zeroinitializer) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %retval @@ -197,24 +227,38 @@ define <2 x double> @test_simplify6v(<2 x double> %x) { ; Check pow(x, 0.5) -> fabs(sqrt(x)), where x != -infinity. define float @test_simplify7(float %x) { -; ANY-LABEL: @test_simplify7( -; ANY-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) [[NUW_RO]] +; CHECK-LABEL: @test_simplify7( +; ANY-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) ; ANY-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) ; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 ; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] ; ANY-NEXT: ret float [[TMP1]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 5.000000e-01) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 5.000000e-01) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) +; VC64-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) +; VC64-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 +; VC64-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] +; VC64-NEXT: ret float [[TMP1]] +; VC83-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) +; VC83-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) +; VC83-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 +; VC83-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] +; VC83-NEXT: ret float [[TMP1]] ; %retval = call float @powf(float %x, float 0.5) ret float %retval } define double @test_simplify8(double %x) { -; ANY-LABEL: @test_simplify8( -; ANY-NEXT: [[SQRT:%.*]] = call double @sqrt(double [[X:%.*]]) [[NUW_RO]] -; ANY-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) -; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 -; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] -; ANY-NEXT: ret double [[TMP1]] +; CHECK-LABEL: @test_simplify8( +; CHECK-NEXT: [[SQRT:%.*]] = call double @sqrt(double [[X:%.*]]) +; CHECK-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) +; CHECK-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] +; CHECK-NEXT: ret double [[TMP1]] ; %retval = call double @pow(double %x, double 0.5) ret double %retval @@ -223,16 +267,22 @@ define double @test_simplify8(double %x) { ; Check pow(-infinity, 0.5) -> +infinity. define float @test_simplify9(float %x) { -; ANY-LABEL: @test_simplify9( +; CHECK-LABEL: @test_simplify9( ; ANY-NEXT: ret float 0x7FF0000000000000 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 0xFFF0000000000000, float 5.000000e-01) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 0xFFF0000000000000, float 5.000000e-01) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 0x7FF0000000000000 +; VC83-NEXT: ret float 0x7FF0000000000000 ; %retval = call float @powf(float 0xFFF0000000000000, float 0.5) ret float %retval } define double @test_simplify10(double %x) { -; ANY-LABEL: @test_simplify10( -; ANY-NEXT: ret double 0x7FF0000000000000 +; CHECK-LABEL: @test_simplify10( +; CHECK-NEXT: ret double 0x7FF0000000000000 ; %retval = call double @pow(double 0xFFF0000000000000, double 0.5) ret double %retval @@ -241,32 +291,42 @@ define double @test_simplify10(double %x) { ; Check pow(x, 1.0) -> x. define float @test_simplify11(float %x) { -; ANY-LABEL: @test_simplify11( +; CHECK-LABEL: @test_simplify11( ; ANY-NEXT: ret float [[X:%.*]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 1.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 1.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float [[X:%.*]] +; VC83-NEXT: ret float [[X:%.*]] ; %retval = call float @powf(float %x, float 1.0) ret float %retval } define <2 x float> @test_simplify11v(<2 x float> %x) { -; ANY-LABEL: @test_simplify11v( +; CHECK-LABEL: @test_simplify11v( ; ANY-NEXT: ret <2 x float> [[X:%.*]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %retval } define double @test_simplify12(double %x) { -; ANY-LABEL: @test_simplify12( -; ANY-NEXT: ret double [[X:%.*]] +; CHECK-LABEL: @test_simplify12( +; CHECK-NEXT: ret double [[X:%.*]] ; %retval = call double @pow(double %x, double 1.0) ret double %retval } define <2 x double> @test_simplify12v(<2 x double> %x) { -; ANY-LABEL: @test_simplify12v( +; CHECK-LABEL: @test_simplify12v( ; ANY-NEXT: ret <2 x double> [[X:%.*]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %retval @@ -275,36 +335,48 @@ define <2 x double> @test_simplify12v(<2 x double> %x) { ; Check pow(x, 2.0) -> x*x. define float @pow2_strict(float %x) { -; ANY-LABEL: @pow2_strict( +; CHECK-LABEL: @pow2_strict( ; ANY-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] ; ANY-NEXT: ret float [[SQUARE]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 2.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 2.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] +; VC64-NEXT: ret float [[SQUARE]] +; VC83-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] +; VC83-NEXT: ret float [[SQUARE]] ; %r = call float @powf(float %x, float 2.0) ret float %r } define <2 x float> @pow2_strictv(<2 x float> %x) { -; ANY-LABEL: @pow2_strictv( +; CHECK-LABEL: @pow2_strictv( ; ANY-NEXT: [[SQUARE:%.*]] = fmul <2 x float> [[X:%.*]], [[X]] ; ANY-NEXT: ret <2 x float> [[SQUARE]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %r = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %r } define double @pow2_double_strict(double %x) { -; ANY-LABEL: @pow2_double_strict( -; ANY-NEXT: [[SQUARE:%.*]] = fmul double [[X:%.*]], [[X]] -; ANY-NEXT: ret double [[SQUARE]] +; CHECK-LABEL: @pow2_double_strict( +; CHECK-NEXT: [[SQUARE:%.*]] = fmul double [[X:%.*]], [[X]] +; CHECK-NEXT: ret double [[SQUARE]] ; %r = call double @pow(double %x, double 2.0) ret double %r } define <2 x double> @pow2_double_strictv(<2 x double> %x) { -; ANY-LABEL: @pow2_double_strictv( +; CHECK-LABEL: @pow2_double_strictv( ; ANY-NEXT: [[SQUARE:%.*]] = fmul <2 x double> [[X:%.*]], [[X]] ; ANY-NEXT: ret <2 x double> [[SQUARE]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %r = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %r @@ -313,9 +385,17 @@ define <2 x double> @pow2_double_strictv(<2 x double> %x) { ; Don't drop the FMF - PR35601 ( https://bugs.llvm.org/show_bug.cgi?id=35601 ) define float @pow2_fast(float %x) { -; ANY-LABEL: @pow2_fast( +; CHECK-LABEL: @pow2_fast( ; ANY-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] ; ANY-NEXT: ret float [[SQUARE]] +; VC32-NEXT: [[POW:%.*]] = call fast float @powf(float [[X:%.*]], float 2.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call fast float @powf(float [[X:%.*]], float 2.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] +; VC64-NEXT: ret float [[SQUARE]] +; VC83-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] +; VC83-NEXT: ret float [[SQUARE]] ; %r = call fast float @powf(float %x, float 2.0) ret float %r @@ -324,48 +404,60 @@ define float @pow2_fast(float %x) { ; Check pow(x, -1.0) -> 1.0/x. define float @pow_neg1_strict(float %x) { -; ANY-LABEL: @pow_neg1_strict( +; CHECK-LABEL: @pow_neg1_strict( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] ; ANY-NEXT: ret float [[RECIPROCAL]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float -1.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float -1.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] +; VC64-NEXT: ret float [[RECIPROCAL]] +; VC83-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] +; VC83-NEXT: ret float [[RECIPROCAL]] ; %r = call float @powf(float %x, float -1.0) ret float %r } define <2 x float> @pow_neg1_strictv(<2 x float> %x) { -; ANY-LABEL: @pow_neg1_strictv( +; CHECK-LABEL: @pow_neg1_strictv( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv <2 x float> , [[X:%.*]] ; ANY-NEXT: ret <2 x float> [[RECIPROCAL]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %r = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %r } define double @pow_neg1_double_fast(double %x) { -; ANY-LABEL: @pow_neg1_double_fast( -; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv fast double 1.000000e+00, [[X:%.*]] -; ANY-NEXT: ret double [[RECIPROCAL]] +; CHECK-LABEL: @pow_neg1_double_fast( +; CHECK-NEXT: [[RECIPROCAL:%.*]] = fdiv fast double 1.000000e+00, [[X:%.*]] +; CHECK-NEXT: ret double [[RECIPROCAL]] ; %r = call fast double @pow(double %x, double -1.0) ret double %r } define <2 x double> @pow_neg1_double_fastv(<2 x double> %x) { -; ANY-LABEL: @pow_neg1_double_fastv( +; CHECK-LABEL: @pow_neg1_double_fastv( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv fast <2 x double> , [[X:%.*]] ; ANY-NEXT: ret <2 x double> [[RECIPROCAL]] +; MSVC-NEXT: [[POW:%.*]] = call fast <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %r = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %r } define double @test_simplify17(double %x) { -; ANY-LABEL: @test_simplify17( -; ANY-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[X:%.*]]) -; ANY-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) -; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 -; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] -; ANY-NEXT: ret double [[TMP1]] +; CHECK-LABEL: @test_simplify17( +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[X:%.*]]) +; CHECK-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) +; CHECK-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] +; CHECK-NEXT: ret double [[TMP1]] ; %retval = call double @llvm.pow.f64(double %x, double 0.5) ret double %retval @@ -374,29 +466,23 @@ define double @test_simplify17(double %x) { ; Check pow(10.0, x) -> __exp10(x) on OS X 10.9+ and iOS 7.0+. define float @test_simplify18(float %x) { -; CHECK-EXP10-LABEL: @test_simplify18( -; CHECK-EXP10-NEXT: [[__EXP10F:%.*]] = call float @__exp10f(float [[X:%.*]]) [[NUW_RO]] -; CHECK-EXP10-NEXT: ret float [[__EXP10F]] -; -; CHECK-NO-EXP10-LABEL: @test_simplify18( -; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call float @powf(float 1.000000e+01, float [[X:%.*]]) -; CHECK-NO-EXP10-NEXT: ret float [[RETVAL]] +; CHECK-LABEL: @test_simplify18( +; CHECK-EXP10-NEXT: [[__EXP10F:%.*]] = call float @__exp10f(float [[X:%.*]]) +; CHECK-EXP10-NEXT: ret float [[__EXP10F]] +; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call float @powf(float 1.000000e+01, float [[X:%.*]]) +; CHECK-NO-EXP10-NEXT: ret float [[RETVAL]] ; %retval = call float @powf(float 10.0, float %x) ret float %retval } define double @test_simplify19(double %x) { -; CHECK-EXP10-LABEL: @test_simplify19( -; CHECK-EXP10-NEXT: [[__EXP10:%.*]] = call double @__exp10(double [[X:%.*]]) [[NUW_RO]] -; CHECK-EXP10-NEXT: ret double [[__EXP10]] -; -; CHECK-NO-EXP10-LABEL: @test_simplify19( -; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call double @pow(double 1.000000e+01, double [[X:%.*]]) -; CHECK-NO-EXP10-NEXT: ret double [[RETVAL]] +; CHECK-LABEL: @test_simplify19( +; CHECK-EXP10-NEXT: [[__EXP10:%.*]] = call double @__exp10(double [[X:%.*]]) +; CHECK-EXP10-NEXT: ret double [[__EXP10]] +; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call double @pow(double 1.000000e+01, double [[X:%.*]]) +; CHECK-NO-EXP10-NEXT: ret double [[RETVAL]] ; %retval = call double @pow(double 10.0, double %x) ret double %retval } - -; CHECK-EXP10: attributes [[NUW_RO]] = { nounwind readonly } diff --git a/llvm/test/Transforms/InstCombine/win-math.ll b/llvm/test/Transforms/InstCombine/win-math.ll index 36947791393d9a..38ed949e949dce 100644 --- a/llvm/test/Transforms/InstCombine/win-math.ll +++ b/llvm/test/Transforms/InstCombine/win-math.ll @@ -1,17 +1,21 @@ -; RUN: opt -O2 -S -mtriple=i386-pc-win32 < %s | FileCheck %s -check-prefix=WIN32 -; RUN: opt -O2 -S -mtriple=x86_64-pc-win32 < %s | FileCheck %s -check-prefix=WIN64 -; RUN: opt -O2 -S -mtriple=i386-pc-mingw32 < %s | FileCheck %s -check-prefix=MINGW32 -; RUN: opt -O2 -S -mtriple=x86_64-pc-mingw32 < %s | FileCheck %s -check-prefix=MINGW64 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVCXX,MSVC32 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC19,MSVC51 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-windows-msvc17 | FileCheck %s --check-prefixes=CHECK,MSVCXX,MSVC64 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-win32 | FileCheck %s --check-prefixes=CHECK,MSVC19,MSVC83 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-mingw32 | FileCheck %s --check-prefixes=CHECK,MINGW32 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-mingw32 | FileCheck %s --check-prefixes=CHECK,MINGW64 ; x86 win32 msvcrt does not provide entry points for single-precision libm. -; x86-64 win32 msvcrt does (except for fabsf) -; msvcrt does not provide C99 math, but mingw32 does. +; x86-64 win32 msvcrt does, but with exceptions +; msvcrt does not provide all of C99 math, but mingw32 does. declare double @acos(double %x) define float @float_acos(float %x) nounwind readnone { -; WIN32-LABEL: @float_acos( -; WIN32-NOT: float @acosf -; WIN32: double @acos +; CHECK-LABEL: @float_acos( +; MSVCXX-NOT: float @acosf +; MSVCXX: double @acos +; MSVC19-NOT: float @acosf +; MSVC19: double @acos %1 = fpext float %x to double %2 = call double @acos(double %1) %3 = fptrunc double %2 to float @@ -20,9 +24,11 @@ define float @float_acos(float %x) nounwind readnone { declare double @asin(double %x) define float @float_asin(float %x) nounwind readnone { -; WIN32-LABEL: @float_asin( -; WIN32-NOT: float @asinf -; WIN32: double @asin +; CHECK-LABEL: @float_asin( +; MSVCXX-NOT: float @asinf +; MSVCXX: double @asin +; MSVC19-NOT: float @asinf +; MSVC19: double @asin %1 = fpext float %x to double %2 = call double @asin(double %1) %3 = fptrunc double %2 to float @@ -31,9 +37,11 @@ define float @float_asin(float %x) nounwind readnone { declare double @atan(double %x) define float @float_atan(float %x) nounwind readnone { -; WIN32-LABEL: @float_atan( -; WIN32-NOT: float @atanf -; WIN32: double @atan +; CHECK-LABEL: @float_atan( +; MSVCXX-NOT: float @atanf +; MSVCXX: double @atan +; MSVC19-NOT: float @atanf +; MSVC19: double @atan %1 = fpext float %x to double %2 = call double @atan(double %1) %3 = fptrunc double %2 to float @@ -42,9 +50,11 @@ define float @float_atan(float %x) nounwind readnone { declare double @atan2(double %x, double %y) define float @float_atan2(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_atan2( -; WIN32-NOT: float @atan2f -; WIN32: double @atan2 +; CHECK-LABEL: @float_atan2( +; MSVCXX-NOT: float @atan2f +; MSVCXX: double @atan2 +; MSVC19-NOT: float @atan2f +; MSVC19: double @atan2 %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @atan2(double %1, double %2) @@ -54,18 +64,15 @@ define float @float_atan2(float %x, float %y) nounwind readnone { declare double @ceil(double %x) define float @float_ceil(float %x) nounwind readnone { -; WIN32-LABEL: @float_ceil( -; WIN32-NOT: float @ceilf -; WIN32: float @llvm.ceil.f32 -; WIN64-LABEL: @float_ceil( -; WIN64: float @llvm.ceil.f32 -; WIN64-NOT: double @ceil -; MINGW32-LABEL: @float_ceil( -; MINGW32: float @llvm.ceil.f32 +; CHECK-LABEL: @float_ceil( +; MSVCXX-NOT: float @ceilf +; MSVCXX: float @llvm.ceil.f32 +; MSVC19-NOT: double @ceil +; MSVC19: float @llvm.ceil.f32 ; MINGW32-NOT: double @ceil -; MINGW64-LABEL: @float_ceil( -; MINGW64: float @llvm.ceil.f32 +; MINGW32: float @llvm.ceil.f32 ; MINGW64-NOT: double @ceil +; MINGW64: float @llvm.ceil.f32 %1 = fpext float %x to double %2 = call double @ceil(double %1) %3 = fptrunc double %2 to float @@ -74,10 +81,11 @@ define float @float_ceil(float %x) nounwind readnone { declare double @_copysign(double %x) define float @float_copysign(float %x) nounwind readnone { -; WIN32-LABEL: @float_copysign( -; WIN32-NOT: float @copysignf -; WIN32-NOT: float @_copysignf -; WIN32: double @_copysign +; CHECK-LABEL: @float_copysign( +; MSVCXX-NOT: float @_copysignf +; MSVCXX: double @_copysign +; MSVC19-NOT: float @_copysignf +; MSVC19: double @_copysign %1 = fpext float %x to double %2 = call double @_copysign(double %1) %3 = fptrunc double %2 to float @@ -86,9 +94,11 @@ define float @float_copysign(float %x) nounwind readnone { declare double @cos(double %x) define float @float_cos(float %x) nounwind readnone { -; WIN32-LABEL: @float_cos( -; WIN32-NOT: float @cosf -; WIN32: double @cos +; CHECK-LABEL: @float_cos( +; MSVCXX-NOT: float @cosf +; MSVCXX: double @cos +; MSVC19-NOT: float @cosf +; MSVC19: double @cos %1 = fpext float %x to double %2 = call double @cos(double %1) %3 = fptrunc double %2 to float @@ -97,9 +107,11 @@ define float @float_cos(float %x) nounwind readnone { declare double @cosh(double %x) define float @float_cosh(float %x) nounwind readnone { -; WIN32-LABEL: @float_cosh( -; WIN32-NOT: float @coshf -; WIN32: double @cosh +; CHECK-LABEL: @float_cosh( +; MSVCXX-NOT: float @coshf +; MSVCXX: double @cosh +; MSVC19-NOT: float @coshf +; MSVC19: double @cosh %1 = fpext float %x to double %2 = call double @cosh(double %1) %3 = fptrunc double %2 to float @@ -108,9 +120,11 @@ define float @float_cosh(float %x) nounwind readnone { declare double @exp(double %x, double %y) define float @float_exp(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_exp( -; WIN32-NOT: float @expf -; WIN32: double @exp +; CHECK-LABEL: @float_exp( +; MSVCXX-NOT: float @expf +; MSVCXX: double @exp +; MSVC19-NOT: float @expf +; MSVC19: double @exp %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @exp(double %1, double %2) @@ -120,12 +134,11 @@ define float @float_exp(float %x, float %y) nounwind readnone { declare double @fabs(double %x, double %y) define float @float_fabs(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_fabs( -; WIN32-NOT: float @fabsf -; WIN32: double @fabs -; WIN64-LABEL: @float_fabs( -; WIN64-NOT: float @fabsf -; WIN64: double @fabs +; CHECK-LABEL: @float_fabs( +; MSVCXX-NOT: float @fabsf +; MSVCXX: double @fabs +; MSVC19-NOT: float @fabsf +; MSVC19: double @fabs %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @fabs(double %1, double %2) @@ -135,18 +148,15 @@ define float @float_fabs(float %x, float %y) nounwind readnone { declare double @floor(double %x) define float @float_floor(float %x) nounwind readnone { -; WIN32-LABEL: @float_floor( -; WIN32-NOT: float @floorf -; WIN32: float @llvm.floor.f32 -; WIN64-LABEL: @float_floor( -; WIN64: float @llvm.floor.f32 -; WIN64-NOT: double @floor -; MINGW32-LABEL: @float_floor( -; MINGW32: float @llvm.floor.f32 +; CHECK-LABEL: @float_floor( +; MSVCXX-NOT: float @floorf +; MSVCXX: float @llvm.floor.f32 +; MSVC19-NOT: double @floor +; MSVC19: float @llvm.floor.f32 ; MINGW32-NOT: double @floor -; MINGW64-LABEL: @float_floor( -; MINGW64: float @llvm.floor.f32 +; MINGW32: float @llvm.floor.f32 ; MINGW64-NOT: double @floor +; MINGW64: float @llvm.floor.f32 %1 = fpext float %x to double %2 = call double @floor(double %1) %3 = fptrunc double %2 to float @@ -155,9 +165,11 @@ define float @float_floor(float %x) nounwind readnone { declare double @fmod(double %x, double %y) define float @float_fmod(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_fmod( -; WIN32-NOT: float @fmodf -; WIN32: double @fmod +; MSVCXX-LABEL: @float_fmod( +; MSVCXX-NOT: float @fmodf +; MSVCXX: double @fmod +; MSVC19-NOT: float @fmodf +; MSVC19: double @fmod %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @fmod(double %1, double %2) @@ -167,20 +179,37 @@ define float @float_fmod(float %x, float %y) nounwind readnone { declare double @log(double %x) define float @float_log(float %x) nounwind readnone { -; WIN32-LABEL: @float_log( -; WIN32-NOT: float @logf -; WIN32: double @log +; CHECK-LABEL: @float_log( +; MSVCXX-NOT: float @logf +; MSVCXX: double @log +; MSVC19-NOT: float @logf +; MSVC19: double @log %1 = fpext float %x to double %2 = call double @log(double %1) %3 = fptrunc double %2 to float ret float %3 } +declare double @logb(double %x) +define float @float_logb(float %x) nounwind readnone { +; CHECK-LABEL: @float_logb( +; MSVCXX-NOT: float @logbf +; MSVCXX: double @logb +; MSVC19-NOT: float @logbf +; MSVC19: double @logb + %1 = fpext float %x to double + %2 = call double @logb(double %1) + %3 = fptrunc double %2 to float + ret float %3 +} + declare double @pow(double %x, double %y) define float @float_pow(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_pow( -; WIN32-NOT: float @powf -; WIN32: double @pow +; CHECK-LABEL: @float_pow( +; MSVCXX-NOT: float @powf +; MSVCXX: double @pow +; MSVC19-NOT: float @powf +; MSVC19: double @pow %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @pow(double %1, double %2) @@ -190,9 +219,11 @@ define float @float_pow(float %x, float %y) nounwind readnone { declare double @sin(double %x) define float @float_sin(float %x) nounwind readnone { -; WIN32-LABEL: @float_sin( -; WIN32-NOT: float @sinf -; WIN32: double @sin +; CHECK-LABEL: @float_sin( +; MSVCXX-NOT: float @sinf +; MSVCXX: double @sin +; MSVC19-NOT: float @sinf +; MSVC19: double @sin %1 = fpext float %x to double %2 = call double @sin(double %1) %3 = fptrunc double %2 to float @@ -201,9 +232,11 @@ define float @float_sin(float %x) nounwind readnone { declare double @sinh(double %x) define float @float_sinh(float %x) nounwind readnone { -; WIN32-LABEL: @float_sinh( -; WIN32-NOT: float @sinhf -; WIN32: double @sinh +; CHECK-LABEL: @float_sinh( +; MSVCXX-NOT: float @sinhf +; MSVCXX: double @sinh +; MSVC19-NOT: float @sinhf +; MSVC19: double @sinh %1 = fpext float %x to double %2 = call double @sinh(double %1) %3 = fptrunc double %2 to float @@ -212,18 +245,19 @@ define float @float_sinh(float %x) nounwind readnone { declare double @sqrt(double %x) define float @float_sqrt(float %x) nounwind readnone { -; WIN32-LABEL: @float_sqrt( -; WIN32-NOT: float @sqrtf -; WIN32: double @sqrt -; WIN64-LABEL: @float_sqrt( -; WIN64: float @sqrtf -; WIN64-NOT: double @sqrt -; MINGW32-LABEL: @float_sqrt( -; MINGW32: float @sqrtf +; CHECK-LABEL: @float_sqrt( +; MSVC32-NOT: float @sqrtf +; MSVC32: double @sqrt +; MSVC51-NOT: float @sqrtf +; MSVC51: double @sqrt +; MSVC64-NOT: double @sqrt +; MSVC64: float @sqrtf +; MSVC83-NOT: double @sqrt +; MSVC83: float @sqrtf ; MINGW32-NOT: double @sqrt -; MINGW64-LABEL: @float_sqrt( -; MINGW64: float @sqrtf +; MINGW32: float @sqrtf ; MINGW64-NOT: double @sqrt +; MINGW64: float @sqrtf %1 = fpext float %x to double %2 = call double @sqrt(double %1) %3 = fptrunc double %2 to float @@ -232,9 +266,11 @@ define float @float_sqrt(float %x) nounwind readnone { declare double @tan(double %x) define float @float_tan(float %x) nounwind readnone { -; WIN32-LABEL: @float_tan( -; WIN32-NOT: float @tanf -; WIN32: double @tan +; CHECK-LABEL: @float_tan( +; MSVCXX-NOT: float @tanf +; MSVCXX: double @tan +; MSVC19-NOT: float @tanf +; MSVC19: double @tan %1 = fpext float %x to double %2 = call double @tan(double %1) %3 = fptrunc double %2 to float @@ -243,30 +279,29 @@ define float @float_tan(float %x) nounwind readnone { declare double @tanh(double %x) define float @float_tanh(float %x) nounwind readnone { -; WIN32-LABEL: @float_tanh( -; WIN32-NOT: float @tanhf -; WIN32: double @tanh +; CHECK-LABEL: @float_tanh( +; MSVCXX-NOT: float @tanhf +; MSVCXX: double @tanh +; MSVC19-NOT: float @tanhf +; MSVC19: double @tanh %1 = fpext float %x to double %2 = call double @tanh(double %1) %3 = fptrunc double %2 to float ret float %3 } -; win32 does not have round; mingw32 does +; win32 does not have roundf; mingw32 does declare double @round(double %x) define float @float_round(float %x) nounwind readnone { -; WIN32-LABEL: @float_round( -; WIN32-NOT: float @roundf -; WIN32: double @round -; WIN64-LABEL: @float_round( -; WIN64-NOT: float @roundf -; WIN64: double @round -; MINGW32-LABEL: @float_round( -; MINGW32: float @llvm.round.f32 +; CHECK-LABEL: @float_round( +; MSVCXX-NOT: double @roundf +; MSVCXX: double @round +; MSVC19-NOT: double @round +; MSVC19: float @llvm.round.f32 ; MINGW32-NOT: double @round -; MINGW64-LABEL: @float_round( -; MINGW64: float @llvm.round.f32 +; MINGW32: float @llvm.round.f32 ; MINGW64-NOT: double @round +; MINGW64: float @llvm.round.f32 %1 = fpext float %x to double %2 = call double @round(double %1) %3 = fptrunc double %2 to float @@ -275,26 +310,26 @@ define float @float_round(float %x) nounwind readnone { declare float @powf(float, float) -; win32 lacks sqrtf&fabsf, win64 lacks fabsf, but +; win32 lacks sqrtf & fabsf, win64 lacks fabsf, but ; calls to the intrinsics can be emitted instead. define float @float_powsqrt(float %x) nounwind readnone { -; WIN32-LABEL: @float_powsqrt( -; WIN32-NOT: float @sqrtf -; WIN32: float @powf - -; WIN64-LABEL: @float_powsqrt( -; WIN64: float @sqrtf -; WIN64: float @llvm.fabs.f32( -; WIN64-NOT: float @powf - -; MINGW32-LABEL: @float_powsqrt( +; CHECK-LABEL: @float_powsqrt( +; MSVC32-NOT: float @sqrtf +; MSVC32: float @powf +; MSVC51-NOT: float @sqrtf +; MSVC51: float @powf +; MSVC64-NOT: float @powf +; MSVC64: float @sqrtf +; MSVC64: float @llvm.fabs.f32( +; MSVC83-NOT: float @powf +; MSVC83: float @sqrtf +; MSVC83: float @llvm.fabs.f32( +; MINGW32-NOT: float @powf ; MINGW32: float @sqrtf ; MINGW32: float @llvm.fabs.f32 -; MINGW32-NOT: float @powf -; MINGW64-LABEL: @float_powsqrt( +; MINGW64-NOT: float @powf ; MINGW64: float @sqrtf ; MINGW64: float @llvm.fabs.f32( -; MINGW64-NOT: float @powf %1 = call float @powf(float %x, float 0.5) ret float %1 } From 6e3c4d584b71628f25bd567335d32f7e00d682eb Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 13 Feb 2019 10:47:50 +0000 Subject: [PATCH 02/35] Revert r350404 This caused https://bugs.llvm.org/show_bug.cgi?id=40642: "After 350404, clang drops volatile load" > Refactor the way we handle diagnosing unused expression results. > > Rather than sprinkle calls to DiagnoseUnusedExprResult() around in places > where we want diagnostics, we now diagnose unused expression statements and > full expressions in a more generic way when acting on the final expression > statement. This results in more appropriate diagnostics for [[nodiscard]] where > we were previously lacking them, such as when the body of a for loop is not a > compound statement. > > This patch fixes PR39837. llvm-svn: 353935 --- clang/include/clang/Parse/Parser.h | 5 -- clang/include/clang/Sema/Sema.h | 19 +++--- clang/lib/Parse/ParseObjc.cpp | 2 +- clang/lib/Parse/ParseOpenMP.cpp | 14 ++-- clang/lib/Parse/ParseStmt.cpp | 26 ++------ clang/lib/Sema/SemaCoroutine.cpp | 17 ++--- clang/lib/Sema/SemaDecl.cpp | 6 +- clang/lib/Sema/SemaDeclCXX.cpp | 14 ++-- clang/lib/Sema/SemaExpr.cpp | 5 +- clang/lib/Sema/SemaExprCXX.cpp | 2 - clang/lib/Sema/SemaLambda.cpp | 2 +- clang/lib/Sema/SemaOpenMP.cpp | 55 +++++++--------- clang/lib/Sema/SemaStmt.cpp | 65 +++++++++++-------- clang/lib/Sema/TreeTransform.h | 15 ++--- clang/test/CXX/stmt.stmt/stmt.select/p3.cpp | 9 +-- .../pragma-macro-token-caching.c | 2 +- clang/test/Parser/cxx1z-init-statement.cpp | 8 +-- clang/test/Parser/switch-recovery.cpp | 2 +- clang/test/SemaCXX/cxx1z-init-statement.cpp | 8 +-- clang/test/SemaCXX/for-range-examples.cpp | 2 +- clang/test/SemaCXX/warn-unused-result.cpp | 40 ------------ 21 files changed, 122 insertions(+), 196 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 438ff0e2ed4507..46e4431913e763 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -360,11 +360,6 @@ class Parser : public CodeCompletionHandler { /// just a regular sub-expression. SourceLocation ExprStatementTokLoc; - /// Tests whether an expression value is discarded based on token lookahead. - /// It will return true if the lexer is currently processing the }) - /// terminating a GNU statement expression and false otherwise. - bool isExprValueDiscarded(); - public: Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); ~Parser() override; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e5b7465820a982..ced5773f0c0737 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1369,7 +1369,6 @@ class Sema { void PopCompoundScope(); sema::CompoundScopeInfo &getCurCompoundScope() const; - bool isCurCompoundStmtAStmtExpr() const; bool hasAnyUnrecoverableErrorsInThisFunction() const; @@ -3690,17 +3689,16 @@ class Sema { return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); } FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { - return FullExprArg( - ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get()); + return FullExprArg(ActOnFinishFullExpr(Arg, CC).get()); } FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { ExprResult FE = - ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), - /*DiscardedValue*/ true); + ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), + /*DiscardedValue*/ true); return FullExprArg(FE.get()); } - StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true); + StmtResult ActOnExprStmt(ExprResult Arg); StmtResult ActOnExprStmtError(); StmtResult ActOnNullStmt(SourceLocation SemiLoc, @@ -5346,12 +5344,13 @@ class Sema { CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference); - ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) { - return ActOnFinishFullExpr( - Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue); + ExprResult ActOnFinishFullExpr(Expr *Expr) { + return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() + : SourceLocation()); } ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC, - bool DiscardedValue, bool IsConstexpr = false); + bool DiscardedValue = false, + bool IsConstexpr = false); StmtResult ActOnFinishFullStmt(Stmt *Stmt); // Marks SS invalid if it represents an incomplete type. diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index bd55f717939959..c8d7bda3d6e91c 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -2741,7 +2741,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Res, isExprValueDiscarded()); + return Actions.ActOnExprStmt(Res); } ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index dd2a8aae9f2fb6..17c3fa3cf2aa51 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -314,7 +314,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); ExprResult CombinerResult = Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), - D->getLocation(), /*DiscardedValue*/ false); + D->getLocation(), /*DiscardedValue=*/true); Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && @@ -356,7 +356,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { if (Actions.getLangOpts().CPlusPlus) { InitializerResult = Actions.ActOnFinishFullExpr( ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); } else { ConsumeToken(); ParseOpenMPReductionInitializerForDecl(OmpPrivParm); @@ -364,7 +364,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { } else { InitializerResult = Actions.ActOnFinishFullExpr( ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); } Actions.ActOnOpenMPDeclareReductionInitializerEnd( D, InitializerResult.get(), OmpPrivParm); @@ -1455,7 +1455,7 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, ExprResult LHS(ParseCastExpression( /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); - Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); // Parse ')'. RLoc = Tok.getLocation(); @@ -1711,8 +1711,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); - Val = - Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); } // Parse ')'. @@ -1997,8 +1996,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.ColonLoc = Tok.getLocation(); SourceLocation ELoc = ConsumeToken(); ExprResult Tail = ParseAssignmentExpression(); - Tail = - Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); + Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); if (Tail.isUsable()) Data.TailExpr = Tail.get(); else diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 2974e6a245b0ef..313793c3e8fb83 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -439,7 +439,7 @@ StmtResult Parser::ParseExprStatement() { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Expr, isExprValueDiscarded()); + return Actions.ActOnExprStmt(Expr); } /// ParseSEHTryBlockCommon @@ -958,16 +958,6 @@ bool Parser::ConsumeNullStmt(StmtVector &Stmts) { return true; } -bool Parser::isExprValueDiscarded() { - if (Actions.isCurCompoundStmtAStmtExpr()) { - // Look to see if the next two tokens close the statement expression; - // if so, this expression statement is the last statement in a - // statment expression. - return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren); - } - return true; -} - /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the /// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// consume the '}' at the end of the block. It does not manipulate the scope @@ -1072,7 +1062,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // Eat the semicolon at the end of stmt and convert the expr into a // statement. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - R = Actions.ActOnExprStmt(Res, isExprValueDiscarded()); + R = Actions.ActOnExprStmt(Res); } } @@ -1708,16 +1698,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (!Value.isInvalid()) { if (ForEach) FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); - else { - // We already know this is not an init-statement within a for loop, so - // if we are parsing a C++11 range-based for loop, we should treat this - // expression statement as being a discarded value expression because - // we will err below. This way we do not warn on an unused expression - // that was an error in the first place, like with: for (expr : expr); - bool IsRangeBasedFor = - getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon); - FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor); - } + else + FirstPart = Actions.ActOnExprStmt(Value); } if (Tok.is(tok::semi)) { diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 181efa6d3dd094..e282bb62f03269 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -646,7 +646,7 @@ bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc, return StmtError(); Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(), /*IsImplicit*/ true); - Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false); + Suspend = ActOnFinishFullExpr(Suspend.get()); if (Suspend.isInvalid()) { Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) << ((Name == "initial_suspend") ? 0 : 1); @@ -867,7 +867,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E, if (PC.isInvalid()) return StmtError(); - Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get(); + Expr *PCE = ActOnFinishFullExpr(PC.get()).get(); Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit); return Res; @@ -1236,7 +1236,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult NewExpr = S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc); - NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false); + NewExpr = S.ActOnFinishFullExpr(NewExpr.get()); if (NewExpr.isInvalid()) return false; @@ -1262,8 +1262,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult DeleteExpr = S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); - DeleteExpr = - S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false); + DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get()); if (DeleteExpr.isInvalid()) return false; @@ -1348,8 +1347,7 @@ bool CoroutineStmtBuilder::makeOnException() { ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc, "unhandled_exception", None); - UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc, - /*DiscardedValue*/ false); + UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc); if (UnhandledException.isInvalid()) return false; @@ -1402,8 +1400,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { "get_return_object type must no longer be dependent"); if (FnRetType->isVoidType()) { - ExprResult Res = - S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false); + ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc); if (Res.isInvalid()) return false; @@ -1435,7 +1432,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { if (Res.isInvalid()) return false; - Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false); + Res = S.ActOnFinishFullExpr(Res.get()); if (Res.isInvalid()) return false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 23c99d45a78d4d..7ddf2e88b78719 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11200,9 +11200,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // struct T { S a, b; } t = { Temp(), Temp() } // // we should destroy the first Temp before constructing the second. - ExprResult Result = - ActOnFinishFullExpr(Init, VDecl->getLocation(), - /*DiscardedValue*/ false, VDecl->isConstexpr()); + ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(), + false, + VDecl->isConstexpr()); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8b3556f715bfdc..950a63aa451be4 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1205,7 +1205,7 @@ static bool checkTupleLikeDecomposition(Sema &S, E = Seq.Perform(S, Entity, Kind, Init); if (E.isInvalid()) return true; - E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false); + E = S.ActOnFinishFullExpr(E.get(), Loc); if (E.isInvalid()) return true; RefVD->setInit(E.get()); @@ -3686,7 +3686,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false); + Init = ActOnFinishFullExpr(Init.get(), InitLoc); if (Init.isInvalid()) { FD->setInvalidDecl(); return; @@ -4044,8 +4044,7 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(), - /*DiscardedValue*/ false); + MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin()); if (MemberInit.isInvalid()) return true; @@ -4100,8 +4099,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - DelegationInit = ActOnFinishFullExpr( - DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false); + DelegationInit = ActOnFinishFullExpr(DelegationInit.get(), + InitRange.getBegin()); if (DelegationInit.isInvalid()) return true; @@ -4230,8 +4229,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(), - /*DiscardedValue*/ false); + BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin()); if (BaseInit.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2bcd47abe35699..db0c62630a9ec0 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4723,9 +4723,8 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, if (Result.isInvalid()) return true; - Result = - ActOnFinishFullExpr(Result.getAs(), Param->getOuterLocStart(), - /*DiscardedValue*/ false); + Result = ActOnFinishFullExpr(Result.getAs(), + Param->getOuterLocStart()); if (Result.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 8c89a3cee3dbbb..cce7a216548fff 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7815,8 +7815,6 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, FullExpr = IgnoredValueConversions(FullExpr.get()); if (FullExpr.isInvalid()) return ExprError(); - - DiagnoseUnusedExprResult(FullExpr.get()); } FullExpr = CorrectDelayedTyposInExpr(FullExpr.get()); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index af233b96d69b49..4e002a853dc217 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1724,7 +1724,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, /*NRVO=*/false), CurrentLocation, Src); if (!Init.isInvalid()) - Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); + Init = ActOnFinishFullExpr(Init.get()); if (Init.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 36048a38b999cb..aedec746af9e79 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5367,7 +5367,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), UB.get()); EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), CondOp.get()); - EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false); + EUB = SemaRef.ActOnFinishFullExpr(EUB.get()); // If we have a combined directive that combines 'distribute', 'for' or // 'simd' we need to be able to access the bounds of the schedule of the @@ -5396,8 +5396,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), CombUB.get()); CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), CombCondOp.get()); - CombEUB = - SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false); + CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get()); const CapturedDecl *CD = cast(AStmt)->getCapturedDecl(); // We expect to have at least 2 more parameters than the 'parallel' @@ -5431,7 +5430,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ? LB.get() : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); - Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); + Init = SemaRef.ActOnFinishFullExpr(Init.get()); if (isOpenMPLoopBoundSharingDirective(DKind)) { Expr *CombRHS = @@ -5442,8 +5441,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); CombInit = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); - CombInit = - SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false); + CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get()); } } @@ -5475,7 +5473,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, if (!Inc.isUsable()) return 0; Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); - Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false); + Inc = SemaRef.ActOnFinishFullExpr(Inc.get()); if (!Inc.isUsable()) return 0; @@ -5493,8 +5491,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); - NextLB = - SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false); + NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get()); if (!NextLB.isUsable()) return 0; // UB + ST @@ -5504,8 +5501,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); - NextUB = - SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false); + NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get()); if (!NextUB.isUsable()) return 0; if (isOpenMPLoopBoundSharingDirective(DKind)) { @@ -5516,8 +5512,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), CombNextLB.get()); - CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), - /*DiscardedValue*/ false); + CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get()); if (!CombNextLB.isUsable()) return 0; // UB + ST @@ -5528,8 +5523,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), CombNextUB.get()); - CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), - /*DiscardedValue*/ false); + CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get()); if (!CombNextUB.isUsable()) return 0; } @@ -5550,8 +5544,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, assert(DistInc.isUsable() && "distribute inc expr was not built"); DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), DistInc.get()); - DistInc = - SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false); + DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get()); assert(DistInc.isUsable() && "distribute inc expr was not built"); // Build expression: UB = min(UB, prevUB) for #for in composite or combined @@ -5563,8 +5556,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get()); PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), CondOp.get()); - PrevEUB = - SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false); + PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get()); // Build IV <= PrevUB to be used in parallel for is in combination with // a distribute directive with schedule(static, 1) @@ -5680,10 +5672,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.IterationVarRef = IV.get(); Built.LastIteration = LastIteration.get(); Built.NumIterations = NumIterations.get(); - Built.CalcLastIteration = SemaRef - .ActOnFinishFullExpr(CalcLastIteration.get(), - /*DiscardedValue*/ false) - .get(); + Built.CalcLastIteration = + SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get(); Built.PreCond = PreCond.get(); Built.PreInits = buildPreInits(C, Captures); Built.Cond = Cond.get(); @@ -10358,8 +10348,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef VarList, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = - ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; @@ -11357,8 +11347,7 @@ static bool actOnOMPReductionKindClause( BO_Assign, LHSDRE, ConditionalOp); } if (ReductionOp.isUsable()) - ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), - /*DiscardedValue*/ false); + ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get()); } if (!ReductionOp.isUsable()) continue; @@ -11688,7 +11677,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); ExprResult CalcStep = BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); - CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false); + CalcStep = ActOnFinishFullExpr(CalcStep.get()); // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). @@ -11776,7 +11765,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, else Update = *CurPrivate; Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); // Build final: Var = InitExpr + NumIterations * Step ExprResult Final; @@ -11787,7 +11776,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, else Final = *CurPrivate; Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); if (!Update.isUsable() || !Final.isUsable()) { Updates.push_back(nullptr); @@ -11955,7 +11944,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef VarList, if (AssignmentOp.isInvalid()) continue; AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; @@ -12063,8 +12052,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef VarList, DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = - ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 9e30c9a396c0a1..dacf8d0cf4e7fd 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -42,11 +42,12 @@ using namespace clang; using namespace sema; -StmtResult Sema::ActOnExprStmt(ExprResult FE, bool DiscardedValue) { +StmtResult Sema::ActOnExprStmt(ExprResult FE) { if (FE.isInvalid()) return StmtError(); - FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), DiscardedValue); + FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), + /*DiscardedValue*/ true); if (FE.isInvalid()) return StmtError(); @@ -347,10 +348,6 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { return getCurFunction()->CompoundScopes.back(); } -bool Sema::isCurCompoundStmtAStmtExpr() const { - return getCurCompoundScope().IsStmtExpr; -} - StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); @@ -373,6 +370,14 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, Diag(D->getLocation(), diag::ext_mixed_decls_code); } } + // Warn about unused expressions in statements. + for (unsigned i = 0; i != NumElts; ++i) { + // Ignore statements that are last in a statement expression. + if (isStmtExpr && i == NumElts - 1) + continue; + + DiagnoseUnusedExprResult(Elts[i]); + } // Check for suspicious empty body (null statement) in `for' and `while' // statements. Don't do anything for template instantiations, this just adds @@ -464,12 +469,15 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal, /// ActOnCaseStmtBody - This installs a statement as the body of a case. void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) { + DiagnoseUnusedExprResult(SubStmt); cast(S)->setSubStmt(SubStmt); } StmtResult Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, Stmt *SubStmt, Scope *CurScope) { + DiagnoseUnusedExprResult(SubStmt); + if (getCurFunction()->SwitchStack.empty()) { Diag(DefaultLoc, diag::err_default_not_in_switch); return SubStmt; @@ -563,6 +571,9 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, if (IsConstexpr || isa(Cond.get().second)) setFunctionHasBranchProtectedScope(); + DiagnoseUnusedExprResult(thenStmt); + DiagnoseUnusedExprResult(elseStmt); + return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, Cond.get().second, thenStmt, ElseLoc, elseStmt); } @@ -1290,6 +1301,8 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) CommaVisitor(*this).Visit(CondVal.second); + DiagnoseUnusedExprResult(Body); + if (isa(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); @@ -1309,7 +1322,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, return StmtError(); Cond = CondResult.get(); - CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false); + CondResult = ActOnFinishFullExpr(Cond, DoLoc); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.get(); @@ -1319,6 +1332,8 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc())) CommaVisitor(*this).Visit(Cond); + DiagnoseUnusedExprResult(Body); + return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); } @@ -1763,6 +1778,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, CommaVisitor(*this).Visit(Second.get().second); Expr *Third = third.release().getAs(); + + DiagnoseUnusedExprResult(First); + DiagnoseUnusedExprResult(Third); + DiagnoseUnusedExprResult(Body); + if (isa(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); @@ -1782,7 +1802,7 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { if (result.isInvalid()) return StmtError(); E = result.get(); - ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); + ExprResult FullExpr = ActOnFinishFullExpr(E); if (FullExpr.isInvalid()) return StmtError(); return StmtResult(static_cast(FullExpr.get())); @@ -1936,8 +1956,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, if (CollectionExprResult.isInvalid()) return StmtError(); - CollectionExprResult = - ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false); + CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get()); if (CollectionExprResult.isInvalid()) return StmtError(); @@ -2574,8 +2593,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, if (!NotEqExpr.isInvalid()) NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get()); if (!NotEqExpr.isInvalid()) - NotEqExpr = - ActOnFinishFullExpr(NotEqExpr.get(), /*DiscardedValue*/ false); + NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); if (NotEqExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 0 << BeginRangeRef.get()->getType(); @@ -2598,7 +2616,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, // co_await during the initial parse. IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get()); if (!IncrExpr.isInvalid()) - IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false); + IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); if (IncrExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 2 << BeginRangeRef.get()->getType() ; @@ -2853,7 +2871,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, return StmtError(); } - ExprResult ExprRes = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); + ExprResult ExprRes = ActOnFinishFullExpr(E); if (ExprRes.isInvalid()) return StmtError(); E = ExprRes.get(); @@ -3203,8 +3221,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ExpressionEvaluationContext::DiscardedStatement && (HasDeducedReturnType || CurCap->HasImplicitReturnType)) { if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3331,8 +3348,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3562,8 +3578,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ExpressionEvaluationContext::DiscardedStatement && FnRetType->getContainedAutoType()) { if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3657,8 +3672,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3737,8 +3751,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3791,7 +3804,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Result.isInvalid()) return StmtError(); - Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); + Result = ActOnFinishFullExpr(Result.get()); if (Result.isInvalid()) return StmtError(); Throw = Result.get(); @@ -3863,7 +3876,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { } // The operand to @synchronized is a full-expression. - return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); + return ActOnFinishFullExpr(operand); } StmtResult diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index df14768cbe812a..9de4e8d654f96e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -328,7 +328,7 @@ class TreeTransform { /// other mechanism. /// /// \returns the transformed statement. - StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false); + StmtResult TransformStmt(Stmt *S); /// Transform the given statement. /// @@ -3269,8 +3269,8 @@ class TreeTransform { bool DeducibleTSTContext); }; -template -StmtResult TreeTransform::TransformStmt(Stmt *S, bool DiscardedValue) { +template +StmtResult TreeTransform::TransformStmt(Stmt *S) { if (!S) return S; @@ -3294,7 +3294,7 @@ StmtResult TreeTransform::TransformStmt(Stmt *S, bool DiscardedValue) { if (E.isInvalid()) return StmtError(); - return getSema().ActOnExprStmt(E, DiscardedValue); + return getSema().ActOnExprStmt(E); } } @@ -4715,8 +4715,7 @@ TreeTransform::TransformVariableArrayType(TypeLocBuilder &TLB, } if (SizeResult.isInvalid()) return QualType(); - SizeResult = - SemaRef.ActOnFinishFullExpr(SizeResult.get(), /*DiscardedValue*/ false); + SizeResult = SemaRef.ActOnFinishFullExpr(SizeResult.get()); if (SizeResult.isInvalid()) return QualType(); @@ -6521,9 +6520,7 @@ TreeTransform::TransformCompoundStmt(CompoundStmt *S, bool SubStmtChanged = false; SmallVector Statements; for (auto *B : S->body()) { - StmtResult Result = - getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back()); - + StmtResult Result = getDerived().TransformStmt(B); if (Result.isInvalid()) { // Immediately fail if this was a DeclStmt, since it's very // likely that this will cause problems for future statements. diff --git a/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp index 4804cc559d007f..7a6a408ec955b8 100644 --- a/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp +++ b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -std=c++1z -Wc++14-compat -verify %s -DCPP17 +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17 int f(); @@ -71,6 +71,7 @@ void whileInitStatement() { // last loop above. It would be nice to remove this. void whileInitStatement2() { while (; false) {} // expected-error {{expected expression}} - // expected-error@-1 {{expected ';' after expression}} - // expected-error@-2 {{expected expression}} + // expected-warning@-1 {{expression result unused}} + // expected-error@-2 {{expected ';' after expression}} + // expected-error@-3 {{expected expression}} } diff --git a/clang/test/CodeCompletion/pragma-macro-token-caching.c b/clang/test/CodeCompletion/pragma-macro-token-caching.c index 59b6621b56ad47..432706e85ceb9c 100644 --- a/clang/test/CodeCompletion/pragma-macro-token-caching.c +++ b/clang/test/CodeCompletion/pragma-macro-token-caching.c @@ -12,7 +12,7 @@ void completeParam(int param) { void completeParamPragmaError(int param) { Outer(__extension__({ _Pragma(2) })); // expected-error {{_Pragma takes a parenthesized string literal}} - param; // expected-warning {{expression result unused}} + param; } // RUN: %clang_cc1 -fsyntax-only -verify -code-completion-at=%s:16:1 %s | FileCheck %s diff --git a/clang/test/Parser/cxx1z-init-statement.cpp b/clang/test/Parser/cxx1z-init-statement.cpp index ade60dc762d5c8..3d119ef8e709cb 100644 --- a/clang/test/Parser/cxx1z-init-statement.cpp +++ b/clang/test/Parser/cxx1z-init-statement.cpp @@ -13,9 +13,9 @@ int f() { if (T(n) = 0; n) {} // init-statement expressions - if (T{f()}; f()) {} // expected-warning {{expression result unused}} - if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}} - if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}} + if (T{f()}; f()) {} + if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} + if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} // condition declarations if (T(n){g}) {} @@ -35,7 +35,7 @@ int f() { // Likewise for 'switch' switch (int n; n) {} - switch (g; int g = 5) {} // expected-warning {{expression result unused}} + switch (g; int g = 5) {} if (int a, b; int c = a) { // expected-note 6{{previous}} int a; // expected-error {{redefinition}} diff --git a/clang/test/Parser/switch-recovery.cpp b/clang/test/Parser/switch-recovery.cpp index eacd017ab2364e..a3a0178cd10b67 100644 --- a/clang/test/Parser/switch-recovery.cpp +++ b/clang/test/Parser/switch-recovery.cpp @@ -105,7 +105,7 @@ void test9(int x) { // expected-note {{'x' declared here}} expected-error {{expected expression}} 8:: x; // expected-error {{expected ';' after expression}} \ expected-error {{no member named 'x' in the global namespace; did you mean simply 'x'?}} \ - expected-warning {{expression result unused}} + expected-warning 2 {{expression result unused}} 9:: :y; // expected-error {{expected ';' after expression}} \ expected-error {{expected unqualified-id}} \ expected-warning {{expression result unused}} diff --git a/clang/test/SemaCXX/cxx1z-init-statement.cpp b/clang/test/SemaCXX/cxx1z-init-statement.cpp index eea2589ab7c62e..d37acd08ce77d1 100644 --- a/clang/test/SemaCXX/cxx1z-init-statement.cpp +++ b/clang/test/SemaCXX/cxx1z-init-statement.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++1z -Wno-unused-value -verify %s -// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify %s +// RUN: %clang_cc1 -std=c++1z -verify %s +// RUN: %clang_cc1 -std=c++17 -verify %s void testIf() { int x = 0; @@ -12,7 +12,7 @@ void testIf() { int x = 0; // expected-error {{redefinition of 'x'}} if (x; int a = 0) ++a; - if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} + if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}} int a = 0; // expected-error {{redefinition of 'a'}} else int a = 0; // expected-error {{redefinition of 'a'}} @@ -48,7 +48,7 @@ void testSwitch() { ++a; } - switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} + switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}} case 0: int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}} case 1: diff --git a/clang/test/SemaCXX/for-range-examples.cpp b/clang/test/SemaCXX/for-range-examples.cpp index 5424b7a8ee7978..477789b56c1420 100644 --- a/clang/test/SemaCXX/for-range-examples.cpp +++ b/clang/test/SemaCXX/for-range-examples.cpp @@ -244,7 +244,7 @@ void foo () { int b = 1, a[b]; a[0] = 0; - [&] { for (int c : a) 0; } (); // expected-warning {{expression result unused}} + [&] { for (int c : a) 0; } (); } diff --git a/clang/test/SemaCXX/warn-unused-result.cpp b/clang/test/SemaCXX/warn-unused-result.cpp index f1de4618a741a7..88f5ab1e85c068 100644 --- a/clang/test/SemaCXX/warn-unused-result.cpp +++ b/clang/test/SemaCXX/warn-unused-result.cpp @@ -33,36 +33,6 @@ void test() { const S &s4 = g1(); } -void testSubstmts(int i) { - switch (i) { - case 0: - f(); // expected-warning {{ignoring return value}} - default: - f(); // expected-warning {{ignoring return value}} - } - - if (i) - f(); // expected-warning {{ignoring return value}} - else - f(); // expected-warning {{ignoring return value}} - - while (i) - f(); // expected-warning {{ignoring return value}} - - do - f(); // expected-warning {{ignoring return value}} - while (i); - - for (f(); // expected-warning {{ignoring return value}} - ; - f() // expected-warning {{ignoring return value}} - ) - f(); // expected-warning {{ignoring return value}} - - f(), // expected-warning {{ignoring return value}} - (void)f(); -} - struct X { int foo() __attribute__((warn_unused_result)); }; @@ -236,13 +206,3 @@ void f() { (void)++p; } } // namespace - -namespace PR39837 { -[[clang::warn_unused_result]] int f(int); - -void g() { - int a[2]; - for (int b : a) - f(b); // expected-warning {{ignoring return value}} -} -} // namespace PR39837 From c957a992959b7c1e5a613d8a953df8a029f922c0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 14 Feb 2019 10:47:35 +0000 Subject: [PATCH 03/35] Merging r353976: ------------------------------------------------------------------------ r353976 | epilk | 2019-02-13 21:32:37 +0100 (Wed, 13 Feb 2019) | 11 lines [Sema] Delay checking whether objc_designated_initializer is being applied to an init method This fixes a regression that was caused by r335084, which reversed the order that attributes are applied. objc_method_family can change whether a method is an init method, so the order that these attributes are applied matters. The commit fixes this by delaying the init check until after all attributes have been applied. rdar://47829358 Differential revision: https://reviews.llvm.org/D58152 ------------------------------------------------------------------------ llvm-svn: 354015 --- clang/include/clang/Basic/Attr.td | 9 +------ .../clang/Basic/DiagnosticSemaKinds.td | 3 +++ clang/lib/Sema/SemaDeclAttr.cpp | 26 +++++++++++++++++-- ...a-attribute-supported-attributes-list.test | 1 + clang/test/SemaObjC/attr-designated-init.m | 15 ++++++++++- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index bf1068019b77bd..b792db2852a80f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -103,13 +103,6 @@ def ObjCInstanceMethod : SubsetSubjectisInstanceMethod()}], "Objective-C instance methods">; -def ObjCInterfaceDeclInitMethod : SubsetSubjectgetMethodFamily() == OMF_init && - (isa(S->getDeclContext()) || - (isa(S->getDeclContext()) && - cast(S->getDeclContext())->IsClassExtension()))}], - "init methods of interface or class extension declarations">; - def Struct : SubsetSubjectisUnion()}], "structs">; @@ -1762,7 +1755,7 @@ def ObjCExplicitProtocolImpl : InheritableAttr { def ObjCDesignatedInitializer : Attr { let Spellings = [Clang<"objc_designated_initializer">]; - let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag>; + let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; let Documentation = [Undocumented]; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b71f65d146cab5..7ef57b02fe1c63 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3460,6 +3460,9 @@ def warn_objc_secondary_init_missing_init_call : Warning< def warn_objc_implementation_missing_designated_init_override : Warning< "method override for the designated initializer of the superclass %objcinstance0 not found">, InGroup; +def err_designated_init_attr_non_init : Error< + "'objc_designated_initializer' attribute only applies to init methods " + "of interface or class extension declarations">; // objc_bridge attribute diagnostics. def err_objc_attr_not_id : Error< diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8819f0396a270d..c4c3598ee7f3cb 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5116,11 +5116,22 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D, static void handleObjCDesignatedInitializer(Sema &S, Decl *D, const ParsedAttr &AL) { + DeclContext *Ctx = D->getDeclContext(); + + // This attribute can only be applied to methods in interfaces or class + // extensions. + if (!isa(Ctx) && + !(isa(Ctx) && + cast(Ctx)->IsClassExtension())) { + S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init); + return; + } + ObjCInterfaceDecl *IFace; - if (auto *CatDecl = dyn_cast(D->getDeclContext())) + if (auto *CatDecl = dyn_cast(Ctx)) IFace = CatDecl->getClassInterface(); else - IFace = cast(D->getDeclContext()); + IFace = cast(Ctx); if (!IFace) return; @@ -7067,6 +7078,17 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } } } + + // Do this check after processing D's attributes because the attribute + // objc_method_family can change whether the given method is in the init + // family, and it can be applied after objc_designated_initializer. This is a + // bit of a hack, but we need it to be compatible with versions of clang that + // processed the attribute list in the wrong order. + if (D->hasAttr() && + cast(D)->getMethodFamily() != OMF_init) { + Diag(D->getLocation(), diag::err_designated_init_attr_non_init); + D->dropAttr(); + } } // Helper for delayed processing TransparentUnion attribute. diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 98935fc21355b9..5ae4a7ca7bbe99 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -94,6 +94,7 @@ // CHECK-NEXT: ObjCBridge (SubjectMatchRule_record, SubjectMatchRule_type_alias) // CHECK-NEXT: ObjCBridgeMutable (SubjectMatchRule_record) // CHECK-NEXT: ObjCBridgeRelated (SubjectMatchRule_record) +// CHECK-NEXT: ObjCDesignatedInitializer (SubjectMatchRule_objc_method) // CHECK-NEXT: ObjCException (SubjectMatchRule_objc_interface) // CHECK-NEXT: ObjCExplicitProtocolImpl (SubjectMatchRule_objc_protocol) // CHECK-NEXT: ObjCExternallyRetained (SubjectMatchRule_variable_not_is_parameter, SubjectMatchRule_function, SubjectMatchRule_block, SubjectMatchRule_objc_method) diff --git a/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m index 05085884784b01..3558916dbe54a6 100644 --- a/clang/test/SemaObjC/attr-designated-init.m +++ b/clang/test/SemaObjC/attr-designated-init.m @@ -3,7 +3,7 @@ #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) #define NS_UNAVAILABLE __attribute__((unavailable)) -void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to init methods of interface or class extension declarations}} +void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{'objc_designated_initializer' attribute only applies to Objective-C methods}} @protocol P1 -(id)init NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to init methods of interface or class extension declarations}} @@ -428,3 +428,16 @@ - (instancetype)init NS_DESIGNATED_INITIALIZER; @interface CategoryForMissingInterface(Cat) // expected-error{{cannot find interface declaration}} - (instancetype)init NS_DESIGNATED_INITIALIZER; // expected-error{{only applies to init methods of interface or class extension declarations}} @end + +@interface TwoAttrs +-(instancetype)foo + __attribute__((objc_designated_initializer)) + __attribute__((objc_method_family(init))); +-(instancetype)bar + __attribute__((objc_method_family(init))) + __attribute__((objc_designated_initializer)); +-(instancetype)baz + __attribute__((objc_designated_initializer, objc_method_family(init))); +-(instancetype)quux + __attribute__((objc_method_family(init), objc_designated_initializer)); +@end From 11521347aff95e61fee986fb937dd5395e41ef57 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 14 Feb 2019 10:49:15 +0000 Subject: [PATCH 04/35] Merging r353968: ------------------------------------------------------------------------ r353968 | ruiu | 2019-02-13 19:51:15 +0100 (Wed, 13 Feb 2019) | 10 lines Recover elf32-bigmips and elf32-powerpc support in LLD This fixes a 7.0 -> 8.0 regression when parsing OUTPUT_FORMAT("elf32-powerpc"); or elf32-bigmips directive in ldscripts as well as an unknown emulation error when lld is invoked by clang due to missed elf32ppclinux case. Patch by vit9696 Differential Revision: https://reviews.llvm.org/D58005 ------------------------------------------------------------------------ llvm-svn: 354016 --- lld/ELF/Driver.cpp | 2 +- lld/ELF/ScriptParser.cpp | 3 ++- lld/test/ELF/emulation-mips.s | 3 +++ lld/test/ELF/emulation-ppc.s | 37 +++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 2e2036310fb21b..bce9d944a4a64f 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -130,7 +130,7 @@ static std::tuple parseEmulation(StringRef Emul) { .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) - .Case("elf32ppc", {ELF32BEKind, EM_PPC}) + .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 7cce94659c9e9d..7dbe1641622b6f 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -392,10 +392,11 @@ static std::pair parseBfdName(StringRef S) { .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) + .Case("elf32-powerpc", {ELF32BEKind, EM_PPC}) .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) - .Case("elf32-tradbigmips", {ELF32BEKind, EM_MIPS}) + .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS}) .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS}) .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS}) .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS}) diff --git a/lld/test/ELF/emulation-mips.s b/lld/test/ELF/emulation-mips.s index 42d0dd973eb365..6d7a1198b761ff 100644 --- a/lld/test/ELF/emulation-mips.s +++ b/lld/test/ELF/emulation-mips.s @@ -7,6 +7,9 @@ # RUN: echo 'OUTPUT_FORMAT(elf32-tradbigmips)' > %tmips.script # RUN: ld.lld %tmips.script -e _start %tmips -o %t4mips # RUN: llvm-readobj -file-headers %t4mips | FileCheck --check-prefix=MIPS %s +# RUN: echo 'OUTPUT_FORMAT(elf32-bigmips)' > %tmips2.script +# RUN: ld.lld %tmips2.script -e _start %tmips -o %t5mips +# RUN: llvm-readobj -file-headers %t5mips | FileCheck --check-prefix=MIPS %s # MIPS: ElfHeader { # MIPS-NEXT: Ident { # MIPS-NEXT: Magic: (7F 45 4C 46) diff --git a/lld/test/ELF/emulation-ppc.s b/lld/test/ELF/emulation-ppc.s index 843e77604779b1..4c8beb10159e6c 100644 --- a/lld/test/ELF/emulation-ppc.s +++ b/lld/test/ELF/emulation-ppc.s @@ -103,5 +103,42 @@ # PPC64LE-NEXT: StringTableSectionIndex: # PPC64LE-NEXT: } +# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-linux %s -o %tppc32 +# RUN: ld.lld -m elf32ppc %tppc32 -o %t2ppc32 +# RUN: llvm-readobj -file-headers %t2ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: ld.lld %tppc32 -o %t3ppc32 +# RUN: llvm-readobj -file-headers %t3ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: echo 'OUTPUT_FORMAT(elf32-powerpc)' > %tppc32.script +# RUN: ld.lld %tppc32.script %tppc32 -o %t4ppc32 +# RUN: llvm-readobj -file-headers %t4ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: ld.lld -m elf32ppclinux %tppc32 -o %t5ppc32 +# RUN: llvm-readobj -file-headers %t5ppc32 | FileCheck --check-prefix=PPC32 %s + +# PPC32: ElfHeader { +# PPC32-NEXT: Ident { +# PPC32-NEXT: Magic: (7F 45 4C 46) +# PPC32-NEXT: Class: 32-bit (0x1) +# PPC32-NEXT: DataEncoding: BigEndian (0x2) +# PPC32-NEXT: FileVersion: 1 +# PPC32-NEXT: OS/ABI: SystemV (0x0) +# PPC32-NEXT: ABIVersion: 0 +# PPC32-NEXT: Unused: (00 00 00 00 00 00 00) +# PPC32-NEXT: } +# PPC32-NEXT: Type: Executable (0x2) +# PPC32-NEXT: Machine: EM_PPC (0x14) +# PPC32-NEXT: Version: 1 +# PPC32-NEXT: Entry: +# PPC32-NEXT: ProgramHeaderOffset: 0x34 +# PPC32-NEXT: SectionHeaderOffset: +# PPC32-NEXT: Flags [ (0x0) +# PPC32-NEXT: ] +# PPC32-NEXT: HeaderSize: 52 +# PPC32-NEXT: ProgramHeaderEntrySize: 32 +# PPC32-NEXT: ProgramHeaderCount: +# PPC32-NEXT: SectionHeaderEntrySize: 40 +# PPC32-NEXT: SectionHeaderCount: +# PPC32-NEXT: StringTableSectionIndex: +# PPC32-NEXT: } + .globl _start _start: From ff290924df20d33f34cc330432ed5a3e4b8428e6 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 15 Feb 2019 13:54:42 +0000 Subject: [PATCH 05/35] Merging r354074: ------------------------------------------------------------------------ r354074 | epilk | 2019-02-14 23:48:01 +0100 (Thu, 14 Feb 2019) | 9 lines [Sema] Fix-up a -Wfloat-conversion diagnostic We were warning on valid ObjC property reference exprs, and passing in the wrong arguments to DiagnoseFloatingImpCast (leading to a badly worded diagnostic). rdar://47644670 Differential revision: https://reviews.llvm.org/D58145 ------------------------------------------------------------------------ llvm-svn: 354129 --- clang/lib/Sema/SemaChecking.cpp | 20 ++++++++++---------- clang/test/SemaCXX/warn-float-conversion.cpp | 12 ++++++------ clang/test/SemaObjC/conversion.m | 7 +++++++ 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 8dc1fdb76988da..b2c727b5c483b7 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -10622,16 +10622,16 @@ static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { // The below checks assume source is floating point. if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; - // If source is floating point but target is not. - if (!ResultBT->isFloatingPoint()) - return DiagnoseFloatingImpCast(S, E, E->getRHS()->getType(), - E->getExprLoc()); - - // If both source and target are floating points. - // Builtin FP kinds are ordered by increasing FP rank. - if (ResultBT->getKind() < RBT->getKind() && - // We don't want to warn for system macro. - !S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) + // If source is floating point but target is an integer. + if (ResultBT->isInteger()) + DiagnoseImpCast(S, E, E->getRHS()->getType(), E->getLHS()->getType(), + E->getExprLoc(), diag::warn_impcast_float_integer); + // If both source and target are floating points. Builtin FP kinds are ordered + // by increasing FP rank. FIXME: except _Float16, we currently emit a bogus + // warning. + else if (ResultBT->isFloatingPoint() && ResultBT->getKind() < RBT->getKind() && + // We don't want to warn for system macro. + !S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) // warn about dropping FP rank. DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(), diag::warn_impcast_float_result_precision); diff --git a/clang/test/SemaCXX/warn-float-conversion.cpp b/clang/test/SemaCXX/warn-float-conversion.cpp index 7dec4844b062e0..fad1ff147e492d 100644 --- a/clang/test/SemaCXX/warn-float-conversion.cpp +++ b/clang/test/SemaCXX/warn-float-conversion.cpp @@ -44,17 +44,17 @@ void Convert(float f, double d, long double ld) { void CompoundAssignment() { int x = 3; - x += 1.234; //expected-warning{{conversion}} - x -= -0.0; //expected-warning{{conversion}} - x *= 1.1f; //expected-warning{{conversion}} - x /= -2.2f; //expected-warning{{conversion}} + x += 1.234; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} + x -= -0.0; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} + x *= 1.1f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} + x /= -2.2f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} - int y = x += 1.4f; //expected-warning{{conversion}} + int y = x += 1.4f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} float z = 1.1f; double w = -2.2; - y += z + w; //expected-warning{{conversion}} + y += z + w; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} } # 1 "foo.h" 3 diff --git a/clang/test/SemaObjC/conversion.m b/clang/test/SemaObjC/conversion.m index 88a1a44b2177be..743f7440e2e431 100644 --- a/clang/test/SemaObjC/conversion.m +++ b/clang/test/SemaObjC/conversion.m @@ -14,4 +14,11 @@ void radar14415662(RDar14415662 *f, char x, int y) { x = y; // expected-warning {{implicit conversion loses integer precision: 'int' to 'char'}} } +__attribute__((objc_root_class)) @interface DoubleProp +@property double d; +@end +void use_double_prop(DoubleProp *dp) { + double local = 42; + dp.d += local; // no warning +} From 8015928085708fd021c3b0ceb75a0b817d9c5faa Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 15 Feb 2019 14:00:25 +0000 Subject: [PATCH 06/35] Merging r353943: ------------------------------------------------------------------------ r353943 | baloghadamsoftware | 2019-02-13 13:25:47 +0100 (Wed, 13 Feb 2019) | 22 lines [Analyzer] Crash fix for FindLastStoreBRVisitor FindLastStoreBRVisitor tries to find the first node in the exploded graph where the current value was assigned to a region. This node is called the "store site". It is identified by a pair of Pred and Succ nodes where Succ already has the binding for the value while Pred does not have it. However the visitor mistakenly identifies a node pair as the store site where the value is a `LazyCompoundVal` and `Pred` does not have a store yet but `Succ` has it. In this case the `LazyCompoundVal` is different in the `Pred` node because it also contains the store which is different in the two nodes. This error may lead to crashes (a declaration is cast to a parameter declaration without check) or misleading bug path notes. In this patch we fix this problem by checking for unequal `LazyCompoundVals`: if their region is equal, and their store is the same as the store of their nodes we consider them as equal when looking for the "store site". This is an approximation because we do not check for differences of the subvalues (structure members or array elements) in the stores. Differential Revision: https://reviews.llvm.org/D58067 ------------------------------------------------------------------------ llvm-svn: 354130 --- .../Core/BugReporterVisitors.cpp | 29 ++++++++++++++++++- clang/test/Analysis/PR40625.cpp | 16 ++++++++++ clang/test/Analysis/uninit-vals.m | 8 ++--- 3 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 clang/test/Analysis/PR40625.cpp diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index da94b6eb21e9b2..ea695c4736a3e4 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -154,6 +154,32 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { return E; } +/// Comparing internal representations of symbolic values (via +/// SVal::operator==()) is a valid way to check if the value was updated, +/// unless it's a LazyCompoundVal that may have a different internal +/// representation every time it is loaded from the state. In this function we +/// do an approximate comparison for lazy compound values, checking that they +/// are the immediate snapshots of the tracked region's bindings within the +/// node's respective states but not really checking that these snapshots +/// actually contain the same set of bindings. +bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal, + const ExplodedNode *RightNode, SVal RightVal) { + if (LeftVal == RightVal) + return true; + + const auto LLCV = LeftVal.getAs(); + if (!LLCV) + return false; + + const auto RLCV = RightVal.getAs(); + if (!RLCV) + return false; + + return LLCV->getRegion() == RLCV->getRegion() && + LLCV->getStore() == LeftNode->getState()->getStore() && + RLCV->getStore() == RightNode->getState()->getStore(); +} + //===----------------------------------------------------------------------===// // Definitions for bug reporter visitors. //===----------------------------------------------------------------------===// @@ -1188,7 +1214,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, if (Succ->getState()->getSVal(R) != V) return nullptr; - if (Pred->getState()->getSVal(R) == V) { + if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) { Optional PS = Succ->getLocationAs(); if (!PS || PS->getLocationValue() != R) return nullptr; @@ -1209,6 +1235,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // UndefinedVal.) if (Optional CE = Succ->getLocationAs()) { if (const auto *VR = dyn_cast(R)) { + const auto *Param = cast(VR->getDecl()); ProgramStateManager &StateMgr = BRC.getStateManager(); diff --git a/clang/test/Analysis/PR40625.cpp b/clang/test/Analysis/PR40625.cpp new file mode 100644 index 00000000000000..6cc27d39b6c089 --- /dev/null +++ b/clang/test/Analysis/PR40625.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core.CallAndMessageUnInitRefArg %s -verify + +void f(const int *end); + +void g(const int (&arrr)[10]) { + f(arrr+sizeof(arrr)); // expected-warning{{1st function call argument is a pointer to uninitialized value}} + // FIXME: This is a false positive that should be fixed. Until then this + // tests the crash fix in FindLastStoreBRVisitor (beside + // uninit-vals.m). +} + +void h() { + int arr[10]; + + g(arr); +} diff --git a/clang/test/Analysis/uninit-vals.m b/clang/test/Analysis/uninit-vals.m index f97af1a6633cce..33352122ca5aa0 100644 --- a/clang/test/Analysis/uninit-vals.m +++ b/clang/test/Analysis/uninit-vals.m @@ -394,11 +394,11 @@ void testSmallStructBitfieldsFirstUnnamed() { struct { int : 4; int y : 4; - } a, b, c; + } a, b, c; // expected-note{{'c' initialized here}} a.y = 2; - b = a; // expected-note{{Value assigned to 'c'}} + b = a; clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -411,11 +411,11 @@ void testSmallStructBitfieldsSecondUnnamed() { struct { int x : 4; int : 4; - } a, b, c; + } a, b, c; // expected-note{{'c' initialized here}} a.x = 1; - b = a; // expected-note{{Value assigned to 'c'}} + b = a; clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} From a7da36bd971a50e8489bdc885a21f4376be9bbca Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 09:31:05 +0000 Subject: [PATCH 07/35] Merging r354035: ------------------------------------------------------------------------ r354035 | brunoricci | 2019-02-14 16:43:17 +0100 (Thu, 14 Feb 2019) | 23 lines [Sema] Fix a regression introduced in "[AST][Sema] Remove CallExpr::setNumArgs" D54902 removed CallExpr::setNumArgs in preparation of tail-allocating the arguments of CallExpr. It did this by allocating storage for max(number of arguments, number of parameters in the prototype). The temporarily nulled arguments however causes issues in BuildResolvedCallExpr when typo correction is done just after the creation of the call expression. This was unfortunately missed by the tests /: To fix this, delay setting the number of arguments to max(number of arguments, number of parameters in the prototype) until we are ready for it. It would be nice to have this encapsulated in CallExpr but this is the best I can come up with under the constraint that we cannot add anything the CallExpr. Fixes PR40286. Differential Revision: https://reviews.llvm.org/D57948 Reviewed By: aaron.ballman ------------------------------------------------------------------------ llvm-svn: 354247 --- clang/include/clang/AST/Expr.h | 5 +++++ clang/lib/Sema/SemaExpr.cpp | 26 ++++++++++++++++++++++---- clang/test/Sema/typo-correction.c | 15 +++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 3de73428829b33..bf4f3babbd3c63 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2577,6 +2577,11 @@ class CallExpr : public Expr { NumArgs = NewNumArgs; } + /// Bluntly set a new number of arguments without doing any checks whatsoever. + /// Only used during construction of a CallExpr in a few places in Sema. + /// FIXME: Find a way to remove it. + void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; } + typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; typedef llvm::iterator_range arg_range; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index db0c62630a9ec0..ff9393a56b9cba 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5676,18 +5676,36 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } if (!getLangOpts().CPlusPlus) { + // Forget about the nulled arguments since typo correction + // do not handle them well. + TheCall->shrinkNumArgs(Args.size()); // C cannot always handle TypoExpr nodes in builtin calls and direct // function calls as their argument checking don't necessarily handle // dependent types properly, so make sure any TypoExprs have been // dealt with. ExprResult Result = CorrectDelayedTyposInExpr(TheCall); if (!Result.isUsable()) return ExprError(); + CallExpr *TheOldCall = TheCall; TheCall = dyn_cast(Result.get()); + bool CorrectedTypos = TheCall != TheOldCall; if (!TheCall) return Result; - // TheCall at this point has max(Args.size(), NumParams) arguments, - // with extra arguments nulled. We don't want to introduce nulled - // arguments in Args and so we only take the first Args.size() arguments. - Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size()); + Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()); + + // A new call expression node was created if some typos were corrected. + // However it may not have been constructed with enough storage. In this + // case, rebuild the node with enough storage. The waste of space is + // immaterial since this only happens when some typos were corrected. + if (CorrectedTypos && Args.size() < NumParams) { + if (Config) + TheCall = CUDAKernelCallExpr::Create( + Context, Fn, cast(Config), Args, ResultTy, VK_RValue, + RParenLoc, NumParams); + else + TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, + RParenLoc, NumParams, UsesADL); + } + // We can now handle the nulled arguments for the default arguments. + TheCall->setNumArgsUnsafe(std::max(Args.size(), NumParams)); } // Bail out early if calling a builtin with custom type checking. diff --git a/clang/test/Sema/typo-correction.c b/clang/test/Sema/typo-correction.c index e7992ac90bb3d6..73ba265509e4ce 100644 --- a/clang/test/Sema/typo-correction.c +++ b/clang/test/Sema/typo-correction.c @@ -100,3 +100,18 @@ void rdar38642201_caller() { structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}} structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}} } + +void PR40286_g(int x, int y); +void PR40286_h(int x, int y, int z); +void PR40286_1(int the_value) { + PR40286_g(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_2(int the_value) { + PR40286_h(the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_3(int the_value) { + PR40286_h(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_4(int the_value) { // expected-note {{'the_value' declared here}} + PR40286_h(the_value, the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'; did you mean 'the_value'?}} +} From 07a7439486a3a7afef93d3c02b9430e1d5552832 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 09:33:35 +0000 Subject: [PATCH 08/35] Merging r354147: ------------------------------------------------------------------------ r354147 | jfb | 2019-02-15 18:26:29 +0100 (Fri, 15 Feb 2019) | 27 lines Variable auto-init of blocks capturing self after init bugfix Summary: Blocks that capture themselves (and escape) after initialization currently codegen wrong because this: bool capturedByInit = Init && emission.IsEscapingByRef && isCapturedBy(D, Init); Address Loc = capturedByInit ? emission.Addr : emission.getObjectAddress(*this); Already adjusts Loc from thr alloca to a GEP. This code: if (emission.IsEscapingByRef) Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false); Was trying to do the same adjustment, and a GEP on a GEP (returning an int) triggers an assertion. Reviewers: ahatanak Subscribers: jkorous, dexonsmith, cfe-commits, rjmccall Tags: #clang Differential Revision: https://reviews.llvm.org/D58218 ------------------------------------------------------------------------ llvm-svn: 354248 --- clang/lib/CodeGen/CGDecl.cpp | 14 ++++----- .../test/CodeGenCXX/trivial-auto-var-init.cpp | 31 ++++++++++++++++--- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index b98657ffd8006c..790a8df3d7e419 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1620,8 +1620,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { bool capturedByInit = Init && emission.IsEscapingByRef && isCapturedBy(D, Init); - Address Loc = - capturedByInit ? emission.Addr : emission.getObjectAddress(*this); + bool locIsByrefHeader = !capturedByInit; + const Address Loc = + locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr; // Note: constexpr already initializes everything correctly. LangOptions::TrivialAutoVarInitKind trivialAutoVarInit = @@ -1637,7 +1638,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { return; // Only initialize a __block's storage: we always initialize the header. - if (emission.IsEscapingByRef) + if (emission.IsEscapingByRef && !locIsByrefHeader) Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false); CharUnits Size = getContext().getTypeSizeInChars(type); @@ -1745,10 +1746,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { } llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace()); - if (Loc.getType() != BP) - Loc = Builder.CreateBitCast(Loc, BP); - - emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant); + emitStoresForConstant( + CGM, D, (Loc.getType() == BP) ? Loc : Builder.CreateBitCast(Loc, BP), + isVolatile, Builder, constant); } /// Emit an expression as an initializer for an object (variable, field, etc.) diff --git a/clang/test/CodeGenCXX/trivial-auto-var-init.cpp b/clang/test/CodeGenCXX/trivial-auto-var-init.cpp index 37ff770abf57eb..0a9ad86c7e2feb 100644 --- a/clang/test/CodeGenCXX/trivial-auto-var-init.cpp +++ b/clang/test/CodeGenCXX/trivial-auto-var-init.cpp @@ -45,14 +45,35 @@ void test_block() { // PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4 // PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8 // PATTERN: %call = call %struct.XYZ* @create( +using Block = void (^)(); +typedef struct XYZ { + Block block; +} * xyz_t; void test_block_self_init() { - using Block = void (^)(); - typedef struct XYZ { - Block block; - } * xyz_t; extern xyz_t create(Block block); __block xyz_t captured = create(^() { - (void)captured; + used(captured); + }); +} + +// Capturing with escape after initialization is also an edge case. +// +// UNINIT-LABEL: test_block_captures_self_after_init( +// ZERO-LABEL: test_block_captures_self_after_init( +// ZERO: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// ZERO: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4 +// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8 +// ZERO: %call = call %struct.XYZ* @create( +// PATTERN-LABEL: test_block_captures_self_after_init( +// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4 +// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8 +// PATTERN: %call = call %struct.XYZ* @create( +void test_block_captures_self_after_init() { + extern xyz_t create(Block block); + __block xyz_t captured; + captured = create(^() { + used(captured); }); } From 25c79d978447cd53224884d1acbe6274578854d0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 09:56:01 +0000 Subject: [PATCH 09/35] Merging r354128 and r354131: ------------------------------------------------------------------------ r354128 | courbet | 2019-02-15 13:58:06 +0100 (Fri, 15 Feb 2019) | 1 line [MergeICmps][NFC] Improve doc. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r354131 | courbet | 2019-02-15 15:17:17 +0100 (Fri, 15 Feb 2019) | 15 lines [MergeICmps] Make base ordering really deterministic. Summary: The idea is that we now manipulate bases through a `unsigned BaseID` based on order of appearance in the comparison chain rather than through the `Value*`. Fixes 40714. Reviewers: gchatelet Subscribers: mgrang, jfb, jdoerfert, llvm-commits, hans Tags: #llvm Differential Revision: https://reviews.llvm.org/D58274 ------------------------------------------------------------------------ llvm-svn: 354249 --- llvm/lib/Transforms/Scalar/MergeICmps.cpp | 227 +++++++++++++--------- 1 file changed, 135 insertions(+), 92 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp index 69fd8b163a070d..a24fee54949d33 100644 --- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp +++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp @@ -11,21 +11,37 @@ // later typically inlined as a chain of efficient hardware comparisons). This // typically benefits c++ member or nonmember operator==(). // -// The basic idea is to replace a larger chain of integer comparisons loaded -// from contiguous memory locations into a smaller chain of such integer +// The basic idea is to replace a longer chain of integer comparisons loaded +// from contiguous memory locations into a shorter chain of larger integer // comparisons. Benefits are double: // - There are less jumps, and therefore less opportunities for mispredictions // and I-cache misses. // - Code size is smaller, both because jumps are removed and because the // encoding of a 2*n byte compare is smaller than that of two n-byte // compares. - +// +// Example: +// +// struct S { +// int a; +// char b; +// char c; +// uint16_t d; +// bool operator==(const S& o) const { +// return a == o.a && b == o.b && c == o.c && d == o.d; +// } +// }; +// +// Is optimized as : +// +// bool S::operator==(const S& o) const { +// return memcmp(this, &o, 8) == 0; +// } +// +// Which will later be expanded (ExpandMemCmp) as a single 8-bytes icmp. +// //===----------------------------------------------------------------------===// -#include -#include -#include -#include #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" @@ -34,6 +50,10 @@ #include "llvm/Pass.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BuildLibCalls.h" +#include +#include +#include +#include using namespace llvm; @@ -50,76 +70,95 @@ static bool isSimpleLoadOrStore(const Instruction *I) { return false; } -// A BCE atom. +// A BCE atom "Binary Compare Expression Atom" represents an integer load +// that is a constant offset from a base value, e.g. `a` or `o.c` in the example +// at the top. struct BCEAtom { - BCEAtom() : GEP(nullptr), LoadI(nullptr), Offset() {} - - const Value *Base() const { return GEP ? GEP->getPointerOperand() : nullptr; } - + BCEAtom() = default; + BCEAtom(GetElementPtrInst *GEP, LoadInst *LoadI, int BaseId, APInt Offset) + : GEP(GEP), LoadI(LoadI), BaseId(BaseId), Offset(Offset) {} + + // We want to order BCEAtoms by (Base, Offset). However we cannot use + // the pointer values for Base because these are non-deterministic. + // To make sure that the sort order is stable, we first assign to each atom + // base value an index based on its order of appearance in the chain of + // comparisons. We call this index `BaseOrdering`. For example, for: + // b[3] == c[2] && a[1] == d[1] && b[4] == c[3] + // | block 1 | | block 2 | | block 3 | + // b gets assigned index 0 and a index 1, because b appears as LHS in block 1, + // which is before block 2. + // We then sort by (BaseOrdering[LHS.Base()], LHS.Offset), which is stable. bool operator<(const BCEAtom &O) const { - assert(Base() && "invalid atom"); - assert(O.Base() && "invalid atom"); - // Just ordering by (Base(), Offset) is sufficient. However because this - // means that the ordering will depend on the addresses of the base - // values, which are not reproducible from run to run. To guarantee - // stability, we use the names of the values if they exist; we sort by: - // (Base.getName(), Base(), Offset). - const int NameCmp = Base()->getName().compare(O.Base()->getName()); - if (NameCmp == 0) { - if (Base() == O.Base()) { - return Offset.slt(O.Offset); - } - return Base() < O.Base(); - } - return NameCmp < 0; + return BaseId != O.BaseId ? BaseId < O.BaseId : Offset.slt(O.Offset); } - GetElementPtrInst *GEP; - LoadInst *LoadI; + GetElementPtrInst *GEP = nullptr; + LoadInst *LoadI = nullptr; + unsigned BaseId = 0; APInt Offset; }; +// A class that assigns increasing ids to values in the order in which they are +// seen. See comment in `BCEAtom::operator<()``. +class BaseIdentifier { +public: + // Returns the id for value `Base`, after assigning one if `Base` has not been + // seen before. + int getBaseId(const Value *Base) { + assert(Base && "invalid base"); + const auto Insertion = BaseToIndex.try_emplace(Base, Order); + if (Insertion.second) + ++Order; + return Insertion.first->second; + } + +private: + unsigned Order = 1; + DenseMap BaseToIndex; +}; + // If this value is a load from a constant offset w.r.t. a base address, and // there are no other users of the load or address, returns the base address and // the offset. -BCEAtom visitICmpLoadOperand(Value *const Val) { - BCEAtom Result; - if (auto *const LoadI = dyn_cast(Val)) { - LLVM_DEBUG(dbgs() << "load\n"); - if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) { - LLVM_DEBUG(dbgs() << "used outside of block\n"); - return {}; - } - // Do not optimize atomic loads to non-atomic memcmp - if (!LoadI->isSimple()) { - LLVM_DEBUG(dbgs() << "volatile or atomic\n"); - return {}; - } - Value *const Addr = LoadI->getOperand(0); - if (auto *const GEP = dyn_cast(Addr)) { - LLVM_DEBUG(dbgs() << "GEP\n"); - if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) { - LLVM_DEBUG(dbgs() << "used outside of block\n"); - return {}; - } - const auto &DL = GEP->getModule()->getDataLayout(); - if (!isDereferenceablePointer(GEP, DL)) { - LLVM_DEBUG(dbgs() << "not dereferenceable\n"); - // We need to make sure that we can do comparison in any order, so we - // require memory to be unconditionnally dereferencable. - return {}; - } - Result.Offset = APInt(DL.getPointerTypeSizeInBits(GEP->getType()), 0); - if (GEP->accumulateConstantOffset(DL, Result.Offset)) { - Result.GEP = GEP; - Result.LoadI = LoadI; - } - } +BCEAtom visitICmpLoadOperand(Value *const Val, BaseIdentifier &BaseId) { + auto *const LoadI = dyn_cast(Val); + if (!LoadI) + return {}; + LLVM_DEBUG(dbgs() << "load\n"); + if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) { + LLVM_DEBUG(dbgs() << "used outside of block\n"); + return {}; + } + // Do not optimize atomic loads to non-atomic memcmp + if (!LoadI->isSimple()) { + LLVM_DEBUG(dbgs() << "volatile or atomic\n"); + return {}; } - return Result; + Value *const Addr = LoadI->getOperand(0); + auto *const GEP = dyn_cast(Addr); + if (!GEP) + return {}; + LLVM_DEBUG(dbgs() << "GEP\n"); + if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) { + LLVM_DEBUG(dbgs() << "used outside of block\n"); + return {}; + } + const auto &DL = GEP->getModule()->getDataLayout(); + if (!isDereferenceablePointer(GEP, DL)) { + LLVM_DEBUG(dbgs() << "not dereferenceable\n"); + // We need to make sure that we can do comparison in any order, so we + // require memory to be unconditionnally dereferencable. + return {}; + } + APInt Offset = APInt(DL.getPointerTypeSizeInBits(GEP->getType()), 0); + if (!GEP->accumulateConstantOffset(DL, Offset)) + return {}; + return BCEAtom(GEP, LoadI, BaseId.getBaseId(GEP->getPointerOperand()), + Offset); } -// A basic block with a comparison between two BCE atoms. +// A basic block with a comparison between two BCE atoms, e.g. `a == o.a` in the +// example at the top. // The block might do extra work besides the atom comparison, in which case // doesOtherWork() returns true. Under some conditions, the block can be // split into the atom comparison part and the "other work" part @@ -137,9 +176,7 @@ class BCECmpBlock { if (Rhs_ < Lhs_) std::swap(Rhs_, Lhs_); } - bool IsValid() const { - return Lhs_.Base() != nullptr && Rhs_.Base() != nullptr; - } + bool IsValid() const { return Lhs_.BaseId != 0 && Rhs_.BaseId != 0; } // Assert the block is consistent: If valid, it should also have // non-null members besides Lhs_ and Rhs_. @@ -265,7 +302,8 @@ bool BCECmpBlock::doesOtherWork() const { // Visit the given comparison. If this is a comparison between two valid // BCE atoms, returns the comparison. BCECmpBlock visitICmp(const ICmpInst *const CmpI, - const ICmpInst::Predicate ExpectedPredicate) { + const ICmpInst::Predicate ExpectedPredicate, + BaseIdentifier &BaseId) { // The comparison can only be used once: // - For intermediate blocks, as a branch condition. // - For the final block, as an incoming value for the Phi. @@ -275,25 +313,27 @@ BCECmpBlock visitICmp(const ICmpInst *const CmpI, LLVM_DEBUG(dbgs() << "cmp has several uses\n"); return {}; } - if (CmpI->getPredicate() == ExpectedPredicate) { - LLVM_DEBUG(dbgs() << "cmp " - << (ExpectedPredicate == ICmpInst::ICMP_EQ ? "eq" : "ne") - << "\n"); - auto Lhs = visitICmpLoadOperand(CmpI->getOperand(0)); - if (!Lhs.Base()) return {}; - auto Rhs = visitICmpLoadOperand(CmpI->getOperand(1)); - if (!Rhs.Base()) return {}; - const auto &DL = CmpI->getModule()->getDataLayout(); - return BCECmpBlock(std::move(Lhs), std::move(Rhs), - DL.getTypeSizeInBits(CmpI->getOperand(0)->getType())); - } - return {}; + if (CmpI->getPredicate() != ExpectedPredicate) + return {}; + LLVM_DEBUG(dbgs() << "cmp " + << (ExpectedPredicate == ICmpInst::ICMP_EQ ? "eq" : "ne") + << "\n"); + auto Lhs = visitICmpLoadOperand(CmpI->getOperand(0), BaseId); + if (!Lhs.BaseId) + return {}; + auto Rhs = visitICmpLoadOperand(CmpI->getOperand(1), BaseId); + if (!Rhs.BaseId) + return {}; + const auto &DL = CmpI->getModule()->getDataLayout(); + return BCECmpBlock(std::move(Lhs), std::move(Rhs), + DL.getTypeSizeInBits(CmpI->getOperand(0)->getType())); } // Visit the given comparison block. If this is a comparison between two valid // BCE atoms, returns the comparison. BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, - const BasicBlock *const PhiBlock) { + const BasicBlock *const PhiBlock, + BaseIdentifier &BaseId) { if (Block->empty()) return {}; auto *const BranchI = dyn_cast(Block->getTerminator()); if (!BranchI) return {}; @@ -306,7 +346,7 @@ BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, auto *const CmpI = dyn_cast(Val); if (!CmpI) return {}; LLVM_DEBUG(dbgs() << "icmp\n"); - auto Result = visitICmp(CmpI, ICmpInst::ICMP_EQ); + auto Result = visitICmp(CmpI, ICmpInst::ICMP_EQ, BaseId); Result.CmpI = CmpI; Result.BranchI = BranchI; return Result; @@ -323,7 +363,8 @@ BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, assert(BranchI->getNumSuccessors() == 2 && "expecting a cond branch"); BasicBlock *const FalseBlock = BranchI->getSuccessor(1); auto Result = visitICmp( - CmpI, FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE); + CmpI, FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE, + BaseId); Result.CmpI = CmpI; Result.BranchI = BranchI; return Result; @@ -335,9 +376,9 @@ static inline void enqueueBlock(std::vector &Comparisons, BCECmpBlock &Comparison) { LLVM_DEBUG(dbgs() << "Block '" << Comparison.BB->getName() << "': Found cmp of " << Comparison.SizeBits() - << " bits between " << Comparison.Lhs().Base() << " + " + << " bits between " << Comparison.Lhs().BaseId << " + " << Comparison.Lhs().Offset << " and " - << Comparison.Rhs().Base() << " + " + << Comparison.Rhs().BaseId << " + " << Comparison.Rhs().Offset << "\n"); LLVM_DEBUG(dbgs() << "\n"); Comparisons.push_back(Comparison); @@ -360,8 +401,8 @@ class BCECmpChain { private: static bool IsContiguous(const BCECmpBlock &First, const BCECmpBlock &Second) { - return First.Lhs().Base() == Second.Lhs().Base() && - First.Rhs().Base() == Second.Rhs().Base() && + return First.Lhs().BaseId == Second.Lhs().BaseId && + First.Rhs().BaseId == Second.Rhs().BaseId && First.Lhs().Offset + First.SizeBits() / 8 == Second.Lhs().Offset && First.Rhs().Offset + First.SizeBits() / 8 == Second.Rhs().Offset; } @@ -385,11 +426,12 @@ BCECmpChain::BCECmpChain(const std::vector &Blocks, PHINode &Phi, assert(!Blocks.empty() && "a chain should have at least one block"); // Now look inside blocks to check for BCE comparisons. std::vector Comparisons; + BaseIdentifier BaseId; for (size_t BlockIdx = 0; BlockIdx < Blocks.size(); ++BlockIdx) { BasicBlock *const Block = Blocks[BlockIdx]; assert(Block && "invalid block"); BCECmpBlock Comparison = visitCmpBlock(Phi.getIncomingValueForBlock(Block), - Block, Phi.getParent()); + Block, Phi.getParent(), BaseId); Comparison.BB = Block; if (!Comparison.IsValid()) { LLVM_DEBUG(dbgs() << "chain with invalid BCECmpBlock, no merge.\n"); @@ -466,9 +508,10 @@ BCECmpChain::BCECmpChain(const std::vector &Blocks, PHINode &Phi, #endif // MERGEICMPS_DOT_ON // Reorder blocks by LHS. We can do that without changing the // semantics because we are only accessing dereferencable memory. - llvm::sort(Comparisons_, [](const BCECmpBlock &a, const BCECmpBlock &b) { - return a.Lhs() < b.Lhs(); - }); + llvm::sort(Comparisons_, + [](const BCECmpBlock &LhsBlock, const BCECmpBlock &RhsBlock) { + return LhsBlock.Lhs() < RhsBlock.Lhs(); + }); #ifdef MERGEICMPS_DOT_ON errs() << "AFTER REORDERING:\n\n"; dump(); From 783fd931b518135bebc62c72aef4828c884523bf Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 10:23:16 +0000 Subject: [PATCH 10/35] Merging r354144: ------------------------------------------------------------------------ r354144 | spatel | 2019-02-15 17:31:55 +0100 (Fri, 15 Feb 2019) | 3 lines [InstCombine] fix crash while trying to narrow a binop of shuffles (PR40734) https://bugs.llvm.org/show_bug.cgi?id=40734 ------------------------------------------------------------------------ llvm-svn: 354252 --- .../InstCombine/InstructionCombining.cpp | 3 ++- llvm/test/Transforms/InstCombine/vec_shuffle.ll | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index f530ee1246e8c2..fef051aa1b7c35 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1376,7 +1376,8 @@ Instruction *InstCombiner::foldVectorBinop(BinaryOperator &Inst) { if (match(LHS, m_ShuffleVector(m_Value(L0), m_Value(L1), m_Constant(Mask))) && match(RHS, m_ShuffleVector(m_Value(R0), m_Value(R1), m_Specific(Mask))) && LHS->hasOneUse() && RHS->hasOneUse() && - cast(LHS)->isConcat()) { + cast(LHS)->isConcat() && + cast(RHS)->isConcat()) { // This transform does not have the speculative execution constraint as // below because the shuffle is a concatenation. The new binops are // operating on exactly the same elements as the existing binop. diff --git a/llvm/test/Transforms/InstCombine/vec_shuffle.ll b/llvm/test/Transforms/InstCombine/vec_shuffle.ll index b82c8117eebf58..8f6818f4eb79d8 100644 --- a/llvm/test/Transforms/InstCombine/vec_shuffle.ll +++ b/llvm/test/Transforms/InstCombine/vec_shuffle.ll @@ -1114,3 +1114,18 @@ define <2 x float> @frem_splat_constant1(<2 x float> %x) { ret <2 x float> %r } +; Equivalent shuffle masks, but only one is a narrowing op. + +define <2 x i1> @PR40734(<1 x i1> %x, <4 x i1> %y) { +; CHECK-LABEL: @PR40734( +; CHECK-NEXT: [[WIDEN:%.*]] = shufflevector <1 x i1> zeroinitializer, <1 x i1> [[X:%.*]], <2 x i32> +; CHECK-NEXT: [[NARROW:%.*]] = shufflevector <4 x i1> [[Y:%.*]], <4 x i1> undef, <2 x i32> +; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[WIDEN]], [[NARROW]] +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %widen = shufflevector <1 x i1> zeroinitializer, <1 x i1> %x, <2 x i32> + %narrow = shufflevector <4 x i1> %y, <4 x i1> undef, <2 x i32> + %r = and <2 x i1> %widen, %narrow + ret <2 x i1> %r +} + From 46fbca3530b2052985f2461e3579a60320944f79 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 10:25:29 +0000 Subject: [PATCH 11/35] Merging r353642: ------------------------------------------------------------------------ r353642 | teemperor | 2019-02-10 16:23:58 +0100 (Sun, 10 Feb 2019) | 13 lines lldb: Fix compilation on OpenBSD Summary: Update the OpenBSD Host.cpp for the new SetFile() function signature. Fixes compiling lldb on OpenBSD. Reviewers: krytarowski Reviewed By: krytarowski Subscribers: lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D57907 ------------------------------------------------------------------------ llvm-svn: 354253 --- lldb/source/Host/openbsd/Host.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lldb/source/Host/openbsd/Host.cpp b/lldb/source/Host/openbsd/Host.cpp index cba1f4ee6b7cb2..8db0498d14b56e 100644 --- a/lldb/source/Host/openbsd/Host.cpp +++ b/lldb/source/Host/openbsd/Host.cpp @@ -68,8 +68,7 @@ GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, cstr = data.GetCStr(&offset); if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, false, - FileSpec::Style::native); + process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); if (!(match_info_ptr == NULL || NameMatches( From 096ef4c9f2ecb0b17df61c48d6601d32f9eaeeef Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 10:30:57 +0000 Subject: [PATCH 12/35] Merging r354029: ------------------------------------------------------------------------ r354029 | mgorny | 2019-02-14 14:52:31 +0100 (Thu, 14 Feb 2019) | 7 lines [lldb] [MainLoop] Report errno for failed kevent() Modify the kevent() error reporting to use errno rather than returning the return value. At least on FreeBSD and NetBSD, kevent() always returns -1 in case of error, and the actual error is returned via errno. Differential Revision: https://reviews.llvm.org/D58229 ------------------------------------------------------------------------ llvm-svn: 354254 --- lldb/source/Host/common/MainLoop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp index 39c353e6717ece..2887feb3e26459 100644 --- a/lldb/source/Host/common/MainLoop.cpp +++ b/lldb/source/Host/common/MainLoop.cpp @@ -109,7 +109,7 @@ Status MainLoop::RunImpl::Poll() { out_events, llvm::array_lengthof(out_events), nullptr); if (num_events < 0) - return Status("kevent() failed with error %d\n", num_events); + return Status(errno, eErrorTypePOSIX); return Status(); } From 81bd9dbdab9b0f514339927cd33ca105956d7dfe Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 10:31:46 +0000 Subject: [PATCH 13/35] Merging r354122: ------------------------------------------------------------------------ r354122 | mgorny | 2019-02-15 13:13:02 +0100 (Fri, 15 Feb 2019) | 10 lines [lldb] [MainLoop] Add kevent() EINTR handling Add missing EINTR handling for kevent() calls. If the call is interrupted, return from Poll() as if zero events were returned and let the polling resume on next iteration. This fixes test flakiness on NetBSD. Includes a test case suggested by Pavel Labath on D42206. Differential Revision: https://reviews.llvm.org/D58230 ------------------------------------------------------------------------ llvm-svn: 354255 --- lldb/source/Host/common/MainLoop.cpp | 10 ++++++++-- lldb/unittests/Host/MainLoopTest.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp index 2887feb3e26459..337ddd51dd6b9e 100644 --- a/lldb/source/Host/common/MainLoop.cpp +++ b/lldb/source/Host/common/MainLoop.cpp @@ -108,8 +108,14 @@ Status MainLoop::RunImpl::Poll() { num_events = kevent(loop.m_kqueue, in_events.data(), in_events.size(), out_events, llvm::array_lengthof(out_events), nullptr); - if (num_events < 0) - return Status(errno, eErrorTypePOSIX); + if (num_events < 0) { + if (errno == EINTR) { + // in case of EINTR, let the main loop run one iteration + // we need to zero num_events to avoid assertions failing + num_events = 0; + } else + return Status(errno, eErrorTypePOSIX); + } return Status(); } diff --git a/lldb/unittests/Host/MainLoopTest.cpp b/lldb/unittests/Host/MainLoopTest.cpp index 8f2c55c2416df7..6b7a5cf1f55de5 100644 --- a/lldb/unittests/Host/MainLoopTest.cpp +++ b/lldb/unittests/Host/MainLoopTest.cpp @@ -137,4 +137,28 @@ TEST_F(MainLoopTest, Signal) { ASSERT_TRUE(loop.Run().Success()); ASSERT_EQ(1u, callback_count); } + +// Test that a signal which is not monitored by the MainLoop does not +// cause a premature exit. +TEST_F(MainLoopTest, UnmonitoredSignal) { + MainLoop loop; + Status error; + struct sigaction sa; + sa.sa_sigaction = [](int, siginfo_t *, void *) { }; + sa.sa_flags = SA_SIGINFO; // important: no SA_RESTART + sigemptyset(&sa.sa_mask); + ASSERT_EQ(0, sigaction(SIGUSR2, &sa, nullptr)); + + auto handle = loop.RegisterSignal(SIGUSR1, make_callback(), error); + ASSERT_TRUE(error.Success()); + std::thread killer([]() { + sleep(1); + kill(getpid(), SIGUSR2); + sleep(1); + kill(getpid(), SIGUSR1); + }); + ASSERT_TRUE(loop.Run().Success()); + killer.join(); + ASSERT_EQ(1u, callback_count); +} #endif From 60514070986e558b264f9174249da70728b421a1 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 10:39:35 +0000 Subject: [PATCH 14/35] Merging r353907: ------------------------------------------------------------------------ r353907 | rnk | 2019-02-13 02:39:32 +0100 (Wed, 13 Feb 2019) | 6 lines [MC] Make symbol version errors non-fatal We stil don't have a source location, which is pretty lame, but at least we won't tell the user to file a clang bug report anymore. Fixes PR40712 ------------------------------------------------------------------------ llvm-svn: 354257 --- llvm/lib/MC/ELFObjectWriter.cpp | 18 ++++++++++++------ llvm/test/MC/ELF/invalid-symver.s | 2 +- llvm/test/MC/ELF/multiple-different-symver.s | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 89f3b30cddd6f4..ade858113a3009 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -1275,14 +1275,20 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, if (!Symbol.isUndefined() && !Rest.startswith("@@@")) continue; - // FIXME: produce a better error message. + // FIXME: Get source locations for these errors or diagnose them earlier. if (Symbol.isUndefined() && Rest.startswith("@@") && - !Rest.startswith("@@@")) - report_fatal_error("A @@ version cannot be undefined"); + !Rest.startswith("@@@")) { + Asm.getContext().reportError(SMLoc(), "versioned symbol " + AliasName + + " must be defined"); + continue; + } - if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) - report_fatal_error(llvm::Twine("Multiple symbol versions defined for ") + - Symbol.getName()); + if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) { + Asm.getContext().reportError( + SMLoc(), llvm::Twine("multiple symbol versions defined for ") + + Symbol.getName()); + continue; + } Renames.insert(std::make_pair(&Symbol, Alias)); } diff --git a/llvm/test/MC/ELF/invalid-symver.s b/llvm/test/MC/ELF/invalid-symver.s index 3c4f8c084b94b6..d9f97b102b579b 100644 --- a/llvm/test/MC/ELF/invalid-symver.s +++ b/llvm/test/MC/ELF/invalid-symver.s @@ -1,7 +1,7 @@ // RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2> %t.out // RUN: FileCheck --input-file=%t.out %s -// CHECK: A @@ version cannot be undefined +// CHECK: error: versioned symbol foo@@bar must be defined .symver undefined, foo@@bar .long undefined diff --git a/llvm/test/MC/ELF/multiple-different-symver.s b/llvm/test/MC/ELF/multiple-different-symver.s index d7706f89f41982..c34626c08173c2 100644 --- a/llvm/test/MC/ELF/multiple-different-symver.s +++ b/llvm/test/MC/ELF/multiple-different-symver.s @@ -1,6 +1,6 @@ // RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2>&1 | FileCheck %s -// CHECK: Multiple symbol versions defined for foo +// CHECK: error: multiple symbol versions defined for foo .symver foo, foo@1 .symver foo, foo@2 From cc3d3f1f0762c8d9bee54748d840669db4654690 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 18 Feb 2019 11:21:42 +0000 Subject: [PATCH 15/35] Merging r354034 and r354117: ------------------------------------------------------------------------ r354034 | rksimon | 2019-02-14 15:45:32 +0100 (Thu, 14 Feb 2019) | 1 line [X86][AVX] Add PR40730 test case ------------------------------------------------------------------------ ------------------------------------------------------------------------ r354117 | rksimon | 2019-02-15 12:39:21 +0100 (Fri, 15 Feb 2019) | 9 lines [X86][AVX] lowerShuffleAsLanePermuteAndPermute - fully populate the lane shuffle mask (PR40730) As detailed on PR40730, we are not correctly filling in the lane shuffle mask (D53148/rL344446) - we fill in for the correct src lane but don't add it to the correct mask element, so any reference to the correct element is likely to see an UNDEF mask index. This allows constant folding to propagate UNDEFs prior to the lane mask being (correctly) lowered to vperm2f128. This patch fixes the issue by fully populating the lane shuffle mask - this is more than is necessary (if we only filled in the required mask elements we might be able to match other shuffle instructions - broadcasts etc.), but its the most cautious approach as this needs to be cherrypicked into the 8.0.0 release branch. Differential Revision: https://reviews.llvm.org/D58237 ------------------------------------------------------------------------ llvm-svn: 354260 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 13 +++++++-- llvm/test/CodeGen/X86/pr40730.ll | 36 +++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/X86/pr40730.ll diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index f4f37a894620ed..e1a6d22f061655 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -13884,7 +13884,6 @@ static SDValue lowerVectorShuffleAsLanePermuteAndPermute( int NumEltsPerLane = NumElts / NumLanes; SmallVector SrcLaneMask(NumLanes, SM_SentinelUndef); - SmallVector LaneMask(NumElts, SM_SentinelUndef); SmallVector PermMask(NumElts, SM_SentinelUndef); for (int i = 0; i != NumElts; ++i) { @@ -13899,10 +13898,20 @@ static SDValue lowerVectorShuffleAsLanePermuteAndPermute( return SDValue(); SrcLaneMask[DstLane] = SrcLane; - LaneMask[i] = (SrcLane * NumEltsPerLane) + (i % NumEltsPerLane); PermMask[i] = (DstLane * NumEltsPerLane) + (M % NumEltsPerLane); } + // Make sure we set all elements of the lane mask, to avoid undef propagation. + SmallVector LaneMask(NumElts, SM_SentinelUndef); + for (int DstLane = 0; DstLane != NumLanes; ++DstLane) { + int SrcLane = SrcLaneMask[DstLane]; + if (0 <= SrcLane) + for (int j = 0; j != NumEltsPerLane; ++j) { + LaneMask[(DstLane * NumEltsPerLane) + j] = + (SrcLane * NumEltsPerLane) + j; + } + } + // If we're only shuffling a single lowest lane and the rest are identity // then don't bother. // TODO - isShuffleMaskInputInPlace could be extended to something like this. diff --git a/llvm/test/CodeGen/X86/pr40730.ll b/llvm/test/CodeGen/X86/pr40730.ll new file mode 100644 index 00000000000000..12b372dea33bbe --- /dev/null +++ b/llvm/test/CodeGen/X86/pr40730.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s + +define <8 x i32> @shuffle_v8i32_0dcd3f14(<8 x i32> %a, <8 x i32> %b) { +; CHECK-LABEL: shuffle_v8i32_0dcd3f14: +; CHECK: # %bb.0: +; CHECK-NEXT: vextractf128 $1, %ymm0, %xmm2 +; CHECK-NEXT: vblendps {{.*#+}} xmm2 = xmm2[0],xmm0[1,2,3] +; CHECK-NEXT: vpermilps {{.*#+}} xmm2 = xmm2[3,1,1,0] +; CHECK-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; CHECK-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3,2,3] +; CHECK-NEXT: vpermilpd {{.*#+}} ymm1 = ymm1[0,0,3,2] +; CHECK-NEXT: vblendps {{.*#+}} ymm0 = ymm0[0],ymm1[1,2,3],ymm0[4],ymm1[5],ymm0[6,7] +; CHECK-NEXT: retq + %shuffle = shufflevector <8 x i32> %a, <8 x i32> %b, <8 x i32> + ret <8 x i32> %shuffle +} + +; CHECK: .LCPI1_0: +; CHECK-NEXT: .quad 60129542157 +; CHECK-NEXT: .quad 60129542157 +; CHECK-NEXT: .quad 68719476736 +; CHECK-NEXT: .quad 60129542157 + +define <8 x i32> @shuffle_v8i32_0dcd3f14_constant(<8 x i32> %a0) { +; CHECK-LABEL: shuffle_v8i32_0dcd3f14_constant: +; CHECK: # %bb.0: +; CHECK-NEXT: vextractf128 $1, %ymm0, %xmm1 +; CHECK-NEXT: vblendps {{.*#+}} xmm1 = xmm1[0],xmm0[1,2,3] +; CHECK-NEXT: vpermilps {{.*#+}} xmm1 = xmm1[3,1,1,0] +; CHECK-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; CHECK-NEXT: vblendps {{.*#+}} ymm0 = ymm0[0],mem[1,2,3],ymm0[4],mem[5],ymm0[6,7] +; CHECK-NEXT: retq + %res = shufflevector <8 x i32> %a0, <8 x i32> , <8 x i32> + ret <8 x i32> %res +} From e3d91da768ac1ae40b2059471676ef3574aa2a1a Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 18 Feb 2019 17:59:47 +0000 Subject: [PATCH 16/35] [ReleaseNotes] Add note about removal of Nios2 backend. Add some notes on X86 changes. llvm-svn: 354281 --- llvm/docs/ReleaseNotes.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 9e2ee95c651944..7129b69c9a648a 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -134,6 +134,18 @@ Changes to the X86 Target * Machine model for AMD bdver2 (Piledriver) CPU was added. It is used to support instruction scheduling and other instruction cost heuristics. +* New AVX512F gather and scatter intrinsics were added that take a mask + instead of a scalar integer. This removes the need for a bitcast in IR. The + new intrinsics are named like the old intrinsics with ``llvm.avx512.`` + replaced with ``llvm.avx512.mask.``. The old intrinsics will be removed in a + future release. + +* Added ``cascadelake`` as a CPU name for -march. This is ``skylake-avx512`` + with the addition of the ``avx512vnni`` instruction set. + +* ADCX instruction will no longer be emitted. This instruction is rarely better + than the legacy ADC instruction and just increased code size. + Changes to the AMDGPU Target ----------------------------- @@ -156,6 +168,10 @@ use for it will be to add support for returning small structs as multiple return values, once the underlying WebAssembly platform itself supports it. Additionally, multithreading support is not yet included in the stable ABI. +Changes to the Nios2 Target +--------------------------- + +* The Nios2 target was removed from this release. Changes to the OCaml bindings ----------------------------- From 79a42b61791952bf5ff7e5e2eaa32402ac65d06f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 19 Feb 2019 13:14:28 +0000 Subject: [PATCH 17/35] docs: Remove in-progress warning llvm-svn: 354320 --- llvm/docs/ReleaseNotes.rst | 45 ++++++++++++++++++-------------------- llvm/docs/index.rst | 5 ----- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 7129b69c9a648a..5de898cd779505 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -5,12 +5,6 @@ LLVM 8.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - - Introduction ============ @@ -31,6 +25,25 @@ LLVM web page, this document applies to the *next* release, not the current one. To see the release notes for a specific release, please see the `releases page `_. +Minimum Required Compiler Version +================================= +As `discussed on the mailing list +`_, +building LLVM will soon require more recent toolchains as follows: + +============= ==== +Clang 3.5 +Apple Clang 6.0 +GCC 5.1 +Visual Studio 2017 +============= ==== + +A new CMake check when configuring LLVM provides a soft-error if your +toolchain will become unsupported soon. You can opt out of the soft-error by +setting the ``LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN`` CMake variable to +``ON``. + + Non-comprehensive list of changes in this release ================================================= .. NOTE @@ -40,27 +53,11 @@ Non-comprehensive list of changes in this release functionality, or simply have a lot to talk about), see the `NOTE` below for adding a new subsection. -* As `discussed on the mailing list - `_, - building LLVM will soon require more recent toolchains as follows: - - ============= ==== - Clang 3.5 - Apple Clang 6.0 - GCC 5.1 - Visual Studio 2017 - ============= ==== - - A new CMake check when configuring LLVM provides a soft-error if your - toolchain will become unsupported soon. You can opt out of the soft-error by - setting the ``LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN`` CMake variable to - ``ON``. - * The **llvm-cov** tool can now export lcov trace files using the `-format=lcov` option of the `export` command. -* The add_llvm_loadable_module CMake macro has been removed. The - add_llvm_library macro with the MODULE argument now provides the same +* The ``add_llvm_loadable_module`` CMake macro has been removed. The + ``add_llvm_library`` macro with the ``MODULE`` argument now provides the same functionality. See `Writing an LLVM Pass `_. diff --git a/llvm/docs/index.rst b/llvm/docs/index.rst index 4527fe5105346b..49bd327f47dec2 100644 --- a/llvm/docs/index.rst +++ b/llvm/docs/index.rst @@ -1,11 +1,6 @@ Overview ======== -.. warning:: - - If you are using a released version of LLVM, see `the download page - `_ to find your documentation. - The LLVM compiler infrastructure supports a wide range of projects, from industrial strength compilers to specialized JIT applications to small research projects. From 81717ef7132c92ef47db5e7c81dc6dc81ebac982 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 19 Feb 2019 13:19:05 +0000 Subject: [PATCH 18/35] remove another in-progress note llvm-svn: 354321 --- llvm/docs/ReleaseNotes.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 5de898cd779505..1a5099cdba9a7d 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -20,11 +20,6 @@ have questions or comments, the `LLVM Developer's Mailing List `_ is a good place to send them. -Note that if you are reading this file from a Subversion checkout or the main -LLVM web page, this document applies to the *next* release, not the current -one. To see the release notes for a specific release, please see the `releases -page `_. - Minimum Required Compiler Version ================================= As `discussed on the mailing list From 6a57428aa6c92a5cd47783f21bebb5758d8f6367 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 19 Feb 2019 13:53:16 +0000 Subject: [PATCH 19/35] ReleaseNotes: remove in-progress warning, and minor tweaks llvm-svn: 354326 --- clang/docs/ReleaseNotes.rst | 21 +++++---------------- clang/docs/UsersManual.rst | 2 ++ 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 50bf636a51f437..62c426f9f2f32d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -======================================= -Clang 8.0.0 (In-Progress) Release Notes -======================================= +========================= +Clang 8.0.0 Release Notes +========================= .. contents:: :local: @@ -8,12 +8,6 @@ Clang 8.0.0 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Clang 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -30,11 +24,6 @@ For more information about Clang or LLVM, including information about the latest release, please see the `Clang Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Clang 8.0.0? ========================== @@ -50,7 +39,7 @@ Major New Features profile data captured for one version of a program to be applied when building another version where symbols have changed (for example, due to renaming a class or namespace). - See the :doc:`UsersManual` for details. + See the :ref:`UsersManual ` for details. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,7 +127,7 @@ New Compiler Flags Clang has now options to filter or exclude some files when instrumenting for gcov-based profiling. - See the :doc:`UsersManual` for details. + See the `UsersManual `_ for details. - When using a custom stack alignment, the ``stackrealign`` attribute is now implicitly set on the main function. diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 7634d24eb5a6ac..38f7615bf95b01 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1799,6 +1799,8 @@ In these cases, you can use the flag ``-fno-profile-instr-generate`` (or Note that these flags should appear after the corresponding profile flags to have an effect. +.. _profile_remapping: + Profile remapping ^^^^^^^^^^^^^^^^^ From 363f1d0f800b3e390f16c7effa4da7e92b35a15e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 19 Feb 2019 13:58:21 +0000 Subject: [PATCH 20/35] ReleaseNotes: remove in-progress warning and doxygen link llvm-svn: 354327 --- clang-tools-extra/docs/ReleaseNotes.rst | 17 +++-------------- clang-tools-extra/docs/index.rst | 18 ------------------ 2 files changed, 3 insertions(+), 32 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8731dc73c64879..09445ae21592f8 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -=================================================== -Extra Clang Tools 8.0.0 (In-Progress) Release Notes -=================================================== +===================================== +Extra Clang Tools 8.0.0 Release Notes +===================================== .. contents:: :local: @@ -8,12 +8,6 @@ Extra Clang Tools 8.0.0 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Extra Clang Tools 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -27,11 +21,6 @@ For more information about Clang or LLVM, including information about the latest release, please see the `Clang Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Extra Clang Tools 8.0.0? ====================================== diff --git a/clang-tools-extra/docs/index.rst b/clang-tools-extra/docs/index.rst index 8e6beb35a60918..55fd1a6d08be2a 100644 --- a/clang-tools-extra/docs/index.rst +++ b/clang-tools-extra/docs/index.rst @@ -29,24 +29,6 @@ Contents clang-doc -Doxygen Documentation -===================== -The Doxygen documentation describes the **internal** software that makes up the -tools of clang-tools-extra, not the **external** use of these tools. The Doxygen -documentation contains no instructions about how to use the tools, only the APIs -that make up the software. For usage instructions, please see the user's guide -or reference manual for each tool. - -* `Doxygen documentation`_ - -.. _`Doxygen documentation`: doxygen/annotated.html - -.. note:: - This documentation is generated directly from the source code with doxygen. - Since the tools of clang-tools-extra are constantly under active - development, what you're about to read is out of date! - - Indices and tables ================== From b1c5e90a1f9246332b42c95ffe0b33619c818a90 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 19 Feb 2019 14:37:52 +0000 Subject: [PATCH 21/35] ReleaseNotes: remove in-progress warning llvm-svn: 354331 --- lld/docs/ReleaseNotes.rst | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 0bebfb3fb1cec8..aab52573d925a4 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -5,11 +5,6 @@ lld 8.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 8.0.0 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -18,7 +13,7 @@ Mach-O (macOS), MinGW and WebAssembly. lld is command-line-compatible with GNU linkers and Microsoft link.exe and is significantly faster than the system default linkers. -nlld 8.0.0 has lots of feature improvements and bug fixes. +lld 8.0.0 has lots of feature improvements and bug fixes. Non-comprehensive list of changes in this release ================================================= From fbaa8ef44d5a88b59da5f0c11edb01e44e9cb57e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 19 Feb 2019 14:49:37 +0000 Subject: [PATCH 22/35] ReleaseNotes: remove in-progress warning llvm-svn: 354334 --- libcxx/docs/ReleaseNotes.rst | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index 20be9f627ef86b..c6db1e7683430c 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -======================================== -Libc++ 8.0.0 (In-Progress) Release Notes -======================================== +========================== +Libc++ 8.0.0 Release Notes +========================== .. contents:: :local: @@ -8,12 +8,6 @@ Libc++ 8.0.0 (In-Progress) Release Notes Written by the `Libc++ Team `_ -.. warning:: - - These are in-progress notes for the upcoming libc++ 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -27,11 +21,6 @@ be downloaded from the `LLVM releases web site `_. For more information about libc++, please see the `Libc++ Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Libc++ web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Libc++ 8.0.0? =========================== From 5decb13379c14539c5b8920817e2cc66625e8ecf Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 20 Feb 2019 08:21:37 +0000 Subject: [PATCH 23/35] Merging r354422: ------------------------------------------------------------------------ r354422 | tstellar | 2019-02-20 02:40:35 +0100 (Wed, 20 Feb 2019) | 11 lines ELF: Fix typo in --build-id option description Reviewers: ruiu, espindola Reviewed By: ruiu Subscribers: emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58265 ------------------------------------------------------------------------ llvm-svn: 354440 --- lld/ELF/Options.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index bc203193661b44..439fe341644c81 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -30,7 +30,7 @@ def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">; def build_id: F<"build-id">, HelpText<"Alias for --build-id=fast">; def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">, - MetaVarName<"[fast,md5,sha,uuid,0x]">; + MetaVarName<"[fast,md5,sha1,uuid,0x]">; defm check_sections: B<"check-sections", "Check section addresses for overlaps (default)", From d6e87c2d2e00a418c2d08e5fff93adbd6f6cb312 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 20 Feb 2019 11:31:40 +0000 Subject: [PATCH 24/35] ReleaseNotes: initial ppc support in llvm-exegesis llvm-svn: 354448 --- llvm/docs/ReleaseNotes.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 1a5099cdba9a7d..8113ef3fa8f37c 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -118,7 +118,8 @@ Changes to the MIPS Target Changes to the PowerPC Target ----------------------------- - During this release ... +* Initial PowerPC support in llvm-exegesis, just enough to run it in latency + mode for at least some opcodes. Changes to the X86 Target ------------------------- From 6977a571fc1609b3e99155c8744b645787439e96 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 20 Feb 2019 11:40:19 +0000 Subject: [PATCH 25/35] ReleaseNotes: mention the new rotation builtins, text by Sanjay llvm-svn: 354450 --- clang/docs/ReleaseNotes.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 62c426f9f2f32d..b0b09f14e3b732 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -120,6 +120,13 @@ Non-comprehensive list of changes in this release - Improved support for MIPS N32 ABI and MIPS R6 target triples. +- Clang now includes builtin functions for bitwise rotation of common value + sizes, such as: `__builtin_rotateleft32 + `_ + +- Improved optimization for the corresponding MSVC compatibility builtins such + as ``_rotl()``. + New Compiler Flags ------------------ From e4bde922b56fe2d9f15540fe5009683eb0e50bed Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 20 Feb 2019 12:38:35 +0000 Subject: [PATCH 26/35] ReleaseNotes: AArch64 tiny code model llvm-svn: 354457 --- llvm/docs/ReleaseNotes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 8113ef3fa8f37c..4851c8c215a95d 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -79,6 +79,9 @@ Changes to the LLVM IR Changes to the AArch64 Target ----------------------------- +* Initial support for the Tiny code model, where code and its statically + defined symbols must live within 1MB of each other. + * Added support for the ``.arch_extension`` assembler directive, just like on ARM. From b936e1cf9766ce2f0e98b2ea1ceb3d96ed029bac Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 20 Feb 2019 12:43:20 +0000 Subject: [PATCH 27/35] ReleaseNotes: all PowerPC changes llvm-svn: 354458 --- llvm/docs/ReleaseNotes.rst | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 4851c8c215a95d..ddf12f61de300b 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -121,8 +121,40 @@ Changes to the MIPS Target Changes to the PowerPC Target ----------------------------- -* Initial PowerPC support in llvm-exegesis, just enough to run it in latency - mode for at least some opcodes. +* Switched to non-PIC default + +* Deprecated Darwin support + +* Enabled Out-of-Order scheduling for P9 + +* Better overload rules for compatible vector type parameter + +* Support constraint ‘wi’, modifier ‘x’ and VSX registers in inline asm + +* More ``__float128`` support + +* Added new builtins like vector int128 ``pack``/``unpack`` and + ``stxvw4x.be``/``stxvd2x.be`` + +* Provided significant improvements to the automatic vectorizer + +* Code-gen improvements (especially for Power9) + +* Fixed some long-standing bugs in the back end + +* Added experimental prologue/epilogue improvements + +* Enabled builtins tests in compiler-rt + +* Add ``___fixunstfti``/``floattitf`` in compiler-rt to support conversion + between IBM double-double and unsigned int128 + +* Disable randomized address space when running the sanitizers on Linux ppc64le + +* Completed support in LLD for ELFv2 + +* Enabled llvm-exegesis latency mode for PPC + Changes to the X86 Target ------------------------- From 83dcd05f7b3bb23509bbaea752cb4dfa781a1fa9 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 20 Feb 2019 12:51:02 +0000 Subject: [PATCH 28/35] Merging r354351: ------------------------------------------------------------------------ r354351 | hans | 2019-02-19 17:58:25 +0100 (Tue, 19 Feb 2019) | 12 lines Remove extraneous space in MSVC-style diagnostic output There was an extra space between the file location and the diagnostic message: /tmp/a.c(1,12): warning: unused parameter 'unused' the tests didn't catch this due to FileCheck not running in --strict-whitespace mode. Reported by Marco: http://lists.llvm.org/pipermail/cfe-dev/2019-February/061326.html Differential revision: https://reviews.llvm.org/D58377 ------------------------------------------------------------------------ llvm-svn: 354459 --- clang/lib/Frontend/TextDiagnostic.cpp | 2 +- clang/test/Misc/diag-format.c | 44 +++++++++++++-------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/clang/lib/Frontend/TextDiagnostic.cpp b/clang/lib/Frontend/TextDiagnostic.cpp index 35b99b10f94a40..8b18fcccb4623e 100644 --- a/clang/lib/Frontend/TextDiagnostic.cpp +++ b/clang/lib/Frontend/TextDiagnostic.cpp @@ -838,7 +838,7 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, if (LangOpts.MSCompatibilityVersion && !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015)) OS << ' '; - OS << ": "; + OS << ':'; break; } diff --git a/clang/test/Misc/diag-format.c b/clang/test/Misc/diag-format.c index bc29894ad03e21..b24aeb9356ae31 100644 --- a/clang/test/Misc/diag-format.c +++ b/clang/test/Misc/diag-format.c @@ -1,30 +1,30 @@ -// RUN: %clang -fsyntax-only %s 2>&1 | FileCheck %s -check-prefix=DEFAULT -// RUN: %clang -fsyntax-only -fdiagnostics-format=clang %s 2>&1 | FileCheck %s -check-prefix=DEFAULT -// RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only -fdiagnostics-format=clang %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT // -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2013 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2013 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2015 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015 // -// RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s -check-prefix=VI +// RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=VI // -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fno-show-column -fmsc-version=1900 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015_ORIG +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fno-show-column -fmsc-version=1900 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015_ORIG // -// RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s -check-prefix=NO_COLUMN +// RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=NO_COLUMN // -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1800 %s 2>&1 | FileCheck %s -check-prefix=MSVC2013-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1900 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1800 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1900 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015-FALLBACK From cd76cbaa8cbbae2db81f36aa59c05028e0268bbe Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 20 Feb 2019 13:00:59 +0000 Subject: [PATCH 29/35] Merging r354402: ------------------------------------------------------------------------ r354402 | eugenis | 2019-02-20 00:41:42 +0100 (Wed, 20 Feb 2019) | 3 lines [msan] Fix name_to_handle_at test on overlayfs. Udev supports name_to_handle_at. Use /dev/null instead of /bin/cat. ------------------------------------------------------------------------ llvm-svn: 354460 --- compiler-rt/test/msan/Linux/name_to_handle_at.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/test/msan/Linux/name_to_handle_at.cc b/compiler-rt/test/msan/Linux/name_to_handle_at.cc index 0ff8d982f4f77c..a8bc75fa2ae5c9 100644 --- a/compiler-rt/test/msan/Linux/name_to_handle_at.cc +++ b/compiler-rt/test/msan/Linux/name_to_handle_at.cc @@ -14,7 +14,7 @@ int main(void) { handle->handle_bytes = MAX_HANDLE_SZ; int mount_id; - int res = name_to_handle_at(AT_FDCWD, "/bin/cat", handle, &mount_id, 0); + int res = name_to_handle_at(AT_FDCWD, "/dev/null", handle, &mount_id, 0); assert(!res); __msan_check_mem_is_initialized(&mount_id, sizeof(mount_id)); __msan_check_mem_is_initialized(&handle->handle_bytes, From 0157e01845f55d897e2c7e76407e12f8314229fc Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 21 Feb 2019 08:53:01 +0000 Subject: [PATCH 30/35] ReleaseNotes: profile-driven cache prefetching. Text by Mircea! llvm-svn: 354554 --- llvm/docs/ReleaseNotes.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index ddf12f61de300b..7adfd13c54f3ff 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -62,6 +62,24 @@ Non-comprehensive list of changes in this release * Added support for labels as offsets in ``.reloc`` directive. +* Support for precise identification of X86 instructions with memory operands, + by using debug information. This supports profile-driven cache prefetching. + It is enabled with the ``-x86-discriminate-memops`` LLVM Flag. + +* Support for profile-driven software cache prefetching on X86. This is part of + a larger system, consisting of: an offline cache prefetches recommender, + AutoFDO tooling, and LLVM. In this system, a binary compiled with + ``-x86-discriminate-memops`` is run under the observation of the recommender. + The recommender identifies certain memory access instructions by their binary + file address, and recommends a prefetch of a specific type (NTA, T0, etc) be + performed at a specified fixed offset from such an instruction's memory + operand. Next, this information needs to be converted to the AutoFDO syntax + and the resulting profile may be passed back to the compiler with the LLVM + flag ``-prefetch-hints-file``, together with the exact same set of + compilation parameters used for the original binary. More information is + available in the `RFC + `_. + .. NOTE If you would like to document a larger change, then you can add a subsection about it right here. You can copy the following boilerplate From 96ddd7d7f00100f9e553d29239a424a6bfefdfdb Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 21 Feb 2019 08:57:12 +0000 Subject: [PATCH 31/35] Merging r354497: ------------------------------------------------------------------------ r354497 | tstellar | 2019-02-20 19:43:45 +0100 (Wed, 20 Feb 2019) | 16 lines AArch64/test: Add check for function name to machine-outliner-bad-adrp.mir Summary: This test was failing in one of our setups because the generated ModuleID had the full path of the test file and that path contained the string BL. Reviewers: t.p.northover, jpaquette, paquette Reviewed By: paquette Subscribers: javed.absar, kristof.beyls, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58217 ------------------------------------------------------------------------ llvm-svn: 354555 --- llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir b/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir index af89ac5885ebea..2fc2cfd5d492ea 100644 --- a/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir +++ b/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir @@ -10,6 +10,7 @@ ... --- name: foo +# CHECK-LABEL: name: foo tracksRegLiveness: true constants: - id: 0 From 9d332ffc219a47af33737a52949e8bd85126e43d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 21 Feb 2019 14:16:48 +0000 Subject: [PATCH 32/35] ReleaseNotes: speculative load hardening; text by Kristof llvm-svn: 354582 --- llvm/docs/ReleaseNotes.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 7adfd13c54f3ff..29a1e01c8f9ca9 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -93,10 +93,16 @@ Non-comprehensive list of changes in this release Changes to the LLVM IR ---------------------- +* Function attribute ``speculative_load_hardening`` has been introduced to + allow indicating that `Speculative Load Hardening + `_ must be enabled for the function body. + Changes to the AArch64 Target ----------------------------- +* Support for Speculative Load Hardening has been added. + * Initial support for the Tiny code model, where code and its statically defined symbols must live within 1MB of each other. From 5a681e47f1f1cc87eccd60437c0087b30ab6d580 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 21 Feb 2019 14:19:52 +0000 Subject: [PATCH 33/35] ReleaseNotes: speculative load hardening; text by Kristof llvm-svn: 354583 --- clang/docs/ReleaseNotes.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b0b09f14e3b732..c7d62933f4bfa1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -130,6 +130,9 @@ Non-comprehensive list of changes in this release New Compiler Flags ------------------ +- ``-mspeculative-load-hardening`` Clang now has an option to enable + Speculative Load Hardening. + - ``-fprofile-filter-files=[regexes]`` and ``-fprofile-exclude-files=[regexes]``. Clang has now options to filter or exclude some files when @@ -171,7 +174,9 @@ New Pragmas in Clang Attribute Changes in Clang -------------------------- -- ... +* Clang now supports enabling/disabling speculative load hardening on a + per-function basis using the function attribute + ``speculative_load_hardening``/``no_speculative_load_hardening``. Windows Support --------------- From 6f2b277f2bed3ad6544a87d8700f9dc7249a703f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 22 Feb 2019 08:09:08 +0000 Subject: [PATCH 34/35] Release notes: a few lldb changes, by Raphael Isemann! llvm-svn: 354659 --- llvm/docs/ReleaseNotes.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 29a1e01c8f9ca9..eafe1f17f76000 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -237,6 +237,14 @@ Changes to the C API Changes to the DAG infrastructure --------------------------------- +Changes to LLDB +=============== +* Printed source code is now syntax highlighted in the terminal (only for C + languages). + +* The expression command now supports tab completing expressions. + + External Open Source Projects Using LLVM 8 ========================================== From b821974465fe070c07e7b235b051641468950147 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 22 Feb 2019 08:45:10 +0000 Subject: [PATCH 35/35] ReleaseNotes: -ftrivial-auto-var-init llvm-svn: 354660 --- clang/docs/ReleaseNotes.rst | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c7d62933f4bfa1..4c593977e2c320 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -41,6 +41,37 @@ Major New Features example, due to renaming a class or namespace). See the :ref:`UsersManual ` for details. +- Clang has new options to initialize automatic variables with either a pattern or with zeroes. The default is still that automatic variables are uninitialized. This isn't meant to change the semantics of C and C++. Rather, it's meant to be a last resort when programmers inadvertently have some undefined behavior in their code. These options aim to make undefined behavior hurt less, which security-minded people will be very happy about. Notably, this means that there's no inadvertent information leak when: + + * The compiler re-uses stack slots, and a value is used uninitialized. + + * The compiler re-uses a register, and a value is used uninitialized. + + * Stack structs / arrays / unions with padding are copied. + + These options only address stack and register information leaks. + + Caveats: + + * Variables declared in unreachable code and used later aren't initialized. This affects goto statements, Duff's device, and other objectionable uses of switch statements. This should instead be a hard-error in any serious codebase. + + * These options don't affect volatile stack variables. + + * Padding isn't fully handled yet. + + How to use it on the command line: + + * ``-ftrivial-auto-var-init=uninitialized`` (the default) + + * ``-ftrivial-auto-var-init=pattern`` + + * ``-ftrivial-auto-var-init=zero`` ``-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang`` + + There is also a new attribute to request a variable to not be initialized, mainly to disable initialization of large stack arrays when deemed too expensive: + + * ``int dont_initialize_me __attribute((uninitialized));`` + + Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^