]> granicus.if.org Git - clang/commitdiff
pre/post increase/decrease for AltiVec vectors
authorAnton Yartsev <anton.yartsev@gmail.com>
Mon, 24 Jan 2011 20:55:22 +0000 (20:55 +0000)
committerAnton Yartsev <anton.yartsev@gmail.com>
Mon, 24 Jan 2011 20:55:22 +0000 (20:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124146 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprScalar.cpp
lib/Sema/SemaExpr.cpp
test/CodeGen/builtins-ppc-altivec.c
test/SemaCXX/altivec.cpp

index 745757977a0b49caca337f8c689ba18ebcfe3b7f..8518dd1d23aa44a10df5c3dec9b344e5e2453468 100644 (file)
@@ -302,6 +302,11 @@ public:
     return EmitScalarPrePostIncDec(E, LV, true, true);
   }
 
+  llvm::Value *EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
+                                               llvm::Value *InVal,
+                                               llvm::Value *NextVal,
+                                               bool IsInc);
+
   llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
                                        bool isInc, bool isPre);
 
@@ -1221,6 +1226,31 @@ Value *ScalarExprEmitter::VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) {
 //                             Unary Operators
 //===----------------------------------------------------------------------===//
 
+llvm::Value *ScalarExprEmitter::
+EmitAddConsiderOverflowBehavior(const UnaryOperator *E,
+                                llvm::Value *InVal,
+                                llvm::Value *NextVal, bool IsInc) {
+  switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+  case LangOptions::SOB_Undefined:
+    return Builder.CreateNSWAdd(InVal, NextVal, IsInc ? "inc" : "dec");
+    break;
+  case LangOptions::SOB_Defined:
+    return Builder.CreateAdd(InVal, NextVal, IsInc ? "inc" : "dec");
+    break;
+  case LangOptions::SOB_Trapping:
+    BinOpInfo BinOp;
+    BinOp.LHS = InVal;
+    BinOp.RHS = NextVal;
+    BinOp.Ty = E->getType();
+    BinOp.Opcode = BO_Add;
+    BinOp.E = E;
+    return EmitOverflowCheckedBinOp(BinOp);
+    break;
+  }
+  assert(false && "Unknown SignedOverflowBehaviorTy");
+  return 0;
+}
+
 llvm::Value *ScalarExprEmitter::
 EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
                         bool isInc, bool isPre) {
@@ -1270,31 +1300,26 @@ EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
     // An interesting aspect of this is that increment is always true.
     // Decrement does not have this property.
     NextVal = llvm::ConstantInt::getTrue(VMContext);
+  } else if (ValTy->isVectorType()) {
+    if (ValTy->hasIntegerRepresentation()) {
+      NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
+
+      NextVal = ValTy->hasSignedIntegerRepresentation() ?
+                EmitAddConsiderOverflowBehavior(E, InVal, NextVal, isInc) :
+                Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
+    } else {
+      NextVal = Builder.CreateFAdd(
+                  InVal,
+                  llvm::ConstantFP::get(InVal->getType(), AmountVal),
+                  isInc ? "inc" : "dec");
+    }
   } else if (isa<llvm::IntegerType>(InVal->getType())) {
     NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
-    
-    if (!ValTy->isSignedIntegerType())
-      // Unsigned integer inc is always two's complement.
-      NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
-    else {
-      switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
-      case LangOptions::SOB_Undefined:
-        NextVal = Builder.CreateNSWAdd(InVal, NextVal, isInc ? "inc" : "dec");
-        break;
-      case LangOptions::SOB_Defined:
-        NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
-        break;
-      case LangOptions::SOB_Trapping:
-        BinOpInfo BinOp;
-        BinOp.LHS = InVal;
-        BinOp.RHS = NextVal;
-        BinOp.Ty = E->getType();
-        BinOp.Opcode = BO_Add;
-        BinOp.E = E;
-        NextVal = EmitOverflowCheckedBinOp(BinOp);
-        break;
-      }
-    }
+
+    NextVal = ValTy->isSignedIntegerType() ?
+              EmitAddConsiderOverflowBehavior(E, InVal, NextVal, isInc) :
+              // Unsigned integer inc is always two's complement.
+              Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
   } else {
     // Add the inc/dec to the real part.
     if (InVal->getType()->isFloatTy())
index e84e0e11fb9913ac76c5d1c4ca49c9e692ba129e..35487fc34f645d63d2208e61aad8398bcea9a882 100644 (file)
@@ -7081,6 +7081,8 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
     if (PR.isInvalid()) return QualType();
     return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc,
                                           isInc, isPrefix);
+  } else if (S.getLangOptions().AltiVec && ResType->isVectorType()) {
+    // OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
   } else {
     S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
       << ResType << int(isInc) << Op->getSourceRange();
index fbc3148dda154c9a2873901c6c6623bb45a12809..88b1ffad2ef1feb550a3497d720b22e3d78d9548 100644 (file)
@@ -3113,3 +3113,14 @@ void test7() {
   res_i = (vf1 <= vf2);                    // CHECK: @llvm.ppc.altivec.vcmpgefp.p(i32 2
   res_i = (vf1 >= vf2);                    // CHECK: @llvm.ppc.altivec.vcmpgefp.p(i32 2
 }
+
+/* ------------------------------- increment/decrement: ----------------------------- */
+// CHECK: define void @test8
+void test8() {
+  vector int vi;
+  vi++;                                    // CHECK: add nsw <4 x i32> {{.*}} <i32 1, i32 1, i32 1, i32 1>
+  vector unsigned int vui;
+  --vui;                                   // CHECK: add <4 x i32> {{.*}} <i32 -1, i32 -1, i32 -1, i32 -1>
+  vector float vf;
+  vf++;                                    // CHECK: fadd <4 x float> {{.*}} <float 1.000000e+000, float 1.000000e+000, float 1.000000e+000, float 1.000000e+000>
+}
index bb7473f742b029748414d2b7bfbc7f439c45c69c..cf0b62a26a27b169338d2aa7033044eccc8222a4 100644 (file)
@@ -6,7 +6,7 @@ void f(V4i a)
 {
 }
 
-void test()
+void test1()
 {
   V4i vGCC;
   vector int vAltiVec;
@@ -16,3 +16,24 @@ void test()
   bool res = vGCC > vAltiVec;
   vAltiVec = 0 ? vGCC : vGCC;
 }
+
+template<typename T>
+void template_f(T param) {
+  param++;
+}
+
+void test2()
+{
+  vector int vi;
+  ++vi;
+  vi++;
+  --vi;
+  vi--;
+  vector float vf;
+  vf++;
+
+  ++vi=vi;
+  vi++=vi;         // expected-error {{expression is not assignable}}
+  (++vi)[1]=1;
+  template_f(vi);
+}