; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -S -passes=gvn -enable-load-pre < %s | FileCheck %s --check-prefixes=CHECK,MDEP ; RUN: opt -S -passes='gvn' -enable-load-pre < %s | FileCheck %s --check-prefixes=CHECK,MSSA target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; These tests exercise situations when instructions that were first instructions ; with implicit control flow get removed. We make sure that after that we don't ; face crashes and are still able to perform PRE correctly. declare i32 @foo(i32 %arg) #0 define hidden void @test_01(i32 %x, i32 %y) { ; c2 only throws if c1 throws, so it can be safely removed and then PRE can ; hoist the load out of loop. ; MDEP-LABEL: define hidden void @test_01( ; MDEP-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; MDEP-NEXT: [[ENTRY:.*:]] ; MDEP-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]]) ; MDEP-NEXT: [[VAL_PRE:%.*]] = load i32, ptr null, align 8 ; MDEP-NEXT: br label %[[LOOP:.*]] ; MDEP: [[LOOP]]: ; MDEP-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[VAL_PRE]]) ; MDEP-NEXT: br label %[[LOOP]] ; ; MSSA-LABEL: define hidden void @test_01( ; MSSA-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; MSSA-NEXT: [[ENTRY:.*:]] ; MSSA-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]]) ; MSSA-NEXT: br label %[[LOOP:.*]] ; MSSA: [[LOOP]]: ; MSSA-NEXT: [[VAL:%.*]] = load i32, ptr null, align 8 ; MSSA-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[VAL]]) ; MSSA-NEXT: br label %[[LOOP]] ; entry: %c1 = call i32 @foo(i32 %x) br label %loop loop: %c2 = call i32 @foo(i32 %x) %val = load i32, ptr null, align 8 %c3 = call i32 @foo(i32 %val) br label %loop } define hidden void @test_02(i32 %x, i32 %y) { ; PRE is not allowed because c2 may throw. ; CHECK-LABEL: define hidden void @test_02( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]]) ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[C2:%.*]] = call i32 @foo(i32 [[Y]]) ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr null, align 8 ; CHECK-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[VAL]]) ; CHECK-NEXT: br label %[[LOOP]] ; entry: %c1 = call i32 @foo(i32 %x) br label %loop loop: %c2 = call i32 @foo(i32 %y) %val = load i32, ptr null, align 8 %c3 = call i32 @foo(i32 %val) br label %loop } define hidden void @test_03(i32 %x, i32 %y) { ; PRE of load is allowed because c2 only throws if c1 throws. c3 should ; not be eliminated. c4 is eliminated because it only throws if c3 throws. ; MDEP-LABEL: define hidden void @test_03( ; MDEP-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; MDEP-NEXT: [[ENTRY:.*:]] ; MDEP-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]]) ; MDEP-NEXT: [[VAL_PRE:%.*]] = load i32, ptr null, align 8 ; MDEP-NEXT: br label %[[LOOP:.*]] ; MDEP: [[LOOP]]: ; MDEP-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[Y]]) ; MDEP-NEXT: [[C5:%.*]] = call i32 @foo(i32 [[VAL_PRE]]) ; MDEP-NEXT: br label %[[LOOP]] ; ; MSSA-LABEL: define hidden void @test_03( ; MSSA-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; MSSA-NEXT: [[ENTRY:.*:]] ; MSSA-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]]) ; MSSA-NEXT: br label %[[LOOP:.*]] ; MSSA: [[LOOP]]: ; MSSA-NEXT: [[VAL:%.*]] = load i32, ptr null, align 8 ; MSSA-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[Y]]) ; MSSA-NEXT: [[VAL2:%.*]] = load i32, ptr null, align 8 ; MSSA-NEXT: [[C5:%.*]] = call i32 @foo(i32 [[VAL]]) ; MSSA-NEXT: br label %[[LOOP]] ; entry: %c1 = call i32 @foo(i32 %x) br label %loop loop: %c2 = call i32 @foo(i32 %x) %val = load i32, ptr null, align 8 %c3 = call i32 @foo(i32 %y) %val2 = load i32, ptr null, align 8 %c4 = call i32 @foo(i32 %y) %c5 = call i32 @foo(i32 %val) br label %loop } define hidden void @test_04(i32 %x, i32 %y) { ; PRE is not allowed even after we remove c2 because now c3 prevents us from it. ; CHECK-LABEL: define hidden void @test_04( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]]) ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[Y]]) ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr null, align 8 ; CHECK-NEXT: [[C5:%.*]] = call i32 @foo(i32 [[VAL]]) ; CHECK-NEXT: br label %[[LOOP]] ; entry: %c1 = call i32 @foo(i32 %x) br label %loop loop: %c2 = call i32 @foo(i32 %x) %c3 = call i32 @foo(i32 %y) %val = load i32, ptr null, align 8 %c4 = call i32 @foo(i32 %y) %c5 = call i32 @foo(i32 %val) br label %loop } attributes #0 = { readnone }