IR: Don't constant fold GEP bitcasts between different address spaces
authorMeador Inge <meadori@codesourcery.com>
Wed, 27 Feb 2013 02:26:42 +0000 (02:26 +0000)
committerMeador Inge <meadori@codesourcery.com>
Wed, 27 Feb 2013 02:26:42 +0000 (02:26 +0000)
PR15262 reported a bug where the following instruction:

  i8 getelementptr inbounds i8* bitcast ([4 x i8] addrspace(12)* @buf to i8*),
                                i32 2

was getting folded into:

  addrspace(12)* getelementptr inbounds ([4 x i8] addrspace(12)* @buf, i32 0,
                                        i32 2)

This caused instcombine to crash because the original instruction and
the folded instruction have different types.  The issue was fixed by
disallowing bitcasts between different address spaces to be folded away.

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

lib/IR/ConstantFold.cpp
test/Other/constant-fold-gep.ll

index a5a9d9f3a7c901d3ad5ef024fa0ef01f35b1270a..bf93d4f95663534061449634a5552b7daa0ea39c 100644 (file)
@@ -1971,21 +1971,30 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
       }
     }
 
-    // Implement folding of:
-    //    i32* getelementptr ([2 x i32]* bitcast ([3 x i32]* %X to [2 x i32]*),
-    //                        i64 0, i64 0)
-    // To: i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
+    // Attempt to fold casts to the same type away.  For example, folding:
     //
+    //   i32* getelementptr ([2 x i32]* bitcast ([3 x i32]* %X to [2 x i32]*),
+    //                       i64 0, i64 0)
+    // into:
+    //
+    //   i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
+    //
+    // Don't fold if the cast is changing address spaces.
     if (CE->isCast() && Idxs.size() > 1 && Idx0->isNullValue()) {
-      if (PointerType *SPT =
-          dyn_cast<PointerType>(CE->getOperand(0)->getType()))
-        if (ArrayType *SAT = dyn_cast<ArrayType>(SPT->getElementType()))
-          if (ArrayType *CAT =
-        dyn_cast<ArrayType>(cast<PointerType>(C->getType())->getElementType()))
-            if (CAT->getElementType() == SAT->getElementType())
-              return
-                ConstantExpr::getGetElementPtr((Constant*)CE->getOperand(0),
-                                               Idxs, inBounds);
+      PointerType *SrcPtrTy =
+        dyn_cast<PointerType>(CE->getOperand(0)->getType());
+      PointerType *DstPtrTy = dyn_cast<PointerType>(CE->getType());
+      if (SrcPtrTy && DstPtrTy) {
+        ArrayType *SrcArrayTy =
+          dyn_cast<ArrayType>(SrcPtrTy->getElementType());
+        ArrayType *DstArrayTy =
+          dyn_cast<ArrayType>(DstPtrTy->getElementType());
+        if (SrcArrayTy && DstArrayTy
+            && SrcArrayTy->getElementType() == DstArrayTy->getElementType()
+            && SrcPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace())
+          return ConstantExpr::getGetElementPtr((Constant*)CE->getOperand(0),
+                                                Idxs, inBounds);
+      }
     }
   }
 
index 0224e9f984c673d6529d02bebf7d282ae23c4eef..44b66284dd73ae759a818e57f891ac9744d8dba0 100644 (file)
@@ -447,4 +447,24 @@ define i32* @fZ() nounwind {
   ret i32* %t
 }
 
+; PR15262 - Check GEP folding with casts between address spaces.
+
+@p0 = global [4 x i8] zeroinitializer, align 1
+@p12 = addrspace(12) global [4 x i8] zeroinitializer, align 1
+
+define i8* @different_addrspace() nounwind noinline {
+; OPT: different_addrspace
+  %p = getelementptr inbounds i8* bitcast ([4 x i8] addrspace(12)* @p12 to i8*),
+                                  i32 2
+  ret i8* %p
+; OPT: ret i8* getelementptr (i8* bitcast ([4 x i8] addrspace(12)* @p12 to i8*), i32 2)
+}
+
+define i8* @same_addrspace() nounwind noinline {
+; OPT: same_addrspace
+  %p = getelementptr inbounds i8* bitcast ([4 x i8] * @p0 to i8*), i32 2
+  ret i8* %p
+; OPT: ret i8* getelementptr inbounds ([4 x i8]* @p0, i32 0, i32 2)
+}
+
 ; CHECK: attributes #0 = { nounwind }