blob: 1bb6b2fb5bd3a75c108090d0dfa0255db02f3601 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 6
; RUN: opt -passes="default<O3>" -S < %s | FileCheck %s
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
declare void @llvm.memmove.p0.p0.i64(ptr writeonly captures(none), ptr readonly captures(none), i64, i1 immarg)
define void @redundant_int_iv(ptr %first) {
; CHECK-LABEL: define void @redundant_int_iv(
; CHECK-SAME: ptr [[FIRST:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[PTR_INT1:%.*]] = ptrtoint ptr [[FIRST]] to i64
; CHECK-NEXT: [[OFF2:%.*]] = add i64 [[PTR_INT1]], 1
; CHECK-NEXT: [[EC_OUTER3:%.*]] = icmp slt i64 [[OFF2]], 0
; CHECK-NEXT: br i1 [[EC_OUTER3]], label %[[INNER_PH:.*]], label %[[EXIT:.*]]
; CHECK: [[INNER_PH]]:
; CHECK-NEXT: [[PTR_INT5:%.*]] = phi i64 [ [[PTR_INT:%.*]], %[[INNER_PH]] ], [ [[PTR_INT1]], %[[ENTRY]] ]
; CHECK-NEXT: [[PTR_IV4:%.*]] = phi ptr [ [[LAST:%.*]], %[[INNER_PH]] ], [ [[FIRST]], %[[ENTRY]] ]
; CHECK-NEXT: [[LAST]] = getelementptr i8, ptr [[PTR_IV4]], i64 7
; CHECK-NEXT: [[CUR_NEXT:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 1
; CHECK-NEXT: [[CUR_INT:%.*]] = ptrtoint ptr [[CUR_NEXT]] to i64
; CHECK-NEXT: [[LEN:%.*]] = sub i64 [[CUR_INT]], [[PTR_INT5]]
; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr align 1 [[CUR_NEXT]], ptr align 1 [[PTR_IV4]], i64 [[LEN]], i1 false)
; CHECK-NEXT: [[CUR_NEXT_1:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 2
; CHECK-NEXT: [[CUR_INT_1:%.*]] = ptrtoint ptr [[CUR_NEXT_1]] to i64
; CHECK-NEXT: [[LEN_1:%.*]] = sub i64 [[CUR_INT_1]], [[PTR_INT5]]
; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr align 1 [[CUR_NEXT_1]], ptr align 1 [[PTR_IV4]], i64 [[LEN_1]], i1 false)
; CHECK-NEXT: [[CUR_NEXT_2:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 3
; CHECK-NEXT: [[CUR_INT_2:%.*]] = ptrtoint ptr [[CUR_NEXT_2]] to i64
; CHECK-NEXT: [[LEN_2:%.*]] = sub i64 [[CUR_INT_2]], [[PTR_INT5]]
; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr align 1 [[CUR_NEXT_2]], ptr align 1 [[PTR_IV4]], i64 [[LEN_2]], i1 false)
; CHECK-NEXT: [[CUR_NEXT_3:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 4
; CHECK-NEXT: [[CUR_INT_3:%.*]] = ptrtoint ptr [[CUR_NEXT_3]] to i64
; CHECK-NEXT: [[LEN_3:%.*]] = sub i64 [[CUR_INT_3]], [[PTR_INT5]]
; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr align 1 [[CUR_NEXT_3]], ptr align 1 [[PTR_IV4]], i64 [[LEN_3]], i1 false)
; CHECK-NEXT: [[CUR_NEXT_4:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 5
; CHECK-NEXT: [[CUR_INT_4:%.*]] = ptrtoint ptr [[CUR_NEXT_4]] to i64
; CHECK-NEXT: [[LEN_4:%.*]] = sub i64 [[CUR_INT_4]], [[PTR_INT5]]
; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr align 1 [[CUR_NEXT_4]], ptr align 1 [[PTR_IV4]], i64 [[LEN_4]], i1 false)
; CHECK-NEXT: [[CUR_NEXT_5:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 6
; CHECK-NEXT: [[CUR_INT_5:%.*]] = ptrtoint ptr [[CUR_NEXT_5]] to i64
; CHECK-NEXT: [[LEN_5:%.*]] = sub i64 [[CUR_INT_5]], [[PTR_INT5]]
; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr align 1 [[CUR_NEXT_5]], ptr align 1 [[PTR_IV4]], i64 [[LEN_5]], i1 false)
; CHECK-NEXT: [[CUR_NEXT_6:%.*]] = getelementptr i8, ptr [[PTR_IV4]], i64 7
; CHECK-NEXT: [[CUR_INT_6:%.*]] = ptrtoint ptr [[CUR_NEXT_6]] to i64
; CHECK-NEXT: [[LEN_6:%.*]] = sub i64 [[CUR_INT_6]], [[PTR_INT5]]
; CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i64(ptr align 1 [[CUR_NEXT_6]], ptr align 1 [[PTR_IV4]], i64 [[LEN_6]], i1 false)
; CHECK-NEXT: [[PTR_INT]] = ptrtoint ptr [[LAST]] to i64
; CHECK-NEXT: [[OFF:%.*]] = add i64 [[PTR_INT]], 1
; CHECK-NEXT: [[EC_OUTER:%.*]] = icmp slt i64 [[OFF]], 0
; CHECK-NEXT: br i1 [[EC_OUTER]], label %[[INNER_PH]], label %[[EXIT]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %outer
outer:
%ptr.iv = phi ptr [ %first, %entry ], [ %ptr.next, %inner.exit ]
%ptr.int = ptrtoint ptr %ptr.iv to i64
%off = add i64 %ptr.int, 1
%ec.outer = icmp slt i64 %off, 0
br i1 %ec.outer, label %inner.ph, label %exit
inner.ph:
%last = getelementptr i8, ptr %ptr.iv, i64 7
br label %inner
inner:
%cur = phi ptr [ %ptr.iv, %inner.ph ], [ %cur.next, %inner ]
%cur.next = getelementptr i8, ptr %cur, i64 1
%cur.int = ptrtoint ptr %cur.next to i64
%len = sub i64 %cur.int, %ptr.int
call void @llvm.memmove.p0.p0.i64(ptr %cur.next, ptr %ptr.iv, i64 %len, i1 false)
%inner.done = icmp eq ptr %cur.next, %last
br i1 %inner.done, label %inner.exit, label %inner
inner.exit:
%ptr.next = getelementptr i8, ptr %ptr.iv, i64 7
br label %outer
exit:
ret void
}
define ptr @cancel_out_of_range(ptr %p) {
; CHECK-LABEL: define noalias noundef ptr @cancel_out_of_range(
; CHECK-SAME: ptr [[P:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store ptr [[P]], ptr [[P]], align 8
; CHECK-NEXT: [[P1:%.*]] = ptrtoint ptr [[P]] to i64
; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[P1]], 255
; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i64 [[TMP0]], 0
; CHECK-NEXT: [[P2:%.*]] = ptrtoaddr ptr [[P]] to i64
; CHECK-NEXT: [[SPEC_SELECT_IDX:%.*]] = select i1 [[IS_ZERO]], i64 0, i64 [[P2]]
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = getelementptr i8, ptr null, i64 [[SPEC_SELECT_IDX]]
; CHECK-NEXT: ret ptr [[SPEC_SELECT]]
;
entry:
store ptr %p, ptr %p, align 8
%first = load i8, ptr %p, align 1
%is.zero = icmp eq i8 %first, 0
br i1 %is.zero, label %exit, label %loop
exit:
%res = phi ptr [ null, %entry ], [ %cur, %loop ]
ret ptr %res
loop:
%cur = phi ptr [ null, %entry ], [ %prev, %loop.dec ]
%found = icmp eq ptr %cur, %p
br i1 %found, label %exit, label %loop.dec
loop.dec:
%prev = getelementptr i8, ptr %cur, i64 -1
br label %loop
}
@end = external global i8
define i64 @cse_two_guards(ptr %base, i64 %n, ptr %cmp) {
; CHECK-LABEL: define i64 @cse_two_guards(
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[N:%.*]], ptr nofree readonly captures(none) [[CMP:%.*]]) local_unnamed_addr #[[ATTR1]] {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[N_FR:%.*]] = freeze i64 [[N]]
; CHECK-NEXT: store ptr [[BASE]], ptr [[BASE]], align 8
; CHECK-NEXT: [[NE_I_NOT6:%.*]] = icmp eq ptr [[BASE]], @end
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[BASE]] to i64
; CHECK-NEXT: br i1 [[NE_I_NOT6]], label %[[RET:.*]], label %[[LOOP1_INC_PREHEADER:.*]]
; CHECK: [[LOOP1_INC_PREHEADER]]:
; CHECK-NEXT: [[TMP2:%.*]] = sub i64 add (i64 ptrtoaddr (ptr @end to i64), i64 -48), [[TMP0]]
; CHECK-NEXT: [[TMP3:%.*]] = udiv i64 [[TMP2]], 48
; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP2]], 144
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[LOOP1_INC_PREHEADER41:.*]], label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP4]], 1152921504606846972
; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[N_VEC]], 48
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[TMP5]]
; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i64 [[N_FR]], 2
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
; CHECK: [[VECTOR_BODY]]:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
; CHECK-NEXT: br i1 [[TMP8]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: [[RDX_SELECT:%.*]] = zext i1 [[TMP7]] to i64
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP4]], [[N_VEC]]
; CHECK-NEXT: br i1 [[CMP_N]], label %[[LOOP2_BODY_LR_PH:.*]], label %[[LOOP1_INC_PREHEADER41]]
; CHECK: [[LOOP1_INC_PREHEADER41]]:
; CHECK-NEXT: [[R8_PH:%.*]] = phi i64 [ 1, %[[LOOP1_INC_PREHEADER]] ], [ [[RDX_SELECT]], %[[MIDDLE_BLOCK]] ]
; CHECK-NEXT: [[IT1_07_PH:%.*]] = phi ptr [ [[BASE]], %[[LOOP1_INC_PREHEADER]] ], [ [[TMP6]], %[[MIDDLE_BLOCK]] ]
; CHECK-NEXT: br label %[[LOOP1_INC:.*]]
; CHECK: [[LOOP2_BODY_LR_PH]]:
; CHECK-NEXT: [[SEL_LCSSA:%.*]] = phi i64 [ [[RDX_SELECT]], %[[MIDDLE_BLOCK]] ], [ [[SEL:%.*]], %[[LOOP1_INC]] ]
; CHECK-NEXT: [[TMP9:%.*]] = uitofp nneg i64 [[SEL_LCSSA]] to double
; CHECK-NEXT: [[TMP21:%.*]] = sub i64 add (i64 ptrtoaddr (ptr @end to i64), i64 -48), [[TMP0]]
; CHECK-NEXT: [[TMP27:%.*]] = udiv i64 [[TMP21]], 48
; CHECK-NEXT: [[TMP28:%.*]] = add nuw nsw i64 [[TMP27]], 1
; CHECK-NEXT: [[MIN_ITERS_CHECK18:%.*]] = icmp ult i64 [[TMP21]], 144
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK18]], label %[[LOOP2_BODY_PREHEADER:.*]], label %[[VECTOR_MEMCHECK:.*]]
; CHECK: [[VECTOR_MEMCHECK]]:
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[BASE]], i64 8
; CHECK-NEXT: [[SCEVGEP16:%.*]] = getelementptr i8, ptr [[CMP]], i64 8
; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[BASE]], [[SCEVGEP16]]
; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[CMP]], [[SCEVGEP]]
; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label %[[LOOP2_BODY_PREHEADER]], label %[[VECTOR_PH19:.*]]
; CHECK: [[VECTOR_PH19]]:
; CHECK-NEXT: [[N_VEC21:%.*]] = and i64 [[TMP28]], 1152921504606846974
; CHECK-NEXT: [[BROADCAST_SPLATINSERT22:%.*]] = insertelement <2 x double> poison, double [[TMP9]], i64 0
; CHECK-NEXT: [[TMP10:%.*]] = mul i64 [[N_VEC21]], 48
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[TMP10]]
; CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr [[CMP]], align 8, !alias.scope [[META3:![0-9]+]]
; CHECK-NEXT: [[BROADCAST_SPLATINSERT24:%.*]] = insertelement <2 x i64> poison, i64 [[TMP12]], i64 0
; CHECK-NEXT: [[TMP13:%.*]] = uitofp <2 x i64> [[BROADCAST_SPLATINSERT24]] to <2 x double>
; CHECK-NEXT: [[TMP14:%.*]] = fmul nnan <2 x double> [[BROADCAST_SPLATINSERT22]], [[TMP13]]
; CHECK-NEXT: [[TMP15:%.*]] = fcmp ugt <2 x double> [[TMP14]], zeroinitializer
; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <2 x i1> [[TMP15]], <2 x i1> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[TMP17:%.*]] = freeze <2 x i1> [[TMP16]]
; CHECK-NEXT: [[TMP18:%.*]] = bitcast <2 x i1> [[TMP17]] to i2
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i2 [[TMP18]], 0
; CHECK-NEXT: [[BROADCAST_SPLATINSERT26:%.*]] = insertelement <2 x i64> poison, i64 [[TMP0]], i64 0
; CHECK-NEXT: [[BROADCAST_SPLAT27:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT26]], <2 x i64> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[TMP19:%.*]] = bitcast <2 x i1> [[TMP17]] to i2
; CHECK-NEXT: [[DOTNOT39:%.*]] = icmp eq i2 [[TMP19]], 0
; CHECK-NEXT: br label %[[VECTOR_BODY28:.*]]
; CHECK: [[VECTOR_BODY28]]:
; CHECK-NEXT: [[INDEX29:%.*]] = phi i64 [ 0, %[[VECTOR_PH19]] ], [ [[INDEX_NEXT33:%.*]], %[[TMP22:.*]] ]
; CHECK-NEXT: [[VEC_PHI30:%.*]] = phi <2 x i64> [ [[BROADCAST_SPLAT27]], %[[VECTOR_PH19]] ], [ [[TMP24:%.*]], %[[TMP22]] ]
; CHECK-NEXT: [[TMP20:%.*]] = phi <2 x i1> [ zeroinitializer, %[[VECTOR_PH19]] ], [ [[TMP23:%.*]], %[[TMP22]] ]
; CHECK-NEXT: br i1 [[DOTNOT39]], label %[[TMP22]], label %[[BB21:.*]]
; CHECK: [[BB21]]:
; CHECK-NEXT: store i64 0, ptr [[BASE]], align 8, !alias.scope [[META6:![0-9]+]], !noalias [[META3]]
; CHECK-NEXT: br label %[[TMP22]]
; CHECK: [[TMP22]]:
; CHECK-NEXT: [[TMP23]] = select i1 [[DOTNOT]], <2 x i1> [[TMP20]], <2 x i1> [[TMP17]]
; CHECK-NEXT: [[TMP24]] = select i1 [[DOTNOT]], <2 x i64> [[VEC_PHI30]], <2 x i64> zeroinitializer
; CHECK-NEXT: [[INDEX_NEXT33]] = add nuw i64 [[INDEX29]], 2
; CHECK-NEXT: [[TMP25:%.*]] = icmp eq i64 [[INDEX_NEXT33]], [[N_VEC21]]
; CHECK-NEXT: br i1 [[TMP25]], label %[[MIDDLE_BLOCK34:.*]], label %[[VECTOR_BODY28]], !llvm.loop [[LOOP8:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK34]]:
; CHECK-NEXT: [[TMP26:%.*]] = tail call i64 @llvm.experimental.vector.extract.last.active.v2i64(<2 x i64> [[TMP24]], <2 x i1> [[TMP23]], i64 [[TMP0]])
; CHECK-NEXT: [[CMP_N35:%.*]] = icmp eq i64 [[TMP28]], [[N_VEC21]]
; CHECK-NEXT: br i1 [[CMP_N35]], label %[[RET]], label %[[LOOP2_BODY_PREHEADER]]
; CHECK: [[LOOP2_BODY_PREHEADER]]:
; CHECK-NEXT: [[RES12_PH:%.*]] = phi i64 [ [[TMP0]], %[[VECTOR_MEMCHECK]] ], [ [[TMP0]], %[[LOOP2_BODY_LR_PH]] ], [ [[TMP26]], %[[MIDDLE_BLOCK34]] ]
; CHECK-NEXT: [[IT2_010_PH:%.*]] = phi ptr [ [[BASE]], %[[VECTOR_MEMCHECK]] ], [ [[BASE]], %[[LOOP2_BODY_LR_PH]] ], [ [[TMP11]], %[[MIDDLE_BLOCK34]] ]
; CHECK-NEXT: br label %[[LOOP2_BODY:.*]]
; CHECK: [[LOOP1_INC]]:
; CHECK-NEXT: [[R8:%.*]] = phi i64 [ [[SEL]], %[[LOOP1_INC]] ], [ [[R8_PH]], %[[LOOP1_INC_PREHEADER41]] ]
; CHECK-NEXT: [[IT1_07:%.*]] = phi ptr [ [[NEXT_I:%.*]], %[[LOOP1_INC]] ], [ [[IT1_07_PH]], %[[LOOP1_INC_PREHEADER41]] ]
; CHECK-NEXT: [[GT:%.*]] = icmp ugt i64 [[N_FR]], [[R8]]
; CHECK-NEXT: [[SEL]] = select i1 [[GT]], i64 0, i64 [[R8]]
; CHECK-NEXT: [[NEXT_I]] = getelementptr nusw nuw i8, ptr [[IT1_07]], i64 48
; CHECK-NEXT: [[NE_I_NOT:%.*]] = icmp eq ptr [[NEXT_I]], @end
; CHECK-NEXT: br i1 [[NE_I_NOT]], label %[[LOOP2_BODY_LR_PH]], label %[[LOOP1_INC]], !llvm.loop [[LOOP9:![0-9]+]]
; CHECK: [[RET]]:
; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[TMP0]], %[[ENTRY]] ], [ [[TMP26]], %[[MIDDLE_BLOCK34]] ], [ [[RES11:%.*]], %[[LOOP2_INC:.*]] ]
; CHECK-NEXT: ret i64 [[RES]]
; CHECK: [[LOOP2_BODY]]:
; CHECK-NEXT: [[RES12:%.*]] = phi i64 [ [[RES11]], %[[LOOP2_INC]] ], [ [[RES12_PH]], %[[LOOP2_BODY_PREHEADER]] ]
; CHECK-NEXT: [[IT2_010:%.*]] = phi ptr [ [[NEXT_I5:%.*]], %[[LOOP2_INC]] ], [ [[IT2_010_PH]], %[[LOOP2_BODY_PREHEADER]] ]
; CHECK-NEXT: [[CMP_VAL_I:%.*]] = load i64, ptr [[CMP]], align 8
; CHECK-NEXT: [[CMP_F_I:%.*]] = uitofp i64 [[CMP_VAL_I]] to double
; CHECK-NEXT: [[PROD_I:%.*]] = fmul nnan double [[TMP9]], [[CMP_F_I]]
; CHECK-NEXT: [[OLE_I:%.*]] = fcmp ugt double [[PROD_I]], 0.000000e+00
; CHECK-NEXT: br i1 [[OLE_I]], label %[[CLEAR:.*]], label %[[LOOP2_INC]]
; CHECK: [[CLEAR]]:
; CHECK-NEXT: store i64 0, ptr [[BASE]], align 8
; CHECK-NEXT: br label %[[LOOP2_INC]]
; CHECK: [[LOOP2_INC]]:
; CHECK-NEXT: [[RES11]] = phi i64 [ 0, %[[CLEAR]] ], [ [[RES12]], %[[LOOP2_BODY]] ]
; CHECK-NEXT: [[NEXT_I5]] = getelementptr nusw nuw i8, ptr [[IT2_010]], i64 48
; CHECK-NEXT: [[NE_I3_NOT:%.*]] = icmp eq ptr [[NEXT_I5]], @end
; CHECK-NEXT: br i1 [[NE_I3_NOT]], label %[[RET]], label %[[LOOP2_BODY]], !llvm.loop [[LOOP10:![0-9]+]]
;
entry:
%it1 = alloca ptr, align 8
%lam = alloca i64, align 8
%it2 = alloca ptr, align 8
store ptr %base, ptr %it1, align 8
store ptr %base, ptr %base, align 8
br label %loop1
loop1:
%r = phi i64 [ 1, %entry ], [ %sel, %loop1.inc ]
%ne1 = call i1 @iter_ne(ptr %it1)
br i1 %ne1, label %loop1.inc, label %between
loop1.inc:
%gt = icmp ugt i64 %n, %r
%sel = select i1 %gt, i64 0, i64 %r
%adv1 = call ptr @iter_inc(ptr %it1)
br label %loop1
between:
store i64 %r, ptr %lam, align 8
store ptr %base, ptr %it2, align 8
br label %loop2
loop2:
%ne2 = call i1 @iter_ne(ptr %it2)
br i1 %ne2, label %loop2.body, label %ret
ret:
%res = load i64, ptr %base, align 8
ret i64 %res
loop2.body:
%pred = call i1 @lambda(ptr %lam, ptr %cmp)
br i1 %pred, label %loop2.inc, label %clear
clear:
store i64 0, ptr %base, align 8
br label %loop2.inc
loop2.inc:
%adv2 = call ptr @iter_inc(ptr %it2)
br label %loop2
}
define i1 @iter_ne(ptr %it) {
; CHECK-LABEL: define i1 @iter_ne(
; CHECK-SAME: ptr nofree readonly captures(none) [[IT:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
; CHECK-NEXT: [[CUR:%.*]] = load ptr, ptr [[IT]], align 8
; CHECK-NEXT: [[NE:%.*]] = icmp ne ptr [[CUR]], @end
; CHECK-NEXT: ret i1 [[NE]]
;
%cur = load ptr, ptr %it, align 8
%ne = icmp ne ptr %cur, @end
ret i1 %ne
}
define ptr @iter_inc(ptr %it) {
; CHECK-LABEL: define noalias noundef ptr @iter_inc(
; CHECK-SAME: ptr nofree captures(none) [[IT:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
; CHECK-NEXT: [[CUR:%.*]] = load ptr, ptr [[IT]], align 8
; CHECK-NEXT: [[NEXT:%.*]] = getelementptr nusw nuw i8, ptr [[CUR]], i64 48
; CHECK-NEXT: store ptr [[NEXT]], ptr [[IT]], align 8
; CHECK-NEXT: ret ptr null
;
%cur = load ptr, ptr %it, align 8
%next = getelementptr nusw i8, ptr %cur, i64 48
store ptr %next, ptr %it, align 8
ret ptr null
}
define i1 @lambda(ptr %lam, ptr %cmp) {
; CHECK-LABEL: define i1 @lambda(
; CHECK-SAME: ptr nofree readonly captures(none) [[LAM:%.*]], ptr nofree readonly captures(none) [[CMP:%.*]]) local_unnamed_addr #[[ATTR3]] {
; CHECK-NEXT: [[CMP_VAL:%.*]] = load i64, ptr [[CMP]], align 8
; CHECK-NEXT: [[CMP_F:%.*]] = uitofp i64 [[CMP_VAL]] to double
; CHECK-NEXT: [[LAM_VAL:%.*]] = load i64, ptr [[LAM]], align 8
; CHECK-NEXT: [[LAM_F:%.*]] = uitofp i64 [[LAM_VAL]] to double
; CHECK-NEXT: [[PROD:%.*]] = fmul nnan double [[CMP_F]], [[LAM_F]]
; CHECK-NEXT: [[OLE:%.*]] = fcmp ole double [[PROD]], 0.000000e+00
; CHECK-NEXT: ret i1 [[OLE]]
;
%cmp.val = load i64, ptr %cmp, align 8
%cmp.f = uitofp i64 %cmp.val to double
%lam.val = load i64, ptr %lam, align 8
%lam.f = uitofp i64 %lam.val to double
%prod = fmul double %cmp.f, %lam.f
%ole = fcmp ole double %prod, 0.000000e+00
ret i1 %ole
}
define ptr @gep_base_cancel(ptr %p, ptr %end, ptr noalias %a) {
; CHECK-LABEL: define noundef ptr @gep_base_cancel(
; CHECK-SAME: ptr nofree readonly captures(address) [[P:%.*]], ptr nofree readnone captures(address) [[END:%.*]], ptr noalias nofree captures(address, ret: address, provenance) [[A:%.*]]) local_unnamed_addr #[[ATTR4:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[IN_BOUNDS6:%.*]] = icmp ult ptr [[P]], [[END]]
; CHECK-NEXT: br i1 [[IN_BOUNDS6]], label %[[BODY_PREHEADER:.*]], label %[[COMMON_RET:.*]]
; CHECK: [[BODY_PREHEADER]]:
; CHECK-NEXT: [[END15:%.*]] = ptrtoaddr ptr [[END]] to i64
; CHECK-NEXT: [[P16:%.*]] = ptrtoaddr ptr [[P]] to i64
; CHECK-NEXT: [[TMP0:%.*]] = xor i64 [[P16]], -1
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], [[END15]]
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP1]]
; CHECK-NEXT: [[CHAR_PEEL:%.*]] = load i8, ptr [[P]], align 1
; CHECK-NEXT: switch i8 [[CHAR_PEEL]], label %[[TRAP:.*]] [
; CHECK-NEXT: i8 33, label %[[ADVANCE_PEEL:.*]]
; CHECK-NEXT: i8 36, label %[[ADVANCE_PEEL]]
; CHECK-NEXT: ]
; CHECK: [[ADVANCE_PEEL]]:
; CHECK-NEXT: [[EXITCOND_PEEL_NOT:%.*]] = icmp eq i64 [[TMP1]], 0
; CHECK-NEXT: br i1 [[EXITCOND_PEEL_NOT]], label %[[COMMON_RET]], label %[[BODY:.*]]
; CHECK: [[COMMON_RET]]:
; CHECK-NEXT: [[RET_KNOWN_TR3:%.*]] = phi ptr [ [[A_TR9_LCSSA:%.*]], %[[TRAP]] ], [ null, %[[ENTRY]] ], [ null, %[[ADVANCE_PEEL]] ], [ null, %[[ADVANCE:.*]] ]
; CHECK-NEXT: ret ptr [[RET_KNOWN_TR3]]
; CHECK: [[BODY]]:
; CHECK-NEXT: [[P_TR7_PN:%.*]] = phi ptr [ [[P_TR7:%.*]], %[[ADVANCE]] ], [ [[P]], %[[ADVANCE_PEEL]] ]
; CHECK-NEXT: [[P_TR7]] = getelementptr i8, ptr [[P_TR7_PN]], i64 1
; CHECK-NEXT: [[CHAR:%.*]] = load i8, ptr [[P_TR7]], align 1
; CHECK-NEXT: switch i8 [[CHAR]], label %[[TRAP]] [
; CHECK-NEXT: i8 33, label %[[ADVANCE]]
; CHECK-NEXT: i8 36, label %[[ADVANCE]]
; CHECK-NEXT: ]
; CHECK: [[ADVANCE]]:
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq ptr [[P_TR7]], [[SCEVGEP]]
; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[COMMON_RET]], label %[[BODY]], !llvm.loop [[LOOP11:![0-9]+]]
; CHECK: [[TRAP]]:
; CHECK-NEXT: [[A_TR9_LCSSA]] = phi ptr [ [[A]], %[[BODY_PREHEADER]] ], [ null, %[[BODY]] ]
; CHECK-NEXT: store volatile i32 0, ptr [[A_TR9_LCSSA]], align 4
; CHECK-NEXT: br label %[[COMMON_RET]]
;
entry:
%in.bounds = icmp ult ptr %p, %end
br i1 %in.bounds, label %body, label %common.ret
common.ret:
%ret = phi ptr [ %a, %trap ], [ null, %recurse ], [ null, %advance ], [ null, %entry ]
ret ptr %ret
body:
%char = load i8, ptr %p, align 1
switch i8 %char, label %trap [
i8 33, label %advance
i8 36, label %advance
]
advance:
%p.next = getelementptr i8, ptr %p, i64 1
%next.in.bounds = icmp ult ptr %p.next, %end
br i1 %next.in.bounds, label %recurse, label %common.ret
recurse:
%rec = call ptr @gep_base_cancel(ptr %p.next, ptr %end)
br label %common.ret
trap:
store volatile i32 0, ptr %a, align 4
br label %common.ret
}