[llvm] eba7605 - [FuncSpec] Don't specialise (or crash) on poison or constexpr values

Sjoerd Meijer via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 27 06:59:37 PDT 2021


Author: Sjoerd Meijer
Date: 2021-09-27T14:58:53+01:00
New Revision: eba76056a364d206de7f0ac944c8601c988b6405

URL: https://github.com/llvm/llvm-project/commit/eba76056a364d206de7f0ac944c8601c988b6405
DIFF: https://github.com/llvm/llvm-project/commit/eba76056a364d206de7f0ac944c8601c988b6405.diff

LOG: [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

Added: 
    llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression2.ll
    llvm/test/Transforms/FunctionSpecialization/function-specialization-poison.ll

Modified: 
    llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
    llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll

Removed: 
    


################################################################################
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 @@ class FunctionSpecializer {
         continue;
 
       auto *V = CS.getArgOperand(A->getArgNo());
+      if (isa<PoisonValue>(V))
+        return false;
+      if (isa<ConstantExpr>(V))
+        return false;
+
       // TrackValueOfGlobalVariable only tracks scalar global variables.
       if (auto *GV = dyn_cast<GlobalVariable>(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,15 +9,37 @@
 %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.1(i64* getelementptr inbounds ([[STRUCT:%.*]], %struct* @Global, i32 0, i32 3))
+; 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.2(i64* getelementptr inbounds ([[STRUCT]], %struct* @Global, i32 0, i32 4))
+; 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]] ]
@@ -41,27 +63,6 @@ merge:
   ret i64 %tmp2
 }
 
-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 i64 @main() {
 ; CHECK-LABEL: @main(
@@ -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 }
+
+ at global.5 = external dso_local global [4 x %struct.pluto], align 1
+ at 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 }
+
+ at 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
+}


        


More information about the llvm-commits mailing list