r175734 - Add support to Sema and CodeGen for floating point vector types in OpenCL.

Joey Gouly joey.gouly at arm.com
Thu Feb 21 03:49:56 PST 2013


Author: joey
Date: Thu Feb 21 05:49:56 2013
New Revision: 175734

URL: http://llvm.org/viewvc/llvm-project?rev=175734&view=rev
Log:

Add support to Sema and CodeGen for floating point vector types in OpenCL.


Added:
    cfe/trunk/test/CodeGenOpenCL/logical-ops.cl
    cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.1.cl
    cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.2.cl
Modified:
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=175734&r1=175733&r2=175734&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Feb 21 05:49:56 2013
@@ -1636,12 +1636,15 @@ Value *ScalarExprEmitter::VisitUnaryNot(
 }
 
 Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
-  
   // Perform vector logical not on comparison with zero vector.
   if (E->getType()->isExtVectorType()) {
     Value *Oper = Visit(E->getSubExpr());
     Value *Zero = llvm::Constant::getNullValue(Oper->getType());
-    Value *Result = Builder.CreateICmp(llvm::CmpInst::ICMP_EQ, Oper, Zero, "cmp");
+    Value *Result;
+    if (Oper->getType()->isFPOrFPVectorTy())
+      Result = Builder.CreateFCmp(llvm::CmpInst::FCMP_OEQ, Oper, Zero, "cmp");
+    else
+      Result = Builder.CreateICmp(llvm::CmpInst::ICMP_EQ, Oper, Zero, "cmp");
     return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext");
   }
   
@@ -2668,16 +2671,20 @@ Value *ScalarExprEmitter::VisitBinAssign
 }
 
 Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
-  
   // Perform vector logical and on comparisons with zero vectors.
   if (E->getType()->isVectorType()) {
     Value *LHS = Visit(E->getLHS());
     Value *RHS = Visit(E->getRHS());
     Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
-    LHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, LHS, Zero, "cmp");
-    RHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, RHS, Zero, "cmp");
+    if (LHS->getType()->isFPOrFPVectorTy()) {
+      LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
+      RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
+    } else {
+      LHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, LHS, Zero, "cmp");
+      RHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, RHS, Zero, "cmp");
+    }
     Value *And = Builder.CreateAnd(LHS, RHS);
-    return Builder.CreateSExt(And, Zero->getType(), "sext");
+    return Builder.CreateSExt(And, ConvertType(E->getType()), "sext");
   }
   
   llvm::Type *ResTy = ConvertType(E->getType());
@@ -2735,16 +2742,20 @@ Value *ScalarExprEmitter::VisitBinLAnd(c
 }
 
 Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
-  
   // Perform vector logical or on comparisons with zero vectors.
   if (E->getType()->isVectorType()) {
     Value *LHS = Visit(E->getLHS());
     Value *RHS = Visit(E->getRHS());
     Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
-    LHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, LHS, Zero, "cmp");
-    RHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, RHS, Zero, "cmp");
+    if (LHS->getType()->isFPOrFPVectorTy()) {
+      LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
+      RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
+    } else {
+      LHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, LHS, Zero, "cmp");
+      RHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, RHS, Zero, "cmp");
+    }
     Value *Or = Builder.CreateOr(LHS, RHS);
-    return Builder.CreateSExt(Or, Zero->getType(), "sext");
+    return Builder.CreateSExt(Or, ConvertType(E->getType()), "sext");
   }
   
   llvm::Type *ResTy = ConvertType(E->getType());

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=175734&r1=175733&r2=175734&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Feb 21 05:49:56 2013
@@ -7446,7 +7446,10 @@ QualType Sema::CheckVectorLogicalOperand
   // Ensure that either both operands are of the same vector type, or
   // one operand is of a vector type and the other is of its element type.
   QualType vType = CheckVectorOperands(LHS, RHS, Loc, false);
-  if (vType.isNull() || vType->isFloatingType())
+  if (vType.isNull())
+    return InvalidOperands(Loc, LHS, RHS);
+  if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 &&
+      vType->hasFloatingRepresentation())
     return InvalidOperands(Loc, LHS, RHS);
   
   return GetSignedVectorType(LHS.get()->getType());
@@ -7522,8 +7525,17 @@ inline QualType Sema::CheckLogicalOperan
                       RHS.get()->getLocEnd()));
       }
   }
