summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms
diff options
context:
space:
mode:
authorJoerg Sonnenberger <joerg@bec.de>2019-10-13 23:00:15 +0000
committerJoerg Sonnenberger <joerg@bec.de>2019-10-13 23:00:15 +0000
commite4300c392de28b659749d77b415b4903786caa0c (patch)
treee2932a42e822bdc97da8cc30e6d80dd87c0518ec /llvm/test/Transforms
parent529f4ed401ea9761461fb42b1efa552c320c40fb (diff)
downloadbcm5719-llvm-e4300c392de28b659749d77b415b4903786caa0c.tar.gz
bcm5719-llvm-e4300c392de28b659749d77b415b4903786caa0c.zip
Add a pass to lower is.constant and objectsize intrinsics
This pass lowers is.constant and objectsize intrinsics not simplified by earlier constant folding, i.e. if the object given is not constant or if not using the optimized pass chain. The result is recursively simplified and constant conditionals are pruned, so that dead blocks are removed even for -O0. This allows inline asm blocks with operand constraints to work all the time. The new pass replaces the existing lowering in the codegen-prepare pass and fallbacks in SDAG/GlobalISEL and FastISel. The latter now assert on the intrinsics. Differential Revision: https://reviews.llvm.org/D65280 llvm-svn: 374743
Diffstat (limited to 'llvm/test/Transforms')
-rw-r--r--llvm/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll20
-rw-r--r--llvm/test/Transforms/CodeGenPrepare/builtin-condition.ll123
-rw-r--r--llvm/test/Transforms/LowerConstantIntrinsics/constant-intrinsics.ll114
-rw-r--r--llvm/test/Transforms/LowerConstantIntrinsics/crash-on-large-allocas.ll (renamed from llvm/test/Transforms/CodeGenPrepare/crash-on-large-allocas.ll)2
-rw-r--r--llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll (renamed from llvm/test/Transforms/CodeGenPrepare/basic.ll)17
5 files changed, 122 insertions, 154 deletions
diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll b/llvm/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll
index fc6d66a6082..9ba1d7db5ad 100644
--- a/llvm/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll
@@ -514,26 +514,6 @@ exit:
ret void
}
-; This was crashing when trying to delay instruction removal/deletion.
-
-declare i64 @llvm.objectsize.i64.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg) #0
-
-define hidden fastcc void @crash() {
-; CHECK-LABEL: @crash(
-; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 undef, i64 undef)
-; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
-; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
-; CHECK-NEXT: [[T2:%.*]] = select i1 undef, i1 undef, i1 [[OV]]
-; CHECK-NEXT: unreachable
-;
- %t0 = add i64 undef, undef
- %t1 = icmp ult i64 %t0, undef
- %t2 = select i1 undef, i1 undef, i1 %t1
- %t3 = call i64 @llvm.objectsize.i64.p0i8(i8* nonnull undef, i1 false, i1 false, i1 false)
- %t4 = icmp ugt i64 %t3, 7
- unreachable
-}
-
; Check that every instruction inserted by -codegenprepare has a debug location.
; DEBUG: CheckModuleDebugify: PASS
diff --git a/llvm/test/Transforms/CodeGenPrepare/builtin-condition.ll b/llvm/test/Transforms/CodeGenPrepare/builtin-condition.ll
deleted file mode 100644
index e42529a7b9a..00000000000
--- a/llvm/test/Transforms/CodeGenPrepare/builtin-condition.ll
+++ /dev/null
@@ -1,123 +0,0 @@
-; RUN: opt -codegenprepare -S < %s | FileCheck %s
-
-; Ensure we act sanely on overflow.
-; CHECK-LABEL: define i32 @bar
-define i32 @bar() {
-entry:
- ; CHECK: ret i32 -1
- %az = alloca [2147483649 x i32], align 16
- %a = alloca i8*, align 8
- %arraydecay = getelementptr inbounds [2147483649 x i32], [2147483649 x i32]* %az, i32 0, i32 0
- %0 = bitcast i32* %arraydecay to i8*
- store i8* %0, i8** %a, align 8
- %1 = load i8*, i8** %a, align 8
- %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false)
- ret i32 %2
-}
-
-; CHECK-LABEL: define i32 @baz
-define i32 @baz(i32 %n) {
-entry:
- ; CHECK: ret i32 -1
- %az = alloca [1 x i32], align 16
- %bz = alloca [4294967297 x i32], align 16
- %tobool = icmp ne i32 %n, 0
- %arraydecay = getelementptr inbounds [1 x i32], [1 x i32]* %az, i64 0, i64 0
- %arraydecay1 = getelementptr inbounds [4294967297 x i32], [4294967297 x i32]* %bz, i64 0, i64 0
- %cond = select i1 %tobool, i32* %arraydecay, i32* %arraydecay1
- %0 = bitcast i32* %cond to i8*
- %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false)
- ret i32 %1
-}
-
-declare i32 @llvm.objectsize.i32.p0i8(i8*, i1)
-
-; The following tests were generated by:
-; #include<stdlib.h>
-; #define STATIC_BUF_SIZE 10
-; #define LARGER_BUF_SIZE 30
-;
-; size_t foo1(int flag) {
-; char *cptr;
-; char chararray[LARGER_BUF_SIZE];
-; char chararray2[STATIC_BUF_SIZE];
-; if(flag)
-; cptr = chararray2;
-; else
-; cptr = chararray;
-;
-; return __builtin_object_size(cptr, 2);
-; }
-;
-; size_t foo2(int n) {
-; char Small[10];
-; char Large[20];
-; char *Ptr = n ? Small : Large + 19;
-; return __builtin_object_size(Ptr, 0);
-; }
-;
-; void foo() {
-; size_t ret;
-; size_t ret1;
-; ret = foo1(0);
-; ret1 = foo2(0);
-; printf("\n%d %d\n", ret, ret1);
-; }
-
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-@.str = private unnamed_addr constant [8 x i8] c"\0A%d %d\0A\00", align 1
-
-define i64 @foo1(i32 %flag) {
-entry:
- %chararray = alloca [30 x i8], align 16
- %chararray2 = alloca [10 x i8], align 1
- %0 = getelementptr inbounds [30 x i8], [30 x i8]* %chararray, i64 0, i64 0
- call void @llvm.lifetime.start.p0i8(i64 30, i8* %0)
- %1 = getelementptr inbounds [10 x i8], [10 x i8]* %chararray2, i64 0, i64 0
- call void @llvm.lifetime.start.p0i8(i64 10, i8* %1)
- %tobool = icmp eq i32 %flag, 0
- %cptr.0 = select i1 %tobool, i8* %0, i8* %1
- %2 = call i64 @llvm.objectsize.i64.p0i8(i8* %cptr.0, i1 true)
- call void @llvm.lifetime.end.p0i8(i64 10, i8* %1)
- call void @llvm.lifetime.end.p0i8(i64 30, i8* %0)
- ret i64 %2
-; CHECK-LABEL: foo1
-; CHECK: ret i64 10
-}
-
-declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
-
-declare i64 @llvm.objectsize.i64.p0i8(i8*, i1)
-
-declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
-
-define i64 @foo2(i32 %n) {
-entry:
- %Small = alloca [10 x i8], align 1
- %Large = alloca [20 x i8], align 16
- %0 = getelementptr inbounds [10 x i8], [10 x i8]* %Small, i64 0, i64 0
- call void @llvm.lifetime.start.p0i8(i64 10, i8* %0)
- %1 = getelementptr inbounds [20 x i8], [20 x i8]* %Large, i64 0, i64 0
- call void @llvm.lifetime.start.p0i8(i64 20, i8* %1)
- %tobool = icmp ne i32 %n, 0
- %add.ptr = getelementptr inbounds [20 x i8], [20 x i8]* %Large, i64 0, i64 19
- %cond = select i1 %tobool, i8* %0, i8* %add.ptr
- %2 = call i64 @llvm.objectsize.i64.p0i8(i8* %cond, i1 false)
- call void @llvm.lifetime.end.p0i8(i64 20, i8* %1)
- call void @llvm.lifetime.end.p0i8(i64 10, i8* %0)
- ret i64 %2
-; CHECK-LABEL: foo2
-; CHECK: ret i64 10
-}
-
-define void @foo() {
-entry:
- %call = tail call i64 @foo1(i32 0)
- %call1 = tail call i64 @foo2(i32 0)
- %call2 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i64 %call, i64 %call1)
- ret void
-}
-
-declare i32 @printf(i8* nocapture readonly, ...)
diff --git a/llvm/test/Transforms/LowerConstantIntrinsics/constant-intrinsics.ll b/llvm/test/Transforms/LowerConstantIntrinsics/constant-intrinsics.ll
new file mode 100644
index 00000000000..b2c98d2049c
--- /dev/null
+++ b/llvm/test/Transforms/LowerConstantIntrinsics/constant-intrinsics.ll
@@ -0,0 +1,114 @@
+; RUN: opt -lower-constant-intrinsics -S < %s | FileCheck %s
+
+;; Ensure that an unfoldable is.constant gets lowered reasonably in
+;; optimized codegen, in particular, that the "true" branch is
+;; eliminated.
+
+;; Also ensure that any unfoldable objectsize is resolved in order.
+
+;; CHECK-NOT: tail call i32 @subfun_1()
+;; CHECK: tail call i32 @subfun_2()
+;; CHECK-NOT: tail call i32 @subfun_1()
+
+declare i1 @llvm.is.constant.i32(i32 %a) nounwind readnone
+declare i1 @llvm.is.constant.i64(i64 %a) nounwind readnone
+declare i1 @llvm.is.constant.i256(i256 %a) nounwind readnone
+declare i1 @llvm.is.constant.v2i64(<2 x i64> %a) nounwind readnone
+declare i1 @llvm.is.constant.f32(float %a) nounwind readnone
+declare i1 @llvm.is.constant.sl_i32i32s({i32, i32} %a) nounwind readnone
+declare i1 @llvm.is.constant.a2i64([2 x i64] %a) nounwind readnone
+declare i1 @llvm.is.constant.p0i64(i64* %a) nounwind readnone
+
+declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) nounwind readnone
+
+declare i32 @subfun_1()
+declare i32 @subfun_2()
+
+define i32 @test_branch(i32 %in) nounwind {
+ %v = call i1 @llvm.is.constant.i32(i32 %in)
+ br i1 %v, label %True, label %False
+
+True:
+ %call1 = tail call i32 @subfun_1()
+ ret i32 %call1
+
+False:
+ %call2 = tail call i32 @subfun_2()
+ ret i32 %call2
+}
+
+;; llvm.objectsize is another tricky case which gets folded to -1 very
+;; late in the game. We'd like to ensure that llvm.is.constant of
+;; llvm.objectsize is true.
+define i1 @test_objectsize(i8* %obj) nounwind {
+;; CHECK-LABEL: test_objectsize
+;; CHECK-NOT: llvm.objectsize
+;; CHECK-NOT: llvm.is.constant
+;; CHECK: ret i1 true
+ %os = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 false, i1 false, i1 false)
+ %os1 = add i64 %os, 1
+ %v = call i1 @llvm.is.constant.i64(i64 %os1)
+ ret i1 %v
+}
+
+@test_phi_a = dso_local global i32 0, align 4
+declare dso_local i32 @test_phi_b(...)
+
+; Function Attrs: nounwind uwtable
+define dso_local i32 @test_phi() {
+entry:
+ %0 = load i32, i32* @test_phi_a, align 4
+ %1 = tail call i1 @llvm.is.constant.i32(i32 %0)
+ br i1 %1, label %cond.end, label %cond.false
+
+cond.false: ; preds = %entry
+ %call = tail call i32 bitcast (i32 (...)* @test_phi_b to i32 ()*)() #3
+ %.pre = load i32, i32* @test_phi_a, align 4
+ br label %cond.end
+
+cond.end: ; preds = %entry, %cond.false
+ %2 = phi i32 [ %.pre, %cond.false ], [ %0, %entry ]
+ %cond = phi i32 [ %call, %cond.false ], [ 1, %entry ]
+ %cmp = icmp eq i32 %cond, %2
+ br i1 %cmp, label %cond.true1, label %cond.end4
+
+cond.true1: ; preds = %cond.end
+ %call2 = tail call i32 bitcast (i32 (...)* @test_phi_b to i32 ()*)() #3
+ br label %cond.end4
+
+cond.end4: ; preds = %cond.end, %cond.true1
+ ret i32 undef
+}
+
+define i1 @test_various_types(i256 %int, float %float, <2 x i64> %vec, {i32, i32} %struct, [2 x i64] %arr, i64* %ptr) #0 {
+; CHECK-LABEL: @test_various_types(
+; CHECK-NOT: llvm.is.constant
+ %v1 = call i1 @llvm.is.constant.i256(i256 %int)
+ %v2 = call i1 @llvm.is.constant.f32(float %float)
+ %v3 = call i1 @llvm.is.constant.v2i64(<2 x i64> %vec)
+ %v4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} %struct)
+ %v5 = call i1 @llvm.is.constant.a2i64([2 x i64] %arr)
+ %v6 = call i1 @llvm.is.constant.p0i64(i64* %ptr)
+
+ %c1 = call i1 @llvm.is.constant.i256(i256 -1)
+ %c2 = call i1 @llvm.is.constant.f32(float 17.0)
+ %c3 = call i1 @llvm.is.constant.v2i64(<2 x i64> <i64 -1, i64 44>)
+ %c4 = call i1 @llvm.is.constant.sl_i32i32s({i32, i32} {i32 -1, i32 32})
+ %c5 = call i1 @llvm.is.constant.a2i64([2 x i64] [i64 -1, i64 32])
+ %c6 = call i1 @llvm.is.constant.p0i64(i64* inttoptr (i32 42 to i64*))
+
+ %x1 = add i1 %v1, %c1
+ %x2 = add i1 %v2, %c2
+ %x3 = add i1 %v3, %c3
+ %x4 = add i1 %v4, %c4
+ %x5 = add i1 %v5, %c5
+ %x6 = add i1 %v6, %c6
+
+ %res2 = add i1 %x1, %x2
+ %res3 = add i1 %res2, %x3
+ %res4 = add i1 %res3, %x4
+ %res5 = add i1 %res4, %x5
+ %res6 = add i1 %res5, %x6
+
+ ret i1 %res6
+}
diff --git a/llvm/test/Transforms/CodeGenPrepare/crash-on-large-allocas.ll b/llvm/test/Transforms/LowerConstantIntrinsics/crash-on-large-allocas.ll
index 5049207ec27..e4e981161fd 100644
--- a/llvm/test/Transforms/CodeGenPrepare/crash-on-large-allocas.ll
+++ b/llvm/test/Transforms/LowerConstantIntrinsics/crash-on-large-allocas.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -codegenprepare %s -o - | FileCheck %s
+; RUN: opt -S -lower-constant-intrinsics %s -o - | FileCheck %s
;
; Ensure that we don't {crash,return a bad value} when given an alloca larger
; than what a pointer can represent.
diff --git a/llvm/test/Transforms/CodeGenPrepare/basic.ll b/llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll
index 1a58d61b6e9..94aba44fcc4 100644
--- a/llvm/test/Transforms/CodeGenPrepare/basic.ll
+++ b/llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll
@@ -1,12 +1,15 @@
-; RUN: opt -codegenprepare -S < %s | FileCheck %s
+; RUN: opt -lower-constant-intrinsics -S < %s | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin10.0.0"
+declare i64 @llvm.objectsize.i64(i8*, i1, i1, i1) nounwind readonly
+declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1, i1) nounwind readonly
+declare void @llvm.trap() nounwind
+
; CHECK-LABEL: @test1(
; objectsize should fold to a constant, which causes the branch to fold to an
-; uncond branch. Next, we fold the control flow alltogether.
-; rdar://8785296
+; uncond branch.
define i32 @test1(i8* %ptr) nounwind ssp noredzone align 2 {
entry:
%0 = tail call i64 @llvm.objectsize.i64(i8* %ptr, i1 false, i1 false, i1 false)
@@ -14,7 +17,7 @@ entry:
br i1 %1, label %T, label %trap
; CHECK: entry:
-; CHECK-NOT: br label %
+; CHECK-NOT: label %trap
trap: ; preds = %0, %entry
tail call void @llvm.trap() noreturn nounwind
@@ -78,9 +81,3 @@ entry:
i1 false, i1 false)
ret i64 %0
}
-
-
-declare i64 @llvm.objectsize.i64(i8*, i1, i1, i1) nounwind readonly
-declare i64 @llvm.objectsize.i64.p1i8(i8 addrspace(1)*, i1, i1, i1) nounwind readonly
-
-declare void @llvm.trap() nounwind
OpenPOWER on IntegriCloud