Extend vector member references to include {.hi, .lo, .e, .o} which return a
vector of the same element type and half the width, with the high, low, even,
and odd elements respectively.

Allow member references to member references, so that .hi.hi gives you the high
quarter of a vector.  This is fairly convenient syntax for some insert/extract
operations.

Remove some unnecessary methods/types in the ExtVectorElementExpr class.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50892 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 3c1ab74..043cfa1 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -182,13 +182,13 @@
                                                          QualType ExprType) {
   llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(), "tmp");
   
-  unsigned EncFields = LV.getExtVectorElts();
+  const llvm::Constant *Elts = LV.getExtVectorElts();
   
   // If the result of the expression is a non-vector type, we must be
   // extracting a single element.  Just codegen as an extractelement.
   const VectorType *ExprVT = ExprType->getAsVectorType();
   if (!ExprVT) {
-    unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(0, EncFields);
+    unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(0, Elts);
     llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
     return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp"));
   }
@@ -202,7 +202,7 @@
   if (NumResultElts == NumSourceElts) {
     llvm::SmallVector<llvm::Constant*, 4> Mask;
     for (unsigned i = 0; i != NumResultElts; ++i) {
-      unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(i, EncFields);
+      unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(i, Elts);
       Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx));
     }
     
@@ -218,7 +218,7 @@
   
   // Extract/Insert each element of the result.
   for (unsigned i = 0; i != NumResultElts; ++i) {
-    unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(i, EncFields);
+    unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(i, Elts);
     llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
     Elt = Builder.CreateExtractElement(Vec, Elt, "tmp");
     
@@ -312,7 +312,7 @@
   // value now.
   llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddr(), "tmp");
   // FIXME: Volatility.
-  unsigned EncFields = Dst.getExtVectorElts();
+  const llvm::Constant *Elts = Dst.getExtVectorElts();
   
   llvm::Value *SrcVal = Src.getScalarVal();
   
@@ -324,13 +324,13 @@
       llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, i);
       Elt = Builder.CreateExtractElement(SrcVal, Elt, "tmp");
       
-      unsigned Idx = ExtVectorElementExpr::getAccessedFieldNo(i, EncFields);
+      unsigned Idx = ExtVectorElementExpr::getAccessedFieldNo(i, Elts);
       llvm::Value *OutIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, Idx);
       Vec = Builder.CreateInsertElement(Vec, Elt, OutIdx, "tmp");
     }
   } else {
     // If the Src is a scalar (not a vector) it must be updating one element.
-    unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(0, EncFields);
+    unsigned InIdx = ExtVectorElementExpr::getAccessedFieldNo(0, Elts);
     llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx);
     Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp");
   }
@@ -460,9 +460,28 @@
 EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
   // Emit the base vector as an l-value.
   LValue Base = EmitLValue(E->getBase());
+  
+  if (Base.isExtVectorElt()) {
+    llvm::Constant *BaseElts = Base.getExtVectorElts();
+    llvm::Constant *ExprElts = E->getEncodedElementAccess();
+    
+    llvm::SmallVector<llvm::Constant *, 8> Indices;
+    
+    for (unsigned i = 0, e = E->getNumElements(); i != e; ++i) {
+      unsigned Idx = ExtVectorElementExpr::getAccessedFieldNo(i, ExprElts);
+      
+      if (isa<llvm::ConstantAggregateZero>(BaseElts))
+        Indices.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
+      else
+        Indices.push_back(cast<llvm::ConstantInt>(BaseElts->getOperand(Idx)));
+    }
+    llvm::Constant *NewElts = llvm::ConstantVector::get(&Indices[0], Indices.size());
+    return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), NewElts);
+  }
+  
   assert(Base.isSimple() && "Can only subscript lvalue vectors here!");
 
-  return LValue::MakeExtVectorElt(Base.getAddress(), 
+  return LValue::MakeExtVectorElt(Base.getAddress(),
                                   E->getEncodedElementAccess());
 }