-  
+
   if (!Context.getLangOpts().CPlusPlus) {
+    // OpenCL v1.1 s6.3.g: The logical operators and (&&), or (||) do
+    // not operate on the built-in scalar and vector float types.
+    if (Context.getLangOpts().OpenCL &&
+        Context.getLangOpts().OpenCLVersion < 120) {
+      if (LHS.get()->getType()->isFloatingType() ||
+          RHS.get()->getType()->isFloatingType())
+        return InvalidOperands(Loc, LHS, RHS);
+    }
+
     LHS = UsualUnaryConversions(LHS.take());
     if (LHS.isInvalid())
       return QualType();
@@ -8849,7 +8861,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(So
 
   case UO_Not: // bitwise complement
     Input = UsualUnaryConversions(Input.take());
-    if (Input.isInvalid()) return ExprError();
+    if (Input.isInvalid())
+      return ExprError();
     resultType = Input.get()->getType();
     if (resultType->isDependentType())
       break;
@@ -8857,12 +8870,22 @@ ExprResult Sema::CreateBuiltinUnaryOp(So
     if (resultType->isComplexType() || resultType->isComplexIntegerType())
       // C99 does not support '~' for complex conjugation.
       Diag(OpLoc, diag::ext_integer_complement_complex)
-        << resultType << Input.get()->getSourceRange();
+          << resultType << Input.get()->getSourceRange();
     else if (resultType->hasIntegerRepresentation())
       break;
-    else {
+    else if (resultType->isExtVectorType()) {
+      if (Context.getLangOpts().OpenCL) {
+        // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate
+        // on vector float types.
+        QualType T = resultType->getAs<ExtVectorType>()->getElementType();
+        if (!T->isIntegerType())
+          return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+                           << resultType << Input.get()->getSourceRange());
+      }
+      break;
+    } else {
       return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
-        << resultType << Input.get()->getSourceRange());
+                       << resultType << Input.get()->getSourceRange());
     }
     break;
 
@@ -8887,8 +8910,24 @@ ExprResult Sema::CreateBuiltinUnaryOp(So
         // operand contextually converted to bool.
         Input = ImpCastExprToType(Input.take(), Context.BoolTy,
                                   ScalarTypeToBooleanCastKind(resultType));
+      } else if (Context.getLangOpts().OpenCL &&
+                 Context.getLangOpts().OpenCLVersion < 120) {
+        // OpenCL v1.1 6.3.h: The logical operator not (!) does not
+        // operate on scalar float types.
+        if (!resultType->isIntegerType())
+          return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+                           << resultType << Input.get()->getSourceRange());
       }
     } else if (resultType->isExtVectorType()) {
+      if (Context.getLangOpts().OpenCL &&
+          Context.getLangOpts().OpenCLVersion < 120) {
+        // OpenCL v1.1 6.3.h: The logical operator not (!) does not
+        // operate on vector float types.
+        QualType T = resultType->getAs<ExtVectorType>()->getElementType();
+        if (!T->isIntegerType())
+          return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+                           << resultType << Input.get()->getSourceRange());
+      }
       // Vector logical not returns the signed variant of the operand type.
       resultType = GetSignedVectorType(resultType);
       break;

