[llvm-commits] [dragonegg] r127400 - in /dragonegg/trunk: llvm-backend.cpp llvm-convert.cpp llvm-internal.h
Duncan Sands
baldrick at free.fr
Thu Mar 10 00:28:09 PST 2011
Author: baldrick
Date: Thu Mar 10 02:28:09 2011
New Revision: 127400
URL: http://llvm.org/viewvc/llvm-project?rev=127400&view=rev
Log:
Get rid of a few more cases in which a register value was being constructed
by casting a memory value. This results in some duplicated code - that will
be cleaned up later. Do some miscellaneous cleanups while there.
Modified:
dragonegg/trunk/llvm-backend.cpp
dragonegg/trunk/llvm-convert.cpp
dragonegg/trunk/llvm-internal.h
Modified: dragonegg/trunk/llvm-backend.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-backend.cpp?rev=127400&r1=127399&r2=127400&view=diff
==============================================================================
--- dragonegg/trunk/llvm-backend.cpp (original)
+++ dragonegg/trunk/llvm-backend.cpp Thu Mar 10 02:28:09 2011
@@ -1007,11 +1007,7 @@
// Reconvert the type in case the forward def of the global and the real def
// differ in type (e.g. declared as 'int A[]', and defined as 'int A[100]').
const Type *Ty = ConvertType(TREE_TYPE(decl));
-
- if (flag_default_initialize_globals)
- Init = Constant::getNullValue(Ty);
- else
- Init = UndefValue::get(Ty);
+ Init = getDefaultValue(Ty);
} else {
assert((TREE_CONSTANT(DECL_INITIAL(decl)) ||
TREE_CODE(DECL_INITIAL(decl)) == STRING_CST) &&
Modified: dragonegg/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-convert.cpp?rev=127400&r1=127399&r2=127400&view=diff
==============================================================================
--- dragonegg/trunk/llvm-convert.cpp (original)
+++ dragonegg/trunk/llvm-convert.cpp Thu Mar 10 02:28:09 2011
@@ -802,7 +802,7 @@
/// DefineSSAName - Use the given value as the definition of the given SSA name.
/// Returns the provided value as a convenience.
-Value *TreeToLLVM::DefineSSAName(tree_node *reg, Value *Val) {
+Value *TreeToLLVM::DefineSSAName(tree reg, Value *Val) {
assert(TREE_CODE(reg) == SSA_NAME && "Not an SSA name!");
if (Value *ExistingValue = SSANames[reg]) {
if (Val != ExistingValue) {
@@ -1377,7 +1377,7 @@
/// CreateAnyAdd - Add two LLVM scalar values with the given GCC type. Does not
/// support complex numbers. The type is used to set overflow flags.
-Value *TreeToLLVM::CreateAnyAdd(Value *LHS, Value *RHS, tree_node *type) {
+Value *TreeToLLVM::CreateAnyAdd(Value *LHS, Value *RHS, tree type) {
if (FLOAT_TYPE_P(type))
return Builder.CreateFAdd(LHS, RHS);
return Builder.CreateAdd(LHS, RHS, "", hasNUW(type), hasNSW(type));
@@ -1385,7 +1385,7 @@
/// CreateAnyMul - Multiply two LLVM scalar values with the given GCC type.
/// Does not support complex numbers. The type is used to set overflow flags.
-Value *TreeToLLVM::CreateAnyMul(Value *LHS, Value *RHS, tree_node *type) {
+Value *TreeToLLVM::CreateAnyMul(Value *LHS, Value *RHS, tree type) {
if (FLOAT_TYPE_P(type))
return Builder.CreateFMul(LHS, RHS);
return Builder.CreateMul(LHS, RHS, "", hasNUW(type), hasNSW(type));
@@ -1393,7 +1393,7 @@
/// CreateAnyNeg - Negate an LLVM scalar value with the given GCC type. Does
/// not support complex numbers. The type is used to set overflow flags.
-Value *TreeToLLVM::CreateAnyNeg(Value *V, tree_node *type) {
+Value *TreeToLLVM::CreateAnyNeg(Value *V, tree type) {
if (FLOAT_TYPE_P(type))
return Builder.CreateFNeg(V);
return Builder.CreateNeg(V, "", hasNUW(type), hasNSW(type));
@@ -1401,7 +1401,7 @@
/// CreateAnySub - Subtract two LLVM scalar values with the given GCC type.
/// Does not support complex numbers. The type is used to set overflow flags.
-Value *TreeToLLVM::CreateAnySub(Value *LHS, Value *RHS, tree_node *type) {
+Value *TreeToLLVM::CreateAnySub(Value *LHS, Value *RHS, tree type) {
if (FLOAT_TYPE_P(type))
return Builder.CreateFSub(LHS, RHS);
return Builder.CreateSub(LHS, RHS, "", hasNUW(type), hasNSW(type));
@@ -3020,7 +3020,7 @@
/// type, passing the provided arguments (which should all be gimple registers
/// or local constants of register type). No marshalling is done: the arguments
/// are directly passed through.
-CallInst *TreeToLLVM::EmitSimpleCall(StringRef CalleeName, tree_node *ret_type,
+CallInst *TreeToLLVM::EmitSimpleCall(StringRef CalleeName, tree ret_type,
/* arguments */ ...) {
va_list ops;
va_start(ops, ret_type);
@@ -5897,39 +5897,57 @@
#endif
assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!");
- Constant *C;
switch (TREE_CODE(reg)) {
default:
debug_tree(reg);
llvm_unreachable("Unhandled GIMPLE constant!");
case INTEGER_CST:
- return EmitRegisterIntegerConstant(reg);
+ return EmitIntegerRegisterConstant(reg);
case REAL_CST:
- C = TreeConstantToLLVM::ConvertREAL_CST(reg);
- break;
+ return EmitRealRegisterConstant(reg);
//case FIXED_CST: // Fixed point constant - not yet supported.
- //case STRING_CST: // Allowed by is_gimple_constant, but no known testcase.
+ //case STRING_CST: // Allowed by is_gimple_constant, but no known examples.
case COMPLEX_CST:
- C = TreeConstantToLLVM::ConvertCOMPLEX_CST(reg);
- break;
+ return EmitComplexRegisterConstant(reg);
case VECTOR_CST:
- C = TreeConstantToLLVM::ConvertVECTOR_CST(reg);
- break;
+ return EmitVectorRegisterConstant(reg);
case CONSTRUCTOR:
// Vector constant constructors are gimple invariant. See GCC testcase
// pr34856.c.
- C = TreeConstantToLLVM::ConvertCONSTRUCTOR(reg);
- break;
+ return Mem2Reg(TreeConstantToLLVM::ConvertCONSTRUCTOR(reg), TREE_TYPE(reg),
+ *TheFolder);
}
+}
- // Convert from in-memory to in-register type.
- return Mem2Reg(C, TREE_TYPE(reg), *TheFolder);
+/// EncodeExpr - Write the given expression into Buffer as it would appear in
+/// memory on the target (the buffer is resized to contain exactly the bytes
+/// written). Return the number of bytes written; this can also be obtained
+/// by querying the buffer's size.
+/// The following kinds of expressions are currently supported: INTEGER_CST,
+/// REAL_CST, COMPLEX_CST, VECTOR_CST, STRING_CST.
+static unsigned EncodeExpr(tree exp, SmallVectorImpl<unsigned char> &Buffer) {
+ const tree type = TREE_TYPE(exp);
+ unsigned SizeInBytes = (TREE_INT_CST_LOW(TYPE_SIZE(type)) + 7) / 8;
+ Buffer.resize(SizeInBytes);
+ unsigned BytesWritten = native_encode_expr(exp, &Buffer[0], SizeInBytes);
+ assert(BytesWritten == SizeInBytes && "Failed to fully encode expression!");
+ return BytesWritten;
+}
+
+/// EmitComplexRegisterConstant - Turn the given COMPLEX_CST into an LLVM
+/// constant of the corresponding register type.
+Constant *TreeToLLVM::EmitComplexRegisterConstant(tree reg) {
+ Constant *Elts[2] = {
+ EmitRegisterConstant(TREE_REALPART(reg)),
+ EmitRegisterConstant(TREE_IMAGPART(reg))
+ };
+ return ConstantStruct::get(Context, Elts, 2, false);
}
-/// EmitRegisterIntegerConstant - Turn the given INTEGER_CST into an LLVM
+/// EmitIntegerRegisterConstant - Turn the given INTEGER_CST into an LLVM
/// constant of the corresponding register type.
-Constant *TreeToLLVM::EmitRegisterIntegerConstant(tree reg) {
+Constant *TreeToLLVM::EmitIntegerRegisterConstant(tree reg) {
unsigned Precision = TYPE_PRECISION(TREE_TYPE(reg));
ConstantInt *CI;
@@ -5955,9 +5973,81 @@
return TheFolder->CreateCast(opcode, CI, Ty);
}
+/// EmitRealRegisterConstant - Turn the given REAL_CST into an LLVM constant
+/// of the corresponding register type.
+Constant *TreeToLLVM::EmitRealRegisterConstant(tree reg) {
+ // TODO: Rather than going through memory, construct the APFloat directly from
+ // the real_value. This works fine for zero, inf and nan values, but APFloat
+ // has no constructor for normal numbers, i.e. constructing a normal number
+ // from the exponent and significand.
+ // TODO: Test implementation on a big-endian machine.
+
+ // Encode the constant in Buffer in target format.
+ SmallVector<unsigned char, 16> Buffer;
+ EncodeExpr(reg, Buffer);
+
+ // Discard any alignment padding, which we assume comes at the end.
+ unsigned Precision = TYPE_PRECISION(TREE_TYPE(reg));
+ assert((Precision & 7) == 0 && "Unsupported real number precision!");
+ Buffer.resize(Precision / 8);
+
+ // We are going to view the buffer as an array of APInt words. Ensure that
+ // the buffer contains a whole number of words by extending it if necessary.
+ unsigned Words = (Precision + integerPartWidth - 1) / integerPartWidth;
+ // On a little-endian machine extend the buffer by adding bytes to the end.
+ Buffer.resize(Words * (integerPartWidth / 8));
+ // On a big-endian machine extend the buffer by adding bytes to the beginning.
+ if (BYTES_BIG_ENDIAN)
+ std::copy_backward(Buffer.begin(), Buffer.begin() + Precision / 8,
+ Buffer.end());
+
+ // Ensure that the least significant word comes first: we are going to make an
+ // APInt, and the APInt constructor wants the least significant word first.
+ integerPart *Parts = (integerPart *)&Buffer[0];
+ if (BYTES_BIG_ENDIAN)
+ std::reverse(Parts, Parts + Words);
+
+ bool isPPC_FP128 = ConvertType(TREE_TYPE(reg))->isPPC_FP128Ty();
+ if (isPPC_FP128) {
+ // This type is actually a pair of doubles in disguise. They turn up the
+ // wrong way round here, so flip them.
+ assert(FLOAT_WORDS_BIG_ENDIAN && "PPC not big endian!");
+ assert(Words == 2 && Precision == 128 && "Strange size for PPC_FP128!");
+ std::swap(Parts[0], Parts[1]);
+ }
+
+ // Form an APInt from the buffer, an APFloat from the APInt, and the desired
+ // floating point constant from the APFloat, phew!
+ const APInt &I = APInt(Precision, Words, Parts);
+ return ConstantFP::get(Context, APFloat(I, !isPPC_FP128));
+}
+
+/// EmitVectorRegisterConstant - Turn the given VECTOR_CST into an LLVM constant
+/// of the corresponding register type.
+Constant *TreeToLLVM::EmitVectorRegisterConstant(tree reg) {
+ // If there are no elements then immediately return the default value for a
+ // small speedup.
+ if (!TREE_VECTOR_CST_ELTS(reg))
+ return getDefaultValue(GetRegType(TREE_TYPE(reg)));
+
+ // Convert the elements.
+ SmallVector<Constant*, 8> Elts;
+ for (tree elt = TREE_VECTOR_CST_ELTS(reg); elt; elt = TREE_CHAIN(elt))
+ Elts.push_back(EmitRegisterConstant(TREE_VALUE(elt)));
+
+ // If there weren't enough elements then set the rest of the vector to the
+ // default value.
+ if (Elts.size() < TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg))) {
+ Constant *Default = getDefaultValue(GetRegType(TREE_TYPE(TREE_TYPE(reg))));
+ Elts.append(TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg)) - Elts.size(), Default);
+ }
+
+ return ConstantVector::get(Elts);
+}
+
/// Mem2Reg - Convert a value of in-memory type (that given by ConvertType)
/// to in-register type (that given by GetRegType).
-Value *TreeToLLVM::Mem2Reg(Value *V, tree_node *type, LLVMBuilder &Builder) {
+Value *TreeToLLVM::Mem2Reg(Value *V, tree type, LLVMBuilder &Builder) {
const Type *MemTy = V->getType();
const Type *RegTy = GetRegType(type);
assert(MemTy == ConvertType(type) && "Not of memory type!");
@@ -5969,8 +6059,7 @@
"Unexpected type mismatch!");
return Builder.CreateIntCast(V, RegTy, /*isSigned*/!TYPE_UNSIGNED(type));
}
-Constant *TreeToLLVM::Mem2Reg(Constant *C, tree_node *type,
- TargetFolder &Folder) {
+Constant *TreeToLLVM::Mem2Reg(Constant *C, tree type, TargetFolder &Folder) {
const Type *MemTy = C->getType();
const Type *RegTy = GetRegType(type);
assert(MemTy == ConvertType(type) && "Not of memory type!");
@@ -5985,7 +6074,7 @@
/// Reg2Mem - Convert a value of in-register type (that given by GetRegType)
/// to in-memory type (that given by ConvertType).
-Value *TreeToLLVM::Reg2Mem(Value *V, tree_node *type, LLVMBuilder &Builder) {
+Value *TreeToLLVM::Reg2Mem(Value *V, tree type, LLVMBuilder &Builder) {
const Type *RegTy = V->getType();
const Type *MemTy = ConvertType(type);
assert(RegTy == GetRegType(type) && "Not of register type!");
@@ -6014,7 +6103,7 @@
/// StoreRegisterToMemory - Stores the given value to the memory pointed to by
/// Loc. Takes care of adjusting for any differences between the value's type
/// (which is the in-register type given by GetRegType) and the in-memory type.
-void TreeToLLVM::StoreRegisterToMemory(Value *V, MemRef Loc, tree_node *type,
+void TreeToLLVM::StoreRegisterToMemory(Value *V, MemRef Loc, tree type,
LLVMBuilder &Builder) {
const Type *MemTy = ConvertType(type);
Value *Ptr = Builder.CreateBitCast(Loc.Ptr, MemTy->getPointerTo());
@@ -7982,21 +8071,6 @@
}
}
-/// EncodeExpr - Write the given expression into Buffer as it would appear in
-/// memory on the target (the buffer is resized to contain exactly the bytes
-/// written). Return the number of bytes written; this can also be obtained
-/// by querying the buffer's size.
-/// The following kinds of expressions are currently supported: INTEGER_CST,
-/// REAL_CST, COMPLEX_CST, VECTOR_CST, STRING_CST.
-static unsigned EncodeExpr(tree exp, SmallVectorImpl<unsigned char> &Buffer) {
- const tree type = TREE_TYPE(exp);
- unsigned SizeInBytes = (TREE_INT_CST_LOW(TYPE_SIZE(type)) + 7) / 8;
- Buffer.resize(SizeInBytes);
- unsigned BytesWritten = native_encode_expr(exp, &Buffer[0], SizeInBytes);
- assert(BytesWritten == SizeInBytes && "Failed to fully encode expression!");
- return BytesWritten;
-}
-
Constant *TreeConstantToLLVM::ConvertINTEGER_CST(tree exp) {
const Type *Ty = ConvertType(TREE_TYPE(exp));
Modified: dragonegg/trunk/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-internal.h?rev=127400&r1=127399&r2=127400&view=diff
==============================================================================
--- dragonegg/trunk/llvm-internal.h (original)
+++ dragonegg/trunk/llvm-internal.h Thu Mar 10 02:28:09 2011
@@ -219,6 +219,14 @@
return TheTypeConverter->ConvertType(type);
}
+/// getDefaultValue - Return the default value to use for a constant or global
+/// that has no value specified. For example in C like languages such variables
+/// are initialized to zero, while in Ada they hold an undefined value.
+inline Constant *getDefaultValue(const Type *Ty) {
+ return flag_default_initialize_globals ?
+ Constant::getNullValue(Ty) : UndefValue::get(Ty);
+}
+
/// GetUnitPointerType - Returns an LLVM pointer type which points to memory one
/// address unit wide. For example, on a machine which has 16 bit bytes returns
/// an i16*.
@@ -782,9 +790,21 @@
/// to an LLVM constant. Creates no code, only constants.
Constant *EmitRegisterConstant(tree_node *reg);
- /// EmitRegisterIntegerConstant - Turn the given INTEGER_CST into an LLVM
+ /// EmitComplexRegisterConstant - Turn the given COMPLEX_CST into an LLVM
/// constant of the corresponding register type.
- Constant *EmitRegisterIntegerConstant(tree_node *reg);
+ Constant *EmitComplexRegisterConstant(tree_node *reg);
+
+ /// EmitIntegerRegisterConstant - Turn the given INTEGER_CST into an LLVM
+ /// constant of the corresponding register type.
+ Constant *EmitIntegerRegisterConstant(tree_node *reg);
+
+ /// EmitRealRegisterConstant - Turn the given REAL_CST into an LLVM constant
+ /// of the corresponding register type.
+ Constant *EmitRealRegisterConstant(tree_node *reg);
+
+ /// EmitVectorRegisterConstant - Turn the given VECTOR_CST into an LLVM
+ // constant of the corresponding register type.
+ Constant *EmitVectorRegisterConstant(tree_node *reg);
/// Mem2Reg - Convert a value of in-memory type (that given by ConvertType)
/// to in-register type (that given by GetRegType). TODO: Eliminate these
More information about the llvm-commits
mailing list