llvm-project/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll
Sjoerd Meijer eba76056a3 [FuncSpec] Don't specialise (or crash) on poison or constexpr values
Function specialization was crashing on poison values and constexpr values.
The problem is that these values are not added to the solver, so it crashes
when a lookup is performed for these values. This fixes that by not
specialising on these values. For poison that is obvious, but for constexpr
this is a change in behaviour. Thus, in one way this is a bit of a stopgap, but
specialising on constexpr values wasn't done very intentionally, and need some
more work and tests if we wanted to support this.

As a follow up, we need to look if the solver should exit more gracefully and
return a "don't know", or that it should really support these constexprs.

This should fix PR51600 (https://bugs.llvm.org/show_bug.cgi?id=51600).

Differential Revision: https://reviews.llvm.org/D110529
2021-09-27 14:58:53 +01:00

79 lines
2.3 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Test function specialization wouldn't crash due to constant expression.
; Note that this test case shows that function specialization pass would
; transform the function even if no specialization happened.
; RUN: opt -function-specialization -force-function-specialization -S < %s | FileCheck %s
%struct = type { i8, i16, i32, i64, i64}
@Global = internal constant %struct {i8 0, i16 1, i32 2, i64 3, i64 4}
define internal i64 @func2(i64 *%x) {
; CHECK-LABEL: @func2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[VAL:%.*]] = ptrtoint i64* [[X:%.*]] to i64
; CHECK-NEXT: ret i64 [[VAL]]
;
entry:
%val = ptrtoint i64* %x to i64
ret i64 %val
}
define internal i64 @func(i64 *%x, i64 (i64*)* %binop) {
; CHECK-LABEL: @func(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = call i64 [[BINOP:%.*]](i64* [[X:%.*]])
; CHECK-NEXT: ret i64 [[TMP0]]
;
entry:
%tmp0 = call i64 %binop(i64* %x)
ret i64 %tmp0
}
define internal i64 @zoo(i1 %flag) {
; CHECK-LABEL: @zoo(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[PLUS:%.*]], label [[MINUS:%.*]]
; CHECK: plus:
; CHECK-NEXT: [[TMP0:%.*]] = call i64 @func2(i64* getelementptr inbounds ([[STRUCT:%.*]], %struct* @Global, i32 0, i32 3))
; CHECK-NEXT: br label [[MERGE:%.*]]
; CHECK: minus:
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @func2(i64* getelementptr inbounds ([[STRUCT]], %struct* @Global, i32 0, i32 4))
; CHECK-NEXT: br label [[MERGE]]
; CHECK: merge:
; CHECK-NEXT: [[TMP2:%.*]] = phi i64 [ [[TMP0]], [[PLUS]] ], [ [[TMP1]], [[MINUS]] ]
; CHECK-NEXT: ret i64 [[TMP2]]
;
entry:
br i1 %flag, label %plus, label %minus
plus:
%arg = getelementptr %struct, %struct* @Global, i32 0, i32 3
%tmp0 = call i64 @func2(i64* %arg)
br label %merge
minus:
%arg2 = getelementptr %struct, %struct* @Global, i32 0, i32 4
%tmp1 = call i64 @func2(i64* %arg2)
br label %merge
merge:
%tmp2 = phi i64 [ %tmp0, %plus ], [ %tmp1, %minus]
ret i64 %tmp2
}
define i64 @main() {
; CHECK-LABEL: @main(
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @zoo(i1 false)
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @zoo(i1 true)
; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret i64 [[TMP3]]
;
%1 = call i64 @zoo(i1 0)
%2 = call i64 @zoo(i1 1)
%3 = add i64 %1, %2
ret i64 %3
}