[llvm] r176156 - IR: Don't constant fold GEP bitcasts between different address spaces

Meador Inge meadori at codesourcery.com
Tue Feb 26 18:26:42 PST 2013


Author: meadori
Date: Tue Feb 26 20:26:42 2013
New Revision: 176156

URL: http://llvm.org/viewvc/llvm-project?rev=176156&view=rev
Log:
IR: Don't constant fold GEP bitcasts between different address spaces

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.

Modified:
    llvm/trunk/lib/IR/ConstantFold.cpp
    llvm/trunk/test/Other/constant-fold-gep.ll

Modified: llvm/trunk/lib/IR/ConstantFold.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantFold.cpp?rev=176156&r1=176155&r2=176156&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantFold.cpp (original)
+++ llvm/trunk/lib/IR/ConstantFold.cpp Tue Feb 26 20:26:42 2013
@@ -1971,21 +1971,30 @@ static Constant *ConstantFoldGetElementP
       }
     }
 
-    // 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);
+      }
     }
   }
 

Modified: llvm/trunk/test/Other/constant-fold-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/constant-fold-gep.ll?rev=176156&r1=176155&r2=176156&view=diff
==============================================================================
--- llvm/trunk/test/Other/constant-fold-gep.ll (original)
+++ llvm/trunk/test/Other/constant-fold-gep.ll Tue Feb 26 20:26:42 2013
@@ -447,4 +447,24 @@ define i32* @fZ() nounwind {
   ret i32* %t
 }
 
+; PR15262 - Check GEP folding with casts between address spaces.
+
+ at p0 = global [4 x i8] zeroinitializer, align 1
+ at 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 }





More information about the llvm-commits mailing list