
Similar to the non-ptr case, directly create the getelementptr instruction. Going through expandAddToGEP() no longer makes sense with opaque pointers, where generating the necessary instruction is trivial. This avoids recursive expansion of (the SCEV of) StepV while the IR is in an inconsistent state, in particular with an incomplete IV phi node, which utilities may not be prepared to deal with. Fixes https://github.com/llvm/llvm-project/issues/80954.
69 lines
2.9 KiB
LLVM
69 lines
2.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
|
|
; RUN: opt -S -passes=loop-idiom < %s | FileCheck %s
|
|
|
|
; Make sure this does not assert in SCEVExpander.
|
|
|
|
define void @test(ptr %p, i8 %arg, i64 %arg1, i32 %arg2) {
|
|
; CHECK-LABEL: define void @test(
|
|
; CHECK-SAME: ptr [[P:%.*]], i8 [[ARG:%.*]], i64 [[ARG1:%.*]], i32 [[ARG2:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[SEXT:%.*]] = sext i8 [[ARG]] to i64
|
|
; CHECK-NEXT: [[ADD:%.*]] = add i64 [[ARG1]], -1
|
|
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[ARG2]] to i64
|
|
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[ARG1]], [[TMP0]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[SEXT]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[TMP2]], -1
|
|
; CHECK-NEXT: [[TMP4:%.*]] = shl i64 [[TMP3]], 2
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[LOOP_IDIOM_IV:%.*]] = phi ptr [ [[SCEVGEP:%.*]], [[LATCH:%.*]] ], [ [[P]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[LATCH]] ], [ 0, [[ENTRY]] ]
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[IV_NEXT:%.*]], [[LATCH]] ]
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[ARG2]], [[ENTRY]] ], [ [[ADD9:%.*]], [[LATCH]] ]
|
|
; CHECK-NEXT: [[TMP5:%.*]] = shl i64 [[INDVAR]], 2
|
|
; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[TMP4]], [[TMP5]]
|
|
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[LOOP_IDIOM_IV]], i8 0, i64 0, i1 false)
|
|
; CHECK-NEXT: br label [[LOOP2:%.*]]
|
|
; CHECK: loop2:
|
|
; CHECK-NEXT: [[IV2:%.*]] = phi i64 [ [[IV2_NEXT:%.*]], [[LOOP2]] ], [ 0, [[LOOP]] ]
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr [4 x i8], ptr [[P]], i64 [[IV]], i64 [[IV2]]
|
|
; CHECK-NEXT: [[IV2_NEXT]] = add i64 [[IV2]], 1
|
|
; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[IV2_NEXT]], 0
|
|
; CHECK-NEXT: br i1 [[ICMP]], label [[LATCH]], label [[LOOP2]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: [[ADD9]] = add nsw i32 [[PHI]], 1
|
|
; CHECK-NEXT: [[SEXT10:%.*]] = sext i32 [[PHI]] to i64
|
|
; CHECK-NEXT: [[ADD11:%.*]] = add i64 [[ADD]], [[SEXT10]]
|
|
; CHECK-NEXT: [[ADD12:%.*]] = add i64 [[ADD11]], [[SEXT]]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[ADD12]], [[IV]]
|
|
; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1
|
|
; CHECK-NEXT: [[SCEVGEP]] = getelementptr i8, ptr [[LOOP_IDIOM_IV]], i64 [[TMP6]]
|
|
; CHECK-NEXT: br label [[LOOP]]
|
|
;
|
|
entry:
|
|
%sext = sext i8 %arg to i64
|
|
%add = add i64 %arg1, -1
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
|
|
%phi = phi i32 [ %arg2, %entry ], [ %add9, %latch ]
|
|
br label %loop2
|
|
|
|
loop2:
|
|
%iv2 = phi i64 [ %iv2.next, %loop2 ], [ 0, %loop ]
|
|
%gep = getelementptr [4 x i8], ptr %p, i64 %iv, i64 %iv2
|
|
store i8 0, ptr %gep, align 1
|
|
%iv2.next = add i64 %iv2, 1
|
|
%icmp = icmp eq i64 %iv2.next, 0
|
|
br i1 %icmp, label %latch, label %loop2
|
|
|
|
latch:
|
|
%add9 = add nsw i32 %phi, 1
|
|
%sext10 = sext i32 %phi to i64
|
|
%add11 = add i64 %add, %sext10
|
|
%add12 = add i64 %add11, %sext
|
|
%iv.next = add i64 %add12, %iv
|
|
br label %loop
|
|
}
|