From: Dan Gohman Date: Tue, 2 Feb 2010 01:41:39 +0000 (+0000) Subject: Factor out alignof expression folding into a separate function and X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6acb86dcfa1ff4e38d2f189ab09e3fbe22f248a7;p=oota-llvm.git Factor out alignof expression folding into a separate function and generalize it to handle more cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95045 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 8441b8fa094..a97396e1249 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -345,18 +345,19 @@ static Constant *getFoldedSizeOf(const Type *Ty, const Type *DestTy, // An empty struct has size zero. if (NumElems == 0) return ConstantExpr::getNullValue(DestTy); - // Check for a struct with all members having the same type. - const Type *MemberTy = STy->getElementType(0); + // Check for a struct with all members having the same size. + Constant *MemberSize = + getFoldedSizeOf(STy->getElementType(0), DestTy, true); bool AllSame = true; for (unsigned i = 1; i != NumElems; ++i) - if (MemberTy != STy->getElementType(i)) { + if (MemberSize != + getFoldedSizeOf(STy->getElementType(i), DestTy, true)) { AllSame = false; break; } if (AllSame) { Constant *N = ConstantInt::get(DestTy, NumElems); - Constant *E = getFoldedSizeOf(MemberTy, DestTy, true); - return ConstantExpr::getNUWMul(E, N); + return ConstantExpr::getNUWMul(MemberSize, N); } } @@ -373,6 +374,62 @@ static Constant *getFoldedSizeOf(const Type *Ty, const Type *DestTy, return C; } +/// getFoldedAlignOf - Return a ConstantExpr with type DestTy for alignof +/// on Ty, with any known factors factored out. If Folded is false, +/// return null if no factoring was possible, to avoid endlessly +/// bouncing an unfoldable expression back into the top-level folder. +/// +static Constant *getFoldedAlignOf(const Type *Ty, const Type *DestTy, + bool Folded) { + // The alignment of an array is equal to the alignment of the + // array element. Note that this is not always true for vectors. + if (const ArrayType *ATy = dyn_cast(Ty)) { + Constant *C = ConstantExpr::getAlignOf(ATy->getElementType()); + C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, + DestTy, + false), + C, DestTy); + return C; + } + + if (const StructType *STy = dyn_cast(Ty)) { + // Packed structs always have an alignment of 1. + if (STy->isPacked()) + return ConstantInt::get(DestTy, 1); + + // Otherwise, struct alignment is the maximum alignment of any member. + // Without target data, we can't compare much, but we can check to see + // if all the members have the same alignment. + unsigned NumElems = STy->getNumElements(); + // An empty struct has minimal alignment. + if (NumElems == 0) + return ConstantInt::get(DestTy, 1); + // Check for a struct with all members having the same alignment. + Constant *MemberAlign = + getFoldedAlignOf(STy->getElementType(0), DestTy, true); + bool AllSame = true; + for (unsigned i = 1; i != NumElems; ++i) + if (MemberAlign != getFoldedAlignOf(STy->getElementType(i), DestTy, true)) { + AllSame = false; + break; + } + if (AllSame) + return MemberAlign; + } + + // If there's no interesting folding happening, bail so that we don't create + // a constant that looks like it needs folding but really doesn't. + if (!Folded) + return 0; + + // Base case: Get a regular alignof expression. + Constant *C = ConstantExpr::getAlignOf(Ty); + C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, + DestTy, false), + C, DestTy); + return C; +} + /// getFoldedOffsetOf - Return a ConstantExpr with type DestTy for offsetof /// on Ty and FieldNo, with any known factors factored out. If Folded is false, /// return null if no factoring was possible, to avoid endlessly @@ -401,11 +458,13 @@ static Constant *getFoldedOffsetOf(const Type *Ty, Constant *FieldNo, // An empty struct has no members. if (NumElems == 0) return 0; - // Check for a struct with all members having the same type. - const Type *MemberTy = STy->getElementType(0); + // Check for a struct with all members having the same size. + Constant *MemberSize = + getFoldedSizeOf(STy->getElementType(0), DestTy, true); bool AllSame = true; for (unsigned i = 1; i != NumElems; ++i) - if (MemberTy != STy->getElementType(i)) { + if (MemberSize != + getFoldedSizeOf(STy->getElementType(i), DestTy, true)) { AllSame = false; break; } @@ -415,8 +474,7 @@ static Constant *getFoldedOffsetOf(const Type *Ty, Constant *FieldNo, DestTy, false), FieldNo, DestTy); - Constant *E = getFoldedSizeOf(MemberTy, DestTy, true); - return ConstantExpr::getNUWMul(E, N); + return ConstantExpr::getNUWMul(MemberSize, N); } } @@ -553,22 +611,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, if (CI->isOne() && STy->getNumElements() == 2 && STy->getElementType(0)->isInteger(1)) { - // The alignment of an array is equal to the alignment of the - // array element. Note that this is not always true for vectors. - if (const ArrayType *ATy = - dyn_cast(STy->getElementType(1))) { - Constant *C = ConstantExpr::getAlignOf(ATy->getElementType()); - C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, - DestTy, - false), - C, DestTy); - return C; - } - // Packed structs always have an alignment of 1. - if (const StructType *InnerSTy = - dyn_cast(STy->getElementType(1))) - if (InnerSTy->isPacked()) - return ConstantInt::get(DestTy, 1); + return getFoldedAlignOf(STy->getElementType(1), DestTy, false); } } // Handle an offsetof-like expression. diff --git a/test/Other/constant-fold-gep.ll b/test/Other/constant-fold-gep.ll index bb93dc761c4..10ff21d4ef8 100644 --- a/test/Other/constant-fold-gep.ll +++ b/test/Other/constant-fold-gep.ll @@ -64,18 +64,21 @@ ; PLAIN: @d = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) ; PLAIN: @e = constant i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) ; PLAIN: @f = constant i64 1 +; PLAIN: @g = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) ; OPT: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) ; OPT: @b = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) ; OPT: @c = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) ; OPT: @d = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) ; OPT: @e = constant i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) ; OPT: @f = constant i64 1 +; OPT: @g = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) ; TO: @a = constant i64 18480 ; TO: @b = constant i64 8 ; TO: @c = constant i64 16 ; TO: @d = constant i64 88 ; TO: @e = constant i64 16 ; TO: @f = constant i64 1 +; TO: @g = constant i64 8 @a = constant i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) @b = constant i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}* null, i64 0, i32 1) to i64) @@ -83,6 +86,7 @@ @d = constant i64 ptrtoint (double* getelementptr ([13 x double]* null, i64 0, i32 11) to i64) @e = constant i64 ptrtoint (double* getelementptr ({double, float, double, double}* null, i64 0, i32 2) to i64) @f = constant i64 ptrtoint (<{ i16, i128 }>* getelementptr ({i1, <{ i16, i128 }>}* null, i64 0, i32 1) to i64) +@g = constant i64 ptrtoint ({double, double}* getelementptr ({i1, {double, double}}* null, i64 0, i32 1) to i64) ; The target-dependent folder should cast GEP indices to integer-sized pointers. @@ -229,6 +233,10 @@ define i1* @hoo1() nounwind { ; PLAIN: %t = bitcast i64 1 to i64 ; PLAIN: ret i64 %t ; PLAIN: } +; PLAIN: define i64 @fg() nounwind { +; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; PLAIN: ret i64 %t +; PLAIN: } ; OPT: define i64 @fa() nounwind { ; OPT: ret i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) ; OPT: } @@ -247,6 +255,9 @@ define i1* @hoo1() nounwind { ; OPT: define i64 @ff() nounwind { ; OPT: ret i64 1 ; OPT: } +; OPT: define i64 @fg() nounwind { +; OPT: ret i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; OPT: } ; TO: define i64 @fa() nounwind { ; TO: ret i64 18480 ; TO: } @@ -265,6 +276,9 @@ define i1* @hoo1() nounwind { ; TO: define i64 @ff() nounwind { ; TO: ret i64 1 ; TO: } +; TO: define i64 @fg() nounwind { +; TO: ret i64 8 +; TO: } ; SCEV: Classifying expressions for: @fa ; SCEV: %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) to i64 ; SCEV: --> (2310 * sizeof(double)) @@ -283,6 +297,9 @@ define i1* @hoo1() nounwind { ; SCEV: Classifying expressions for: @ff ; SCEV: %t = bitcast i64 1 to i64 ; SCEV: --> 1 +; SCEV: Classifying expressions for: @fg +; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; SCEV: --> alignof(double) define i64 @fa() nounwind { %t = bitcast i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) to i64 @@ -308,6 +325,10 @@ define i64 @ff() nounwind { %t = bitcast i64 ptrtoint (<{ i16, i128 }>* getelementptr ({i1, <{ i16, i128 }>}* null, i64 0, i32 1) to i64) to i64 ret i64 %t } +define i64 @fg() nounwind { + %t = bitcast i64 ptrtoint ({double, double}* getelementptr ({i1, {double, double}}* null, i64 0, i32 1) to i64) to i64 + ret i64 %t +} ; PLAIN: define i64* @fM() nounwind { ; PLAIN: %t = bitcast i64* getelementptr (i64* null, i32 1) to i64*