[cfe-commits] r39673 - in /cfe/cfe/trunk/CodeGen: CGDecl.cpp CGExpr.cpp CodeGenFunction.h

clattner at cs.uiuc.edu clattner at cs.uiuc.edu
Wed Jul 11 09:47:00 PDT 2007


Author: clattner
Date: Wed Jul 11 11:47:00 2007
New Revision: 39673

URL: http://llvm.org/viewvc/llvm-project?rev=39673&view=rev
Log:
add some infrastructure for codegen'ing complex numbers.  implement addition
of complex.  We now produce optimal code for:

void test(_Complex float *Y) {
  *Y = *Y + *Y;
}

$ clang -emit-llvm cg.c | llvm-as | opt -std-compile-opts | llc -march=x86-64
..
_test:
        movss (%rdi), %xmm0
        addss %xmm0, %xmm0
        movss 4(%rdi), %xmm1
        movss %xmm0, (%rdi)
        addss %xmm1, %xmm1
        movss %xmm1, 4(%rdi)
        ret

Modified:
    cfe/cfe/trunk/CodeGen/CGDecl.cpp
    cfe/cfe/trunk/CodeGen/CGExpr.cpp
    cfe/cfe/trunk/CodeGen/CodeGenFunction.h

Modified: cfe/cfe/trunk/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/CodeGen/CGDecl.cpp?rev=39673&r1=39672&r2=39673&view=diff

==============================================================================
--- cfe/cfe/trunk/CodeGen/CGDecl.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CGDecl.cpp Wed Jul 11 11:47:00 2007
@@ -74,7 +74,7 @@
     // A normal fixed sized variable becomes an alloca in the entry block.
     const llvm::Type *LTy = ConvertType(Ty);
     // TODO: Alignment
-    DeclPtr = new llvm::AllocaInst(LTy, 0, D.getName(), AllocaInsertPt);
+    DeclPtr = CreateTempAlloca(LTy, D.getName());
   } else {
     // TODO: Create a dynamic alloca.
     assert(0 && "FIXME: Local VLAs not implemented yet");

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

==============================================================================
--- cfe/cfe/trunk/CodeGen/CGExpr.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CGExpr.cpp Wed Jul 11 11:47:00 2007
@@ -25,6 +25,12 @@
 //                        Miscellaneous Helper Methods
 //===--------------------------------------------------------------------===//
 
+/// CreateTempAlloca - This creates a alloca and inserts it into the entry
+/// block.
+llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty,
+                                                    const char *Name) {
+  return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);
+}
 
 /// EvaluateExprAsBool - Perform the usual unary conversions on the specified
 /// expression and compare the result against zero, returning an Int1Ty value.
@@ -34,6 +40,36 @@
   return ConvertScalarValueToBool(Val, Ty);
 }
 
+/// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to
+/// load the real and imaginary pieces, returning them as Real/Imag.
+void CodeGenFunction::EmitLoadOfComplex(RValue V,
+                                        llvm::Value *&Real, llvm::Value *&Imag){
+  llvm::Value *Ptr = V.getAggregateAddr();
+  
+  llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
+  llvm::Constant *One  = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1);
+  llvm::Value *RealPtr = Builder.CreateGEP(Ptr, Zero, Zero, "realp");
+  llvm::Value *ImagPtr = Builder.CreateGEP(Ptr, Zero, One, "imagp");
+  
+  // FIXME: Handle volatility.
+  Real = Builder.CreateLoad(RealPtr, "real");
+  Imag = Builder.CreateLoad(ImagPtr, "imag");
+}
+
+/// EmitStoreOfComplex - Store the specified real/imag parts into the
+/// specified value pointer.
+void CodeGenFunction::EmitStoreOfComplex(llvm::Value *Real, llvm::Value *Imag,
+                                         llvm::Value *ResPtr) {
+  llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
+  llvm::Constant *One  = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1);
+  llvm::Value *RealPtr = Builder.CreateGEP(ResPtr, Zero, Zero, "real");
+  llvm::Value *ImagPtr = Builder.CreateGEP(ResPtr, Zero, One, "imag");
+  
+  // FIXME: Handle volatility.
+  Builder.CreateStore(Real, RealPtr);
+  Builder.CreateStore(Imag, ImagPtr);
+}
+
 //===--------------------------------------------------------------------===//
 //                               Conversions
 //===--------------------------------------------------------------------===//
@@ -260,6 +296,14 @@
     return;
   }
   
+  // Don't use memcpy for complex numbers.
+  if (Ty->isComplexType()) {
+    llvm::Value *Real, *Imag;
+    EmitLoadOfComplex(Src, Real, Imag);
+    EmitStoreOfComplex(Real, Imag, Dst.getAddress());
+    return;
+  }
+  
   // Aggregate assignment turns into llvm.memcpy.
   const llvm::Type *SBP = llvm::PointerType::get(llvm::Type::Int8Ty);
   llvm::Value *SrcAddr = Src.getAggregateAddr();
@@ -759,9 +803,19 @@
   
   if (LHS.isScalar())
     return RValue::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "add"));
-  
-  assert(0 && "FIXME: This doesn't handle complex operands yet");
 
+  // Otherwise, this must be a complex number.
+  llvm::Value *LHSR, *LHSI, *RHSR, *RHSI;
+  
+  EmitLoadOfComplex(LHS, LHSR, LHSI);
+  EmitLoadOfComplex(RHS, RHSR, RHSI);
+  
+  llvm::Value *ResR = Builder.CreateAdd(LHSR, RHSR, "add.r");
+  llvm::Value *ResI = Builder.CreateAdd(LHSI, RHSI, "add.i");
+  
+  llvm::Value *Res = CreateTempAlloca(ConvertType(E->getType()));
+  EmitStoreOfComplex(ResR, ResI, Res);
+  return RValue::getAggregate(Res);
 }
 
 RValue CodeGenFunction::EmitBinarySub(const BinaryOperator *E) {

Modified: cfe/cfe/trunk/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/CodeGen/CodeGenFunction.h?rev=39673&r1=39672&r2=39673&view=diff

==============================================================================
--- cfe/cfe/trunk/CodeGen/CodeGenFunction.h (original)
+++ cfe/cfe/trunk/CodeGen/CodeGenFunction.h Wed Jul 11 11:47:00 2007
@@ -160,11 +160,29 @@
   
   void EmitBlock(llvm::BasicBlock *BB);
 
-
+  //===--------------------------------------------------------------------===//
+  //                                  Helpers
+  //===--------------------------------------------------------------------===//
+  
+  /// CreateTempAlloca - This creates a alloca and inserts it into the entry
+  /// block.
+  llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty,
+                                     const char *Name = "tmp");
+  
   /// EvaluateExprAsBool - Perform the usual unary conversions on the specified
   /// expression and compare the result against zero, returning an Int1Ty value.
   llvm::Value *EvaluateExprAsBool(const Expr *E);
+
   
+  /// EmitLoadOfComplex - Given an RValue reference for a complex, emit code to
+  /// load the real and imaginary pieces, returning them as Real/Imag.
+  void EmitLoadOfComplex(RValue V, llvm::Value *&Real, llvm::Value *&Imag);
+  
+  /// EmitStoreOfComplex - Store the specified real/imag parts into the
+  /// specified value pointer.
+  void EmitStoreOfComplex(llvm::Value *Real, llvm::Value *Imag,
+                          llvm::Value *ResPtr);
+
   //===--------------------------------------------------------------------===//
   //                                Conversions
   //===--------------------------------------------------------------------===//





More information about the cfe-commits mailing list