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 = !{}
|