| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: opt -p loop-idiom -S %s | FileCheck %s |
| |
| target datalayout = "e-m:e-i64:64-i128:128-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2" |
| |
| declare void @foo() |
| declare void @bar() |
| |
| define void @scev_expand_ptrtoint(i8 %x, ptr %start) { |
| ; CHECK-LABEL: define void @scev_expand_ptrtoint( |
| ; CHECK-SAME: i8 [[X:%.*]], ptr [[START:%.*]]) { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: [[START1:%.*]] = ptrtoint ptr [[START]] to i64 |
| ; CHECK-NEXT: br label %[[LOOP_1_HEADER:.*]] |
| ; CHECK: [[LOOP_1_HEADER]]: |
| ; CHECK-NEXT: [[PTR_IV_1:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[PTR_IV_1_NEXT:%.*]], %[[LOOP_1_LATCH:.*]] ] |
| ; CHECK-NEXT: [[C:%.*]] = icmp ule i8 [[X]], 1 |
| ; CHECK-NEXT: br i1 [[C]], label %[[LOOP_1_LATCH]], label %[[MIDDLE:.*]] |
| ; CHECK: [[LOOP_1_LATCH]]: |
| ; CHECK-NEXT: [[PTR_IV_1_NEXT]] = getelementptr i8, ptr [[PTR_IV_1]], i64 1 |
| ; CHECK-NEXT: br label %[[LOOP_1_HEADER]] |
| ; CHECK: [[MIDDLE]]: |
| ; CHECK-NEXT: [[PTR_IV_1_LCSSA:%.*]] = phi ptr [ [[PTR_IV_1]], %[[LOOP_1_HEADER]] ] |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 0 |
| ; CHECK-NEXT: [[CMP_EXT:%.*]] = zext i1 [[CMP]] to i64 |
| ; CHECK-NEXT: [[GEP_START:%.*]] = getelementptr i8, ptr [[PTR_IV_1_LCSSA]], i64 [[CMP_EXT]] |
| ; CHECK-NEXT: br label %[[LOOP_2_HEADER:.*]] |
| ; CHECK: [[LOOP_2_HEADER]]: |
| ; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], %[[LOOP_2_LATCH:.*]] ], [ 0, %[[MIDDLE]] ] |
| ; CHECK-NEXT: [[PTR_IV_2:%.*]] = phi ptr [ [[GEP_START]], %[[MIDDLE]] ], [ [[PTR_IV_2_NEXT:%.*]], %[[LOOP_2_LATCH]] ] |
| ; CHECK-NEXT: switch i8 [[X]], label %[[LOOP_2_LATCH]] [ |
| ; CHECK-NEXT: i8 1, label %[[LOOP_3_PREHEADER:.*]] |
| ; CHECK-NEXT: i8 4, label %[[LOOP_3_PREHEADER]] |
| ; CHECK-NEXT: ] |
| ; CHECK: [[LOOP_3_PREHEADER]]: |
| ; CHECK-NEXT: [[INDVAR_LCSSA:%.*]] = phi i64 [ [[INDVAR]], %[[LOOP_2_HEADER]] ], [ [[INDVAR]], %[[LOOP_2_HEADER]] ] |
| ; CHECK-NEXT: [[PTR_IV_2_LCSSA:%.*]] = phi ptr [ [[PTR_IV_2]], %[[LOOP_2_HEADER]] ], [ [[PTR_IV_2]], %[[LOOP_2_HEADER]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = sub i64 1, [[START1]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR_IV_1_LCSSA]] to i64 |
| ; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[TMP0]] |
| ; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[CMP_EXT]], [[TMP2]] |
| ; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[INDVAR_LCSSA]], [[TMP4]] |
| ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP5]] |
| ; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(ptr [[SCEVGEP]]) |
| ; CHECK-NEXT: br label %[[LOOP_3:.*]] |
| ; CHECK: [[LOOP_2_LATCH]]: |
| ; CHECK-NEXT: [[PTR_IV_2_NEXT]] = getelementptr i8, ptr [[PTR_IV_2]], i64 1 |
| ; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 |
| ; CHECK-NEXT: br label %[[LOOP_2_HEADER]] |
| ; CHECK: [[LOOP_3]]: |
| ; CHECK-NEXT: [[IV_3:%.*]] = phi i64 [ [[IV_3_NEXT:%.*]], %[[LOOP_3]] ], [ 1, %[[LOOP_3_PREHEADER]] ] |
| ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[PTR_IV_2_LCSSA]], i64 [[IV_3]] |
| ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[GEP]], align 1 |
| ; CHECK-NEXT: [[EC:%.*]] = icmp eq i8 [[TMP6]], 0 |
| ; CHECK-NEXT: [[IV_3_NEXT]] = add i64 [[IV_3]], 1 |
| ; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP_3]] |
| ; CHECK: [[EXIT]]: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %loop.1.header |
| |
| loop.1.header: |
| %ptr.iv.1 = phi ptr [ %start, %entry ], [ %ptr.iv.1.next, %loop.1.latch ] |
| %c = icmp ule i8 %x, 1 |
| br i1 %c, label %loop.1.latch, label %middle |
| |
| loop.1.latch: |
| %ptr.iv.1.next = getelementptr i8, ptr %ptr.iv.1, i64 1 |
| br label %loop.1.header |
| |
| middle: |
| %cmp = icmp eq i8 %x, 0 |
| %cmp.ext = zext i1 %cmp to i64 |
| %gep.start = getelementptr i8, ptr %ptr.iv.1, i64 %cmp.ext |
| br label %loop.2.header |
| |
| loop.2.header: |
| %ptr.iv.2 = phi ptr [ %gep.start, %middle ], [ %ptr.iv.2.next, %loop.2.latch ] |
| switch i8 %x, label %loop.2.latch [ |
| i8 1, label %loop.3 |
| i8 4, label %loop.3 |
| ] |
| |
| loop.2.latch: |
| %ptr.iv.2.next = getelementptr i8, ptr %ptr.iv.2, i64 1 |
| br label %loop.2.header |
| |
| loop.3: |
| %iv.3 = phi i64 [ 1, %loop.2.header ], [ 1, %loop.2.header ], [ %iv.3.next, %loop.3 ] |
| %gep = getelementptr i8, ptr %ptr.iv.2, i64 %iv.3 |
| %1 = load i8, ptr %gep, align 1 |
| %ec = icmp eq i8 %1, 0 |
| %iv.3.next = add i64 %iv.3, 1 |
| br i1 %ec, label %exit, label %loop.3 |
| |
| exit: |
| ret void |
| } |
| |
| declare i1 @cond() |
| |
| define ptr @test_lcssa_reuse_preserve_lcssa() { |
| ; CHECK-LABEL: define ptr @test_lcssa_reuse_preserve_lcssa() { |
| ; CHECK-NEXT: [[ENTRY:.*:]] |
| ; CHECK-NEXT: br label %[[LOOP_0_HEADER:.*]] |
| ; CHECK: [[LOOP_0_HEADER]]: |
| ; CHECK-NEXT: br label %[[LOOP_1:.*]] |
| ; CHECK: [[LOOP_1]]: |
| ; CHECK-NEXT: [[IV_1:%.*]] = phi ptr [ null, %[[LOOP_0_HEADER]] ], [ [[IV_1_NEXT:%.*]], %[[LOOP_1]] ] |
| ; CHECK-NEXT: [[IV_1_NEXT]] = getelementptr i8, ptr [[IV_1]], i64 1 |
| ; CHECK-NEXT: [[EC_1:%.*]] = call i1 @cond() |
| ; CHECK-NEXT: br i1 [[EC_1]], label %[[THEN:.*]], label %[[LOOP_1]] |
| ; CHECK: [[THEN]]: |
| ; CHECK-NEXT: [[IV_1_LCSSA1:%.*]] = phi ptr [ [[IV_1]], %[[LOOP_1]] ] |
| ; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; CHECK-NEXT: br i1 [[C_2]], label %[[LOOP_2_PREHEADER:.*]], label %[[LOOP_0_LATCH:.*]] |
| ; CHECK: [[LOOP_2_PREHEADER]]: |
| ; CHECK-NEXT: [[IV_1_LCSSA:%.*]] = phi ptr [ [[IV_1_LCSSA1]], %[[THEN]] ] |
| ; CHECK-NEXT: [[IV_1_LCSSA_LCSSA:%.*]] = phi ptr [ [[IV_1_LCSSA1]], %[[THEN]] ] |
| ; CHECK-NEXT: [[STRLEN:%.*]] = call i64 @strlen(ptr null) |
| ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[IV_1_LCSSA]], i64 1 |
| ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 [[STRLEN]] |
| ; CHECK-NEXT: br label %[[LOOP_2:.*]] |
| ; CHECK: [[LOOP_2]]: |
| ; CHECK-NEXT: [[IV_2:%.*]] = phi ptr [ [[RES:%.*]], %[[LOOP_2]] ], [ [[IV_1_LCSSA_LCSSA]], %[[LOOP_2_PREHEADER]] ] |
| ; CHECK-NEXT: [[RES]] = getelementptr i8, ptr [[IV_2]], i64 1 |
| ; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[IV_1_LCSSA_LCSSA]], align 1 |
| ; CHECK-NEXT: [[EC_2:%.*]] = icmp eq i8 [[L]], 0 |
| ; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP_2]] |
| ; CHECK: [[LOOP_0_LATCH]]: |
| ; CHECK-NEXT: br label %[[LOOP_0_HEADER]] |
| ; CHECK: [[EXIT]]: |
| ; CHECK-NEXT: ret ptr [[SCEVGEP]] |
| ; |
| entry: |
| br label %loop.0.header |
| |
| loop.0.header: |
| br label %loop.1 |
| |
| loop.1: |
| %iv.1 = phi ptr [ null, %loop.0.header ], [ %iv.1.next, %loop.1 ] |
| %iv.1.next = getelementptr i8, ptr %iv.1, i64 1 |
| %ec.1 = call i1 @cond() |
| br i1 %ec.1, label %then, label %loop.1 |
| |
| then: |
| %c.2 = call i1 @cond() |
| br i1 %c.2, label %loop.2, label %loop.0.latch |
| |
| loop.2: |
| %iv.2 = phi ptr [ %res, %loop.2 ], [ %iv.1, %then ] |
| %res = getelementptr i8, ptr %iv.2, i64 1 |
| %l = load i8, ptr %iv.1, align 1 |
| %ec.2 = icmp eq i8 %l, 0 |
| br i1 %ec.2, label %exit, label %loop.2 |
| |
| loop.0.latch: |
| br label %loop.0.header |
| |
| exit: |
| ret ptr %res |
| } |
| |
| ; Test case for https://github.com/llvm/llvm-project/issues/155287. |
| ; Make sure we don't crash when trying to construct a PtrToInt SCEV expression |
| ; results in SCEVCouldNotCompute. |
| define void @phi_ptr_addressspace_ptrtoint_fail(ptr addrspace(1) %arg) { |
| ; CHECK-LABEL: define void @phi_ptr_addressspace_ptrtoint_fail( |
| ; CHECK-SAME: ptr addrspace(1) [[ARG:%.*]]) { |
| ; CHECK-NEXT: [[BB:.*]]: |
| ; CHECK-NEXT: br label %[[LOOP_1:.*]] |
| ; CHECK: [[LOOP_1]]: |
| ; CHECK-NEXT: [[IV_1:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[ADD5:%.*]], %[[LOOP_1]] ] |
| ; CHECK-NEXT: [[ADD5]] = add i64 [[IV_1]], 1 |
| ; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i16, ptr addrspace(1) [[ARG]], i64 [[ADD5]] |
| ; CHECK-NEXT: br i1 false, label %[[LOOP_1]], label %[[LOOP_2_PH:.*]] |
| ; CHECK: [[LOOP_2_PH]]: |
| ; CHECK-NEXT: [[IV_1_LCSSA1:%.*]] = phi i64 [ [[IV_1]], %[[LOOP_1]] ] |
| ; CHECK-NEXT: [[IV_1_LCSSA:%.*]] = phi i64 [ [[IV_1]], %[[LOOP_1]] ] |
| ; CHECK-NEXT: [[PHI:%.*]] = phi ptr addrspace(1) [ [[GETELEMENTPTR]], %[[LOOP_1]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = shl nuw nsw i64 [[IV_1_LCSSA1]], 2 |
| ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr addrspace(1) [[ARG]], i64 [[TMP0]] |
| ; CHECK-NEXT: call void @llvm.memset.p1.i64(ptr addrspace(1) align 4 [[SCEVGEP]], i8 0, i64 8, i1 false) |
| ; CHECK-NEXT: br label %[[LOOP_2_HEADER:.*]] |
| ; CHECK: [[LOOP_2_HEADER]]: |
| ; CHECK-NEXT: [[IV_2:%.*]] = phi i64 [ [[IV_1_LCSSA]], %[[LOOP_2_PH]] ], [ [[IV_2_NEXT:%.*]], %[[LOOP_2_LATCH:.*]] ] |
| ; CHECK-NEXT: [[GREP_ARG:%.*]] = getelementptr i32, ptr addrspace(1) [[ARG]], i64 [[IV_2]] |
| ; CHECK-NEXT: [[EC:%.*]] = icmp ult i64 [[IV_2]], 1 |
| ; CHECK-NEXT: br i1 [[EC]], label %[[LOOP_2_LATCH]], label %[[EXIT:.*]] |
| ; CHECK: [[LOOP_2_LATCH]]: |
| ; CHECK-NEXT: [[IV_2_NEXT]] = add i64 [[IV_2]], 1 |
| ; CHECK-NEXT: br label %[[LOOP_2_HEADER]] |
| ; CHECK: [[EXIT]]: |
| ; CHECK-NEXT: ret void |
| ; |
| bb: |
| br label %loop.1 |
| |
| loop.1: |
| %iv.1 = phi i64 [ 0, %bb ], [ %add5, %loop.1] |
| %add5 = add i64 %iv.1, 1 |
| %getelementptr = getelementptr i16, ptr addrspace(1) %arg, i64 %add5 |
| br i1 false, label %loop.1, label %loop.2.ph |
| |
| loop.2.ph: |
| %phi = phi ptr addrspace(1) [ %getelementptr, %loop.1] |
| br label %loop.2.header |
| |
| loop.2.header: |
| %iv.2 = phi i64 [ %iv.1, %loop.2.ph ], [ %iv.2.next, %loop.2.latch ] |
| %grep.arg = getelementptr i32, ptr addrspace(1) %arg, i64 %iv.2 |
| store i32 0, ptr addrspace(1) %grep.arg, align 4 |
| %ec = icmp ult i64 %iv.2, 1 |
| br i1 %ec, label %loop.2.latch, label %exit |
| |
| loop.2.latch: |
| %iv.2.next = add i64 %iv.2, 1 |
| br label %loop.2.header |
| |
| exit: |
| ret void |
| } |