| ; RUN: opt < %s -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: define float* @single_store |
| ; CHECK: %arg.load = load float*, float** %arg, align 8 |
| ; CHECK: [[ASSUME:%(.*)]] = icmp ne float* %arg.load, null |
| ; CHECK: call void @llvm.assume(i1 {{.*}}[[ASSUME]]) |
| ; CHECK: 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: define float* @single_block |
| ; CHECK: %arg.load = load float*, float** %arg, align 8 |
| ; CHECK: [[ASSUME:%(.*)]] = icmp ne float* %arg.load, null |
| ; CHECK: call void @llvm.assume(i1 {{.*}}[[ASSUME]]) |
| ; CHECK: 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: define float* @multi_block |
| ; CHECK-LABEL: entry: |
| ; CHECK: %arg.load = load float*, float** %arg, align 8 |
| ; CHECK: br label %next |
| ; CHECK-LABEL: next: |
| ; CHECK: [[ASSUME:%(.*)]] = icmp ne float* %arg.load, null |
| ; CHECK: call void @llvm.assume(i1 {{.*}}[[ASSUME]]) |
| ; CHECK: 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: define float* @no_assume |
| ; CHECK-LABEL: entry: |
| ; CHECK: %arg.load = load float*, float** %arg, align 8 |
| ; CHECK: %cn = icmp ne float* %arg.load, null |
| ; CHECK: br i1 %cn, label %next, label %fin |
| ; CHECK-LABEL: next: |
| ; CHECK-NOT: call void @llvm.assume |
| ; CHECK: ret float* %arg.load |
| ; CHECK-LABEL: fin: |
| ; CHECK: 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 |
| } |
| |
| !0 = !{} |