diff --git a/lib/Analysis/TargetTransformInfo.cpp b/lib/Analysis/TargetTransformInfo.cpp index 0a215aa53c6..8c6005b31cb 100644 --- a/lib/Analysis/TargetTransformInfo.cpp +++ b/lib/Analysis/TargetTransformInfo.cpp @@ -269,26 +269,34 @@ struct NoTTI : ImmutablePass, TargetTransformInfo { // Otherwise, the default basic cost is used. return TCC_Basic; - case Instruction::IntToPtr: + case Instruction::IntToPtr: { + if (!DL) + return TCC_Basic; + // An inttoptr cast is free so long as the input is a legal integer type // which doesn't contain values outside the range of a pointer. - if (DL && DL->isLegalInteger(OpTy->getScalarSizeInBits()) && - OpTy->getScalarSizeInBits() <= DL->getPointerSizeInBits()) + unsigned OpSize = OpTy->getScalarSizeInBits(); + if (DL->isLegalInteger(OpSize) && + OpSize <= DL->getPointerTypeSizeInBits(Ty)) return TCC_Free; // Otherwise it's not a no-op. return TCC_Basic; + } + case Instruction::PtrToInt: { + if (!DL) + return TCC_Basic; - case Instruction::PtrToInt: // A ptrtoint cast is free so long as the result is large enough to store // the pointer, and a legal integer type. - if (DL && DL->isLegalInteger(Ty->getScalarSizeInBits()) && - Ty->getScalarSizeInBits() >= DL->getPointerSizeInBits()) + unsigned DestSize = Ty->getScalarSizeInBits(); + if (DL->isLegalInteger(DestSize) && + DestSize >= DL->getPointerTypeSizeInBits(OpTy)) return TCC_Free; // Otherwise it's not a no-op. return TCC_Basic; - + } case Instruction::Trunc: // trunc to a native type is free (assuming the target has compare and // shift-right of the same width). diff --git a/test/Transforms/Inline/ptr-diff.ll b/test/Transforms/Inline/ptr-diff.ll index 01b42daddfa..af42bc7cede 100644 --- a/test/Transforms/Inline/ptr-diff.ll +++ b/test/Transforms/Inline/ptr-diff.ll @@ -1,6 +1,6 @@ ; RUN: opt -inline < %s -S -o - -inline-threshold=10 | FileCheck %s -target datalayout = "p:32:32" +target datalayout = "p:32:32-p1:64:64-p2:16:16-n16:32:64" define i32 @outer1() { ; CHECK-LABEL: @outer1( @@ -56,3 +56,46 @@ else: %t = load i32* %begin ret i32 %t } + +; The inttoptrs are free since it is a smaller integer to a larger +; pointer size +define i32 @inttoptr_free_cost(i32 %a, i32 %b, i32 %c) { + %p1 = inttoptr i32 %a to i32 addrspace(1)* + %p2 = inttoptr i32 %b to i32 addrspace(1)* + %p3 = inttoptr i32 %c to i32 addrspace(1)* + %t1 = load i32 addrspace(1)* %p1 + %t2 = load i32 addrspace(1)* %p2 + %t3 = load i32 addrspace(1)* %p3 + %s = add i32 %t1, %t2 + %s1 = add i32 %s, %t3 + ret i32 %s1 +} + +define i32 @inttoptr_free_cost_user(i32 %begin, i32 %end) { +; CHECK-LABEL: @inttoptr_free_cost_user( +; CHECK-NOT: call + %x = call i32 @inttoptr_free_cost(i32 %begin, i32 %end, i32 9) + ret i32 %x +} + +; The inttoptrs have a cost since it is a larger integer to a smaller +; pointer size +define i32 @inttoptr_cost_smaller_ptr(i32 %a, i32 %b, i32 %c) { + %p1 = inttoptr i32 %a to i32 addrspace(2)* + %p2 = inttoptr i32 %b to i32 addrspace(2)* + %p3 = inttoptr i32 %c to i32 addrspace(2)* + %t1 = load i32 addrspace(2)* %p1 + %t2 = load i32 addrspace(2)* %p2 + %t3 = load i32 addrspace(2)* %p3 + %s = add i32 %t1, %t2 + %s1 = add i32 %s, %t3 + ret i32 %s1 +} + +define i32 @inttoptr_cost_smaller_ptr_user(i32 %begin, i32 %end) { +; CHECK-LABEL: @inttoptr_cost_smaller_ptr_user( +; CHECK: call + %x = call i32 @inttoptr_cost_smaller_ptr(i32 %begin, i32 %end, i32 9) + ret i32 %x +} +