diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp index 9d7c7c68d2d5..0d2d55aa0cf7 100644 --- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp +++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp @@ -675,6 +675,11 @@ private: continue; auto *V = CS.getArgOperand(A->getArgNo()); + if (isa(V)) + return false; + if (isa(V)) + return false; + // TrackValueOfGlobalVariable only tracks scalar global variables. if (auto *GV = dyn_cast(V)) { // Check if we want to specialize on the address of non-constant diff --git a/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll b/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll index d0a912447822..d5420108e733 100644 --- a/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll +++ b/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll @@ -9,38 +9,6 @@ %struct = type { i8, i16, i32, i64, i64} @Global = internal constant %struct {i8 0, i16 1, i32 2, i64 3, i64 4} -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.1(i64* getelementptr inbounds ([[STRUCT:%.*]], %struct* @Global, i32 0, i32 3)) -; CHECK-NEXT: br label [[MERGE:%.*]] -; CHECK: minus: -; CHECK-NEXT: [[TMP1:%.*]] = call i64 @func2.2(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 internal i64 @func2(i64 *%x) { ; CHECK-LABEL: @func2( ; CHECK-NEXT: entry: @@ -63,6 +31,39 @@ entry: 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) @@ -75,13 +76,3 @@ define i64 @main() { %3 = add i64 %1, %2 ret i64 %3 } - -; CHECK-LABEL: define internal i64 @func2.1( -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i64 ptrtoint (i64* getelementptr inbounds (%struct, %struct* @Global, i32 0, i32 3) to i64) -; CHECK-NEXT: } - -; CHECK-LABEL: define internal i64 @func2.2( -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i64 ptrtoint (i64* getelementptr inbounds (%struct, %struct* @Global, i32 0, i32 4) to i64) -; CHECK-NEXT: } diff --git a/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression2.ll b/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression2.ll new file mode 100644 index 000000000000..0f3c79cb8e9f --- /dev/null +++ b/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression2.ll @@ -0,0 +1,44 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -function-specialization -force-function-specialization -S < %s | FileCheck %s + +; Check that we don't crash and specialise on a constant expression. + +%struct.pluto = type { %struct.spam } +%struct.quux = type { i16 } +%struct.spam = type { i16 } + +@global.5 = external dso_local global [4 x %struct.pluto], align 1 +@global.12 = external global %struct.quux, align 1 + +define internal i16 @wobble.972(%struct.quux* byval(%struct.quux) align 1 %arg, i16 %arg1, %struct.spam* byval(%struct.spam) align 1 %arg2, %struct.quux* byval(%struct.quux) align 1 %arg3) #4 { +; CHECK-LABEL: @wobble.972( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP34:%.*]] = bitcast %struct.spam* [[ARG2:%.*]] to i16* +; CHECK-NEXT: unreachable +; +bb: + %tmp34 = bitcast %struct.spam* %arg2 to i16* + unreachable +} + +define internal i16 @snork() { +; CHECK-LABEL: @snork( +; CHECK-NEXT: bb4: +; CHECK-NEXT: [[TMP:%.*]] = call i16 @wobble.972(%struct.quux* byval([[STRUCT_QUUX:%.*]]) align 1 undef, i16 undef, %struct.spam* byval([[STRUCT_SPAM:%.*]]) align 1 getelementptr inbounds ([4 x %struct.pluto], [4 x %struct.pluto]* @global.5, i32 0, i32 3, i32 0), %struct.quux* byval([[STRUCT_QUUX]]) align 1 @global.12) +; CHECK-NEXT: unreachable +; +bb4: + %tmp = call i16 @wobble.972(%struct.quux* byval(%struct.quux) align 1 undef, i16 undef, %struct.spam* byval(%struct.spam) align 1 getelementptr inbounds ([4 x %struct.pluto], [4 x %struct.pluto]* @global.5, i32 0, i32 3, i32 0), %struct.quux* byval(%struct.quux) align 1 @global.12) + unreachable +} + +define i16 @main() { +; CHECK-LABEL: @main( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP:%.*]] = call i16 @snork() +; CHECK-NEXT: unreachable +; +bb: + %tmp = call i16 @snork() + unreachable +} diff --git a/llvm/test/Transforms/FunctionSpecialization/function-specialization-poison.ll b/llvm/test/Transforms/FunctionSpecialization/function-specialization-poison.ll new file mode 100644 index 000000000000..d359deedcc49 --- /dev/null +++ b/llvm/test/Transforms/FunctionSpecialization/function-specialization-poison.ll @@ -0,0 +1,42 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -function-specialization -force-function-specialization -S < %s | FileCheck %s + +; Check that we don't crash and specialise on a poison value. + +%struct.quux = type { i16 } +%struct.spam = type { i16 } + +@global.12 = external global %struct.quux, align 1 + +define internal i16 @wobble(%struct.spam* byval(%struct.spam) %arg2) { +; CHECK-LABEL: @wobble( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[C:%.*]] = bitcast %struct.spam* [[ARG2:%.*]] to i16* +; CHECK-NEXT: unreachable +; +bb: + %C = bitcast %struct.spam* %arg2 to i16* + unreachable +} + +define internal i16 @snork() { +; CHECK-LABEL: @snork( +; CHECK-NEXT: bb4: +; CHECK-NEXT: [[B:%.*]] = call i16 @wobble(%struct.spam* poison) +; CHECK-NEXT: unreachable +; +bb4: + %B = call i16 @wobble(%struct.spam* poison) + unreachable +} + +define i16 @main() { +; CHECK-LABEL: @main( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[A:%.*]] = call i16 @snork() +; CHECK-NEXT: unreachable +; +bb: + %A = call i16 @snork() + unreachable +}