| ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py |
| ; RUN: opt -passes='print<scalar-evolution>' -disable-output %s 2>&1 | FileCheck %s |
| |
| target datalayout = "e-p:64:64:64-p1:128:128:128:64-pu2:64:64:64:64-pe3:64:64:64:64" |
| |
| ; Address space 1: integral fat pointer, 128-bit representation, 64-bit address. |
| ; Address space 2: unstable representation (must stay SCEVUnknown). |
| ; Address space 3: external state but stable representation. |
| |
| ; The difference of two ptrtoints of a 128-bit fat pointer to i64 (the address |
| ; width) equals the difference of the addresses, so it can be modeled via |
| ; ptrtoaddr. |
| define i64 @sub_ptrtoint_fat_to_addrwidth(ptr addrspace(1) %p, ptr addrspace(1) %q) { |
| ; CHECK-LABEL: 'sub_ptrtoint_fat_to_addrwidth' |
| ; CHECK-NEXT: Classifying expressions for: @sub_ptrtoint_fat_to_addrwidth |
| ; CHECK-NEXT: %p.int = ptrtoint ptr addrspace(1) %p to i64 |
| ; CHECK-NEXT: --> %p.int U: full-set S: full-set |
| ; CHECK-NEXT: %q.int = ptrtoint ptr addrspace(1) %q to i64 |
| ; CHECK-NEXT: --> %q.int U: full-set S: full-set |
| ; CHECK-NEXT: %sub = sub i64 %p.int, %q.int |
| ; CHECK-NEXT: --> ((-1 * (ptrtoaddr ptr addrspace(1) %q to i64)) + (ptrtoaddr ptr addrspace(1) %p to i64)) U: full-set S: full-set |
| ; CHECK-NEXT: Determining loop execution counts for: @sub_ptrtoint_fat_to_addrwidth |
| ; |
| %p.int = ptrtoint ptr addrspace(1) %p to i64 |
| %q.int = ptrtoint ptr addrspace(1) %q to i64 |
| %sub = sub i64 %p.int, %q.int |
| ret i64 %sub |
| } |
| |
| ; ptrtoint to i128 (wider than the 64-bit address) cannot be modeled via |
| ; ptrtoaddr without losing the high bits, so it must stay opaque. |
| define i128 @sub_ptrtoint_fat_wider_than_addr(ptr addrspace(1) %p, ptr addrspace(1) %q) { |
| ; CHECK-LABEL: 'sub_ptrtoint_fat_wider_than_addr' |
| ; CHECK-NEXT: Classifying expressions for: @sub_ptrtoint_fat_wider_than_addr |
| ; CHECK-NEXT: %p.int = ptrtoint ptr addrspace(1) %p to i128 |
| ; CHECK-NEXT: --> %p.int U: full-set S: full-set |
| ; CHECK-NEXT: %q.int = ptrtoint ptr addrspace(1) %q to i128 |
| ; CHECK-NEXT: --> %q.int U: full-set S: full-set |
| ; CHECK-NEXT: %sub = sub i128 %p.int, %q.int |
| ; CHECK-NEXT: --> ((-1 * %q.int) + %p.int) U: full-set S: full-set |
| ; CHECK-NEXT: Determining loop execution counts for: @sub_ptrtoint_fat_wider_than_addr |
| ; |
| %p.int = ptrtoint ptr addrspace(1) %p to i128 |
| %q.int = ptrtoint ptr addrspace(1) %q to i128 |
| %sub = sub i128 %p.int, %q.int |
| ret i128 %sub |
| } |
| |
| ; Unstable representation: ptrtoaddr is not valid, so the difference must stay |
| ; opaque (SCEVUnknown for each ptrtoint). |
| define i64 @sub_ptrtoint_unstable(ptr addrspace(2) %p, ptr addrspace(2) %q) { |
| ; CHECK-LABEL: 'sub_ptrtoint_unstable' |
| ; CHECK-NEXT: Classifying expressions for: @sub_ptrtoint_unstable |
| ; CHECK-NEXT: %p.int = ptrtoint ptr addrspace(2) %p to i64 |
| ; CHECK-NEXT: --> %p.int U: full-set S: full-set |
| ; CHECK-NEXT: %q.int = ptrtoint ptr addrspace(2) %q to i64 |
| ; CHECK-NEXT: --> %q.int U: full-set S: full-set |
| ; CHECK-NEXT: %sub = sub i64 %p.int, %q.int |
| ; CHECK-NEXT: --> ((-1 * %q.int) + %p.int) U: full-set S: full-set |
| ; CHECK-NEXT: Determining loop execution counts for: @sub_ptrtoint_unstable |
| ; |
| %p.int = ptrtoint ptr addrspace(2) %p to i64 |
| %q.int = ptrtoint ptr addrspace(2) %q to i64 |
| %sub = sub i64 %p.int, %q.int |
| ret i64 %sub |
| } |
| |
| ; External state but stable representation: the address bits can be extracted |
| ; via ptrtoaddr, so the difference can be modeled. |
| define i64 @sub_ptrtoint_external_state(ptr addrspace(3) %p, ptr addrspace(3) %q) { |
| ; CHECK-LABEL: 'sub_ptrtoint_external_state' |
| ; CHECK-NEXT: Classifying expressions for: @sub_ptrtoint_external_state |
| ; CHECK-NEXT: %p.int = ptrtoint ptr addrspace(3) %p to i64 |
| ; CHECK-NEXT: --> %p.int U: full-set S: full-set |
| ; CHECK-NEXT: %q.int = ptrtoint ptr addrspace(3) %q to i64 |
| ; CHECK-NEXT: --> %q.int U: full-set S: full-set |
| ; CHECK-NEXT: %sub = sub i64 %p.int, %q.int |
| ; CHECK-NEXT: --> ((-1 * (ptrtoaddr ptr addrspace(3) %q to i64)) + (ptrtoaddr ptr addrspace(3) %p to i64)) U: full-set S: full-set |
| ; CHECK-NEXT: Determining loop execution counts for: @sub_ptrtoint_external_state |
| ; |
| %p.int = ptrtoint ptr addrspace(3) %p to i64 |
| %q.int = ptrtoint ptr addrspace(3) %q to i64 |
| %sub = sub i64 %p.int, %q.int |
| ret i64 %sub |
| } |
| |
| ; ptrtoint of a pointer add-rec to the address width is modeled via ptrtoaddr. |
| define void @ptrtoint_addrec_fat_to_addrwidth(ptr addrspace(1) %in) { |
| ; CHECK-LABEL: 'ptrtoint_addrec_fat_to_addrwidth' |
| ; CHECK-NEXT: Classifying expressions for: @ptrtoint_addrec_fat_to_addrwidth |
| ; CHECK-NEXT: %iv = phi ptr addrspace(1) [ %in, %entry ], [ %iv.next, %loop ] |
| ; CHECK-NEXT: --> {%in,+,4}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable } |
| ; CHECK-NEXT: %iv.int = ptrtoint ptr addrspace(1) %iv to i64 |
| ; CHECK-NEXT: --> {(ptrtoaddr ptr addrspace(1) %in to i64),+,4}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable } |
| ; CHECK-NEXT: %iv.next = getelementptr inbounds i32, ptr addrspace(1) %iv, i64 1 |
| ; CHECK-NEXT: --> {(4 + %in),+,4}<nw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable } |
| ; CHECK-NEXT: %c = call i1 @cond() |
| ; CHECK-NEXT: --> %c U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant } |
| ; CHECK-NEXT: Determining loop execution counts for: @ptrtoint_addrec_fat_to_addrwidth |
| ; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. |
| ; CHECK-NEXT: Loop %loop: Unpredictable constant max backedge-taken count. |
| ; CHECK-NEXT: Loop %loop: Unpredictable symbolic max backedge-taken count. |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi ptr addrspace(1) [ %in, %entry ], [ %iv.next, %loop ] |
| %iv.int = ptrtoint ptr addrspace(1) %iv to i64 |
| %iv.next = getelementptr inbounds i32, ptr addrspace(1) %iv, i64 1 |
| %c = call i1 @cond() |
| br i1 %c, label %loop, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; ptrtoint of a pointer add-rec on an unstable pointer must stay opaque. |
| define void @ptrtoint_addrec_unstable(ptr addrspace(2) %in) { |
| ; CHECK-LABEL: 'ptrtoint_addrec_unstable' |
| ; CHECK-NEXT: Classifying expressions for: @ptrtoint_addrec_unstable |
| ; CHECK-NEXT: %iv = phi ptr addrspace(2) [ %in, %entry ], [ %iv.next, %loop ] |
| ; CHECK-NEXT: --> {%in,+,4}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable } |
| ; CHECK-NEXT: %iv.int = ptrtoint ptr addrspace(2) %iv to i64 |
| ; CHECK-NEXT: --> %iv.int U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant } |
| ; CHECK-NEXT: %iv.next = getelementptr inbounds i32, ptr addrspace(2) %iv, i64 1 |
| ; CHECK-NEXT: --> {(4 + %in),+,4}<nw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable } |
| ; CHECK-NEXT: %c = call i1 @cond() |
| ; CHECK-NEXT: --> %c U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant } |
| ; CHECK-NEXT: Determining loop execution counts for: @ptrtoint_addrec_unstable |
| ; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. |
| ; CHECK-NEXT: Loop %loop: Unpredictable constant max backedge-taken count. |
| ; CHECK-NEXT: Loop %loop: Unpredictable symbolic max backedge-taken count. |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi ptr addrspace(2) [ %in, %entry ], [ %iv.next, %loop ] |
| %iv.int = ptrtoint ptr addrspace(2) %iv to i64 |
| %iv.next = getelementptr inbounds i32, ptr addrspace(2) %iv, i64 1 |
| %c = call i1 @cond() |
| br i1 %c, label %loop, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| ; ptrtoint to i32 (narrower than the 64-bit address). |
| define i32 @sub_ptrtoint_narrower_than_addr(ptr addrspace(1) %p, ptr addrspace(1) %q) { |
| ; CHECK-LABEL: 'sub_ptrtoint_narrower_than_addr' |
| ; CHECK-NEXT: Classifying expressions for: @sub_ptrtoint_narrower_than_addr |
| ; CHECK-NEXT: %p.int = ptrtoint ptr addrspace(1) %p to i32 |
| ; CHECK-NEXT: --> %p.int U: full-set S: full-set |
| ; CHECK-NEXT: %q.int = ptrtoint ptr addrspace(1) %q to i32 |
| ; CHECK-NEXT: --> %q.int U: full-set S: full-set |
| ; CHECK-NEXT: %sub = sub i32 %p.int, %q.int |
| ; CHECK-NEXT: --> ((trunc i64 (ptrtoaddr ptr addrspace(1) %p to i64) to i32) + (-1 * (trunc i64 (ptrtoaddr ptr addrspace(1) %q to i64) to i32))) U: full-set S: full-set |
| ; CHECK-NEXT: Determining loop execution counts for: @sub_ptrtoint_narrower_than_addr |
| ; |
| %p.int = ptrtoint ptr addrspace(1) %p to i32 |
| %q.int = ptrtoint ptr addrspace(1) %q to i32 |
| %sub = sub i32 %p.int, %q.int |
| ret i32 %sub |
| } |
| |
| ; The backedge-taken count of a loop iterating over a 128 bit fat pointer. |
| define void @fat_ptr_ult_backedge_count(ptr addrspace(1) %start, ptr addrspace(1) %end) { |
| ; CHECK-LABEL: 'fat_ptr_ult_backedge_count' |
| ; CHECK-NEXT: Classifying expressions for: @fat_ptr_ult_backedge_count |
| ; CHECK-NEXT: %iv = phi ptr addrspace(1) [ %start, %entry ], [ %iv.next, %loop ] |
| ; CHECK-NEXT: --> {%start,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * ((-1 + (-1 * (ptrtoaddr ptr addrspace(1) %start to i64)) + ((4 + (ptrtoaddr ptr addrspace(1) %start to i64))<nuw> umax (ptrtoaddr ptr addrspace(1) %end to i64))) /u 4))<nuw> + %start) LoopDispositions: { %loop: Computable } |
| ; CHECK-NEXT: %iv.next = getelementptr inbounds i32, ptr addrspace(1) %iv, i64 1 |
| ; CHECK-NEXT: --> {(4 + %start)<nuw>,+,4}<nuw><%loop> U: [4,0) S: [4,0) Exits: (4 + (4 * ((-1 + (-1 * (ptrtoaddr ptr addrspace(1) %start to i64)) + ((4 + (ptrtoaddr ptr addrspace(1) %start to i64))<nuw> umax (ptrtoaddr ptr addrspace(1) %end to i64))) /u 4))<nuw> + %start) LoopDispositions: { %loop: Computable } |
| ; CHECK-NEXT: Determining loop execution counts for: @fat_ptr_ult_backedge_count |
| ; CHECK-NEXT: Loop %loop: backedge-taken count is ((-1 + (-1 * (ptrtoaddr ptr addrspace(1) %start to i64)) + ((4 + (ptrtoaddr ptr addrspace(1) %start to i64))<nuw> umax (ptrtoaddr ptr addrspace(1) %end to i64))) /u 4) |
| ; CHECK-NEXT: Loop %loop: constant max backedge-taken count is i64 4611686018427387902 |
| ; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-1 + (-1 * (ptrtoaddr ptr addrspace(1) %start to i64)) + ((4 + (ptrtoaddr ptr addrspace(1) %start to i64))<nuw> umax (ptrtoaddr ptr addrspace(1) %end to i64))) /u 4) |
| ; CHECK-NEXT: Loop %loop: Trip multiple is 1 |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi ptr addrspace(1) [ %start, %entry ], [ %iv.next, %loop ] |
| %iv.next = getelementptr inbounds i32, ptr addrspace(1) %iv, i64 1 |
| %c = icmp ult ptr addrspace(1) %iv.next, %end |
| br i1 %c, label %loop, label %exit |
| |
| exit: |
| ret void |
| } |
| |
| declare i1 @cond() |