Added: cfe/trunk/test/CodeGenOpenCL/logical-ops.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/logical-ops.cl?rev=175734&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenOpenCL/logical-ops.cl (added)
+++ cfe/trunk/test/CodeGenOpenCL/logical-ops.cl Thu Feb 21 05:49:56 2013
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL1.2 -O1 | FileCheck %s
+
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+
+typedef int int4 __attribute((ext_vector_type(4)));
+typedef long long4 __attribute((ext_vector_type(4)));
+typedef float float4 __attribute((ext_vector_type(4)));
+typedef double double4 __attribute((ext_vector_type(4)));
+
+// CHECK: floatops
+kernel void floatops(global int4 *out, global float4 *fout) {
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
+  out[0] = (float4)(1, 1, 1, 1) && 1.0f;
+  // CHECK: store <4 x i32> zeroinitializer
+  out[1] = (float4)(0, 0, 0, 0) && (float4)(0, 0, 0, 0);
+
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
+  out[2] = (float4)(0, 0, 0, 0) || (float4)(1, 1, 1, 1);
+  // CHECK: store <4 x i32> zeroinitializer
+  out[3] = (float4)(0, 0, 0, 0) || 0.0f;
+
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
+  out[4] = !(float4)(0, 0, 0, 0);
+  // CHECK: store <4 x i32> zeroinitializer
+  out[5] = !(float4)(1, 2, 3, 4);
+  // CHECK: store <4 x i32> <i32 -1, i32 0, i32 -1, i32 0>
+  out[6] = !(float4)(0, 1, 0, 1);
+  // CHECK: store <4 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
+  fout[0] = (float4)(!0.0f);
+  // CHECK: store <4 x float> zeroinitializer
+  fout[1] = (float4)(!1.0f);
+}
+
+// CHECK: doubleops
+kernel void doubleops(global long4 *out, global double4 *dout) {
+  // CHECK: store <4 x i64> <i64 -1, i64 -1, i64 -1, i64 -1>
+  out[0] = (double4)(1, 1, 1, 1) && 1.0;
+  // CHECK: store <4 x i64> zeroinitializer
+  out[1] = (double4)(0, 0, 0, 0) && (double4)(0, 0, 0, 0);
+
+  // CHECK: store <4 x i64> <i64 -1, i64 -1, i64 -1, i64 -1>
+  out[2] = (double4)(0, 0, 0, 0) || (double4)(1, 1, 1, 1);
+  // CHECK: store <4 x i64> zeroinitializer
+  out[3] = (double4)(0, 0, 0, 0) || 0.0f;
+
+  // CHECK: store <4 x i64> <i64 -1, i64 -1, i64 -1, i64 -1>
+  out[4] = !(double4)(0, 0, 0, 0);
+  // CHECK: store <4 x i64> zeroinitializer
+  out[5] = !(double4)(1, 2, 3, 4);
+  // CHECK: store <4 x i64> <i64 -1, i64 0, i64 -1, i64 0>
+  out[6] = !(double4)(0, 1, 0, 1);
+  // CHECK: store <4 x double> <double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00>
+  dout[0] = (double4)(!0.0f);
+  // CHECK: store <4 x double> zeroinitializer
+  dout[1] = (double4)(!1.0f);
+}

Added: cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.1.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.1.cl?rev=175734&view=auto
==============================================================================
--- cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.1.cl (added)
+++ cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.1.cl Thu Feb 21 05:49:56 2013
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 %s -verify -cl-std=CL1.1
+
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+typedef __attribute__((ext_vector_type(4))) float float4;
+typedef __attribute__((ext_vector_type(4))) double double4;
+typedef __attribute__((ext_vector_type(4))) int int4;
+typedef __attribute__((ext_vector_type(4))) long long4;
+
+kernel void float_ops() {
+  int flaf = 0.0f && 0.0f; // expected-error {{invalid operands}}
+  int flof = 0.0f || 0.0f; // expected-error {{invalid operands}}
+  float fbaf = 0.0f & 0.0f; // expected-error {{invalid operands}}
+  float fbof = 0.0f | 0.0f; // expected-error {{invalid operands}}
+  float fbxf = 0.0f ^ 0.0f; // expected-error {{invalid operands}}
+  int flai = 0.0f && 0; // expected-error {{invalid operands}}
+  int floi = 0.0f || 0; // expected-error {{invalid operands}}
+  float ibaf = 0 & 0.0f; // expected-error {{invalid operands}}
+  float ibof = 0 | 0.0f; // expected-error {{invalid operands}}
+  float bnf = ~0.0f; // expected-error {{invalid argument type}}
+  float lnf = !0.0f; // expected-error {{invalid argument type}}
+}
+
+kernel void vec_float_ops() {
+  float4 f4 = (float4)(0, 0, 0, 0);
+  int4 f4laf = f4 && 0.0f; // expected-error {{invalid operands}}
+  int4 f4lof = f4 || 0.0f; // expected-error {{invalid operands}}
+  float4 f4baf = f4 & 0.0f; // expected-error {{invalid operands}}
+  float4 f4bof = f4 | 0.0f; // expected-error {{invalid operands}}
+  float4 f4bxf = f4 ^ 0.0f; // expected-error {{invalid operands}}
+  float bnf4 = ~f4; // expected-error {{invalid argument type}}
+  int4 lnf4 = !f4; // expected-error {{invalid argument type}}
+}
+
+kernel void double_ops() {
+  int flaf = 0.0 && 0.0; // expected-error {{invalid operands}}
+  int flof = 0.0 || 0.0; // expected-error {{invalid operands}}
+  double fbaf = 0.0 & 0.0; // expected-error {{invalid operands}}
+  double fbof = 0.0 | 0.0; // expected-error {{invalid operands}}
+  double fbxf = 0.0 ^ 0.0; // expected-error {{invalid operands}}
+  int flai = 0.0 && 0; // expected-error {{invalid operands}}
+  int floi = 0.0 || 0; // expected-error {{invalid operands}}
+  double ibaf = 0 & 0.0; // expected-error {{invalid operands}}
+  double ibof = 0 | 0.0; // expected-error {{invalid operands}}
+  double bnf = ~0.0; // expected-error {{invalid argument type}}
+  double lnf = !0.0; // expected-error {{invalid argument type}}
+}
+
+kernel void vec_double_ops() {
+  double4 f4 = (double4)(0, 0, 0, 0);
+  long4 f4laf = f4 && 0.0; // expected-error {{invalid operands}}
+  long4 f4lof = f4 || 0.0; // expected-error {{invalid operands}}
+  double4 f4baf = f4 & 0.0; // expected-error {{invalid operands}}
+  double4 f4bof = f4 | 0.0; // expected-error {{invalid operands}}
+  double4 f4bxf = f4 ^ 0.0; // expected-error {{invalid operands}}
+  double bnf4 = ~f4; // expected-error {{invalid argument type}}
+  long4 lnf4 = !f4; // expected-error {{invalid argument type}}
+}

