summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-06-22 21:44:33 +0000
committerChris Lattner <sabre@nondot.org>2007-06-22 21:44:33 +0000
commite9a6453ded48e319aec7a8be4a0a477915aaa8f8 (patch)
tree7813978379d937ec2b371b9d3a8d18d9c51cd889
parentc6395936ae1c35e755a3fd7e4a67c7b47142643c (diff)
downloadbcm5719-llvm-e9a6453ded48e319aec7a8be4a0a477915aaa8f8.tar.gz
bcm5719-llvm-e9a6453ded48e319aec7a8be4a0a477915aaa8f8.zip
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 llvm-svn: 39673
-rw-r--r--clang/CodeGen/CGDecl.cpp2
-rw-r--r--clang/CodeGen/CGExpr.cpp58
-rw-r--r--clang/CodeGen/CodeGenFunction.h20
3 files changed, 76 insertions, 4 deletions
diff --git a/clang/CodeGen/CGDecl.cpp b/clang/CodeGen/CGDecl.cpp
index 15f8610ed0c..822aca3f557 100644
--- a/clang/CodeGen/CGDecl.cpp
+++ b/clang/CodeGen/CGDecl.cpp
@@ -74,7 +74,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const BlockVarDecl &D) {
// 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");
diff --git a/clang/CodeGen/CGExpr.cpp b/clang/CodeGen/CGExpr.cpp
index f0a0f6ee189..8c3c2d4898c 100644
--- a/clang/CodeGen/CGExpr.cpp
+++ b/clang/CodeGen/CGExpr.cpp
@@ -25,6 +25,12 @@ using namespace CodeGen;
// 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 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
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 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
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 @@ RValue CodeGenFunction::EmitBinaryAdd(const BinaryOperator *E) {
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) {
diff --git a/clang/CodeGen/CodeGenFunction.h b/clang/CodeGen/CodeGenFunction.h
index ad7deea46a1..a1d009f4f0d 100644
--- a/clang/CodeGen/CodeGenFunction.h
+++ b/clang/CodeGen/CodeGenFunction.h
@@ -160,11 +160,29 @@ public:
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
//===--------------------------------------------------------------------===//
OpenPOWER on IntegriCloud