junparser updated this revision to Diff 268366.
junparser added a comment.

address the comment. 
hi @erichkeane, most of the function in vector-1.cpp  are copied from 
ext-vector.c with vector type changed to gcc vector type, they should emit same 
ir.  I add test7 and test8 which test logic operation of gcc vector type.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80979/new/

https://reviews.llvm.org/D80979

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGen/vector-1.cpp
  clang/test/Sema/vector-gcc-compat.cpp

Index: clang/test/Sema/vector-gcc-compat.cpp
===================================================================
--- clang/test/Sema/vector-gcc-compat.cpp
+++ clang/test/Sema/vector-gcc-compat.cpp
@@ -83,7 +83,7 @@
   v2i64 v2i64_c = (v2i64){3, 1}; // expected-warning {{compound literals are a C99-specific feature}}
   v2i64 v2i64_r;
 
-  v2i64_r = !v2i64_a;  // expected-error {{invalid argument type 'v2i64' (vector of 2 'long long' values) to unary expression}}
+  v2i64_r = !v2i64_a;
   v2i64_r = ~v2i64_a;
 
   v2i64_r = v2i64_a ? v2i64_b : v2i64_c;
Index: clang/test/CodeGen/vector-1.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/vector-1.cpp
@@ -0,0 +1,216 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+
+typedef __attribute__((__vector_size__(16))) float float4;
+typedef __attribute__((__vector_size__(16))) int int4;
+typedef __attribute__((__vector_size__(16))) unsigned int uint4;
+
+// CHECK: @_Z4testPDv4_f
+// CHECK: store <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>
+void test(float4 *out) {
+  *out = ((float4){1.0f, 2.0f, 3.0f, 4.0f});
+}
+
+// CHECK: @_Z5test1PDv4_f
+// CHECK: store <4 x float>
+// CHECK: store <4 x float>
+void test1(float4 *out) {
+  float a = 1.0f;
+  float b = 2.0f;
+  float c = 3.0f;
+  float d = 4.0f;
+  *out = ((float4){a, b, c, d});
+}
+
+// CHECK: @_Z5test3PDv4_fS0_f
+void test3(float4 *ap, float4 *bp, float c) {
+  float4 a = *ap;
+  float4 b = *bp;
+
+  // CHECK: fadd <4 x float>
+  // CHECK: fsub <4 x float>
+  // CHECK: fmul <4 x float>
+  // CHECK: fdiv <4 x float>
+  a = a + b;
+  a = a - b;
+  a = a * b;
+  a = a / b;
+
+  // CHECK: fadd <4 x float>
+  // CHECK: fsub <4 x float>
+  // CHECK: fmul <4 x float>
+  // CHECK: fdiv <4 x float>
+  a = a + c;
+  a = a - c;
+  a = a * c;
+  a = a / c;
+
+  // CHECK: fadd <4 x float>
+  // CHECK: fsub <4 x float>
+  // CHECK: fmul <4 x float>
+  // CHECK: fdiv <4 x float>
+  a += b;
+  a -= b;
+  a *= b;
+  a /= b;
+
+  // CHECK: fadd <4 x float>
+  // CHECK: fsub <4 x float>
+  // CHECK: fmul <4 x float>
+  // CHECK: fdiv <4 x float>
+  a += c;
+  a -= c;
+  a *= c;
+  a /= c;
+}
+
+// CHECK: @_Z5test4PDv4_iS0_i
+void test4(int4 *ap, int4 *bp, int c) {
+  int4 a = *ap;
+  int4 b = *bp;
+
+  // CHECK: add <4 x i32>
+  // CHECK: sub <4 x i32>
+  // CHECK: mul <4 x i32>
+  // CHECK: sdiv <4 x i32>
+  // CHECK: srem <4 x i32>
+  a = a + b;
+  a = a - b;
+  a = a * b;
+  a = a / b;
+  a = a % b;
+
+  // CHECK: add <4 x i32>
+  // CHECK: sub <4 x i32>
+  // CHECK: mul <4 x i32>
+  // CHECK: sdiv <4 x i32>
+  // CHECK: srem <4 x i32>
+  a = a + c;
+  a = a - c;
+  a = a * c;
+  a = a / c;
+  a = a % c;
+
+  // CHECK: add <4 x i32>
+  // CHECK: sub <4 x i32>
+  // CHECK: mul <4 x i32>
+  // CHECK: sdiv <4 x i32>
+  // CHECK: srem <4 x i32>
+  a += b;
+  a -= b;
+  a *= b;
+  a /= b;
+  a %= b;
+
+  // CHECK: add <4 x i32>
+  // CHECK: sub <4 x i32>
+  // CHECK: mul <4 x i32>
+  // CHECK: sdiv <4 x i32>
+  // CHECK: srem <4 x i32>
+  a += c;
+  a -= c;
+  a *= c;
+  a /= c;
+  a %= c;
+
+  // Vector comparisons.
+  // CHECK: icmp slt
+  // CHECK: icmp sle
+  // CHECK: icmp sgt
+  // CHECK: icmp sge
+  // CHECK: icmp eq
+  // CHECK: icmp ne
+  int4 cmp;
+  cmp = a < b;
+  cmp = a <= b;
+  cmp = a > b;
+  cmp = a >= b;
+  cmp = a == b;
+  cmp = a != b;
+}
+
+// CHECK: @_Z5test5PDv4_fS0_i
+void test5(float4 *ap, float4 *bp, int c) {
+  float4 a = *ap;
+  float4 b = *bp;
+
+  // Vector comparisons.
+  // CHECK: fcmp olt
+  // CHECK: fcmp ole
+  // CHECK: fcmp ogt
+  // CHECK: fcmp oge
+  // CHECK: fcmp oeq
+  // CHECK: fcmp une
+  int4 cmp;
+  cmp = a < b;
+  cmp = a <= b;
+  cmp = a > b;
+  cmp = a >= b;
+  cmp = a == b;
+  cmp = a != b;
+}
+
+// CHECK: @_Z5test6PDv4_jS0_j
+void test6(uint4 *ap, uint4 *bp, unsigned c) {
+  uint4 a = *ap;
+  uint4 b = *bp;
+  int4 d;
+
+  // CHECK: udiv <4 x i32>
+  // CHECK: urem <4 x i32>
+  a = a / b;
+  a = a % b;
+
+  // CHECK: udiv <4 x i32>
+  // CHECK: urem <4 x i32>
+  a = a / c;
+  a = a % c;
+
+  // CHECK: icmp ult
+  // CHECK: icmp ule
+  // CHECK: icmp ugt
+  // CHECK: icmp uge
+  // CHECK: icmp eq
+  // CHECK: icmp ne
+  d = a < b;
+  d = a <= b;
+  d = a > b;
+  d = a >= b;
+  d = a == b;
+  d = a != b;
+}
+
+// CHECK: @_Z5test7Dv4_j
+int4 test7(uint4 V0) {
+  // CHECK: [[CMP0:%.*]] = icmp eq <4 x i32> [[V0:%.*]], zeroinitializer
+  // CHECK-NEXT: [[V1:%.*]] = sext <4 x i1> [[CMP0]] to <4 x i32>
+  int4 V = !V0;
+  // CHECK: [[CMP1:%.*]] = icmp ne <4 x i32> [[V2:%.*]], zeroinitializer
+  // CHECK-NEXT: [[CMP2:%.*]] = icmp ne <4 x i32> [[V3:%.*]], zeroinitializer
+  // CHECK-NEXT: [[AND0:%.*]] = and <4 x i1> [[CMP1]], [[CMP2]]
+  // CHECK-NEXT: [[V4:%.*]] = sext <4 x i1> [[AND0]] to <4 x i32>
+  V = V && V;
+  // CHECK: [[CMP3:%.*]] = icmp ne <4 x i32> [[V5:%.*]], zeroinitializer
+  // CHECK-NEXT: [[CMP4:%.*]] = icmp ne <4 x i32> [[V6:%.*]], zeroinitializer
+  // CHECK-NEXT: [[OR0:%.*]] = or <4 x i1> [[CMP3]], [[CMP4]]
+  // CHECK-NEXT: [[V7:%.*]] = sext <4 x i1> [[OR0]] to <4 x i32>
+  V = V || V;
+  return V;
+}
+
+// CHECK: @_Z5test8Dv4_fS_
+int4 test8(float4 V0, float4 V1) {
+  // CHECK: [[CMP0:%.*]] = fcmp oeq <4 x float> [[V0:%.*]], zeroinitializer
+  // CHECK-NEXT: [[V1:%.*]] = sext <4 x i1> [[CMP0]] to <4 x i32>
+  int4 V = !V0;
+  // CHECK: [[CMP1:%.*]] = fcmp une <4 x float> [[V2:%.*]], zeroinitializer
+  // CHECK-NEXT: [[CMP2:%.*]] = fcmp une <4 x float> [[V3:%.*]], zeroinitializer
+  // CHECK-NEXT: [[AND0:%.*]] = and <4 x i1> [[CMP1]], [[CMP2]]
+  // CHECK-NEXT: [[V4:%.*]] = sext <4 x i1> [[AND0]] to <4 x i32>
+  V = V0 && V1;
+  // CHECK: [[CMP3:%.*]] = fcmp une <4 x float> [[V5:%.*]], zeroinitializer
+  // CHECK-NEXT: [[CMP4:%.*]] = fcmp une <4 x float> [[V6:%.*]], zeroinitializer
+  // CHECK-NEXT: [[OR0:%.*]] = or <4 x i1> [[CMP3]], [[CMP4]]
+  // CHECK-NEXT: [[V7:%.*]] = sext <4 x i1> [[OR0]] to <4 x i32>
+  V = V0 || V1;
+  return V;
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -14436,12 +14436,19 @@
           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;
+    } else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) {
+      const VectorType *VTy = resultType->castAs<VectorType>();
+      if (VTy->getVectorKind() != VectorType::GenericVector)
+        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;
     } else {
-      // FIXME: GCC's vector extension permits the usage of '!' with a vector
-      //        type in C++. We should allow that here too.
       return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
         << resultType << Input.get()->getSourceRange());
     }
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -2742,7 +2742,9 @@
 
 Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
   // Perform vector logical not on comparison with zero vector.
-  if (E->getType()->isExtVectorType()) {
+  if (E->getType()->isVectorType() &&
+      E->getType()->castAs<VectorType>()->getVectorKind() ==
+          VectorType::GenericVector) {
     Value *Oper = Visit(E->getSubExpr());
     Value *Zero = llvm::Constant::getNullValue(Oper->getType());
     Value *Result;
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -475,7 +475,7 @@
 +,--,*,/,%                       yes     yes       yes         --
 bitwise operators &,|,^,~        yes     yes       yes         --
 >>,<<                            yes     yes       yes         --
-!, &&, ||                        yes     --        yes [#]_    --
+!, &&, ||                        yes     --        yes         --
 ==, !=, >, <, >=, <=             yes     yes       yes         --
 =                                yes     yes       yes         yes
 :? [#]_                          yes     --        yes         --
@@ -488,7 +488,6 @@
 
 See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`.
 
-.. [#] unary operator ! is not implemented, however && and || are.
 .. [#] While OpenCL and GCC vectors both implement the comparison operator(?:) as a
   'select', they operate somewhat differently. OpenCL selects based on signedness of
   the condition operands, but GCC vectors use normal bool conversions (that is, != 0).
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to