mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
a3594b33f7
This patch adds handling for zero-extended GEP indices.
224 lines
9.3 KiB
LLVM
224 lines
9.3 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -constraint-elimination -S %s | FileCheck %s
|
|
|
|
declare void @use(i1)
|
|
define void @checks_in_loops_removable(i8* %ptr, i8* %lower, i8* %upper, i32 %n) {
|
|
; CHECK-LABEL: @checks_in_loops_removable(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]]
|
|
; CHECK: pre.1:
|
|
; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64
|
|
; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IDX_EXT]]
|
|
; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[PTR_N]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[PRE_2:%.*]], label [[TRAP]]
|
|
; CHECK: pre.2:
|
|
; CHECK-NEXT: [[CMP_N_NOT_ZERO:%.*]] = icmp eq i32 [[N]], 0
|
|
; CHECK-NEXT: br i1 [[CMP_N_NOT_ZERO]], label [[EXIT:%.*]], label [[LOOP_HEADER:%.*]]
|
|
; CHECK: trap:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[PRE_2]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV]]
|
|
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_PTR_IV_LOWER]], [[CMP_PTR_IV_UPPER]]
|
|
; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: store i8 0, i8* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[IDX_EXT]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp.ptr.lower = icmp ult i8* %ptr, %lower
|
|
br i1 %cmp.ptr.lower, label %trap, label %pre.1
|
|
|
|
pre.1:
|
|
%idx.ext = zext i32 %n to i64
|
|
%ptr.n = getelementptr inbounds i8, i8* %ptr, i64 %idx.ext
|
|
%cmp.ptr.n.upper = icmp ult i8* %ptr.n, %upper
|
|
br i1 %cmp.ptr.n.upper, label %pre.2, label %trap
|
|
|
|
pre.2:
|
|
%cmp.n.not.zero = icmp eq i32 %n, 0
|
|
br i1 %cmp.n.not.zero, label %exit, label %loop.header
|
|
|
|
trap:
|
|
ret void
|
|
|
|
loop.header:
|
|
%iv = phi i64 [ 0, %pre.2 ], [ %iv.next, %loop.latch ]
|
|
%ptr.iv = getelementptr inbounds i8, i8* %ptr, i64 %iv
|
|
%cmp.ptr.iv.lower = icmp ugt i8* %lower, %ptr.iv
|
|
%cmp.ptr.iv.upper = icmp ule i8* %upper, %ptr.iv
|
|
%or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper
|
|
br i1 %or, label %trap, label %loop.latch
|
|
|
|
loop.latch:
|
|
store i8 0, i8* %ptr.iv, align 4
|
|
%iv.next = add nuw nsw i64 %iv, 1
|
|
%exitcond = icmp ne i64 %iv.next, %idx.ext
|
|
br i1 %exitcond, label %loop.header, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @some_checks_in_loops_removable(i8* %ptr, i8* %lower, i8* %upper, i32 %n) {
|
|
; CHECK-LABEL: @some_checks_in_loops_removable(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]]
|
|
; CHECK: pre.1:
|
|
; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64
|
|
; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IDX_EXT]]
|
|
; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[PTR_N]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[PRE_2:%.*]], label [[TRAP]]
|
|
; CHECK: pre.2:
|
|
; CHECK-NEXT: [[CMP_N_NOT_ZERO:%.*]] = icmp eq i32 [[N]], 0
|
|
; CHECK-NEXT: br i1 [[CMP_N_NOT_ZERO]], label [[EXIT:%.*]], label [[LOOP_HEADER:%.*]]
|
|
; CHECK: trap:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[PRE_2]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV]]
|
|
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_PTR_IV_LOWER]], [[CMP_PTR_IV_UPPER]]
|
|
; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_BODY:%.*]]
|
|
; CHECK: loop.body:
|
|
; CHECK-NEXT: [[IV_1:%.*]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[PTR_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV_1]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV_1]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV_1]]
|
|
; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_PTR_IV_1_UPPER]]
|
|
; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: store i8 0, i8* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[IDX_EXT]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp.ptr.lower = icmp ult i8* %ptr, %lower
|
|
br i1 %cmp.ptr.lower, label %trap, label %pre.1
|
|
|
|
pre.1:
|
|
%idx.ext = zext i32 %n to i64
|
|
%ptr.n = getelementptr inbounds i8, i8* %ptr, i64 %idx.ext
|
|
%cmp.ptr.n.upper = icmp ult i8* %ptr.n, %upper
|
|
br i1 %cmp.ptr.n.upper, label %pre.2, label %trap
|
|
|
|
pre.2:
|
|
%cmp.n.not.zero = icmp eq i32 %n, 0
|
|
br i1 %cmp.n.not.zero, label %exit, label %loop.header
|
|
|
|
trap:
|
|
ret void
|
|
|
|
loop.header:
|
|
%iv = phi i64 [ 0, %pre.2 ], [ %iv.next, %loop.latch ]
|
|
%ptr.iv = getelementptr inbounds i8, i8* %ptr, i64 %iv
|
|
%cmp.ptr.iv.lower = icmp ugt i8* %lower, %ptr.iv
|
|
%cmp.ptr.iv.upper = icmp ule i8* %upper, %ptr.iv
|
|
%or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper
|
|
br i1 %or, label %trap, label %loop.body
|
|
|
|
loop.body:
|
|
%iv.1 = add nuw nsw i64 %iv, 1
|
|
%ptr.iv.1 = getelementptr inbounds i8, i8* %ptr, i64 %iv.1
|
|
%cmp.ptr.iv.1.lower = icmp ugt i8* %lower, %ptr.iv.1
|
|
%cmp.ptr.iv.1.upper = icmp ule i8* %upper, %ptr.iv.1
|
|
%or.1 = or i1 %cmp.ptr.iv.1.lower, %cmp.ptr.iv.1.upper
|
|
br i1 %or, label %trap, label %loop.latch
|
|
|
|
loop.latch:
|
|
store i8 0, i8* %ptr.iv, align 4
|
|
%iv.next = add nuw nsw i64 %iv, 1
|
|
%exitcond = icmp ne i64 %iv.next, %idx.ext
|
|
br i1 %exitcond, label %loop.header, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
|
|
; N might be zero, cannot remove upper checks.
|
|
define void @no_checks_in_loops_removable(i8* %ptr, i8* %lower, i8* %upper, i32 %n) {
|
|
; CHECK-LABEL: @no_checks_in_loops_removable(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP_PTR_LOWER:%.*]] = icmp ult i8* [[PTR:%.*]], [[LOWER:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_PTR_LOWER]], label [[TRAP:%.*]], label [[PRE_1:%.*]]
|
|
; CHECK: pre.1:
|
|
; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[N:%.*]] to i64
|
|
; CHECK-NEXT: [[PTR_N:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IDX_EXT]]
|
|
; CHECK-NEXT: [[CMP_PTR_N_UPPER:%.*]] = icmp ult i8* [[PTR_N]], [[UPPER:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP_PTR_N_UPPER]], label [[LOOP_HEADER:%.*]], label [[TRAP]]
|
|
; CHECK: trap:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[PRE_1]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV]]
|
|
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_PTR_IV_LOWER]], [[CMP_PTR_IV_UPPER]]
|
|
; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_BODY:%.*]]
|
|
; CHECK: loop.body:
|
|
; CHECK-NEXT: [[IV_1:%.*]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[PTR_IV_1:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[IV_1]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_1_LOWER:%.*]] = icmp ugt i8* [[LOWER]], [[PTR_IV_1]]
|
|
; CHECK-NEXT: [[CMP_PTR_IV_1_UPPER:%.*]] = icmp ule i8* [[UPPER]], [[PTR_IV_1]]
|
|
; CHECK-NEXT: [[OR_1:%.*]] = or i1 false, [[CMP_PTR_IV_1_UPPER]]
|
|
; CHECK-NEXT: br i1 [[OR]], label [[TRAP]], label [[LOOP_LATCH]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: store i8 0, i8* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[IDX_EXT]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp.ptr.lower = icmp ult i8* %ptr, %lower
|
|
br i1 %cmp.ptr.lower, label %trap, label %pre.1
|
|
|
|
pre.1:
|
|
%idx.ext = zext i32 %n to i64
|
|
%ptr.n = getelementptr inbounds i8, i8* %ptr, i64 %idx.ext
|
|
%cmp.ptr.n.upper = icmp ult i8* %ptr.n, %upper
|
|
br i1 %cmp.ptr.n.upper, label %loop.header, label %trap
|
|
|
|
trap:
|
|
ret void
|
|
|
|
loop.header:
|
|
%iv = phi i64 [ 0, %pre.1 ], [ %iv.next, %loop.latch ]
|
|
%ptr.iv = getelementptr inbounds i8, i8* %ptr, i64 %iv
|
|
%cmp.ptr.iv.lower = icmp ugt i8* %lower, %ptr.iv
|
|
%cmp.ptr.iv.upper = icmp ule i8* %upper, %ptr.iv
|
|
%or = or i1 %cmp.ptr.iv.lower, %cmp.ptr.iv.upper
|
|
br i1 %or, label %trap, label %loop.body
|
|
|
|
loop.body:
|
|
%iv.1 = add nuw nsw i64 %iv, 1
|
|
%ptr.iv.1 = getelementptr inbounds i8, i8* %ptr, i64 %iv.1
|
|
%cmp.ptr.iv.1.lower = icmp ugt i8* %lower, %ptr.iv.1
|
|
%cmp.ptr.iv.1.upper = icmp ule i8* %upper, %ptr.iv.1
|
|
%or.1 = or i1 %cmp.ptr.iv.1.lower, %cmp.ptr.iv.1.upper
|
|
br i1 %or, label %trap, label %loop.latch
|
|
|
|
loop.latch:
|
|
store i8 0, i8* %ptr.iv, align 4
|
|
%iv.next = add nuw nsw i64 %iv, 1
|
|
%exitcond = icmp ne i64 %iv.next, %idx.ext
|
|
br i1 %exitcond, label %loop.header, label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|