canonicalize inttoptr and ptrtoint instructions which cast pointers
authorChris Lattner <sabre@nondot.org>
Tue, 24 Mar 2009 18:35:40 +0000 (18:35 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 24 Mar 2009 18:35:40 +0000 (18:35 +0000)
to/from integer types that are not intptr_t to convert to intptr_t
then do an integer conversion to the dest type.  This exposes the
cast to the optimizer.

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

lib/Transforms/Scalar/InstructionCombining.cpp
test/Transforms/InstCombine/ptr-int-cast.ll [new file with mode: 0644]

index e4e7971549e21d89a57018094bbe1559e1f828a0..17ac5b7d8d5550362fa71ebb75d2928d6dc24554 100644 (file)
@@ -218,7 +218,7 @@ namespace {
     Instruction *visitFPToSI(FPToSIInst &FI);
     Instruction *visitUIToFP(CastInst &CI);
     Instruction *visitSIToFP(CastInst &CI);
-    Instruction *visitPtrToInt(CastInst &CI);
+    Instruction *visitPtrToInt(PtrToIntInst &CI);
     Instruction *visitIntToPtr(IntToPtrInst &CI);
     Instruction *visitBitCast(BitCastInst &CI);
     Instruction *FoldSelectOpOp(SelectInst &SI, Instruction *TI,
@@ -474,9 +474,16 @@ isEliminableCastPair(
   Instruction::CastOps firstOp = Instruction::CastOps(CI->getOpcode());
   Instruction::CastOps secondOp = Instruction::CastOps(opcode);
 
-  return Instruction::CastOps(
-      CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy,
-                                     DstTy, TD->getIntPtrType()));
+  unsigned Res = CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy,
+                                                DstTy, TD->getIntPtrType());
+  
+  // We don't want to form an inttoptr or ptrtoint that converts to an integer
+  // type that differs from the pointer size.
+  if ((Res == Instruction::IntToPtr && SrcTy != TD->getIntPtrType()) ||
+      (Res == Instruction::PtrToInt && DstTy != TD->getIntPtrType()))
+    Res = 0;
+  
+  return Instruction::CastOps(Res);
 }
 
 /// ValueRequiresCast - Return true if the cast from "V to Ty" actually results
@@ -8536,11 +8543,36 @@ Instruction *InstCombiner::visitSIToFP(CastInst &CI) {
   return commonCastTransforms(CI);
 }
 
-Instruction *InstCombiner::visitPtrToInt(CastInst &CI) {
+Instruction *InstCombiner::visitPtrToInt(PtrToIntInst &CI) {
+  // If the destination integer type is smaller than the intptr_t type for
+  // this target, do a ptrtoint to intptr_t then do a trunc.  This allows the
+  // trunc to be exposed to other transforms.  Don't do this for extending
+  // ptrtoint's, because we don't know if the target sign or zero extends its
+  // pointers.
+  if (CI.getType()->getPrimitiveSizeInBits() < TD->getPointerSizeInBits()) {
+    Value *P = InsertNewInstBefore(new PtrToIntInst(CI.getOperand(0),
+                                                    TD->getIntPtrType(),
+                                                    "tmp"), CI);
+    return new TruncInst(P, CI.getType());
+  }
+  
   return commonPointerCastTransforms(CI);
 }
 
 Instruction *InstCombiner::visitIntToPtr(IntToPtrInst &CI) {
+  // If the source integer type is larger than the intptr_t type for
+  // this target, do a trunc to the intptr_t type, then inttoptr of it.  This
+  // allows the trunc to be exposed to other transforms.  Don't do this for
+  // extending inttoptr's, because we don't know if the target sign or zero
+  // extends to pointers.
+  if (CI.getOperand(0)->getType()->getPrimitiveSizeInBits() >
+      TD->getPointerSizeInBits()) {
+    Value *P = InsertNewInstBefore(new TruncInst(CI.getOperand(0),
+                                                 TD->getIntPtrType(),
+                                                 "tmp"), CI);
+    return new IntToPtrInst(P, CI.getType());
+  }
+  
   if (Instruction *I = commonCastTransforms(CI))
     return I;
   
diff --git a/test/Transforms/InstCombine/ptr-int-cast.ll b/test/Transforms/InstCombine/ptr-int-cast.ll
new file mode 100644 (file)
index 0000000..5c15439
--- /dev/null
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis > %t
+
+define i1 @test1(i32 *%x) nounwind {
+entry:
+; RUN: grep {ptrtoint i32\\* %x to i64} %t
+       %tmp = ptrtoint i32* %x to i1
+       ret i1 %tmp
+}
+
+define i32* @test2(i128 %x) nounwind {
+entry:
+; RUN: grep {inttoptr i64 %.mp1 to i32\\*} %t
+       %tmp = inttoptr i128 %x to i32*
+       ret i32* %tmp
+}
+