[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.

llvm-svn: 238625
This commit is contained in:
Ahmed Bougacha 2015-05-29 22:54:57 +00:00
parent 32a9da5668
commit 5b63908f9f
2 changed files with 145 additions and 1 deletions

View File

@ -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,

View File

@ -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(