diff options
author | Chris Lattner <sabre@nondot.org> | 2007-07-16 05:43:05 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-07-16 05:43:05 +0000 |
commit | 99e0d7905d1576ac85bb6f969a2d969c4d2e7f82 (patch) | |
tree | ae2e410c174b02e47bed22f43d26492d714de229 | |
parent | 1467e03df1dce515ed3013c7dcb6f5c541ab0d5f (diff) |
Add a hack (mirroring llvm-gcc) to pointer difference
codegen to compile:
int test(int *A, int *B) {
return A-B;
}
into:
_test:
movl 4(%esp), %eax
subl 8(%esp), %eax
sarl $2, %eax
ret
instead of:
_test:
movl 4(%esp), %eax
subl 8(%esp), %eax
movl %eax, %ecx
sarl $31, %ecx
shrl $30, %ecx
addl %ecx, %eax
sarl $2, %eax
ret
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39902 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | CodeGen/CGExpr.cpp | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index 3ec0f25064..40c25ae0bb 100644 --- a/CodeGen/CGExpr.cpp +++ b/CodeGen/CGExpr.cpp @@ -18,6 +18,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/GlobalVariable.h" +#include "llvm/Support/MathExtras.h" using namespace clang; using namespace CodeGen; @@ -1168,7 +1169,7 @@ RValue CodeGenFunction::EmitPointerSub(RValue LHS, QualType LHSTy, QualType LHSElementType = LHSPtrType->getPointeeType(); assert(LHSElementType == RHSPtrType->getPointeeType() && "can't subtract pointers with differing element types"); - unsigned ElementSize = getContext().getTypeSize(LHSElementType, + uint64_t ElementSize = getContext().getTypeSize(LHSElementType, SourceLocation()) / 8; const llvm::Type *ResultType = ConvertType(ResTy); llvm::Value *CastLHS = Builder.CreatePtrToInt(LHSValue, ResultType, @@ -1177,12 +1178,21 @@ RValue CodeGenFunction::EmitPointerSub(RValue LHS, QualType LHSTy, "sub.ptr.rhs.cast"); llvm::Value *BytesBetween = Builder.CreateSub(CastLHS, CastRHS, "sub.ptr.sub"); - llvm::Value *BytesPerElement = llvm::ConstantInt::get(ResultType, - ElementSize); - llvm::Value *ElementsBetween = Builder.CreateSDiv(BytesBetween, - BytesPerElement, - "sub.ptr.div"); - return RValue::get(ElementsBetween); + + // HACK: LLVM doesn't have an divide instruction that 'knows' there is no + // remainder. As such, we handle common power-of-two cases here to generate + // better code. + if (llvm::isPowerOf2_64(ElementSize)) { + llvm::Value *ShAmt = + llvm::ConstantInt::get(ResultType, llvm::Log2_64(ElementSize)); + return RValue::get(Builder.CreateAShr(BytesBetween, ShAmt,"sub.ptr.shr")); + } else { + // Otherwise, do a full sdiv. + llvm::Value *BytesPerElement = + llvm::ConstantInt::get(ResultType, ElementSize); + return RValue::get(Builder.CreateSDiv(BytesBetween, BytesPerElement, + "sub.ptr.div")); + } } else { // pointer - int llvm::Value *NegatedRHS = Builder.CreateNeg(RHSValue, "sub.ptr.neg"); |