diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index f706d351420b..6333613eb065 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1442,6 +1442,12 @@ inline CastClass_match m_PtrToInt(const OpTy &Op) { return CastClass_match(Op); } +/// Matches IntToPtr. +template +inline CastClass_match m_IntToPtr(const OpTy &Op) { + return CastClass_match(Op); +} + /// Matches Trunc. template inline CastClass_match m_Trunc(const OpTy &Op) { diff --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll index eaf946ef9259..500ef7f65423 100644 --- a/llvm/test/Transforms/InstCombine/cast_ptr.ll +++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; Tests to make sure elimination of casts is working correctly ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -8,51 +9,68 @@ target datalayout = "p:32:32-p1:32:32-p2:16:16" ; This shouldn't convert to getelementptr because the relationship ; between the arithmetic and the layout of allocated memory is ; entirely unknown. -; CHECK-LABEL: @test1( -; CHECK: ptrtoint -; CHECK: add -; CHECK: inttoptr + define i8* @test1(i8* %t) { - %tmpc = ptrtoint i8* %t to i32 ; [#uses=1] - %tmpa = add i32 %tmpc, 32 ; [#uses=1] - %tv = inttoptr i32 %tmpa to i8* ; [#uses=1] - ret i8* %tv +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[TC:%.*]] = ptrtoint i8* [[T:%.*]] to i32 +; CHECK-NEXT: [[TA:%.*]] = add i32 [[TC]], 32 +; CHECK-NEXT: [[TV:%.*]] = inttoptr i32 [[TA]] to i8* +; CHECK-NEXT: ret i8* [[TV]] +; + %tc = ptrtoint i8* %t to i32 + %ta = add i32 %tc, 32 + %tv = inttoptr i32 %ta to i8* + ret i8* %tv } ; These casts should be folded away. -; CHECK-LABEL: @test2( -; CHECK: icmp eq i8* %a, %b + define i1 @test2(i8* %a, i8* %b) { - %tmpa = ptrtoint i8* %a to i32 ; [#uses=1] - %tmpb = ptrtoint i8* %b to i32 ; [#uses=1] - %r = icmp eq i32 %tmpa, %tmpb ; [#uses=1] - ret i1 %r -} - -; These casts should be folded away. -; CHECK-LABEL: @test2_as2_same_int( -; CHECK: icmp eq i8 addrspace(2)* %a, %b -define i1 @test2_as2_same_int(i8 addrspace(2)* %a, i8 addrspace(2)* %b) { - %tmpa = ptrtoint i8 addrspace(2)* %a to i16 - %tmpb = ptrtoint i8 addrspace(2)* %b to i16 - %r = icmp eq i16 %tmpa, %tmpb +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %ta = ptrtoint i8* %a to i32 + %tb = ptrtoint i8* %b to i32 + %r = icmp eq i32 %ta, %tb ret i1 %r } ; These casts should be folded away. -; CHECK-LABEL: @test2_as2_larger( -; CHECK: icmp eq i8 addrspace(2)* %a, %b + +define i1 @test2_as2_same_int(i8 addrspace(2)* %a, i8 addrspace(2)* %b) { +; CHECK-LABEL: @test2_as2_same_int( +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 addrspace(2)* [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %ta = ptrtoint i8 addrspace(2)* %a to i16 + %tb = ptrtoint i8 addrspace(2)* %b to i16 + %r = icmp eq i16 %ta, %tb + ret i1 %r +} + +; These casts should be folded away. + define i1 @test2_as2_larger(i8 addrspace(2)* %a, i8 addrspace(2)* %b) { - %tmpa = ptrtoint i8 addrspace(2)* %a to i32 - %tmpb = ptrtoint i8 addrspace(2)* %b to i32 - %r = icmp eq i32 %tmpa, %tmpb +; CHECK-LABEL: @test2_as2_larger( +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 addrspace(2)* [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %ta = ptrtoint i8 addrspace(2)* %a to i32 + %tb = ptrtoint i8 addrspace(2)* %b to i32 + %r = icmp eq i32 %ta, %tb ret i1 %r } ; These casts should not be folded away. -; CHECK-LABEL: @test2_diff_as -; CHECK: icmp sge i32 %i0, %i1 + define i1 @test2_diff_as(i8* %p, i8 addrspace(1)* %q) { +; CHECK-LABEL: @test2_diff_as( +; CHECK-NEXT: [[I0:%.*]] = ptrtoint i8* [[P:%.*]] to i32 +; CHECK-NEXT: [[I1:%.*]] = ptrtoint i8 addrspace(1)* [[Q:%.*]] to i32 +; CHECK-NEXT: [[R0:%.*]] = icmp sge i32 [[I0]], [[I1]] +; CHECK-NEXT: ret i1 [[R0]] +; %i0 = ptrtoint i8* %p to i32 %i1 = ptrtoint i8 addrspace(1)* %q to i32 %r0 = icmp sge i32 %i0, %i1 @@ -60,9 +78,13 @@ define i1 @test2_diff_as(i8* %p, i8 addrspace(1)* %q) { } ; These casts should not be folded away. -; CHECK-LABEL: @test2_diff_as_global -; CHECK: icmp sge i32 %i1 + define i1 @test2_diff_as_global(i8 addrspace(1)* %q) { +; CHECK-LABEL: @test2_diff_as_global( +; CHECK-NEXT: [[I1:%.*]] = ptrtoint i8 addrspace(1)* [[Q:%.*]] to i32 +; CHECK-NEXT: [[R0:%.*]] = icmp sge i32 [[I1]], ptrtoint (i8* @global to i32) +; CHECK-NEXT: ret i1 [[R0]] +; %i0 = ptrtoint i8* @global to i32 %i1 = ptrtoint i8 addrspace(1)* %q to i32 %r0 = icmp sge i32 %i1, %i0 @@ -70,27 +92,32 @@ define i1 @test2_diff_as_global(i8 addrspace(1)* %q) { } ; These casts should also be folded away. -; CHECK-LABEL: @test3( -; CHECK: icmp eq i8* %a, @global + define i1 @test3(i8* %a) { - %tmpa = ptrtoint i8* %a to i32 - %r = icmp eq i32 %tmpa, ptrtoint (i8* @global to i32) - ret i1 %r +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[R:%.*]] = icmp eq i8* [[A:%.*]], @global +; CHECK-NEXT: ret i1 [[R]] +; + %ta = ptrtoint i8* %a to i32 + %r = icmp eq i32 %ta, ptrtoint (i8* @global to i32) + ret i1 %r } define i1 @test4(i32 %A) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], 0 +; CHECK-NEXT: ret i1 [[C]] +; %B = inttoptr i32 %A to i8* %C = icmp eq i8* %B, null ret i1 %C -; CHECK-LABEL: @test4( -; CHECK-NEXT: %C = icmp eq i32 %A, 0 -; CHECK-NEXT: ret i1 %C } define i1 @test4_as2(i16 %A) { ; CHECK-LABEL: @test4_as2( -; CHECK-NEXT: %C = icmp eq i16 %A, 0 -; CHECK-NEXT: ret i1 %C +; CHECK-NEXT: [[C:%.*]] = icmp eq i16 [[A:%.*]], 0 +; CHECK-NEXT: ret i1 [[C]] +; %B = inttoptr i16 %A to i8 addrspace(2)* %C = icmp eq i8 addrspace(2)* %B, null ret i1 %C @@ -102,16 +129,19 @@ define i1 @test4_as2(i16 %A) { %op = type { float } %unop = type { i32 } -@Array = internal constant [1 x %op* (%op*)*] [ %op* (%op*)* @foo ] ; <[1 x %op* (%op*)*]*> [#uses=1] +@Array = internal constant [1 x %op* (%op*)*] [ %op* (%op*)* @foo ] declare %op* @foo(%op* %X) define %unop* @test5(%op* %O) { - %tmp = load %unop* (%op*)*, %unop* (%op*)** bitcast ([1 x %op* (%op*)*]* @Array to %unop* (%op*)**); <%unop* (%op*)*> [#uses=1] - %tmp.2 = call %unop* %tmp( %op* %O ) ; <%unop*> [#uses=1] - ret %unop* %tmp.2 ; CHECK-LABEL: @test5( -; CHECK: call %op* @foo(%op* %O) +; CHECK-NEXT: [[T_2:%.*]] = call %op* @foo(%op* [[O:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = bitcast %op* [[T_2]] to %unop* +; CHECK-NEXT: ret %unop* [[TMP1]] +; + %t = load %unop* (%op*)*, %unop* (%op*)** bitcast ([1 x %op* (%op*)*]* @Array to %unop* (%op*)**); <%unop* (%op*)*> [#uses=1] + %t.2 = call %unop* %t( %op* %O ) + ret %unop* %t.2 } @@ -120,10 +150,14 @@ define %unop* @test5(%op* %O) { ; the address space. define i8 @test6(i8 addrspace(1)* %source) { +; CHECK-LABEL: @test6( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX223:%.*]] = addrspacecast i8 addrspace(1)* [[SOURCE:%.*]] to i8* +; CHECK-NEXT: [[T4:%.*]] = load i8, i8* [[ARRAYIDX223]], align 1 +; CHECK-NEXT: ret i8 [[T4]] +; entry: %arrayidx223 = addrspacecast i8 addrspace(1)* %source to i8* - %tmp4 = load i8, i8* %arrayidx223 - ret i8 %tmp4 -; CHECK-LABEL: @test6( -; CHECK: load i8, i8* %arrayidx223 + %t4 = load i8, i8* %arrayidx223 + ret i8 %t4 }