[cfe-commits] r62458 - in /cfe/trunk: lib/AST/ASTContext.cpp lib/CodeGen/CGBuiltin.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/Sema.cpp test/CodeGen/ext-vector-shuffle.c

Nate Begeman natebegeman at mac.com
Sat Jan 17 22:42:52 PST 2009


Author: sampo
Date: Sun Jan 18 00:42:49 2009
New Revision: 62458

URL: http://llvm.org/viewvc/llvm-project?rev=62458&view=rev
Log:
Vector codegen improvements

Added:
    cfe/trunk/test/CodeGen/ext-vector-shuffle.c
Modified:
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/Sema.cpp

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=62458&r1=62457&r2=62458&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sun Jan 18 00:42:49 2009
@@ -20,6 +20,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Bitcode/Serialize.h"
 #include "llvm/Bitcode/Deserialize.h"
+#include "llvm/Support/MathExtras.h"
 
 using namespace clang;
 
@@ -284,8 +285,11 @@
     std::pair<uint64_t, unsigned> EltInfo = 
       getTypeInfo(cast<VectorType>(T)->getElementType());
     Width = EltInfo.first*cast<VectorType>(T)->getNumElements();
-    // FIXME: This isn't right for unusual vectors
     Align = Width;
+    // If the alignment is not a power of 2, round up to the next power of 2.
+    // This happens for non-power-of-2 length vectors.
+    // FIXME: this should probably be a target property.
+    Align = 1 << llvm::Log2_32_Ceil(Align);
     break;
   }
 

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=62458&r1=62457&r2=62458&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Sun Jan 18 00:42:49 2009
@@ -631,6 +631,8 @@
   case X86::BI__builtin_ia32_vec_ext_v2di:
   case X86::BI__builtin_ia32_vec_ext_v4sf:
   case X86::BI__builtin_ia32_vec_ext_v4si:
+  case X86::BI__builtin_ia32_vec_ext_v8hi:
+  case X86::BI__builtin_ia32_vec_ext_v4hi:
   case X86::BI__builtin_ia32_vec_ext_v2df:
     return Builder.CreateExtractElement(Ops[0], Ops[1], "result");
   case X86::BI__builtin_ia32_cmpordss:

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=62458&r1=62457&r2=62458&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Jan 18 00:42:49 2009
@@ -309,8 +309,8 @@
   return EmitObjCPropertyGet(LV.getKVCRefExpr());
 }
 
-// If this is a reference to a subset of the elements of a vector, either
-// shuffle the input or extract/insert them as appropriate.
+// If this is a reference to a subset of the elements of a vector, create an
+// appropriate shufflevector.
 RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV,
                                                          QualType ExprType) {
   llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(),
@@ -326,41 +326,21 @@
     llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
     return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp"));
   }
-  
-  // If the source and destination have the same number of elements, use a
-  // vector shuffle instead of insert/extracts.
+
+  // Always use shuffle vector to try to retain the original program structure
   unsigned NumResultElts = ExprVT->getNumElements();
-  unsigned NumSourceElts =
-    cast<llvm::VectorType>(Vec->getType())->getNumElements();
-  
-  if (NumResultElts == NumSourceElts) {
-    llvm::SmallVector<llvm::Constant*, 4> Mask;
-    for (unsigned i = 0; i != NumResultElts; ++i) {
-      unsigned InIdx = getAccessedFieldNo(i, Elts);
-      Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
-    }
-    
-    llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
-    Vec = Builder.CreateShuffleVector(Vec,
-                                      llvm::UndefValue::get(Vec->getType()),
-                                      MaskV, "tmp");
-    return RValue::get(Vec);
-  }
-  
-  // Start out with an undef of the result type.
-  llvm::Value *Result = llvm::UndefValue::get(ConvertType(ExprType));
   
-  // Extract/Insert each element of the result.
+  llvm::SmallVector<llvm::Constant*, 4> Mask;
   for (unsigned i = 0; i != NumResultElts; ++i) {
     unsigned InIdx = getAccessedFieldNo(i, Elts);
-    llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
-    Elt = Builder.CreateExtractElement(Vec, Elt, "tmp");
-    
-    llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
-    Result = Builder.CreateInsertElement(Result, Elt, OutIdx, "tmp");
+    Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
   }
   
-  return RValue::get(Result);
+  llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
+  Vec = Builder.CreateShuffleVector(Vec,
+                                    llvm::UndefValue::get(Vec->getType()),
+                                    MaskV, "tmp");
+  return RValue::get(Vec);
 }
 
 
