| ; 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 |
| } |