From: Ahmed Bougacha Date: Fri, 29 May 2015 22:54:57 +0000 (+0000) Subject: [Sema] Promote compound assignment exprs. with fp16 LHS and int. RHS. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f7739e8ed67fc3edb5ae712eecfe7f90585a2b93;p=clang [Sema] Promote compound assignment exprs. with fp16 LHS and int. RHS. We catch most of the various other __fp16 implicit conversions to float, but not this one: __fp16 a; int i; ... a += i; For which we used to generate something 'fun' like: %conv = sitofp i32 %i to float %1 = tail call i16 @llvm.convert.to.fp16.f32(float %conv) %add = add i16 %0, %1 Instead, when we have an __fp16 LHS and an integer RHS, we should use float as the result type. While there, add a bunch of missing tests for mixed __fp16/integer expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@238625 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7ab269c3b6..dfb17f4bbc 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1110,10 +1110,15 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS, return RHSType; } - if (LHSFloat) + if (LHSFloat) { + // Half FP has to be promoted to float unless it is natively supported + if (LHSType->isHalfType() && !S.getLangOpts().NativeHalfType) + LHSType = S.Context.FloatTy; + return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType, /*convertFloat=*/!IsCompAssign, /*convertInt=*/ true); + } assert(RHSFloat); return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType, /*convertInt=*/ true, diff --git a/test/CodeGen/fp16-ops.c b/test/CodeGen/fp16-ops.c index fe0fa2c266..7cd08a03d6 100644 --- a/test/CodeGen/fp16-ops.c +++ b/test/CodeGen/fp16-ops.c @@ -10,6 +10,7 @@ typedef unsigned cond_t; volatile cond_t test; +volatile int i0; volatile __fp16 h0 = 0.0, h1 = 1.0, h2; volatile float f0, f1, f2; volatile double d0; @@ -91,6 +92,11 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fmul float h1 = f0 * h2; + // CHECK: [[F16TOF32]] + // CHECK: fmul float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: fmul half + h1 = h0 * i0; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -116,6 +122,11 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fdiv float h1 = (f0 / h2); + // CHECK: [[F16TOF32]] + // CHECK: fdiv float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: fdiv half + h1 = (h0 / i0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -141,6 +152,11 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fadd float h1 = (f2 + h0); + // CHECK: [[F16TOF32]] + // CHECK: fadd float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: fadd half + h1 = (h0 + i0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -166,6 +182,11 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fsub float h1 = (f2 - h0); + // CHECK: [[F16TOF32]] + // CHECK: fsub float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: fsub half + h1 = (h0 - i0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -187,6 +208,14 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fcmp olt float test = (f2 < h0); + // CHECK: [[F16TOF32]] + // CHECK: fcmp olt float + // NATIVE-HALF: fcmp olt half + test = (i0 < h0); + // CHECK: [[F16TOF32]] + // CHECK: fcmp olt float + // NATIVE-HALF: fcmp olt half + test = (h0 < i0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -208,6 +237,14 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fcmp ogt float test = (f0 > h2); + // CHECK: [[F16TOF32]] + // CHECK: fcmp ogt float + // NATIVE-HALF: fcmp ogt half + test = (i0 > h0); + // CHECK: [[F16TOF32]] + // CHECK: fcmp ogt float + // NATIVE-HALF: fcmp ogt half + test = (h0 > i0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -229,6 +266,15 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fcmp ole float test = (f2 <= h0); + // CHECK: [[F16TOF32]] + // CHECK: fcmp ole float + // NATIVE-HALF: fcmp ole half + test = (i0 <= h0); + // CHECK: [[F16TOF32]] + // CHECK: fcmp ole float + // NATIVE-HALF: fcmp ole half + test = (h0 <= i0); + // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -250,6 +296,14 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fcmp oge float test = (f0 >= h2); + // CHECK: [[F16TOF32]] + // CHECK: fcmp oge float + // NATIVE-HALF: fcmp oge half + test = (i0 >= h0); + // CHECK: [[F16TOF32]] + // CHECK: fcmp oge float + // NATIVE-HALF: fcmp oge half + test = (h0 >= i0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -271,6 +325,14 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fcmp oeq float test = (f1 == h1); + // CHECK: [[F16TOF32]] + // CHECK: fcmp oeq float + // NATIVE-HALF: fcmp oeq half + test = (i0 == h0); + // CHECK: [[F16TOF32]] + // CHECK: fcmp oeq float + // NATIVE-HALF: fcmp oeq half + test = (h0 == i0); // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -292,6 +354,14 @@ void foo(void) { // NATIVE-HALF: fpext half // NATIVE-HALF: fcmp une float test = (f1 != h1); + // CHECK: [[F16TOF32]] + // CHECK: fcmp une float + // NATIVE-HALF: fcmp une half + test = (i0 != h0); + // CHECK: [[F16TOF32]] + // CHECK: fcmp une float + // NATIVE-HALF: fcmp une half + test = (h0 != i0); // CHECK: [[F16TOF32]] // CHECK: fcmp une float @@ -310,6 +380,15 @@ void foo(void) { // NATIVE-HALF: fptrunc float h0 = f0; + // CHECK: sitofp i32 {{.*}} to float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: sitofp i32 {{.*}} to half + h0 = i0; + // CHECK: [[F16TOF32]] + // CHECK: fptosi float {{.*}} to i32 + // NATIVE-HALF: fptosi half {{.*}} to i32 + i0 = h0; + // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] // CHECK: fadd float @@ -329,6 +408,21 @@ void foo(void) { // NATIVE-HALF: fadd float // NATIVE-HALF: fptrunc float h0 += f2; + // CHECK: [[F16TOF32]] + // CHECK: sitofp i32 {{.*}} to float + // CHECK: fadd float + // CHECK: fptosi float {{.*}} to i32 + // NATIVE-HALF: sitofp i32 {{.*}} to half + // NATIVE-HALF: fadd half + // NATIVE-HALF: fptosi half {{.*}} to i32 + i0 += h0; + // CHECK: sitofp i32 {{.*}} to float + // CHECK: [[F16TOF32]] + // CHECK: fadd float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: sitofp i32 {{.*}} to half + // NATIVE-HALF: fadd half + h0 += i0; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -349,6 +443,21 @@ void foo(void) { // NATIVE-HALF: fsub float // NATIVE-HALF: fptrunc float h0 -= f2; + // CHECK: [[F16TOF32]] + // CHECK: sitofp i32 {{.*}} to float + // CHECK: fsub float + // CHECK: fptosi float {{.*}} to i32 + // NATIVE-HALF: sitofp i32 {{.*}} to half + // NATIVE-HALF: fsub half + // NATIVE-HALF: fptosi half {{.*}} to i32 + i0 -= h0; + // CHECK: sitofp i32 {{.*}} to float + // CHECK: [[F16TOF32]] + // CHECK: fsub float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: sitofp i32 {{.*}} to half + // NATIVE-HALF: fsub half + h0 -= i0; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -369,6 +478,21 @@ void foo(void) { // NATIVE-HALF: fmul float // NATIVE-HALF: fptrunc float h0 *= f2; + // CHECK: [[F16TOF32]] + // CHECK: sitofp i32 {{.*}} to float + // CHECK: fmul float + // CHECK: fptosi float {{.*}} to i32 + // NATIVE-HALF: sitofp i32 {{.*}} to half + // NATIVE-HALF: fmul half + // NATIVE-HALF: fptosi half {{.*}} to i32 + i0 *= h0; + // CHECK: sitofp i32 {{.*}} to float + // CHECK: [[F16TOF32]] + // CHECK: fmul float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: sitofp i32 {{.*}} to half + // NATIVE-HALF: fmul half + h0 *= i0; // CHECK: [[F16TOF32]] // CHECK: [[F16TOF32]] @@ -389,6 +513,21 @@ void foo(void) { // NATIVE-HALF: fdiv float // NATIVE-HALF: fptrunc float h0 /= f2; + // CHECK: [[F16TOF32]] + // CHECK: sitofp i32 {{.*}} to float + // CHECK: fdiv float + // CHECK: fptosi float {{.*}} to i32 + // NATIVE-HALF: sitofp i32 {{.*}} to half + // NATIVE-HALF: fdiv half + // NATIVE-HALF: fptosi half {{.*}} to i32 + i0 /= h0; + // CHECK: sitofp i32 {{.*}} to float + // CHECK: [[F16TOF32]] + // CHECK: fdiv float + // CHECK: [[F32TOF16]] + // NATIVE-HALF: sitofp i32 {{.*}} to half + // NATIVE-HALF: fdiv half + h0 /= i0; // Check conversions to/from double // NOHALF: call i16 @llvm.convert.to.fp16.f64(