mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
5a174914f6
As being discussed in https://reviews.llvm.org/D100721, this modelling is lossy, we can't reconstruct `ash`/`ashr exact` from it, which means that whenever we actually expand the IR, we've just pessimized the code.. It would be good to model this pattern, after all it comes up every time you want to compute a distance between two pointers, but not at this cost. This reverts commit ec54867df5e7f20e12146e628af34f0384308bcb.
192 lines
8.2 KiB
LLVM
192 lines
8.2 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -indvars -S %s | FileCheck %s
|
|
|
|
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
|
|
|
|
define float @ashr_expansion_valid(i64 %x, float* %ptr) {
|
|
; CHECK-LABEL: @ashr_expansion_valid(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[BOUND:%.*]] = ashr exact i64 [[X:%.*]], 4
|
|
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[BOUND]], i64 1)
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[RED:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, float* [[PTR:%.*]], i64 [[IV]]
|
|
; CHECK-NEXT: [[LV:%.*]] = load float, float* [[GEP]], align 4
|
|
; CHECK-NEXT: [[RED_NEXT]] = fadd float [[LV]], [[RED]]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[UMAX]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[LCSSA_RED_NEXT:%.*]] = phi float [ [[RED_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: ret float [[LCSSA_RED_NEXT]]
|
|
;
|
|
entry:
|
|
%bound = ashr exact i64 %x, 4
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
|
|
%red = phi float [ 0.0, %entry ], [ %red.next, %loop ]
|
|
%gep = getelementptr float, float* %ptr, i64 %iv
|
|
%lv = load float, float* %gep
|
|
%red.next = fadd float %lv, %red
|
|
%iv.next = add nuw i64 %iv, 1
|
|
%cond = icmp ult i64 %iv.next, %bound
|
|
br i1 %cond, label %loop, label %exit
|
|
|
|
exit: ; preds = %bb135
|
|
%lcssa.red.next = phi float [ %red.next, %loop ]
|
|
ret float %lcssa.red.next
|
|
}
|
|
|
|
; No explicit ashr, but a chain of operations that can be replaced by ashr.
|
|
define float @ashr_equivalent_expansion(i64 %x, float* %ptr) {
|
|
; CHECK-LABEL: @ashr_equivalent_expansion(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ABS_X:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 false)
|
|
; CHECK-NEXT: [[T0:%.*]] = call i64 @llvm.smax.i64(i64 [[X]], i64 -1)
|
|
; CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.smin.i64(i64 [[T0]], i64 1)
|
|
; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[ABS_X]], 4
|
|
; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[T1]], [[TMP0]]
|
|
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP1]], i64 1)
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[RED:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, float* [[PTR:%.*]], i64 [[IV]]
|
|
; CHECK-NEXT: [[LV:%.*]] = load float, float* [[GEP]], align 4
|
|
; CHECK-NEXT: [[RED_NEXT]] = fadd float [[LV]], [[RED]]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[UMAX]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[LCSSA_RED_NEXT:%.*]] = phi float [ [[RED_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: ret float [[LCSSA_RED_NEXT]]
|
|
;
|
|
entry:
|
|
%abs_x = call i64 @llvm.abs.i64(i64 %x, i1 false)
|
|
%div = udiv exact i64 %abs_x, 16
|
|
%t0 = call i64 @llvm.smax.i64(i64 %x, i64 -1)
|
|
%t1 = call i64 @llvm.smin.i64(i64 %t0, i64 1)
|
|
%bound = mul nsw i64 %div, %t1
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
|
|
%red = phi float [ 0.0, %entry ], [ %red.next, %loop ]
|
|
%gep = getelementptr float, float* %ptr, i64 %iv
|
|
%lv = load float, float* %gep
|
|
%red.next = fadd float %lv, %red
|
|
%iv.next = add nuw i64 %iv, 1
|
|
%cond = icmp ult i64 %iv.next, %bound
|
|
br i1 %cond, label %loop, label %exit
|
|
|
|
exit: ; preds = %bb135
|
|
%lcssa.red.next = phi float [ %red.next, %loop ]
|
|
ret float %lcssa.red.next
|
|
}
|
|
|
|
; Chain of operations that *cannot* be replaced by ashr, because the udiv is
|
|
; missing exact.
|
|
define float @no_ashr_due_to_missing_exact_udiv(i64 %x, float* %ptr) {
|
|
; CHECK-LABEL: @no_ashr_due_to_missing_exact_udiv(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ABS_X:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 false)
|
|
; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[ABS_X]], 16
|
|
; CHECK-NEXT: [[T0:%.*]] = call i64 @llvm.smax.i64(i64 [[X]], i64 -1)
|
|
; CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.smin.i64(i64 [[T0]], i64 1)
|
|
; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[T1]], [[DIV]]
|
|
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP0]], i64 1)
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[RED:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, float* [[PTR:%.*]], i64 [[IV]]
|
|
; CHECK-NEXT: [[LV:%.*]] = load float, float* [[GEP]], align 4
|
|
; CHECK-NEXT: [[RED_NEXT]] = fadd float [[LV]], [[RED]]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[UMAX]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[LCSSA_RED_NEXT:%.*]] = phi float [ [[RED_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: ret float [[LCSSA_RED_NEXT]]
|
|
;
|
|
entry:
|
|
%abs_x = call i64 @llvm.abs.i64(i64 %x, i1 false)
|
|
%div = udiv i64 %abs_x, 16
|
|
%t0 = call i64 @llvm.smax.i64(i64 %x, i64 -1)
|
|
%t1 = call i64 @llvm.smin.i64(i64 %t0, i64 1)
|
|
%bound = mul nsw i64 %div, %t1
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
|
|
%red = phi float [ 0.0, %entry ], [ %red.next, %loop ]
|
|
%gep = getelementptr float, float* %ptr, i64 %iv
|
|
%lv = load float, float* %gep
|
|
%red.next = fadd float %lv, %red
|
|
%iv.next = add nuw i64 %iv, 1
|
|
%cond = icmp ult i64 %iv.next, %bound
|
|
br i1 %cond, label %loop, label %exit
|
|
|
|
exit: ; preds = %bb135
|
|
%lcssa.red.next = phi float [ %red.next, %loop ]
|
|
ret float %lcssa.red.next
|
|
}
|
|
|
|
; Chain of operations that *cannot* be replaced by ashr, because abs and
|
|
; signum have different operands.
|
|
define float @no_ashr_due_to_different_ops(i64 %x, i64 %y, float* %ptr) {
|
|
; CHECK-LABEL: @no_ashr_due_to_different_ops(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ABS_X:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 false)
|
|
; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[ABS_X]], 16
|
|
; CHECK-NEXT: [[T0:%.*]] = call i64 @llvm.smax.i64(i64 [[Y:%.*]], i64 -1)
|
|
; CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.smin.i64(i64 [[T0]], i64 1)
|
|
; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[T1]], [[DIV]]
|
|
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP0]], i64 1)
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[RED:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr float, float* [[PTR:%.*]], i64 [[IV]]
|
|
; CHECK-NEXT: [[LV:%.*]] = load float, float* [[GEP]], align 4
|
|
; CHECK-NEXT: [[RED_NEXT]] = fadd float [[LV]], [[RED]]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[UMAX]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[LCSSA_RED_NEXT:%.*]] = phi float [ [[RED_NEXT]], [[LOOP]] ]
|
|
; CHECK-NEXT: ret float [[LCSSA_RED_NEXT]]
|
|
;
|
|
entry:
|
|
%abs_x = call i64 @llvm.abs.i64(i64 %x, i1 false)
|
|
%div = udiv i64 %abs_x, 16
|
|
%t0 = call i64 @llvm.smax.i64(i64 %y, i64 -1)
|
|
%t1 = call i64 @llvm.smin.i64(i64 %t0, i64 1)
|
|
%bound = mul nsw i64 %div, %t1
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
|
|
%red = phi float [ 0.0, %entry ], [ %red.next, %loop ]
|
|
%gep = getelementptr float, float* %ptr, i64 %iv
|
|
%lv = load float, float* %gep
|
|
%red.next = fadd float %lv, %red
|
|
%iv.next = add nuw i64 %iv, 1
|
|
%cond = icmp ult i64 %iv.next, %bound
|
|
br i1 %cond, label %loop, label %exit
|
|
|
|
exit: ; preds = %bb135
|
|
%lcssa.red.next = phi float [ %red.next, %loop ]
|
|
ret float %lcssa.red.next
|
|
}
|
|
|
|
declare i64 @llvm.abs.i64(i64, i1)
|
|
|
|
declare i64 @llvm.smax.i64(i64, i64)
|
|
|
|
declare i64 @llvm.smin.i64(i64, i64)
|