[cfe-commits] r39902 - /cfe/trunk/CodeGen/CGExpr.cpp

Chris Lattner sabre at nondot.org
Sun Jul 15 22:43:05 PDT 2007


Author: lattner
Date: Mon Jul 16 00:43:05 2007
New Revision: 39902

URL: http://llvm.org/viewvc/llvm-project?rev=39902&view=rev
Log:
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


Modified:
    cfe/trunk/CodeGen/CGExpr.cpp

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

==============================================================================
--- cfe/trunk/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/CodeGen/CGExpr.cpp Mon Jul 16 00:43:05 2007
@@ -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 @@
     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 @@
                                                   "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");





More information about the cfe-commits mailing list