When checking to see if we can apply IR flags to a SCEV, we need to identify a bound on the defining scope of the SCEV to be produced. We'd previously added support for a couple SCEVExpr types which trivially imply bounds, but hadn't handled types such as umax where the bounds come from the bounds of the operands. This does the obvious thing, and recurses through operands searching for a tighter bound on the defining scope. I'm honestly surprised by how little this seems to mater on existing tests, but it's worth doing for completeness sake alone. Differential Revision: https://reviews.llvm.org/D111191
1871 lines
95 KiB
LLVM
1871 lines
95 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py
|
|
; RUN: opt < %s -S -disable-output "-passes=print<scalar-evolution>" 2>&1 | FileCheck %s
|
|
|
|
; Positive and negative tests for inferring flags like nsw from
|
|
; reasoning about how a poison value from overflow would trigger
|
|
; undefined behavior.
|
|
|
|
define void @foo() {
|
|
; CHECK-LABEL: 'foo'
|
|
; CHECK-NEXT: Classifying expressions for: @foo
|
|
; CHECK-NEXT: Determining loop execution counts for: @foo
|
|
;
|
|
ret void
|
|
}
|
|
|
|
; Example where an add should get the nsw flag, so that a sext can be
|
|
; distributed over the add.
|
|
define void @test-add-nsw(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-nsw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-nsw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> {(sext i32 %offset to i64),+,1}<nsw><%loop> U: [-2147483648,6442450943) S: [-2147483648,6442450943) Exits: ((zext i32 (-1 + %numIterations) to i64) + (sext i32 %offset to i64)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {((4 * (sext i32 %offset to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %offset to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-nsw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
call void @foo()
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where an add should get the nuw flag.
|
|
define void @test-add-nuw(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-nuw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-nuw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nuw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,1}<nuw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-1 + %offset + %numIterations) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nuw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-nuw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nuw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nuw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Case where we're checking to see if add flags are valid in defining scope
|
|
; and all operands (other than addrec) are invariant
|
|
define void @test-add-scope-invariant(i32* %input, i32 %needle) {
|
|
; CHECK-LABEL: 'test-add-scope-invariant'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-scope-invariant
|
|
; CHECK-NEXT: %offset = load i32, i32* %input, align 4
|
|
; CHECK-NEXT: --> %offset U: full-set S: full-set
|
|
; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + (-1 * %offset) + %needle) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %i.next = add nuw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: ((-1 * %offset) + %needle) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %of_interest = add nuw nsw i32 %i.next, %offset
|
|
; CHECK-NEXT: --> {(1 + %offset)<nuw><nsw>,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %needle LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %gep2 = getelementptr i32, i32* %input, i32 %of_interest
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {(1 + %offset)<nuw><nsw>,+,1}<nuw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 %needle to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-scope-invariant
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %offset) + %needle)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + (-1 * %offset) + %needle)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
%offset = load i32, i32* %input
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
%i.next = add nuw i32 %i, 1
|
|
%of_interest = add nuw nsw i32 %i.next, %offset
|
|
%gep2 = getelementptr i32, i32* %input, i32 %of_interest
|
|
store i32 0, i32* %gep2
|
|
%exitcond = icmp eq i32 %of_interest, %needle
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Case where we're checking to see if add flags are valid in defining scope
|
|
; and other operands are *not* invariant.
|
|
define void @test-add-scope-bound(i32* %input, i32 %needle) {
|
|
; CHECK-LABEL: 'test-add-scope-bound'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-scope-bound
|
|
; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %gep = getelementptr i32, i32* %input, i32 %i
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {0,+,1}<nuw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %offset = load i32, i32* %gep, align 4
|
|
; CHECK-NEXT: --> %offset U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %i.next = add nuw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %of_interest = add nuw nsw i32 %i.next, %offset
|
|
; CHECK-NEXT: --> ({1,+,1}<nuw><%loop> + %offset)<nuw><nsw> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %gep2 = getelementptr i32, i32* %input, i32 %of_interest
|
|
; CHECK-NEXT: --> ((4 * ((sext i32 {1,+,1}<nuw><%loop> to i64) + (sext i32 %offset to i64))<nsw>)<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-scope-bound
|
|
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
%gep = getelementptr i32, i32* %input, i32 %i
|
|
%offset = load i32, i32* %gep
|
|
%i.next = add nuw i32 %i, 1
|
|
%of_interest = add nuw nsw i32 %i.next, %offset
|
|
%gep2 = getelementptr i32, i32* %input, i32 %of_interest
|
|
store i32 0, i32* %gep2
|
|
%exitcond = icmp eq i32 %of_interest, %needle
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test-add-scope-bound-unkn-preheader(i32* %input, i32 %needle) {
|
|
; CHECK-LABEL: 'test-add-scope-bound-unkn-preheader'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-scope-bound-unkn-preheader
|
|
; CHECK-NEXT: %offset = load i32, i32* %input, align 4
|
|
; CHECK-NEXT: --> %offset U: full-set S: full-set
|
|
; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,%offset}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %i.next = add nuw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,%offset}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,%offset}<nuw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-scope-bound-unkn-preheader
|
|
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
%offset = load i32, i32* %input
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
%i.next = add nuw i32 %i, %offset
|
|
%gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
store i32 0, i32* %gep2
|
|
%exitcond = icmp eq i32 %i.next, %needle
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test-add-scope-bound-unkn-preheader-neg1(i32* %input, i32 %needle) {
|
|
; CHECK-LABEL: 'test-add-scope-bound-unkn-preheader-neg1'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-scope-bound-unkn-preheader-neg1
|
|
; CHECK-NEXT: %offset = load i32, i32* %input, align 4
|
|
; CHECK-NEXT: --> %offset U: full-set S: full-set
|
|
; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,%offset}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %i.next = add nuw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,%offset}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,%offset}<nuw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-scope-bound-unkn-preheader-neg1
|
|
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
%offset = load i32, i32* %input
|
|
call void @foo()
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
%i.next = add nuw i32 %i, %offset
|
|
%gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
store i32 0, i32* %gep2
|
|
%exitcond = icmp eq i32 %i.next, %needle
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test-add-scope-bound-unkn-preheader-neg2(i32* %input, i32 %needle) {
|
|
; CHECK-LABEL: 'test-add-scope-bound-unkn-preheader-neg2'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-scope-bound-unkn-preheader-neg2
|
|
; CHECK-NEXT: %offset = load i32, i32* %input, align 4
|
|
; CHECK-NEXT: --> %offset U: full-set S: full-set
|
|
; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,%offset}<nuw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %i.next = add nuw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,%offset}<nw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,%offset}<nw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-scope-bound-unkn-preheader-neg2
|
|
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
%offset = load i32, i32* %input
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
call void @foo()
|
|
%i.next = add nuw i32 %i, %offset
|
|
%gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
store i32 0, i32* %gep2
|
|
%exitcond = icmp eq i32 %i.next, %needle
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
|
|
define void @test-add-scope-bound-unkn-header(i32* %input, i32 %needle) {
|
|
; CHECK-LABEL: 'test-add-scope-bound-unkn-header'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-scope-bound-unkn-header
|
|
; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> %i U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %gep = getelementptr i32, i32* %input, i32 %i
|
|
; CHECK-NEXT: --> ((4 * (sext i32 %i to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %offset = load i32, i32* %gep, align 4
|
|
; CHECK-NEXT: --> %offset U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %i.next = add nuw i32 %i, %offset
|
|
; CHECK-NEXT: --> (%offset + %i)<nuw> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
; CHECK-NEXT: --> ((4 * (sext i32 (%offset + %i)<nuw> to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-scope-bound-unkn-header
|
|
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
%gep = getelementptr i32, i32* %input, i32 %i
|
|
%offset = load i32, i32* %gep
|
|
%i.next = add nuw i32 %i, %offset
|
|
%gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
store i32 0, i32* %gep2
|
|
%exitcond = icmp eq i32 %i.next, %needle
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test-add-scope-bound-unkn-header2(i32* %input, i32 %needle) {
|
|
; CHECK-LABEL: 'test-add-scope-bound-unkn-header2'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-scope-bound-unkn-header2
|
|
; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> %i U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %gep = getelementptr i32, i32* %input, i32 %i
|
|
; CHECK-NEXT: --> ((4 * (sext i32 %i to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %offset = load i32, i32* %gep, align 4
|
|
; CHECK-NEXT: --> %offset U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %i.next = add nuw i32 %i, %offset
|
|
; CHECK-NEXT: --> (%offset + %i)<nuw> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
; CHECK-NEXT: --> ((4 * (sext i32 (%offset + %i)<nuw> to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-scope-bound-unkn-header2
|
|
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
call void @foo()
|
|
%gep = getelementptr i32, i32* %input, i32 %i
|
|
%offset = load i32, i32* %gep
|
|
%i.next = add nuw i32 %i, %offset
|
|
%gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
store i32 0, i32* %gep2
|
|
%exitcond = icmp eq i32 %i.next, %needle
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test-add-scope-bound-unkn-header-neg(i32* %input, i32 %needle) {
|
|
; CHECK-LABEL: 'test-add-scope-bound-unkn-header-neg'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-scope-bound-unkn-header-neg
|
|
; CHECK-NEXT: %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> %i U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %gep = getelementptr i32, i32* %input, i32 %i
|
|
; CHECK-NEXT: --> ((4 * (sext i32 %i to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %offset = load i32, i32* %gep, align 4
|
|
; CHECK-NEXT: --> %offset U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %i.next = add nuw i32 %i, %offset
|
|
; CHECK-NEXT: --> (%offset + %i) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
; CHECK-NEXT: --> ((4 * (sext i32 (%offset + %i) to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-scope-bound-unkn-header-neg
|
|
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
|
|
%gep = getelementptr i32, i32* %input, i32 %i
|
|
%offset = load i32, i32* %gep
|
|
call void @foo()
|
|
%i.next = add nuw i32 %i, %offset
|
|
%gep2 = getelementptr i32, i32* %input, i32 %i.next
|
|
store i32 0, i32* %gep2
|
|
%exitcond = icmp eq i32 %i.next, %needle
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test-add-nuw-from-icmp(float* %input, i32 %offset,
|
|
; CHECK-LABEL: 'test-add-nuw-from-icmp'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-nuw-from-icmp
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nuw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %cmp.idx = sext i1 %cmp to i32
|
|
; CHECK-NEXT: --> (sext i1 %cmp to i32) U: [-1,1) S: [-1,1) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %cmp.idx
|
|
; CHECK-NEXT: --> ((4 * (sext i1 %cmp to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %nexti = add nuw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-nuw-from-icmp
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
i32 %numIterations) {
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nuw i32 %i, %offset
|
|
%cmp = icmp sgt i32 %index32, 0
|
|
%cmp.idx = sext i1 %cmp to i32
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %cmp.idx
|
|
%nexti = add nuw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; With no load to trigger UB from poison, we cannot infer nsw.
|
|
define void @test-add-no-load(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-no-load'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-no-load
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,1}<nw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-1 + %offset + %numIterations) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nuw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-no-load
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nuw i32 %i, 1
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; The current code is only supposed to look at the loop header, so
|
|
; it should not infer nsw in this case, as that would require looking
|
|
; outside the loop header.
|
|
define void @test-add-not-header(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-not-header'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-not-header
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,1}<nw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-1 + %offset + %numIterations) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-not-header
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
br label %loop2
|
|
loop2:
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Same thing as test-add-not-header, but in this case only the load
|
|
; instruction is outside the loop header.
|
|
define void @test-add-not-header2(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-not-header2'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-not-header2
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> {((4 * (sext i32 %offset to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %offset to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-not-header2
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
br label %loop2
|
|
loop2:
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Similar to test-add-not-header, but in this case the load
|
|
; instruction may not be executed.
|
|
define void @test-add-not-header3(float* %input, i32 %offset, i32 %numIterations,
|
|
; CHECK-LABEL: 'test-add-not-header3'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-not-header3
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,1}<nw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %cond = load volatile i1, i1* %cond_buf, align 1
|
|
; CHECK-NEXT: --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-not-header3
|
|
; CHECK-NEXT: Loop %loop: <multiple exits> Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: exit count for loop: ***COULDNOTCOMPUTE***
|
|
; CHECK-NEXT: exit count for loop2: (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
i1* %cond_buf) {
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
%cond = load volatile i1, i1* %cond_buf
|
|
br i1 %cond, label %loop2, label %exit
|
|
loop2:
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Same thing as test-add-not-header2, except we have a few extra
|
|
; blocks.
|
|
define void @test-add-not-header4(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-not-header4'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-not-header4
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> {((4 * (sext i32 %offset to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %offset to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-not-header4
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
br label %loop3
|
|
loop3:
|
|
br label %loop4
|
|
loop4:
|
|
br label %loop2
|
|
loop2:
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Demonstrate why we need a Visited set in llvm::programUndefinedIfPoison.
|
|
define void @test-add-not-header5(float* %input, i32 %offset) {
|
|
; CHECK-LABEL: 'test-add-not-header5'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-not-header5
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,1}<nw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-not-header5
|
|
; CHECK-NEXT: Loop %loop: <multiple exits> Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
br label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; The call instruction makes it not guaranteed that the add will be
|
|
; executed, since it could run forever or throw an exception, so we
|
|
; cannot assume that the UB is realized.
|
|
define void @test-add-call(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-call'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-call
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,1}<nw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-1 + %offset + %numIterations) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-call
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
call void @foo()
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Same issue as test-add-call, but this time the call is between the
|
|
; producer of poison and the load that consumes it.
|
|
define void @test-add-call2(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-call2'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-call2
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {%offset,+,1}<nw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-1 + %offset + %numIterations) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-call2
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
call void @foo()
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Any poison input makes getelementptr produce poison
|
|
define void @test-gep-propagates-poison(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-gep-propagates-poison'
|
|
; CHECK-NEXT: Classifying expressions for: @test-gep-propagates-poison
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> {((4 * (sext i32 %offset to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %offset to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-gep-propagates-poison
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Multiplication by a non-zero constant propagates poison if there is
|
|
; a nuw or nsw flag on the multiplication.
|
|
define void @test-add-mul-propagates(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-mul-propagates'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-mul-propagates
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %indexmul = mul nuw i32 %index32, 2
|
|
; CHECK-NEXT: --> {(2 * %offset),+,2}<%loop> U: [0,-1) S: [-2147483648,2147483647) Exits: (-2 + (2 * %offset) + (2 * %numIterations)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %indexmul
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {(2 * %offset),+,2}<%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-2 + (2 * %offset) + (2 * %numIterations)) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-mul-propagates
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%indexmul = mul nuw i32 %index32, 2
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %indexmul
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Any poison input to multiplication propages poison.
|
|
define void @test-mul-propagates-poison(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-mul-propagates-poison'
|
|
; CHECK-NEXT: Classifying expressions for: @test-mul-propagates-poison
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %indexmul = mul nsw i32 %index32, %offset
|
|
; CHECK-NEXT: --> {(%offset * %offset),+,%offset}<nsw><%loop> U: full-set S: full-set Exits: ((-1 + %offset + %numIterations) * %offset) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %indexmul
|
|
; CHECK-NEXT: --> {((4 * (sext i32 (%offset * %offset) to i64))<nsw> + %input),+,(4 * (sext i32 %offset to i64))<nsw>}<nw><%loop> U: full-set S: full-set Exits: ((4 * (sext i32 (%offset * %offset) to i64))<nsw> + (4 * (zext i32 (-1 + %numIterations) to i64) * (sext i32 %offset to i64)) + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-mul-propagates-poison
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%indexmul = mul nsw i32 %index32, %offset
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %indexmul
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @test-mul-propagates-poison-2(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-mul-propagates-poison-2'
|
|
; CHECK-NEXT: Classifying expressions for: @test-mul-propagates-poison-2
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %indexmul = mul i32 %index32, 2
|
|
; CHECK-NEXT: --> {(2 * %offset),+,2}<%loop> U: [0,-1) S: [-2147483648,2147483647) Exits: (-2 + (2 * %offset) + (2 * %numIterations)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %indexmul
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {(2 * %offset),+,2}<%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-2 + (2 * %offset) + (2 * %numIterations)) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-mul-propagates-poison-2
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%indexmul = mul i32 %index32, 2
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %indexmul
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Division by poison triggers UB.
|
|
define void @test-add-div(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-div'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-div
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %j = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %q = sdiv i32 %numIterations, %j
|
|
; CHECK-NEXT: --> %q U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-div
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%j = add nsw i32 %i, %offset
|
|
|
|
%q = sdiv i32 %numIterations, %j
|
|
%nexti = add nsw i32 %i, 1
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Remainder of poison by non-poison divisor does not trigger UB.
|
|
define void @test-add-div2(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-div2'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-div2
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %j = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %q = sdiv i32 %j, %numIterations
|
|
; CHECK-NEXT: --> %q U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-div2
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%j = add nsw i32 %i, %offset
|
|
|
|
%q = sdiv i32 %j, %numIterations
|
|
%nexti = add nsw i32 %i, 1
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Store to poison address triggers UB.
|
|
define void @test-add-store(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-store'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-store
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %i, %offset
|
|
; CHECK-NEXT: --> {%offset,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> {((4 * (sext i32 %offset to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %offset to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-store
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = add nsw i32 %i, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
store float 1.0, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Three sequential adds where the middle add should have nsw. There is
|
|
; a special case for sequential adds and this test covers that. We have to
|
|
; put the final add first in the program since otherwise the special case
|
|
; is not triggered, hence the strange basic block ordering.
|
|
define void @test-add-twice(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-add-twice'
|
|
; CHECK-NEXT: Classifying expressions for: @test-add-twice
|
|
; CHECK-NEXT: %seq = add nuw nsw i32 %index32, 1
|
|
; CHECK-NEXT: --> {(2 + %offset),+,1}<nw><%loop> U: full-set S: full-set Exits: (1 + %offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %j = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = add nsw i32 %j, %offset
|
|
; CHECK-NEXT: --> {(1 + %offset)<nsw>,+,1}<nsw><%loop> U: [-2147483647,-2147483648) S: [-2147483647,-2147483648) Exits: (%offset + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> {(4 + (4 * (sext i32 %offset to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: (4 + (4 * (zext i32 (-1 + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %offset to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-add-twice
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop2:
|
|
%seq = add nsw nuw i32 %index32, 1
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
|
|
%j = add nsw i32 %i, 1
|
|
%index32 = add nsw i32 %j, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
store float 1.0, float* %ptr, align 4
|
|
br label %loop2
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a mul should get the nsw flag, so that a sext can be
|
|
; distributed over the mul.
|
|
define void @test-mul-nsw(float* %input, i32 %stride, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-mul-nsw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-mul-nsw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = mul nsw i32 %i, %stride
|
|
; CHECK-NEXT: --> {0,+,%stride}<nsw><%loop> U: full-set S: full-set Exits: ((-1 + %numIterations) * %stride) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> {0,+,(sext i32 %stride to i64)}<nsw><%loop> U: [-9223372034707292160,9223372030412324866) S: [-9223372034707292160,9223372030412324866) Exits: ((zext i32 (-1 + %numIterations) to i64) * (sext i32 %stride to i64)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {%input,+,(4 * (sext i32 %stride to i64))<nsw>}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + %numIterations) to i64) * (sext i32 %stride to i64)) + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-mul-nsw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = mul nsw i32 %i, %stride
|
|
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a mul should get the nuw flag.
|
|
define void @test-mul-nuw(float* %input, i32 %stride, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-mul-nuw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-mul-nuw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = mul nuw i32 %i, %stride
|
|
; CHECK-NEXT: --> {0,+,%stride}<nuw><%loop> U: full-set S: full-set Exits: ((-1 + %numIterations) * %stride) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {0,+,%stride}<nuw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 ((-1 + %numIterations) * %stride) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nuw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-mul-nuw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = mul nuw i32 %i, %stride
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nuw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a shl should get the nsw flag, so that a sext can be
|
|
; distributed over the shl.
|
|
define void @test-shl-nsw(float* %input, i32 %start, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-shl-nsw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-shl-nsw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
; CHECK-NEXT: --> {%start,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = shl nsw i32 %i, 8
|
|
; CHECK-NEXT: --> {(256 * %start),+,256}<nsw><%loop> U: [0,-255) S: [-2147483648,2147483393) Exits: (-256 + (256 * %numIterations)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> {(sext i32 (256 * %start) to i64),+,256}<nsw><%loop> U: [0,-255) S: [-2147483648,1101659110913) Exits: ((sext i32 (256 * %start) to i64) + (256 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nuw><nsw>) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {((4 * (sext i32 (256 * %start) to i64))<nsw> + %input),+,1024}<nw><%loop> U: full-set S: full-set Exits: ((4 * (sext i32 (256 * %start) to i64))<nsw> + (1024 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nuw><nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {(1 + %start),+,1}<nsw><%loop> U: full-set S: full-set Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-shl-nsw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
|
|
%index32 = shl nsw i32 %i, 8
|
|
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a shl should get the nuw flag
|
|
define void @test-shl-nuw-edgecase(float* %input, i32 %start, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-shl-nuw-edgecase'
|
|
; CHECK-NEXT: Classifying expressions for: @test-shl-nuw-edgecase
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
; CHECK-NEXT: --> {%start,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = shl nuw i32 %i, 31
|
|
; CHECK-NEXT: --> {(-2147483648 * %start),+,-2147483648}<%loop> U: [0,-2147483647) S: [-2147483648,1) Exits: (-2147483648 + (-2147483648 * %numIterations)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> (sext i32 {(-2147483648 * %start),+,-2147483648}<%loop> to i64) U: [0,-2147483647) S: [-2147483648,1) Exits: (sext i32 (-2147483648 + (-2147483648 * %numIterations)) to i64) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {(-2147483648 * %start),+,-2147483648}<%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-2147483648 + (-2147483648 * %numIterations)) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {(1 + %start),+,1}<nsw><%loop> U: full-set S: full-set Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-shl-nuw-edgecase
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
|
|
%index32 = shl nuw i32 %i, 31
|
|
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a shl should get the nuw flag
|
|
define void @test-shl-nuw-nsw(float* %input, i32 %start, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-shl-nuw-nsw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-shl-nuw-nsw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
; CHECK-NEXT: --> {%start,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = shl nuw nsw i32 %i, 31
|
|
; CHECK-NEXT: --> {(-2147483648 * %start),+,-2147483648}<nsw><%loop> U: [0,-2147483647) S: [-2147483648,1) Exits: (-2147483648 + (-2147483648 * %numIterations)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> {(sext i32 (-2147483648 * %start) to i64),+,-2147483648}<nsw><%loop> U: [0,-2147483647) S: [-9223372036854775808,1) Exits: ((sext i32 (-2147483648 * %start) to i64) + (-2147483648 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nsw>) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {((4 * (sext i32 (-2147483648 * %start) to i64))<nsw> + %input),+,-8589934592}<nw><%loop> U: full-set S: full-set Exits: ((4 * (sext i32 (-2147483648 * %start) to i64))<nsw> + (-8589934592 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64)) + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {(1 + %start),+,1}<nsw><%loop> U: full-set S: full-set Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-shl-nuw-nsw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
|
|
%index32 = shl nuw nsw i32 %i, 31
|
|
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a shl should not get the nsw flag
|
|
define void @test-shl-no-nsw(float* %input, i32 %start, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-shl-no-nsw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-shl-no-nsw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
; CHECK-NEXT: --> {%start,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = shl nsw i32 %i, 31
|
|
; CHECK-NEXT: --> {(-2147483648 * %start),+,-2147483648}<%loop> U: [0,-2147483647) S: [-2147483648,1) Exits: (-2147483648 + (-2147483648 * %numIterations)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> (sext i32 {(-2147483648 * %start),+,-2147483648}<%loop> to i64) U: [0,-2147483647) S: [-2147483648,1) Exits: (sext i32 (-2147483648 + (-2147483648 * %numIterations)) to i64) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {(-2147483648 * %start),+,-2147483648}<%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-2147483648 + (-2147483648 * %numIterations)) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {(1 + %start),+,1}<nsw><%loop> U: full-set S: full-set Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-shl-no-nsw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
|
|
%index32 = shl nsw i32 %i, 31
|
|
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a shl should get the nsw flag.
|
|
define void @test-shl-nsw-edgecase(float* %input, i32 %start, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-shl-nsw-edgecase'
|
|
; CHECK-NEXT: Classifying expressions for: @test-shl-nsw-edgecase
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
; CHECK-NEXT: --> {%start,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = shl nsw i32 %i, 30
|
|
; CHECK-NEXT: --> {(1073741824 * %start),+,1073741824}<nsw><%loop> U: [0,-1073741823) S: [-2147483648,1073741825) Exits: (-1073741824 + (1073741824 * %numIterations)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> {(sext i32 (1073741824 * %start) to i64),+,1073741824}<nsw><%loop> U: [0,-1073741823) S: [-2147483648,4611686018427387905) Exits: ((sext i32 (1073741824 * %start) to i64) + (1073741824 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nuw><nsw>) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {((4 * (sext i32 (1073741824 * %start) to i64))<nsw> + %input),+,4294967296}<nw><%loop> U: full-set S: full-set Exits: ((4 * (sext i32 (1073741824 * %start) to i64))<nsw> + (4294967296 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nuw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {(1 + %start),+,1}<nsw><%loop> U: full-set S: full-set Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-shl-nsw-edgecase
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
|
|
%index32 = shl nsw i32 %i, 30
|
|
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a shl should get the nuw flag.
|
|
define void @test-shl-nuw(float* %input, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-shl-nuw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-shl-nuw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = shl nuw i32 %i, 9
|
|
; CHECK-NEXT: --> {0,+,512}<nuw><%loop> U: [0,-511) S: [-2147483648,2147483137) Exits: (-512 + (512 * %numIterations)) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> ((4 * (sext i32 {0,+,512}<nuw><%loop> to i64))<nsw> + %input) U: full-set S: full-set Exits: ((4 * (sext i32 (-512 + (512 * %numIterations)) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nuw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-shl-nuw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = shl nuw i32 %i, 9
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nuw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a sub should *not* get the nsw flag, because of how
|
|
; scalar evolution represents A - B as A + (-B) and -B can wrap even
|
|
; in cases where A - B does not.
|
|
define void @test-sub-no-nsw(float* %input, i32 %start, i32 %sub, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-sub-no-nsw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-sub-no-nsw
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
; CHECK-NEXT: --> {%start,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = sub nsw i32 %i, %sub
|
|
; CHECK-NEXT: --> {((-1 * %sub) + %start),+,1}<nw><%loop> U: full-set S: full-set Exits: (-1 + (-1 * %sub) + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> {((sext i32 %start to i64) + (-1 * (sext i32 %sub to i64))<nsw>)<nsw>,+,1}<nsw><%loop> U: [-4294967295,8589934591) S: [-4294967295,8589934591) Exits: ((zext i32 (-1 + (-1 * %start) + %numIterations) to i64) + (sext i32 %start to i64) + (-1 * (sext i32 %sub to i64))<nsw>) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {((4 * (sext i32 %start to i64))<nsw> + (-4 * (sext i32 %sub to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %start to i64))<nsw> + (-4 * (sext i32 %sub to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {(1 + %start),+,1}<nsw><%loop> U: full-set S: full-set Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-sub-no-nsw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
|
|
%index32 = sub nsw i32 %i, %sub
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a sub should get the nsw flag as the RHS cannot be the
|
|
; minimal signed value.
|
|
define void @test-sub-nsw(float* %input, i32 %start, i32 %sub, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-sub-nsw'
|
|
; CHECK-NEXT: Classifying expressions for: @test-sub-nsw
|
|
; CHECK-NEXT: %halfsub = ashr i32 %sub, 1
|
|
; CHECK-NEXT: --> %halfsub U: [-1073741824,1073741824) S: [-1073741824,1073741824)
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
; CHECK-NEXT: --> {%start,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = sub nsw i32 %i, %halfsub
|
|
; CHECK-NEXT: --> {((-1 * %halfsub)<nsw> + %start)<nsw>,+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + (-1 * %halfsub)<nsw> + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> {((sext i32 %start to i64) + (-1 * (sext i32 %halfsub to i64))<nsw>)<nsw>,+,1}<nsw><%loop> U: [-3221225471,7516192767) S: [-3221225471,7516192767) Exits: ((zext i32 (-1 + (-1 * %start) + %numIterations) to i64) + (sext i32 %start to i64) + (-1 * (sext i32 %halfsub to i64))<nsw>) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {((4 * (sext i32 %start to i64))<nsw> + (-4 * (sext i32 %halfsub to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + (-1 * %start) + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 %start to i64))<nsw> + (-4 * (sext i32 %halfsub to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {(1 + %start),+,1}<nsw><%loop> U: full-set S: full-set Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-sub-nsw
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + (-1 * %start) + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
%halfsub = ashr i32 %sub, 1
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ %start, %entry ]
|
|
|
|
%index32 = sub nsw i32 %i, %halfsub
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example where a sub should get the nsw flag, since the LHS is non-negative,
|
|
; which implies that the RHS cannot be the minimal signed value.
|
|
define void @test-sub-nsw-lhs-non-negative(float* %input, i32 %sub, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-sub-nsw-lhs-non-negative'
|
|
; CHECK-NEXT: Classifying expressions for: @test-sub-nsw-lhs-non-negative
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = sub nsw i32 %i, %sub
|
|
; CHECK-NEXT: --> {(-1 * %sub),+,1}<nsw><%loop> U: full-set S: full-set Exits: (-1 + (-1 * %sub) + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index64 = sext i32 %index32 to i64
|
|
; CHECK-NEXT: --> {(-1 * (sext i32 %sub to i64))<nsw>,+,1}<nsw><%loop> U: [-2147483647,6442450944) S: [-2147483647,6442450944) Exits: ((zext i32 (-1 + %numIterations) to i64) + (-1 * (sext i32 %sub to i64))<nsw>) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {((-4 * (sext i32 %sub to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: ((4 * (zext i32 (-1 + %numIterations) to i64))<nuw><nsw> + (-4 * (sext i32 %sub to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-sub-nsw-lhs-non-negative
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
|
|
|
|
%index32 = sub nsw i32 %i, %sub
|
|
|
|
%index64 = sext i32 %index32 to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Example checking that a sext is pushed onto a sub's operands if the sub is an
|
|
; overflow intrinsic.
|
|
define void @test-sext-sub(float* %input, i32 %sub, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-sext-sub'
|
|
; CHECK-NEXT: Classifying expressions for: @test-sext-sub
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %cont ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %val = extractvalue { i32, i1 } %ssub, 0
|
|
; CHECK-NEXT: --> {(-1 * %sub),+,1}<nw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ovfl = extractvalue { i32, i1 } %ssub, 1
|
|
; CHECK-NEXT: --> %ovfl U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
|
; CHECK-NEXT: %index64 = sext i32 %val to i64
|
|
; CHECK-NEXT: --> {(-1 * (sext i32 %sub to i64))<nsw>,+,1}<nsw><%loop> U: [-2147483647,6442450944) S: [-2147483647,6442450944) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
; CHECK-NEXT: --> {((-4 * (sext i32 %sub to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-sext-sub
|
|
; CHECK-NEXT: Loop %loop: <multiple exits> Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: exit count for loop: ***COULDNOTCOMPUTE***
|
|
; CHECK-NEXT: exit count for cont: (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [ %nexti, %cont ], [ 0, %entry ]
|
|
|
|
%ssub = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %i, i32 %sub)
|
|
%val = extractvalue { i32, i1 } %ssub, 0
|
|
%ovfl = extractvalue { i32, i1 } %ssub, 1
|
|
br i1 %ovfl, label %trap, label %cont
|
|
|
|
trap:
|
|
tail call void @llvm.trap()
|
|
unreachable
|
|
|
|
cont:
|
|
%index64 = sext i32 %val to i64
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i64 %index64
|
|
%nexti = add nsw i32 %i, 1
|
|
%f = load float, float* %ptr, align 4
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Two adds with a sub in the middle and the sub should have nsw. There is
|
|
; a special case for sequential adds/subs and this test covers that. We have to
|
|
; put the final add first in the program since otherwise the special case
|
|
; is not triggered, hence the strange basic block ordering.
|
|
define void @test-sub-with-add(float* %input, i32 %offset, i32 %numIterations) {
|
|
; CHECK-LABEL: 'test-sub-with-add'
|
|
; CHECK-NEXT: Classifying expressions for: @test-sub-with-add
|
|
; CHECK-NEXT: %seq = add nuw nsw i32 %index32, 1
|
|
; CHECK-NEXT: --> {(2 + (-1 * %offset)),+,1}<nw><%loop> U: full-set S: full-set Exits: (1 + (-1 * %offset) + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %j = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %index32 = sub nsw i32 %j, %offset
|
|
; CHECK-NEXT: --> {(1 + (-1 * %offset))<nsw>,+,1}<nsw><%loop> U: [-2147483647,-2147483648) S: [-2147483647,-2147483648) Exits: ((-1 * %offset) + %numIterations) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
; CHECK-NEXT: --> {(4 + (4 * (sext i32 (-1 * %offset) to i64))<nsw> + %input),+,4}<nw><%loop> U: full-set S: full-set Exits: (4 + (4 * (zext i32 (-1 + %numIterations) to i64))<nuw><nsw> + (4 * (sext i32 (-1 * %offset) to i64))<nsw> + %input) LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: %nexti = add nsw i32 %i, 1
|
|
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %numIterations LoopDispositions: { %loop: Computable }
|
|
; CHECK-NEXT: Determining loop execution counts for: @test-sub-with-add
|
|
; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Loop %loop: max backedge-taken count is -1
|
|
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %numIterations)
|
|
; CHECK-NEXT: Predicates:
|
|
; CHECK: Loop %loop: Trip multiple is 1
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop2:
|
|
%seq = add nsw nuw i32 %index32, 1
|
|
%exitcond = icmp eq i32 %nexti, %numIterations
|
|
br i1 %exitcond, label %exit, label %loop
|
|
|
|
loop:
|
|
%i = phi i32 [ %nexti, %loop2 ], [ 0, %entry ]
|
|
|
|
%j = add nsw i32 %i, 1
|
|
%index32 = sub nsw i32 %j, %offset
|
|
|
|
%ptr = getelementptr inbounds float, float* %input, i32 %index32
|
|
%nexti = add nsw i32 %i, 1
|
|
store float 1.0, float* %ptr, align 4
|
|
br label %loop2
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; PR28932: Don't assert on non-SCEV-able value %2.
|
|
%struct.anon = type { i8* }
|
|
@a = common global %struct.anon* null, align 8
|
|
@b = common global i32 0, align 4
|
|
declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32)
|
|
declare void @llvm.trap()
|
|
define i32 @pr28932() {
|
|
; CHECK-LABEL: 'pr28932'
|
|
; CHECK-NEXT: Classifying expressions for: @pr28932
|
|
; CHECK-NEXT: %pre = load %struct.anon*, %struct.anon** @a, align 8
|
|
; CHECK-NEXT: --> %pre U: full-set S: full-set
|
|
; CHECK-NEXT: %pre7 = load i32, i32* @b, align 4
|
|
; CHECK-NEXT: --> %pre7 U: full-set S: full-set
|
|
; CHECK-NEXT: %0 = phi i32 [ %3, %cont6 ], [ %pre7, %entry ]
|
|
; CHECK-NEXT: --> {%pre7,+,-1}<%for.cond> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Computable }
|
|
; CHECK-NEXT: %1 = phi %struct.anon* [ %ph, %cont6 ], [ %pre, %entry ]
|
|
; CHECK-NEXT: --> %1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: %3 = extractvalue { i32, i1 } %2, 0
|
|
; CHECK-NEXT: --> {(-1 + %pre7),+,-1}<%for.cond> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Computable }
|
|
; CHECK-NEXT: %4 = extractvalue { i32, i1 } %2, 1
|
|
; CHECK-NEXT: --> %4 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: %idxprom = sext i32 %3 to i64
|
|
; CHECK-NEXT: --> (sext i32 {(-1 + %pre7),+,-1}<%for.cond> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: <<Unknown>> LoopDispositions: { %for.cond: Computable }
|
|
; CHECK-NEXT: %5 = getelementptr inbounds %struct.anon, %struct.anon* %1, i64 0, i32 0
|
|
; CHECK-NEXT: --> %1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: %6 = load i8*, i8** %5, align 8
|
|
; CHECK-NEXT: --> %6 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: %7 = getelementptr inbounds i8, i8* %6, i64 %idxprom
|
|
; CHECK-NEXT: --> ((sext i32 {(-1 + %pre7),+,-1}<%for.cond> to i64) + %6) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: %8 = load i8, i8* %7, align 1
|
|
; CHECK-NEXT: --> %8 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: %conv5 = sext i8 %8 to i64
|
|
; CHECK-NEXT: --> (sext i8 %8 to i64) U: [-128,128) S: [-128,128) Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: %9 = inttoptr i64 %conv5 to %struct.anon*
|
|
; CHECK-NEXT: --> %9 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: %ph = phi %struct.anon* [ %9, %cont1 ], [ %1, %if.then ]
|
|
; CHECK-NEXT: --> %ph U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
|
|
; CHECK-NEXT: Determining loop execution counts for: @pr28932
|
|
; CHECK-NEXT: Loop %for.cond: <multiple exits> Unpredictable backedge-taken count.
|
|
; CHECK-NEXT: exit count for if.then: ***COULDNOTCOMPUTE***
|
|
; CHECK-NEXT: exit count for if.else: ***COULDNOTCOMPUTE***
|
|
; CHECK-NEXT: Loop %for.cond: Unpredictable max backedge-taken count.
|
|
; CHECK-NEXT: Loop %for.cond: Unpredictable predicated backedge-taken count.
|
|
;
|
|
entry:
|
|
%pre = load %struct.anon*, %struct.anon** @a, align 8
|
|
%pre7 = load i32, i32* @b, align 4
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %cont6, %entry
|
|
%0 = phi i32 [ %3, %cont6 ], [ %pre7, %entry ]
|
|
%1 = phi %struct.anon* [ %ph, %cont6 ], [ %pre, %entry ]
|
|
%tobool = icmp eq %struct.anon* %1, null
|
|
%2 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %0, i32 1)
|
|
%3 = extractvalue { i32, i1 } %2, 0
|
|
%4 = extractvalue { i32, i1 } %2, 1
|
|
%idxprom = sext i32 %3 to i64
|
|
%5 = getelementptr inbounds %struct.anon, %struct.anon* %1, i64 0, i32 0
|
|
%6 = load i8*, i8** %5, align 8
|
|
%7 = getelementptr inbounds i8, i8* %6, i64 %idxprom
|
|
%8 = load i8, i8* %7, align 1
|
|
br i1 %tobool, label %if.else, label %if.then
|
|
|
|
if.then: ; preds = %for.cond
|
|
br i1 %4, label %trap, label %cont6
|
|
|
|
trap: ; preds = %if.else, %if.then
|
|
tail call void @llvm.trap()
|
|
unreachable
|
|
|
|
if.else: ; preds = %for.cond
|
|
br i1 %4, label %trap, label %cont1
|
|
|
|
cont1: ; preds = %if.else
|
|
%conv5 = sext i8 %8 to i64
|
|
%9 = inttoptr i64 %conv5 to %struct.anon*
|
|
store %struct.anon* %9, %struct.anon** @a, align 8
|
|
br label %cont6
|
|
|
|
cont6: ; preds = %cont1, %if.then
|
|
%ph = phi %struct.anon* [ %9, %cont1 ], [ %1, %if.then ]
|
|
store i32 %3, i32* @b, align 4
|
|
br label %for.cond
|
|
}
|
|
|
|
define noundef i32 @add-basic(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: 'add-basic'
|
|
; CHECK-NEXT: Classifying expressions for: @add-basic
|
|
; CHECK-NEXT: %res = add nuw nsw i32 %a, %b
|
|
; CHECK-NEXT: --> (%a + %b)<nuw><nsw> U: full-set S: full-set
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-basic
|
|
;
|
|
%res = add nuw nsw i32 %a, %b
|
|
ret i32 %res
|
|
}
|
|
|
|
define noundef i32 @sub-basic(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: 'sub-basic'
|
|
; CHECK-NEXT: Classifying expressions for: @sub-basic
|
|
; CHECK-NEXT: %res = sub nuw nsw i32 %a, %b
|
|
; CHECK-NEXT: --> ((-1 * %b) + %a) U: full-set S: full-set
|
|
; CHECK-NEXT: Determining loop execution counts for: @sub-basic
|
|
;
|
|
%res = sub nuw nsw i32 %a, %b
|
|
ret i32 %res
|
|
}
|
|
|
|
define noundef i32 @mul-basic(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: 'mul-basic'
|
|
; CHECK-NEXT: Classifying expressions for: @mul-basic
|
|
; CHECK-NEXT: %res = mul nuw nsw i32 %a, %b
|
|
; CHECK-NEXT: --> (%a * %b)<nuw><nsw> U: full-set S: full-set
|
|
; CHECK-NEXT: Determining loop execution counts for: @mul-basic
|
|
;
|
|
%res = mul nuw nsw i32 %a, %b
|
|
ret i32 %res
|
|
}
|
|
|
|
define noundef i32 @udiv-basic(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: 'udiv-basic'
|
|
; CHECK-NEXT: Classifying expressions for: @udiv-basic
|
|
; CHECK-NEXT: %res = udiv exact i32 %a, %b
|
|
; CHECK-NEXT: --> (%a /u %b) U: full-set S: full-set
|
|
; CHECK-NEXT: Determining loop execution counts for: @udiv-basic
|
|
;
|
|
%res = udiv exact i32 %a, %b
|
|
ret i32 %res
|
|
}
|
|
|
|
@gA = external global i32
|
|
@gB = external global i32
|
|
@gC = external global i32
|
|
@gD = external global i32
|
|
|
|
define noundef i64 @add-zext-recurse(i64 %arg) {
|
|
; CHECK-LABEL: 'add-zext-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-zext-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = zext i32 %a to i64
|
|
; CHECK-NEXT: --> (zext i32 %a to i64) U: [0,4294967296) S: [0,4294967296)
|
|
; CHECK-NEXT: %res = add nuw i64 %x, %arg
|
|
; CHECK-NEXT: --> ((zext i32 %a to i64) + %arg)<nuw> U: full-set S: full-set
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-zext-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = zext i32 %a to i64
|
|
%res = add nuw i64 %x, %arg
|
|
ret i64 %res
|
|
}
|
|
|
|
define noundef i64 @add-sext-recurse(i64 %arg) {
|
|
; CHECK-LABEL: 'add-sext-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-sext-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = sext i32 %a to i64
|
|
; CHECK-NEXT: --> (sext i32 %a to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
|
|
; CHECK-NEXT: %res = add nuw i64 %x, %arg
|
|
; CHECK-NEXT: --> ((sext i32 %a to i64) + %arg)<nuw> U: full-set S: full-set
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-sext-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = sext i32 %a to i64
|
|
%res = add nuw i64 %x, %arg
|
|
ret i64 %res
|
|
}
|
|
|
|
define noundef i16 @add-trunc-recurse() {
|
|
; CHECK-LABEL: 'add-trunc-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-trunc-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = trunc i32 %a to i16
|
|
; CHECK-NEXT: --> (trunc i32 %a to i16) U: full-set S: full-set
|
|
; CHECK-NEXT: %res = add nuw i16 %x, 1
|
|
; CHECK-NEXT: --> (1 + (trunc i32 %a to i16))<nuw> U: [1,0) S: [1,0)
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-trunc-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = trunc i32 %a to i16
|
|
%res = add nuw i16 %x, 1
|
|
ret i16 %res
|
|
}
|
|
|
|
define noundef i32 @add-udiv-recurse(i32 %arg) {
|
|
; CHECK-LABEL: 'add-udiv-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-udiv-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = udiv i32 %a, %arg
|
|
; CHECK-NEXT: --> (%a /u %arg) U: full-set S: full-set
|
|
; CHECK-NEXT: %res = add nuw i32 %x, 1
|
|
; CHECK-NEXT: --> (1 + (%a /u %arg))<nuw> U: [1,0) S: [1,0)
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-udiv-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = udiv i32 %a, %arg
|
|
%res = add nuw i32 %x, 1
|
|
ret i32 %res
|
|
}
|
|
|
|
define noundef i32 @add-mul-recurse() {
|
|
; CHECK-LABEL: 'add-mul-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-mul-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = mul i32 %a, 3
|
|
; CHECK-NEXT: --> (3 * %a) U: full-set S: full-set
|
|
; CHECK-NEXT: %res = add nuw i32 %x, 1
|
|
; CHECK-NEXT: --> (1 + (3 * %a))<nuw> U: [1,0) S: [1,0)
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-mul-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = mul i32 %a, 3
|
|
%res = add nuw i32 %x, 1
|
|
ret i32 %res
|
|
}
|
|
|
|
declare i32 @llvm.smin.i32(i32, i32)
|
|
declare i32 @llvm.smax.i32(i32, i32)
|
|
declare i32 @llvm.umin.i32(i32, i32)
|
|
declare i32 @llvm.umax.i32(i32, i32)
|
|
|
|
define noundef i32 @add-smin-recurse(i32 %arg) {
|
|
; CHECK-LABEL: 'add-smin-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-smin-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = call i32 @llvm.smin.i32(i32 %a, i32 %arg)
|
|
; CHECK-NEXT: --> (%arg smin %a) U: full-set S: full-set
|
|
; CHECK-NEXT: %res = add nuw i32 %x, 1
|
|
; CHECK-NEXT: --> (1 + (%arg smin %a))<nuw> U: [1,0) S: [1,0)
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-smin-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = call i32 @llvm.smin.i32(i32 %a, i32 %arg)
|
|
%res = add nuw i32 %x, 1
|
|
ret i32 %res
|
|
}
|
|
|
|
define noundef i32 @add-smax-recurse(i32 %arg) {
|
|
; CHECK-LABEL: 'add-smax-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-smax-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = call i32 @llvm.smax.i32(i32 %a, i32 %arg)
|
|
; CHECK-NEXT: --> (%arg smax %a) U: full-set S: full-set
|
|
; CHECK-NEXT: %res = add nuw i32 %x, 1
|
|
; CHECK-NEXT: --> (1 + (%arg smax %a))<nuw> U: [1,0) S: [1,0)
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-smax-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = call i32 @llvm.smax.i32(i32 %a, i32 %arg)
|
|
%res = add nuw i32 %x, 1
|
|
ret i32 %res
|
|
}
|
|
|
|
define noundef i32 @add-umin-recurse(i32 %arg) {
|
|
; CHECK-LABEL: 'add-umin-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-umin-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = call i32 @llvm.umin.i32(i32 %a, i32 %arg)
|
|
; CHECK-NEXT: --> (%arg umin %a) U: full-set S: full-set
|
|
; CHECK-NEXT: %res = add nuw i32 %x, 1
|
|
; CHECK-NEXT: --> (1 + (%arg umin %a))<nuw> U: [1,0) S: [1,0)
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-umin-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = call i32 @llvm.umin.i32(i32 %a, i32 %arg)
|
|
%res = add nuw i32 %x, 1
|
|
ret i32 %res
|
|
}
|
|
|
|
define noundef i32 @add-umax-recurse(i32 %arg) {
|
|
; CHECK-LABEL: 'add-umax-recurse'
|
|
; CHECK-NEXT: Classifying expressions for: @add-umax-recurse
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %x = call i32 @llvm.umax.i32(i32 %a, i32 %arg)
|
|
; CHECK-NEXT: --> (%arg umax %a) U: full-set S: full-set
|
|
; CHECK-NEXT: %res = add nuw i32 %x, 1
|
|
; CHECK-NEXT: --> (1 + (%arg umax %a))<nuw> U: [1,0) S: [1,0)
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-umax-recurse
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%x = call i32 @llvm.umax.i32(i32 %a, i32 %arg)
|
|
%res = add nuw i32 %x, 1
|
|
ret i32 %res
|
|
}
|
|
|
|
|
|
define noundef i32 @add-recurse-inline() {
|
|
; CHECK-LABEL: 'add-recurse-inline'
|
|
; CHECK-NEXT: Classifying expressions for: @add-recurse-inline
|
|
; CHECK-NEXT: %a = load i32, i32* @gA, align 4
|
|
; CHECK-NEXT: --> %a U: full-set S: full-set
|
|
; CHECK-NEXT: %b = load i32, i32* @gB, align 4
|
|
; CHECK-NEXT: --> %b U: full-set S: full-set
|
|
; CHECK-NEXT: %c = load i32, i32* @gC, align 4
|
|
; CHECK-NEXT: --> %c U: full-set S: full-set
|
|
; CHECK-NEXT: %d = load i32, i32* @gD, align 4
|
|
; CHECK-NEXT: --> %d U: full-set S: full-set
|
|
; CHECK-NEXT: %x = add nuw i32 %a, %b
|
|
; CHECK-NEXT: --> (%a + %b)<nuw> U: full-set S: full-set
|
|
; CHECK-NEXT: %y = add nuw i32 %c, %d
|
|
; CHECK-NEXT: --> (%c + %d)<nuw> U: full-set S: full-set
|
|
; CHECK-NEXT: %res = add nuw i32 %x, %y
|
|
; CHECK-NEXT: --> (%a + %b + %c + %d)<nuw> U: full-set S: full-set
|
|
; CHECK-NEXT: Determining loop execution counts for: @add-recurse-inline
|
|
;
|
|
call void @foo()
|
|
%a = load i32, i32* @gA
|
|
%b = load i32, i32* @gB
|
|
%c = load i32, i32* @gC
|
|
%d = load i32, i32* @gD
|
|
|
|
%x = add nuw i32 %a, %b
|
|
%y = add nuw i32 %c, %d
|
|
%res = add nuw i32 %x, %y
|
|
ret i32 %res
|
|
}
|