Files
clang-p2996/llvm/test/Transforms/FunctionSpecialization/literal-const.ll
Momchil Velikov 38f44ccfba Recommit: [FuncSpec] Fix specialisation based on literals
[fixed test to work with reverse iteration]

The `FunctionSpecialization` pass has support for specialising
functions, which are called with literal arguments. This functionality
is disabled by default and is enabled with the option
`-function-specialization-for-literal-constant` .  There are a few
issues with the implementation, though:

* even with the default, the pass will still specialise based on
   floating-point literals

* even when it's enabled, the pass will specialise only for the `i1`
    type (or `i2` if all of the possible 4 values occur, or `i3` if all
    of the possible 8 values occur, etc)

The reason for this is incorrect check of the lattice value of the
function formal parameter. The lattice value is `overdefined` when the
constant range of the possible arguments is the full set, and this is
the reason for the specialisation to trigger. However, if the set of
the possible arguments is not the full set, that must not prevent the
specialisation.

This patch changes the pass to NOT consider a formal parameter when
specialising a function if the lattice value for that parameter is:

* unknown or undef
* a constant
* a constant range with a single element

on the basis that specialisation is pointless for those cases.

Is also changes the criteria for picking up an actual argument to
specialise if the argument is:

* a LLVM IR constant
* has `constant` lattice value
 has `constantrange` lattice value with a single element.

Reviewed By: ChuanqiXu

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

Change-Id: Iea273423176082ec51339aa66a5fe9fea83557ee
2022-10-27 12:48:20 +01:00

93 lines
2.2 KiB
LLVM

; RUN: opt -S --passes=function-specialization \
; RUN: -force-function-specialization < %s | FileCheck %s -check-prefix CHECK-NOLIT
; RUN: opt -S --passes=function-specialization \
; RUN: -function-specialization-for-literal-constant \
; RUN: -force-function-specialization < %s | FileCheck %s -check-prefix CHECK-LIT
define i32 @f0(i32 noundef %x) {
entry:
%call = tail call i32 @neg(i32 noundef %x, i1 noundef zeroext false)
ret i32 %call
}
define i32 @f1(i32 noundef %x) {
entry:
%call = tail call i32 @neg(i32 noundef %x, i1 noundef zeroext true)
ret i32 %call
}
define i32 @g0(i32 noundef %x) {
entry:
%call = tail call i32 @add(i32 noundef %x, i32 noundef 1)
ret i32 %call
}
define i32 @g1(i32 noundef %x) {
entry:
%call = tail call i32 @add(i32 noundef %x, i32 noundef 2)
ret i32 %call
}
define float @h0(float noundef %x) {
entry:
%call = tail call float @addf(float noundef %x, float noundef 1.000000e+00)
ret float %call
}
define float @h1(float noundef %x) {
entry:
%call = tail call float @addf(float noundef %x, float noundef 2.000000e+00)
ret float %call
}
define internal i32 @neg(i32 noundef %x, i1 noundef zeroext %b) {
entry:
%sub = sub nsw i32 0, %x
%cond = select i1 %b, i32 %sub, i32 %x
ret i32 %cond
}
define internal i32 @add(i32 noundef %x, i32 noundef %y) {
entry:
%add = add nsw i32 %y, %x
ret i32 %add
}
define internal float @addf(float noundef %x, float noundef %y) {
entry:
%add = fadd float %x, %y
ret float %add
}
; Check no functions were specialised.
; CHECK-NOLIT-NOT: @neg.
; CHECK-NOLIT-NOT: @add.
; CHECK-NOLIT-NOT: @addf.
; CHECK-LIT-LABEL: define i32 @f0
; CHECK-LIT: call i32 @neg.[[#A:]]
; CHECK-LIT-LABEL: define i32 @f1
; CHECK-LIT: call i32 @neg.[[#B:]]
; CHECK-LIT-LABEL: define i32 @g0
; CHECK-LIT: call i32 @add.[[#C:]]
; CHECK-LIT-LABEL: define i32 @g1
; CHECK-LIT: call i32 @add.[[#D:]]
; CHECK-LIT-LABEL: define float @h0
; CHECK-LIT: call float @addf.[[#E:]]
; CHECK-LIT-LABEL: define float @h1
; CHECK-LIT: call float @addf.[[#F:]]
; Check all of `neg`, `add`, and `addf` were specialised.
; CHECK-LIT-DAG: @neg.[[#A]]
; CHECK-LIT-DAG: @neg.[[#B]]
; CHECK-LIT-DAG: @add.[[#C]]
; CHECK-LIT-DAG: @add.[[#D]]
; CHECK-LIT-DAG: @addf.[[#E]]
; CHECK-LIT-DAG: @addf.[[#F]]