2024-12-20 12:16:49 +00:00

422 lines
16 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=lower-constant-intrinsics -S < %s | FileCheck %s
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
declare dso_local noalias noundef ptr @malloc(i64 noundef) local_unnamed_addr allocsize(0)
declare i64 @llvm.objectsize.i64.p0(ptr, i1 immarg, i1 immarg, i1 immarg)
@buffer = dso_local global [4 x i8] zeroinitializer, align 1
define dso_local i64 @pick_max(i32 noundef %n) local_unnamed_addr {
; CHECK-LABEL: @pick_max(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[MALLOCED:%.*]] = call noalias dereferenceable_or_null(8) ptr @malloc(i64 noundef 8)
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[MALLOCED]], [[IF_ELSE]] ], [ @buffer, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i64 8
;
entry:
%cond = icmp eq i32 %n, 0
br i1 %cond, label %if.else, label %if.end
if.else:
%malloced = call noalias dereferenceable_or_null(8) ptr @malloc(i64 noundef 8)
br label %if.end
if.end:
%p = phi ptr [ %malloced, %if.else ], [ @buffer, %entry ]
%size = call i64 @llvm.objectsize.i64.p0(ptr %p, i1 false, i1 true, i1 false)
ret i64 %size
}
define dso_local i64 @pick_min(i32 noundef %n) local_unnamed_addr {
; CHECK-LABEL: @pick_min(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[MALLOCED:%.*]] = call noalias dereferenceable_or_null(8) ptr @malloc(i64 noundef 8)
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[MALLOCED]], [[IF_ELSE]] ], [ @buffer, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i64 4
;
entry:
%cond = icmp eq i32 %n, 0
br i1 %cond, label %if.else, label %if.end
if.else:
%malloced = call noalias dereferenceable_or_null(8) ptr @malloc(i64 noundef 8)
br label %if.end
if.end:
%p = phi ptr [ %malloced, %if.else ], [ @buffer, %entry ]
%size = call i64 @llvm.objectsize.i64.p0(ptr %p, i1 true, i1 true, i1 false)
ret i64 %size
}
define i64 @pick_max_same(i32 %n) {
; CHECK-LABEL: @pick_max_same(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BUFFER:%.*]] = alloca i8, i64 20, align 1
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[OFFSETED:%.*]] = getelementptr i8, ptr [[BUFFER]], i64 10
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[OFFSETED]], [[IF_ELSE]] ], [ [[BUFFER]], [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i64 20
;
entry:
%buffer = alloca i8, i64 20
%cond = icmp eq i32 %n, 0
br i1 %cond, label %if.else, label %if.end
if.else:
%offseted = getelementptr i8, ptr %buffer, i64 10
br label %if.end
if.end:
%p = phi ptr [ %offseted, %if.else ], [ %buffer, %entry ]
%size = call i64 @llvm.objectsize.i64.p0(ptr %p, i1 false, i1 true, i1 false)
ret i64 %size
}
define i64 @pick_min_same(i32 %n) {
; CHECK-LABEL: @pick_min_same(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BUFFER:%.*]] = alloca i8, i64 20, align 1
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[OFFSETED:%.*]] = getelementptr i8, ptr [[BUFFER]], i64 10
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[OFFSETED]], [[IF_ELSE]] ], [ [[BUFFER]], [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i64 10
;
entry:
%buffer = alloca i8, i64 20
%cond = icmp eq i32 %n, 0
br i1 %cond, label %if.else, label %if.end
if.else:
%offseted = getelementptr i8, ptr %buffer, i64 10
br label %if.end
if.end:
%p = phi ptr [ %offseted, %if.else ], [ %buffer, %entry ]
%size = call i64 @llvm.objectsize.i64.p0(ptr %p, i1 true, i1 true, i1 false)
ret i64 %size
}
define dso_local i64 @pick_max_large(i1 %c) local_unnamed_addr {
; CHECK-LABEL: @pick_max_large(
; CHECK-NEXT: [[BUFFER:%.*]] = alloca i8, i64 -7, align 1
; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], ptr null, ptr [[BUFFER]]
; CHECK-NEXT: ret i64 -1
;
%buffer = alloca i8, i64 -7 ; Actually a very large positive integer
%s = select i1 %c, ptr null, ptr %buffer
%objsize = tail call i64 @llvm.objectsize.i64.p0(ptr %s, i1 false, i1 false, i1 false)
ret i64 %objsize
}
define dso_local i64 @pick_max_one_oob(i1 %c0, i1 %c1) {
; CHECK-LABEL: @pick_max_one_oob(
; CHECK-NEXT: [[P:%.*]] = alloca [2 x i8], align 1
; CHECK-NEXT: br i1 [[C0:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then:
; CHECK-NEXT: [[P_THEN:%.*]] = getelementptr inbounds [2 x i8], ptr [[P]], i64 0, i64 1
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[P_ELSE:%.*]] = getelementptr inbounds [2 x i8], ptr [[P]], i64 0, i64 -1
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[P_END:%.*]] = phi ptr [ [[P_ELSE]], [[IF_ELSE]] ], [ [[P_THEN]], [[IF_THEN]] ]
; CHECK-NEXT: [[OBJSIZE:%.*]] = select i1 [[C1:%.*]], i64 -1, i64 0
; CHECK-NEXT: ret i64 [[OBJSIZE]]
;
%p = alloca [2 x i8], align 1
br i1 %c0, label %if.then, label %if.else
if.then:
%p.then = getelementptr inbounds [2 x i8], ptr %p, i64 0, i64 1
br label %if.end
if.else:
%p.else = getelementptr inbounds [2 x i8], ptr %p, i64 0, i64 -1
br label %if.end
if.end:
%p.end = phi ptr [%p.else, %if.else], [%p.then, %if.then]
%objsize.max = call i64 @llvm.objectsize.i64.p0(ptr %p.end, i1 false, i1 true, i1 false)
%objsize.min = call i64 @llvm.objectsize.i64.p0(ptr %p.end, i1 true, i1 true, i1 false)
%objsize = select i1 %c1, i64 %objsize.max, i64 %objsize.min
ret i64 %objsize
}
define i64 @pick_negative_offset(i32 %n) {
; CHECK-LABEL: @pick_negative_offset(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BUFFER0:%.*]] = alloca i8, i64 20, align 1
; CHECK-NEXT: [[OFFSETED0:%.*]] = getelementptr i8, ptr [[BUFFER0]], i64 20
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[BUFFER1:%.*]] = alloca i8, i64 20, align 1
; CHECK-NEXT: [[OFFSETED1:%.*]] = getelementptr i8, ptr [[BUFFER1]], i64 20
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[OFFSETED1]], [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[POFFSETED:%.*]] = getelementptr i8, ptr [[P]], i64 -4
; CHECK-NEXT: ret i64 4
;
entry:
%buffer0 = alloca i8, i64 20
%offseted0 = getelementptr i8, ptr %buffer0, i64 20
%cond = icmp eq i32 %n, 0
br i1 %cond, label %if.else, label %if.end
if.else:
%buffer1 = alloca i8, i64 20
%offseted1 = getelementptr i8, ptr %buffer1, i64 20
br label %if.end
if.end:
%p = phi ptr [ %offseted1, %if.else ], [ %offseted0, %entry ]
%poffseted = getelementptr i8, ptr %p, i64 -4
%size = call i64 @llvm.objectsize.i64.p0(ptr %poffseted, i1 false, i1 false, i1 false)
ret i64 %size
}
define i64 @pick_negative_offset_different_width(i32 %n) {
; CHECK-LABEL: @pick_negative_offset_different_width(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BUFFER0:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: [[BUFFER1:%.*]] = alloca i8, i64 8, align 1
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: [[OFFSETED0:%.*]] = getelementptr i8, ptr [[BUFFER0]], i64 1
; CHECK-NEXT: br label [[IF_END1:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[OFFSETED1:%.*]] = getelementptr i8, ptr [[BUFFER1]], i64 6
; CHECK-NEXT: br label [[IF_END1]]
; CHECK: if.end:
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[OFFSETED0]], [[IF_ELSE]] ], [ [[OFFSETED1]], [[IF_END]] ]
; CHECK-NEXT: [[POFFSETED:%.*]] = getelementptr i8, ptr [[P]], i64 -2
; CHECK-NEXT: ret i64 5
;
entry:
%buffer0 = alloca i8, i64 4
%buffer1 = alloca i8, i64 8
%cond = icmp eq i32 %n, 0
br i1 %cond, label %if.then, label %if.else
if.then:
%offseted0 = getelementptr i8, ptr %buffer0, i64 1
br label %if.end
if.else:
%offseted1 = getelementptr i8, ptr %buffer1, i64 6
br label %if.end
if.end:
%p = phi ptr [ %offseted0, %if.then ], [ %offseted1, %if.else ]
%poffseted = getelementptr i8, ptr %p, i64 -2
%size = call i64 @llvm.objectsize.i64.p0(ptr %poffseted, i1 false, i1 false, i1 false)
ret i64 %size
}
define i64 @pick_negative_offset_with_nullptr(i32 %n) {
; CHECK-LABEL: @pick_negative_offset_with_nullptr(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BUFFER0:%.*]] = alloca i8, i64 20, align 1
; CHECK-NEXT: [[OFFSETED0:%.*]] = getelementptr i8, ptr [[BUFFER0]], i64 20
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[P0:%.*]] = phi ptr [ [[OFFSETED0]], [[ENTRY:%.*]] ], [ null, [[IF_ELSE]] ]
; CHECK-NEXT: [[P1:%.*]] = phi ptr [ null, [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY]] ]
; CHECK-NEXT: [[P0OFFSETED:%.*]] = getelementptr i8, ptr [[P0]], i64 -4
; CHECK-NEXT: [[P1OFFSETED:%.*]] = getelementptr i8, ptr [[P1]], i64 -4
; CHECK-NEXT: ret i64 4
;
entry:
%buffer0 = alloca i8, i64 20
%offseted0 = getelementptr i8, ptr %buffer0, i64 20
%cond = icmp eq i32 %n, 0
br i1 %cond, label %if.else, label %if.end
if.else:
br label %if.end
if.end:
%p0 = phi ptr [ %offseted0, %entry ], [ null, %if.else ]
%p1 = phi ptr [ null, %if.else ], [ %offseted0, %entry ]
%p0offseted = getelementptr i8, ptr %p0, i64 -4
%p1offseted = getelementptr i8, ptr %p1, i64 -4
%size0 = call i64 @llvm.objectsize.i64.p0(ptr %p0offseted, i1 false, i1 false, i1 false)
%size1 = call i64 @llvm.objectsize.i64.p0(ptr %p1offseted, i1 false, i1 false, i1 false)
%size = select i1 %cond, i64 %size0, i64 %size1
ret i64 %size
}
define i64 @pick_negative_offset_with_unsized_nullptr(i32 %n) {
; CHECK-LABEL: @pick_negative_offset_with_unsized_nullptr(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BUFFER0:%.*]] = alloca i8, i64 20, align 1
; CHECK-NEXT: [[OFFSETED0:%.*]] = getelementptr i8, ptr [[BUFFER0]], i64 20
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[P0:%.*]] = phi ptr [ [[OFFSETED0]], [[ENTRY:%.*]] ], [ null, [[IF_ELSE]] ]
; CHECK-NEXT: [[P1:%.*]] = phi ptr [ null, [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY]] ]
; CHECK-NEXT: [[P0OFFSETED:%.*]] = getelementptr i8, ptr [[P0]], i64 -4
; CHECK-NEXT: [[P1OFFSETED:%.*]] = getelementptr i8, ptr [[P1]], i64 -4
; CHECK-NEXT: ret i64 -1
;
entry:
%buffer0 = alloca i8, i64 20
%offseted0 = getelementptr i8, ptr %buffer0, i64 20
%cond = icmp eq i32 %n, 0
br i1 %cond, label %if.else, label %if.end
if.else:
br label %if.end
if.end:
%p0 = phi ptr [ %offseted0, %entry ], [ null, %if.else ]
%p1 = phi ptr [ null, %if.else ], [ %offseted0, %entry ]
%p0offseted = getelementptr i8, ptr %p0, i64 -4
%p1offseted = getelementptr i8, ptr %p1, i64 -4
%size0 = call i64 @llvm.objectsize.i64.p0(ptr %p0offseted, i1 false, i1 true, i1 false)
%size1 = call i64 @llvm.objectsize.i64.p0(ptr %p1offseted, i1 false, i1 true, i1 false)
%size = select i1 %cond, i64 %size0, i64 %size1
ret i64 %size
}
define i64 @chain_pick_negative_offset_with_nullptr(i32 %x) {
; CHECK-LABEL: @chain_pick_negative_offset_with_nullptr(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [4 x i32], align 4
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[P:%.*]] = getelementptr i8, ptr [[ARRAY]], i64 8
; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], ptr [[P]], ptr null
; CHECK-NEXT: [[P4:%.*]] = getelementptr i8, ptr [[COND]], i64 8
; CHECK-NEXT: [[COND6:%.*]] = select i1 [[C]], ptr [[P4]], ptr null
; CHECK-NEXT: [[P7:%.*]] = getelementptr i8, ptr [[COND6]], i64 -4
; CHECK-NEXT: ret i64 4
;
entry:
%array = alloca [4 x i32]
%c = icmp eq i32 %x, 0
%p = getelementptr i8, ptr %array, i64 8
%cond = select i1 %c, ptr %p, ptr null
%p4 = getelementptr i8, ptr %cond, i64 8
%cond6 = select i1 %c, ptr %p4, ptr null
%p7 = getelementptr i8, ptr %cond6, i64 -4
%size = call i64 @llvm.objectsize.i64.p0(ptr %p7, i1 false, i1 false, i1 false)
ret i64 %size
}
define i64 @negative_offset_dynamic_eval(i32 %x, i64 %i) {
; CHECK-LABEL: @negative_offset_dynamic_eval(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ARRAY1:%.*]] = alloca [4 x i32], align 16
; CHECK-NEXT: [[ARRAY2:%.*]] = alloca [8 x i32], align 16
; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[ARRAY2]], i64 16
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ 16, [[IF_THEN]] ], [ 32, [[IF_ELSE]] ]
; CHECK-NEXT: [[TMP5:%.*]] = phi i64 [ 0, [[IF_THEN]] ], [ 16, [[IF_ELSE]] ]
; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[ARRAY1]], [[IF_THEN]] ], [ [[ADD_PTR]], [[IF_ELSE]] ]
; CHECK-NEXT: [[ADD_PTR2_IDX:%.*]] = mul i64 [[I:%.*]], 4
; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[TMP5]], [[ADD_PTR2_IDX]]
; CHECK-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[I]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[TMP6]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i64 [[TMP0]], [[TMP6]]
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP1]]
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[TMP3]], -1
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP4]])
; CHECK-NEXT: ret i64 [[TMP3]]
;
entry:
%array1 = alloca [4 x i32], align 16
%array2 = alloca [8 x i32], align 16
%tobool.not = icmp eq i32 %x, 0
br i1 %tobool.not, label %if.else, label %if.then
if.then:
br label %if.end
if.else:
%add.ptr = getelementptr inbounds i8, ptr %array2, i64 16
br label %if.end
if.end:
%ptr = phi ptr [ %array1, %if.then ], [ %add.ptr, %if.else ]
%add.ptr2 = getelementptr inbounds i32, ptr %ptr, i64 %i
%objsize = call i64 @llvm.objectsize.i64.p0(ptr %add.ptr2, i1 false, i1 true, i1 true)
ret i64 %objsize
}
define i64 @outofbound_offset_eval(i32 %x) {
; CHECK-LABEL: @outofbound_offset_eval(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ARRAY:%.*]] = alloca [4 x i8], align 16
; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
; CHECK-NEXT: [[ADD_PTR0:%.*]] = getelementptr i8, ptr [[ARRAY]], i64 10
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: [[ADD_PTR1:%.*]] = getelementptr i8, ptr [[ARRAY]], i64 12
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[ADD_PTR0]], [[IF_THEN]] ], [ [[ADD_PTR1]], [[IF_ELSE]] ]
; CHECK-NEXT: [[ADD_PTR2:%.*]] = getelementptr i8, ptr [[PTR]], i64 -10
; CHECK-NEXT: ret i64 4
;
entry:
%array = alloca [4 x i8], align 16
%tobool.not = icmp eq i32 %x, 0
br i1 %tobool.not, label %if.else, label %if.then
if.then:
%add.ptr0 = getelementptr i8, ptr %array, i64 10
br label %if.end
if.else:
%add.ptr1 = getelementptr i8, ptr %array, i64 12
br label %if.end
if.end:
%ptr = phi ptr [ %add.ptr0, %if.then ], [ %add.ptr1, %if.else ]
%add.ptr2 = getelementptr i8, ptr %ptr, i64 -10
%objsize = call i64 @llvm.objectsize.i64.p0(ptr %add.ptr2, i1 false, i1 false, i1 false)
ret i64 %objsize
}