blob: b9877f46189d8a1cdc057e7e91a15901f9ec34cc [file] [edit]
; 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()