Files
Nikita Popov bf4a9f7325 [SimplifyIndVar] Simplify non-overflowing saturating add/sub
If we can detect that saturating math that depends on an IV cannot
overflow, replace it with simple math. This is similar to the CVP
optimization from D62703, just based on a different underlying
analysis (SCEV vs LVI) that catches different cases.

Differential Revision: https://reviews.llvm.org/D62792

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363489 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-15 08:48:52 +00:00

124 lines
3.6 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -S -indvars | FileCheck %s
declare i32 @llvm.uadd.sat.i32(i32, i32)
declare i32 @llvm.sadd.sat.i32(i32, i32)
declare i32 @llvm.usub.sat.i32(i32, i32)
declare i32 @llvm.ssub.sat.i32(i32, i32)
define void @uadd_sat(i32* %p) {
; CHECK-LABEL: @uadd_sat(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[SAT1:%.*]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
%sat = call i32 @llvm.uadd.sat.i32(i32 %i, i32 1)
store volatile i32 %sat, i32* %p
%i.inc = add nuw nsw i32 %i, 1
%cmp = icmp ne i32 %i.inc, 100
br i1 %cmp, label %loop, label %end
end:
ret void
}
define void @sadd_sat(i32* %p) {
; CHECK-LABEL: @sadd_sat(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[SAT1:%.*]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
%sat = call i32 @llvm.sadd.sat.i32(i32 %i, i32 1)
store volatile i32 %sat, i32* %p
%i.inc = add nuw nsw i32 %i, 1
%cmp = icmp ne i32 %i.inc, 100
br i1 %cmp, label %loop, label %end
end:
ret void
}
define void @usub_sat(i32* %p) {
; CHECK-LABEL: @usub_sat(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[SAT1:%.*]] = sub nuw nsw i32 [[I]], 1
; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%i = phi i32 [ 1, %entry ], [ %i.inc, %loop ]
%sat = call i32 @llvm.usub.sat.i32(i32 %i, i32 1)
store volatile i32 %sat, i32* %p
%i.inc = add nuw nsw i32 %i, 1
%cmp = icmp ne i32 %i.inc, 100
br i1 %cmp, label %loop, label %end
end:
ret void
}
define void @ssub_sat(i32* %p) {
; CHECK-LABEL: @ssub_sat(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[SAT1:%.*]] = sub nsw i32 [[I]], 1
; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
; CHECK: end:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
%sat = call i32 @llvm.ssub.sat.i32(i32 %i, i32 1)
store volatile i32 %sat, i32* %p
%i.inc = add nuw nsw i32 %i, 1
%cmp = icmp ne i32 %i.inc, 100
br i1 %cmp, label %loop, label %end
end:
ret void
}