As part of making ScalarEvolution's handling of pointers consistent, we want to forbid multiplying a pointer by -1 (or any other value). This means we can't blindly subtract pointers. There are a few ways we could deal with this: 1. We could completely forbid subtracting pointers in getMinusSCEV() 2. We could forbid subracting pointers with different pointer bases (this patch). 3. We could try to ptrtoint pointer operands. The option in this patch is more friendly to non-integral pointers: code that works with normal pointers will also work with non-integral pointers. And it seems like there are very few places that actually benefit from the third option. As a minimal patch, the ScalarEvolution implementation of getMinusSCEV still ends up subtracting pointers if they have the same base. This should eliminate the shared pointer base, but eventually we'll need to rewrite it to avoid negating the pointer base. I plan to do this as a separate step to allow measuring the compile-time impact. This doesn't cause obvious functional changes in most cases; the one case that is significantly affected is ICmpZero handling in LSR (which is the source of almost all the test changes). The resulting changes seem okay to me, but suggestions welcome. As an alternative, I tried explicitly ptrtoint'ing the operands, but the result doesn't seem obviously better. I deleted the test lsr-undef-in-binop.ll becuase I couldn't figure out how to repair it to test what it was actually trying to test. Recommitting with fix to MemoryDepChecker::isDependent. Differential Revision: https://reviews.llvm.org/D104806
378 lines
14 KiB
LLVM
378 lines
14 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -loop-reduce -S | FileCheck %s
|
|
|
|
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
|
|
target triple = "i686-pc-windows-msvc"
|
|
|
|
declare i32 @_except_handler3(...)
|
|
declare i32 @__CxxFrameHandler3(...)
|
|
|
|
declare void @external(i32*)
|
|
declare void @reserve()
|
|
|
|
define void @f() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @f(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[THROW:%.*]]
|
|
; CHECK: throw:
|
|
; CHECK-NEXT: [[TMP96:%.*]] = getelementptr inbounds i8, i8* undef, i32 1
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]]
|
|
; CHECK: pad:
|
|
; CHECK-NEXT: [[PHI2:%.*]] = phi i8* [ [[TMP96]], [[THROW]] ]
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %unreachable] unwind label [[BLAH2:%.*]]
|
|
; CHECK: unreachable:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: blah2:
|
|
; CHECK-NEXT: [[CLEANUPPADI4_I_I_I:%.*]] = cleanuppad within none []
|
|
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* [[PHI2]], i32 -1
|
|
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
|
|
; CHECK: loop_body:
|
|
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP1:%.*]], [[ITER:%.*]] ], [ [[SCEVGEP]], [[BLAH2]] ]
|
|
; CHECK-NEXT: [[SCEVGEP1]] = getelementptr i8, i8* [[LSR_IV]], i32 1
|
|
; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[SCEVGEP1]], undef
|
|
; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
|
|
; CHECK: iter:
|
|
; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
|
|
; CHECK: unwind_out:
|
|
; CHECK-NEXT: cleanupret from [[CLEANUPPADI4_I_I_I]] unwind to caller
|
|
;
|
|
entry:
|
|
br label %throw
|
|
|
|
throw: ; preds = %throw, %entry
|
|
%tmp96 = getelementptr inbounds i8, i8* undef, i32 1
|
|
invoke void @reserve()
|
|
to label %throw unwind label %pad
|
|
|
|
pad: ; preds = %throw
|
|
%phi2 = phi i8* [ %tmp96, %throw ]
|
|
%cs = catchswitch within none [label %unreachable] unwind label %blah2
|
|
|
|
unreachable:
|
|
catchpad within %cs []
|
|
unreachable
|
|
|
|
blah2:
|
|
%cleanuppadi4.i.i.i = cleanuppad within none []
|
|
br label %loop_body
|
|
|
|
loop_body: ; preds = %iter, %pad
|
|
%tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blah2 ]
|
|
%tmp100 = icmp eq i8* %tmp99, undef
|
|
br i1 %tmp100, label %unwind_out, label %iter
|
|
|
|
iter: ; preds = %loop_body
|
|
%tmp101 = getelementptr inbounds i8, i8* %tmp99, i32 1
|
|
br i1 undef, label %unwind_out, label %loop_body
|
|
|
|
unwind_out: ; preds = %iter, %loop_body
|
|
cleanupret from %cleanuppadi4.i.i.i unwind to caller
|
|
}
|
|
|
|
define void @g() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @g(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[THROW:%.*]]
|
|
; CHECK: throw:
|
|
; CHECK-NEXT: [[TMP96:%.*]] = getelementptr inbounds i8, i8* undef, i32 1
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]]
|
|
; CHECK: pad:
|
|
; CHECK-NEXT: [[PHI2:%.*]] = phi i8* [ [[TMP96]], [[THROW]] ]
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label %blah] unwind to caller
|
|
; CHECK: unreachable:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: blah:
|
|
; CHECK-NEXT: [[CATCHPAD:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* [[PHI2]], i32 -1
|
|
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
|
|
; CHECK: unwind_out:
|
|
; CHECK-NEXT: catchret from [[CATCHPAD]] to label [[LEAVE:%.*]]
|
|
; CHECK: leave:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: loop_body:
|
|
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP1:%.*]], [[ITER:%.*]] ], [ [[SCEVGEP]], [[BLAH:%.*]] ]
|
|
; CHECK-NEXT: [[SCEVGEP1]] = getelementptr i8, i8* [[LSR_IV]], i32 1
|
|
; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[SCEVGEP1]], undef
|
|
; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
|
|
; CHECK: iter:
|
|
; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
|
|
;
|
|
entry:
|
|
br label %throw
|
|
|
|
throw: ; preds = %throw, %entry
|
|
%tmp96 = getelementptr inbounds i8, i8* undef, i32 1
|
|
invoke void @reserve()
|
|
to label %throw unwind label %pad
|
|
|
|
pad:
|
|
%phi2 = phi i8* [ %tmp96, %throw ]
|
|
%cs = catchswitch within none [label %unreachable, label %blah] unwind to caller
|
|
|
|
unreachable:
|
|
catchpad within %cs []
|
|
unreachable
|
|
|
|
blah:
|
|
%catchpad = catchpad within %cs []
|
|
br label %loop_body
|
|
|
|
unwind_out:
|
|
catchret from %catchpad to label %leave
|
|
|
|
leave:
|
|
ret void
|
|
|
|
loop_body: ; preds = %iter, %pad
|
|
%tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blah ]
|
|
%tmp100 = icmp eq i8* %tmp99, undef
|
|
br i1 %tmp100, label %unwind_out, label %iter
|
|
|
|
iter: ; preds = %loop_body
|
|
%tmp101 = getelementptr inbounds i8, i8* %tmp99, i32 1
|
|
br i1 undef, label %unwind_out, label %loop_body
|
|
}
|
|
|
|
define void @h() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @h(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[THROW:%.*]]
|
|
; CHECK: throw:
|
|
; CHECK-NEXT: [[TMP96:%.*]] = getelementptr inbounds i8, i8* undef, i32 1
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[THROW]] unwind label [[PAD:%.*]]
|
|
; CHECK: pad:
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label [[UNREACHABLE:%.*]], label %blug] unwind to caller
|
|
; CHECK: unreachable:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: blug:
|
|
; CHECK-NEXT: [[PHI2:%.*]] = phi i8* [ [[TMP96]], [[PAD]] ]
|
|
; CHECK-NEXT: [[CATCHPAD:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* [[PHI2]], i32 -1
|
|
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
|
|
; CHECK: unwind_out:
|
|
; CHECK-NEXT: catchret from [[CATCHPAD]] to label [[LEAVE:%.*]]
|
|
; CHECK: leave:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: loop_body:
|
|
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP1:%.*]], [[ITER:%.*]] ], [ [[SCEVGEP]], [[BLUG:%.*]] ]
|
|
; CHECK-NEXT: [[SCEVGEP1]] = getelementptr i8, i8* [[LSR_IV]], i32 1
|
|
; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[SCEVGEP1]], undef
|
|
; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
|
|
; CHECK: iter:
|
|
; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
|
|
;
|
|
entry:
|
|
br label %throw
|
|
|
|
throw: ; preds = %throw, %entry
|
|
%tmp96 = getelementptr inbounds i8, i8* undef, i32 1
|
|
invoke void @reserve()
|
|
to label %throw unwind label %pad
|
|
|
|
pad:
|
|
%cs = catchswitch within none [label %unreachable, label %blug] unwind to caller
|
|
|
|
unreachable:
|
|
catchpad within %cs []
|
|
unreachable
|
|
|
|
blug:
|
|
%phi2 = phi i8* [ %tmp96, %pad ]
|
|
%catchpad = catchpad within %cs []
|
|
br label %loop_body
|
|
|
|
unwind_out:
|
|
catchret from %catchpad to label %leave
|
|
|
|
leave:
|
|
ret void
|
|
|
|
loop_body: ; preds = %iter, %pad
|
|
%tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blug ]
|
|
%tmp100 = icmp eq i8* %tmp99, undef
|
|
br i1 %tmp100, label %unwind_out, label %iter
|
|
|
|
iter: ; preds = %loop_body
|
|
%tmp101 = getelementptr inbounds i8, i8* %tmp99, i32 1
|
|
br i1 undef, label %unwind_out, label %loop_body
|
|
}
|
|
|
|
define void @i() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @i(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[THROW:%.*]]
|
|
; CHECK: throw:
|
|
; CHECK-NEXT: [[TMP96:%.*]] = getelementptr inbounds i8, i8* undef, i32 1
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[THROW]] unwind label [[CATCHPAD:%.*]]
|
|
; CHECK: catchpad:
|
|
; CHECK-NEXT: [[PHI2:%.*]] = phi i8* [ [[TMP96]], [[THROW]] ]
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %cp_body] unwind label [[CLEANUPPAD:%.*]]
|
|
; CHECK: cp_body:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] []
|
|
; CHECK-NEXT: br label [[LOOP_HEAD:%.*]]
|
|
; CHECK: cleanuppad:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = cleanuppad within none []
|
|
; CHECK-NEXT: br label [[LOOP_HEAD]]
|
|
; CHECK: loop_head:
|
|
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, i8* [[PHI2]], i32 -1
|
|
; CHECK-NEXT: br label [[LOOP_BODY:%.*]]
|
|
; CHECK: loop_body:
|
|
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i8* [ [[SCEVGEP1:%.*]], [[ITER:%.*]] ], [ [[SCEVGEP]], [[LOOP_HEAD]] ]
|
|
; CHECK-NEXT: [[SCEVGEP1]] = getelementptr i8, i8* [[LSR_IV]], i32 1
|
|
; CHECK-NEXT: [[TMP100:%.*]] = icmp eq i8* [[SCEVGEP1]], undef
|
|
; CHECK-NEXT: br i1 [[TMP100]], label [[UNWIND_OUT:%.*]], label [[ITER]]
|
|
; CHECK: iter:
|
|
; CHECK-NEXT: br i1 true, label [[UNWIND_OUT]], label [[LOOP_BODY]]
|
|
; CHECK: unwind_out:
|
|
; CHECK-NEXT: unreachable
|
|
;
|
|
entry:
|
|
br label %throw
|
|
|
|
throw: ; preds = %throw, %entry
|
|
%tmp96 = getelementptr inbounds i8, i8* undef, i32 1
|
|
invoke void @reserve()
|
|
to label %throw unwind label %catchpad
|
|
|
|
catchpad: ; preds = %throw
|
|
%phi2 = phi i8* [ %tmp96, %throw ]
|
|
%cs = catchswitch within none [label %cp_body] unwind label %cleanuppad
|
|
|
|
cp_body:
|
|
catchpad within %cs []
|
|
br label %loop_head
|
|
|
|
cleanuppad:
|
|
cleanuppad within none []
|
|
br label %loop_head
|
|
|
|
loop_head:
|
|
br label %loop_body
|
|
|
|
loop_body: ; preds = %iter, %catchpad
|
|
%tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %loop_head ]
|
|
%tmp100 = icmp eq i8* %tmp99, undef
|
|
br i1 %tmp100, label %unwind_out, label %iter
|
|
|
|
iter: ; preds = %loop_body
|
|
%tmp101 = getelementptr inbounds i8, i8* %tmp99, i32 1
|
|
br i1 undef, label %unwind_out, label %loop_body
|
|
|
|
unwind_out: ; preds = %iter, %loop_body
|
|
unreachable
|
|
}
|
|
|
|
define void @test1(i32* %b, i32* %c) personality i32 (...)* @__CxxFrameHandler3 {
|
|
; CHECK-LABEL: @test1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_COND:%.*]]
|
|
; CHECK: for.cond:
|
|
; CHECK-NEXT: [[D_0:%.*]] = phi i32* [ [[B:%.*]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC:%.*]] ]
|
|
; CHECK-NEXT: invoke void @external(i32* [[D_0]])
|
|
; CHECK-NEXT: to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
|
|
; CHECK: for.inc:
|
|
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i32, i32* [[D_0]], i32 1
|
|
; CHECK-NEXT: br label [[FOR_COND]]
|
|
; CHECK: catch.dispatch:
|
|
; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label %catch] unwind label [[CATCH_DISPATCH_2:%.*]]
|
|
; CHECK: catch:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = catchpad within [[CS]] [i8* null, i32 64, i8* null]
|
|
; CHECK-NEXT: catchret from [[TMP0]] to label [[TRY_CONT:%.*]]
|
|
; CHECK: try.cont:
|
|
; CHECK-NEXT: invoke void @external(i32* [[C:%.*]])
|
|
; CHECK-NEXT: to label [[TRY_CONT_7:%.*]] unwind label [[CATCH_DISPATCH_2]]
|
|
; CHECK: catch.dispatch.2:
|
|
; CHECK-NEXT: [[E_0:%.*]] = phi i32* [ [[C]], [[TRY_CONT]] ], [ [[B]], [[CATCH_DISPATCH]] ]
|
|
; CHECK-NEXT: [[CS2:%.*]] = catchswitch within none [label %catch.4] unwind to caller
|
|
; CHECK: catch.4:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = catchpad within [[CS2]] [i8* null, i32 64, i8* null]
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: try.cont.7:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.inc, %entry
|
|
%d.0 = phi i32* [ %b, %entry ], [ %incdec.ptr, %for.inc ]
|
|
invoke void @external(i32* %d.0)
|
|
to label %for.inc unwind label %catch.dispatch
|
|
|
|
for.inc: ; preds = %for.cond
|
|
%incdec.ptr = getelementptr inbounds i32, i32* %d.0, i32 1
|
|
br label %for.cond
|
|
|
|
catch.dispatch: ; preds = %for.cond
|
|
%cs = catchswitch within none [label %catch] unwind label %catch.dispatch.2
|
|
|
|
catch: ; preds = %catch.dispatch
|
|
%0 = catchpad within %cs [i8* null, i32 64, i8* null]
|
|
catchret from %0 to label %try.cont
|
|
|
|
try.cont: ; preds = %catch
|
|
invoke void @external(i32* %c)
|
|
to label %try.cont.7 unwind label %catch.dispatch.2
|
|
|
|
catch.dispatch.2: ; preds = %try.cont, %catchendblock
|
|
%e.0 = phi i32* [ %c, %try.cont ], [ %b, %catch.dispatch ]
|
|
%cs2 = catchswitch within none [label %catch.4] unwind to caller
|
|
|
|
catch.4: ; preds = %catch.dispatch.2
|
|
catchpad within %cs2 [i8* null, i32 64, i8* null]
|
|
unreachable
|
|
|
|
try.cont.7: ; preds = %try.cont
|
|
ret void
|
|
}
|
|
|
|
define i32 @test2() personality i32 (...)* @_except_handler3 {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: invoke void @reserve()
|
|
; CHECK-NEXT: to label [[FOR_INC]] unwind label [[CATCH_DISPATCH:%.*]]
|
|
; CHECK: catch.dispatch:
|
|
; CHECK-NEXT: [[TMP18:%.*]] = catchswitch within none [label %catch.handler] unwind to caller
|
|
; CHECK: catch.handler:
|
|
; CHECK-NEXT: [[PHI_LCSSA:%.*]] = phi i32 [ [[PHI]], [[CATCH_DISPATCH]] ]
|
|
; CHECK-NEXT: [[TMP19:%.*]] = catchpad within [[TMP18]] [i8* null]
|
|
; CHECK-NEXT: catchret from [[TMP19]] to label [[DONE:%.*]]
|
|
; CHECK: done:
|
|
; CHECK-NEXT: ret i32 [[PHI_LCSSA]]
|
|
; CHECK: for.inc:
|
|
; CHECK-NEXT: [[INC]] = add i32 [[PHI]], 1
|
|
; CHECK-NEXT: br label [[FOR_BODY]]
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.inc, %entry
|
|
%phi = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
|
|
invoke void @reserve()
|
|
to label %for.inc unwind label %catch.dispatch
|
|
|
|
catch.dispatch: ; preds = %for.body
|
|
%tmp18 = catchswitch within none [label %catch.handler] unwind to caller
|
|
|
|
catch.handler: ; preds = %catch.dispatch
|
|
%phi.lcssa = phi i32 [ %phi, %catch.dispatch ]
|
|
%tmp19 = catchpad within %tmp18 [i8* null]
|
|
catchret from %tmp19 to label %done
|
|
|
|
done:
|
|
ret i32 %phi.lcssa
|
|
|
|
for.inc: ; preds = %for.body
|
|
%inc = add i32 %phi, 1
|
|
br label %for.body
|
|
}
|