@@ -548,15 +528,54 @@
   
   if (const VectorType *VTy = Ty->getAsVectorType()) {
     unsigned NumSrcElts = VTy->getNumElements();
-
-    // Extract/Insert each element.
-    for (unsigned i = 0; i != NumSrcElts; ++i) {
-      llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
-      Elt = Builder.CreateExtractElement(SrcVal, Elt, "tmp");
-      
-      unsigned Idx = getAccessedFieldNo(i, Elts);
-      llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, Idx);
-      Vec = Builder.CreateInsertElement(Vec, Elt, OutIdx, "tmp");
+    unsigned NumDstElts =
+       cast<llvm::VectorType>(Vec->getType())->getNumElements();
+    if (NumDstElts == NumSrcElts) {
+      // Use shuffle vector is the src and destination are the same number
+      // of elements
+      llvm::SmallVector<llvm::Constant*, 4> Mask;
+      for (unsigned i = 0; i != NumSrcElts; ++i) {
+        unsigned InIdx = getAccessedFieldNo(i, Elts);
+        Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
+      }
+    
+      llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
+      Vec = Builder.CreateShuffleVector(SrcVal,
+                                        llvm::UndefValue::get(Vec->getType()),
+                                        MaskV, "tmp");
+    }
+    else if (NumDstElts > NumSrcElts) {
+      // Extended the source vector to the same length and then shuffle it
+      // into the destination.
+      // FIXME: since we're shuffling with undef, can we just use the indices
+      //        into that?  This could be simpler.
+      llvm::SmallVector<llvm::Constant*, 4> ExtMask;
+      unsigned i;
+      for (i = 0; i != NumSrcElts; ++i)
+        ExtMask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, i));
+      for (; i != NumDstElts; ++i)
+        ExtMask.push_back(llvm::UndefValue::get(llvm::Type::Int32Ty));
+      llvm::Value *ExtMaskV = llvm::ConstantVector::get(&ExtMask[0],
+                                                        ExtMask.size());
+      llvm::Value *ExtSrcVal = Builder.CreateShuffleVector(SrcVal,
+                                        llvm::UndefValue::get(SrcVal->getType()),
+                                        ExtMaskV, "tmp");
+      // build identity
+      llvm::SmallVector<llvm::Constant*, 4> Mask;
+      for (unsigned i = 0; i != NumDstElts; ++i) {
+        Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, i));
+      }
+      // modify when what gets shuffled in
+      for (unsigned i = 0; i != NumSrcElts; ++i) {
+        unsigned Idx = getAccessedFieldNo(i, Elts);
+        Mask[Idx] =llvm::ConstantInt::get(llvm::Type::Int32Ty, i+NumDstElts);
+      }
+      llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size());
+      Vec = Builder.CreateShuffleVector(Vec, ExtSrcVal, MaskV, "tmp");
+    }
+    else {
+      // We should never shorten the vector
+      assert(0 && "unexpected shorten vector length");
     }
   } else {
     // If the Src is a scalar (not a vector) it must be updating one element.

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=62458&r1=62457&r2=62458&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Sun Jan 18 00:42:49 2009
@@ -409,10 +409,26 @@
   }
   
   // A scalar can be splatted to an extended vector of the same element type
-  if (DstType->isExtVectorType() && !isa<VectorType>(SrcType) &&
-      cast<llvm::VectorType>(DstTy)->getElementType() == Src->getType())
-    return CGF.EmitVector(&Src, DstType->getAsVectorType()->getNumElements(), 
-                          true);
+  if (DstType->isExtVectorType() && !isa<VectorType>(SrcType)) {
+    // Cast the scalar to element type
+    QualType EltTy = DstType->getAsExtVectorType()->getElementType();
+    llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy);
+
+    // Insert the element in element zero of an undef vector
+    llvm::Value *UnV = llvm::UndefValue::get(DstTy);
+    llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
+    UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp");
+
+    // Splat the element across to all elements
+    llvm::SmallVector<llvm::Constant*, 16> Args;
+    unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
+    for (unsigned i = 0; i < NumElements; i++)
+      Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
+    
+    llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements);
+    llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
+    return Yay;
+  }
 
   // Allow bitcast from vector to integer/fp of the same size.
   if (isa<llvm::VectorType>(Src->getType()) ||

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=62458&r1=62457&r2=62458&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Sun Jan 18 00:42:49 2009
@@ -151,7 +151,7 @@
 
 /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. 
 /// If there is already an implicit cast, merge into the existing one.
-  /// If isLvalue, the result of the cast is an lvalue.
+/// If isLvalue, the result of the cast is an lvalue.
 void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, bool isLvalue) {
   QualType ExprTy = Context.getCanonicalType(Expr->getType());
   QualType TypeTy = Context.getCanonicalType(Ty);

Added: cfe/trunk/test/CodeGen/ext-vector-shuffle.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ext-vector-shuffle.c?rev=62458&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/ext-vector-shuffle.c (added)
+++ cfe/trunk/test/CodeGen/ext-vector-shuffle.c Sun Jan 18 00:42:49 2009
@@ -0,0 +1,15 @@
+// RUN: clang %s -emit-llvm -o - | not grep 'extractelement'
+// RUN: clang %s -emit-llvm -o - | not grep 'insertelement'
+// RUN: clang %s -emit-llvm -o - | grep 'shufflevector'
+
+typedef __attribute__(( ext_vector_type(2) )) float float2;
+typedef __attribute__(( ext_vector_type(4) )) float float4;
+
+float2 test1(float4 V) {
+  return V.xy + V.wz;
+}
+
+float4 test2(float4 V) {
+  float2 W = V.ww;
+  return W.xyxy + W.yxyx;
+}





More information about the cfe-commits mailing list