If a GEP index simply advances by multiples of a type of zero size,
authorDuncan Sands <baldrick@free.fr>
Mon, 22 Nov 2010 16:32:50 +0000 (16:32 +0000)
committerDuncan Sands <baldrick@free.fr>
Mon, 22 Nov 2010 16:32:50 +0000 (16:32 +0000)
then replace the index with zero.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119974 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/InstructionSimplify.cpp
lib/Transforms/InstCombine/InstructionCombining.cpp
test/Transforms/InstCombine/2010-11-21-SizeZeroTypeGEP.ll

index e617ff2980db4f61d40713f7f5921776ff7d8297..4b6320bb46a8c5b9201ecd16b99582b930801b88 100644 (file)
@@ -714,7 +714,7 @@ Value *llvm::SimplifyGEPInst(Value *const *Ops, unsigned NumOps,
     // getelementptr P, N -> P if P points to a type of zero size.
     if (TD) {
       const Type *Ty = PtrTy->getElementType();
-      if (Ty->isSized() && !TD->getTypeAllocSize(Ty))
+      if (Ty->isSized() && TD->getTypeAllocSize(Ty) == 0)
         return Ops[0];
     }
   }
index 89d5bfbb6fc09ddf73fbf38f656cd98f2c7b2f7c..cfc418256aab96b5f6397723c7f8f6a25b1d57ad 100644 (file)
@@ -523,25 +523,35 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
 
   Value *PtrOp = GEP.getOperand(0);
 
-  // Eliminate unneeded casts for indices.
+  // Eliminate unneeded casts for indices, and replace indices which displace
+  // by multiples of a zero size type with zero.
   if (TD) {
     bool MadeChange = false;
-    unsigned PtrSize = TD->getPointerSizeInBits();
-    
+    const Type *IntPtrTy = TD->getIntPtrType(GEP.getContext());
+
     gep_type_iterator GTI = gep_type_begin(GEP);
     for (User::op_iterator I = GEP.op_begin() + 1, E = GEP.op_end();
          I != E; ++I, ++GTI) {
-      if (!isa<SequentialType>(*GTI)) continue;
-      
-      // If we are using a wider index than needed for this platform, shrink it
-      // to what we need.  If narrower, sign-extend it to what we need.  This
-      // explicit cast can make subsequent optimizations more obvious.
-      unsigned OpBits = cast<IntegerType>((*I)->getType())->getBitWidth();
-      if (OpBits == PtrSize)
-        continue;
-      
-      *I = Builder->CreateIntCast(*I, TD->getIntPtrType(GEP.getContext()),true);
-      MadeChange = true;
+      // Skip indices into struct types.
+      const SequentialType *SeqTy = dyn_cast<SequentialType>(*GTI);
+      if (!SeqTy) continue;
+
+      // If the element type has zero size then any index over it is equivalent
+      // to an index of zero, so replace it with zero if it is not zero already.
+      if (SeqTy->getElementType()->isSized() &&
+          TD->getTypeAllocSize(SeqTy->getElementType()) == 0)
+        if (!isa<Constant>(*I) || !cast<Constant>(*I)->isNullValue()) {
+          *I = Constant::getNullValue(IntPtrTy);
+          MadeChange = true;
+        }
+
+      if ((*I)->getType() != IntPtrTy) {
+        // If we are using a wider index than needed for this platform, shrink
+        // it to what we need.  If narrower, sign-extend it to what we need.
+        // This explicit cast can make subsequent optimizations more obvious.
+        *I = Builder->CreateIntCast(*I, IntPtrTy, true);
+        MadeChange = true;
+      }
     }
     if (MadeChange) return &GEP;
   }
index 24da5bb3df24732f46c0627e3fb53af52aabaf2c..720365c4d6b2399514f3facb01d791e7afa79e43 100644 (file)
@@ -1,8 +1,17 @@
-; RUN: opt < %s -instcombine -S | not grep getelementptr
+; RUN: opt < %s -instcombine -S | FileCheck %s
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
 
 define {}* @foo({}* %x, i32 %n) {
+; CHECK: @foo
+; CHECK-NOT: getelementptr
   %p = getelementptr {}* %x, i32 %n
   ret {}* %p
 }
+
+define i8* @bar(i64 %n, {{}, [0 x {[0 x i8]}]}* %p) {
+; CHECK: @bar
+  %g = getelementptr {{}, [0 x {[0 x i8]}]}* %p, i64 %n, i32 1, i64 %n, i32 0, i64 %n
+; CHECK: %p, i64 0, i32 1, i64 0, i32 0, i64 %n
+  ret i8* %g
+}