File: preserve-nonnull-load-metadata.ll

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (134 lines) | stat: -rw-r--r-- 4,410 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=mem2reg -S | FileCheck %s

; This tests that mem2reg preserves the !nonnull metadata on loads
; from allocas that get optimized out.

; Check the case where the alloca in question has a single store.
define float* @single_store(float** %arg) {
; CHECK-LABEL: @single_store(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[ARG_LOAD:%.*]] = load float*, float** [[ARG:%.*]], align 8
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne float* [[ARG_LOAD]], null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    ret float* [[ARG_LOAD]]
;
entry:
  %buf = alloca float*
  %arg.load = load float*, float** %arg, align 8
  store float* %arg.load, float** %buf, align 8
  %buf.load = load float*, float **%buf, !nonnull !0
  ret float* %buf.load
}

; Check the case where the alloca in question has more than one
; store but still within one basic block.
define float* @single_block(float** %arg) {
; CHECK-LABEL: @single_block(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[ARG_LOAD:%.*]] = load float*, float** [[ARG:%.*]], align 8
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne float* [[ARG_LOAD]], null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    ret float* [[ARG_LOAD]]
;
entry:
  %buf = alloca float*
  %arg.load = load float*, float** %arg, align 8
  store float* null, float** %buf, align 8
  store float* %arg.load, float** %buf, align 8
  %buf.load = load float*, float **%buf, !nonnull !0
  ret float* %buf.load
}

; Check the case where the alloca in question has more than one
; store and also reads ands writes in multiple blocks.
define float* @multi_block(float** %arg) {
; CHECK-LABEL: @multi_block(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[ARG_LOAD:%.*]] = load float*, float** [[ARG:%.*]], align 8
; CHECK-NEXT:    br label [[NEXT:%.*]]
; CHECK:       next:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne float* [[ARG_LOAD]], null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    ret float* [[ARG_LOAD]]
;
entry:
  %buf = alloca float*
  %arg.load = load float*, float** %arg, align 8
  store float* null, float** %buf, align 8
  br label %next
next:
  store float* %arg.load, float** %buf, align 8
  %buf.load = load float*, float** %buf, !nonnull !0
  ret float* %buf.load
}

; Check that we don't add an assume if it's not
; necessary i.e. the value is already implied to be nonnull
define float* @no_assume(float** %arg) {
; CHECK-LABEL: @no_assume(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[ARG_LOAD:%.*]] = load float*, float** [[ARG:%.*]], align 8
; CHECK-NEXT:    [[CN:%.*]] = icmp ne float* [[ARG_LOAD]], null
; CHECK-NEXT:    br i1 [[CN]], label [[NEXT:%.*]], label [[FIN:%.*]]
; CHECK:       next:
; CHECK-NEXT:    ret float* [[ARG_LOAD]]
; CHECK:       fin:
; CHECK-NEXT:    ret float* null
;
entry:
  %buf = alloca float*
  %arg.load = load float*, float** %arg, align 8
  %cn = icmp ne float* %arg.load, null
  br i1 %cn, label %next, label %fin
next:
; At this point the above nonnull check ensures that
; the value %arg.load is nonnull in this block and thus
; we need not add the assume.
  store float* %arg.load, float** %buf, align 8
  %buf.load = load float*, float** %buf, !nonnull !0
  ret float* %buf.load
fin:
  ret float* null
}

define float* @no_store_single_load() {
; CHECK-LABEL: @no_store_single_load(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne float* undef, null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    ret float* undef
;
entry:
  %buf = alloca float*
  %buf.load = load float*, float **%buf, !nonnull !0
  ret float* %buf.load
}

define float* @no_store_multiple_loads(i1 %c) {
; CHECK-LABEL: @no_store_multiple_loads(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK:       if:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne float* undef, null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    ret float* undef
; CHECK:       else:
; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne float* undef, null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP1]])
; CHECK-NEXT:    ret float* undef
;
entry:
  %buf = alloca float*
  br i1 %c, label %if, label %else

if:
  %buf.load = load float*, float **%buf, !nonnull !0
  ret float* %buf.load

  else:
  %buf.load2 = load float*, float **%buf, !nonnull !0
  ret float* %buf.load2
}

!0 = !{}