Added: cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.2.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.2.cl?rev=175734&view=auto
==============================================================================
--- cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.2.cl (added)
+++ cfe/trunk/test/SemaOpenCL/invalid-logical-ops-1.2.cl Thu Feb 21 05:49:56 2013
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 %s -verify -cl-std=CL1.2
+
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+typedef __attribute__((ext_vector_type(4))) float float4;
+typedef __attribute__((ext_vector_type(4))) double double4;
+typedef __attribute__((ext_vector_type(4))) int int4;
+typedef __attribute__((ext_vector_type(4))) long long4;
+
+kernel void float_ops() {
+  int flaf = 0.0f && 0.0f;
+  int flof = 0.0f || 0.0f;
+  float fbaf = 0.0f & 0.0f; // expected-error {{invalid operands}}
+  float fbof = 0.0f | 0.0f; // expected-error {{invalid operands}}
+  float fbxf = 0.0f ^ 0.0f; // expected-error {{invalid operands}}
+  int flai = 0.0f && 0;
+  int floi = 0.0f || 0;
+  float ibaf = 0 & 0.0f; // expected-error {{invalid operands}}
+  float ibof = 0 | 0.0f; // expected-error {{invalid operands}}
+  float bnf = ~0.0f;// expected-error {{invalid argument type}}
+  float lnf = !0.0f;
+}
+
+kernel void vec_float_ops() {
+  float4 f4 = (float4)(0, 0, 0, 0);
+  int4 f4laf = f4 && 0.0f;
+  int4 f4lof = f4 || 0.0f;
+  float4 f4baf = f4 & 0.0f; // expected-error {{invalid operands}}
+  float4 f4bof = f4 | 0.0f; // expected-error {{invalid operands}}
+  float4 f4bxf = f4 ^ 0.0f; // expected-error {{invalid operands}}
+  float bnf4 = ~f4; // expected-error {{invalid argument type}}
+  int4 lnf4 = !f4;
+}
+
+kernel void double_ops() {
+  int flaf = 0.0 && 0.0;
+  int flof = 0.0 || 0.0;
+  double fbaf = 0.0 & 0.0; // expected-error {{invalid operands}}
+  double fbof = 0.0 | 0.0; // expected-error {{invalid operands}}
+  double fbxf = 0.0 ^ 0.0; // expected-error {{invalid operands}}
+  int flai = 0.0 && 0;
+  int floi = 0.0 || 0;
+  double ibaf = 0 & 0.0; // expected-error {{invalid operands}}
+  double ibof = 0 | 0.0; // expected-error {{invalid operands}}
+  double bnf = ~0.0; // expected-error {{invalid argument type}}
+  double lnf = !0.0;
+}
+
+kernel void vec_double_ops() {
+  double4 f4 = (double4)(0, 0, 0, 0);
+  long4 f4laf = f4 && 0.0;
+  long4 f4lof = f4 || 0.0;
+  double4 f4baf = f4 & 0.0; // expected-error {{invalid operands}}
+  double4 f4bof = f4 | 0.0; // expected-error {{invalid operands}}
+  double4 f4bxf = f4 ^ 0.0; // expected-error {{invalid operands}}
+  double bnf4 = ~f4; // expected-error {{invalid argument type}}
+  long4 lnf4 = !f4;
+}





More information about the cfe-commits mailing list