Fix PR4748: don't fold gep(bitcast(x)) into bitcast(gep) when x
authorChris Lattner <sabre@nondot.org>
Sun, 30 Aug 2009 20:38:21 +0000 (20:38 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 30 Aug 2009 20:38:21 +0000 (20:38 +0000)
is itself a bitcast.  Since we have gep(bitcast(bitcast(y))) in this
case, just wait for the two bitcasts to get zapped.  This prevents
instcombine from confusing some aliasing stuff, and allows it to
directly eliminate the load in the testcase.

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

lib/Transforms/Scalar/InstructionCombining.cpp
test/Transforms/InstCombine/getelementptr-2.ll [new file with mode: 0644]

index a02aa5dff8bbe174224a3b5959b85e8583e76ef1..1bfce5dfcbd44c2ad79365b270bb7c1693f0e03b 100644 (file)
@@ -10896,6 +10896,13 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
   if (Value *X = getBitCastOperand(PtrOp)) {
     assert(isa<PointerType>(X->getType()) && "Must be cast from pointer");
 
   if (Value *X = getBitCastOperand(PtrOp)) {
     assert(isa<PointerType>(X->getType()) && "Must be cast from pointer");
 
+    // If the input bitcast is actually "bitcast(bitcast(x))", then we don't 
+    // want to change the gep until the bitcasts are eliminated.
+    if (getBitCastOperand(X)) {
+      Worklist.AddValue(PtrOp);
+      return 0;
+    }
+    
     // Transform: GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ...
     // into     : GEP [10 x i8]* X, i32 0, ...
     //
     // Transform: GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ...
     // into     : GEP [10 x i8]* X, i32 0, ...
     //
diff --git a/test/Transforms/InstCombine/getelementptr-2.ll b/test/Transforms/InstCombine/getelementptr-2.ll
new file mode 100644 (file)
index 0000000..4cffbcd
--- /dev/null
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep load
+; PR4748
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9"
+       %struct.B = type { double }
+       %struct.A = type { %struct.B, i32, i32 }
+
+define i32 @_Z4funcv(%struct.A* %a) {
+entry:
+  %g3 = getelementptr %struct.A* %a, i32 0, i32 1
+  store i32 10, i32* %g3, align 4
+
+  %g4 = getelementptr %struct.A* %a, i32 0, i32 0
+  
+  %new_a = bitcast %struct.B* %g4 to %struct.A*
+
+  %g5 = getelementptr %struct.A* %new_a, i32 0, i32 1  
+  %a_a = load i32* %g5, align 4        
+  ret i32 %a_a
+}
+