| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 |
| ; RUN: opt -S -passes=gvn < %s | FileCheck %s |
| |
| declare void @capture(ptr) |
| declare void @some_call() |
| |
| define i32 @test_call_before_capture(ptr %p) { |
| ; CHECK-LABEL: define i32 @test_call_before_capture( |
| ; CHECK-SAME: ptr [[P:%.*]]) { |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: store i32 123, ptr [[A]], align 4 |
| ; CHECK-NEXT: call void @some_call() |
| ; CHECK-NEXT: call void @capture(ptr [[A]]) |
| ; CHECK-NEXT: ret i32 123 |
| ; |
| %a = alloca i32 |
| store i32 123, ptr %a |
| call void @some_call() |
| %v = load i32, ptr %a |
| call void @capture(ptr %a) |
| ret i32 %v |
| } |
| |
| define i32 @test_call_after_capture(ptr %p) { |
| ; CHECK-LABEL: define i32 @test_call_after_capture( |
| ; CHECK-SAME: ptr [[P:%.*]]) { |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: store i32 123, ptr [[A]], align 4 |
| ; CHECK-NEXT: call void @capture(ptr [[A]]) |
| ; CHECK-NEXT: call void @some_call() |
| ; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4 |
| ; CHECK-NEXT: ret i32 [[V]] |
| ; |
| %a = alloca i32 |
| store i32 123, ptr %a |
| call void @capture(ptr %a) |
| call void @some_call() |
| %v = load i32, ptr %a |
| ret i32 %v |
| } |
| |
| define i32 @test_store_before_capture(ptr %p) { |
| ; CHECK-LABEL: define i32 @test_store_before_capture( |
| ; CHECK-SAME: ptr [[P:%.*]]) { |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: store i32 123, ptr [[A]], align 4 |
| ; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P]], align 8 |
| ; CHECK-NEXT: store i32 42, ptr [[P2]], align 4 |
| ; CHECK-NEXT: call void @capture(ptr [[A]]) |
| ; CHECK-NEXT: ret i32 123 |
| ; |
| %a = alloca i32 |
| store i32 123, ptr %a |
| %p2 = load ptr, ptr %p |
| store i32 42, ptr %p2 |
| %v = load i32, ptr %a |
| call void @capture(ptr %a) |
| ret i32 %v |
| } |
| |
| define i32 @test_store_after_capture(ptr %p) { |
| ; CHECK-LABEL: define i32 @test_store_after_capture( |
| ; CHECK-SAME: ptr [[P:%.*]]) { |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: store i32 123, ptr [[A]], align 4 |
| ; CHECK-NEXT: call void @capture(ptr [[A]]) |
| ; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P]], align 8 |
| ; CHECK-NEXT: store i32 42, ptr [[P2]], align 4 |
| ; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4 |
| ; CHECK-NEXT: ret i32 [[V]] |
| ; |
| %a = alloca i32 |
| store i32 123, ptr %a |
| call void @capture(ptr %a) |
| %p2 = load ptr, ptr %p |
| store i32 42, ptr %p2 |
| %v = load i32, ptr %a |
| ret i32 %v |
| } |
| |
| define i32 @test_capture_readonly() { |
| ; CHECK-LABEL: define i32 @test_capture_readonly() { |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: store i32 123, ptr [[A]], align 4 |
| ; CHECK-NEXT: call void @capture(ptr readonly [[A]]) |
| ; CHECK-NEXT: ret i32 123 |
| ; |
| %a = alloca i32 |
| store i32 123, ptr %a |
| call void @capture(ptr readonly %a) |
| %v = load i32, ptr %a |
| ret i32 %v |
| } |
| |
| define i32 @test_capture_readonly_with_following_call() { |
| ; CHECK-LABEL: define i32 @test_capture_readonly_with_following_call() { |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: store i32 123, ptr [[A]], align 4 |
| ; CHECK-NEXT: call void @capture(ptr readonly [[A]]) |
| ; CHECK-NEXT: call void @some_call() |
| ; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4 |
| ; CHECK-NEXT: ret i32 [[V]] |
| ; |
| %a = alloca i32 |
| store i32 123, ptr %a |
| call void @capture(ptr readonly %a) |
| call void @some_call() |
| %v = load i32, ptr %a |
| ret i32 %v |
| } |
| |
| declare void @use(i32) |
| |
| define i32 @test_capture_readonly_in_loop() { |
| ; CHECK-LABEL: define i32 @test_capture_readonly_in_loop() { |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: store i32 123, ptr [[A]], align 4 |
| ; CHECK-NEXT: br label [[LOOP:%.*]] |
| ; CHECK: loop: |
| ; CHECK-NEXT: call void @capture(ptr readonly [[A]]) |
| ; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4 |
| ; CHECK-NEXT: call void @use(i32 [[V]]) #[[ATTR0:[0-9]+]] |
| ; CHECK-NEXT: br label [[LOOP]] |
| ; |
| %a = alloca i32 |
| store i32 123, ptr %a |
| br label %loop |
| |
| loop: |
| call void @capture(ptr readonly %a) |
| %v = load i32, ptr %a |
| call void @use(i32 %v) memory(none) |
| br label %loop |
| } |
| |
| define i32 @test_splat_gep_capture(<1 x i32> %index) { |
| ; CHECK-LABEL: define i32 @test_splat_gep_capture( |
| ; CHECK-SAME: <1 x i32> [[INDEX:%.*]]) { |
| ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 |
| ; CHECK-NEXT: store i32 123, ptr [[A]], align 4 |
| ; CHECK-NEXT: [[PTRS:%.*]] = getelementptr inbounds i32, ptr [[A]], <1 x i32> [[INDEX]] |
| ; CHECK-NEXT: call void @some_call(<1 x ptr> [[PTRS]]) |
| ; CHECK-NEXT: [[RELOAD:%.*]] = load i32, ptr [[A]], align 4 |
| ; CHECK-NEXT: ret i32 [[RELOAD]] |
| ; |
| %a = alloca i32 |
| store i32 123, ptr %a |
| %ptrs = getelementptr inbounds i32, ptr %a, <1 x i32> %index |
| call void @some_call(<1 x ptr> %ptrs) |
| %reload = load i32, ptr %a |
| ret i32 %reload |
| } |