142 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -S -passes=gvn -enable-load-pre < %s | FileCheck %s --check-prefixes=CHECK,MDEP3; RUN: opt -S -passes='gvn<memoryssa>' -enable-load-pre < %s | FileCheck %s --check-prefixes=CHECK,MSSA4 5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"6 7; These tests exercise situations when instructions that were first instructions8; with implicit control flow get removed. We make sure that after that we don't9; face crashes and are still able to perform PRE correctly.10 11declare i32 @foo(i32 %arg) #012 13define hidden void @test_01(i32 %x, i32 %y) {14; c2 only throws if c1 throws, so it can be safely removed and then PRE can15; hoist the load out of loop.16; MDEP-LABEL: define hidden void @test_01(17; MDEP-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {18; MDEP-NEXT: [[ENTRY:.*:]]19; MDEP-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]])20; MDEP-NEXT: [[VAL_PRE:%.*]] = load i32, ptr null, align 821; MDEP-NEXT: br label %[[LOOP:.*]]22; MDEP: [[LOOP]]:23; MDEP-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[VAL_PRE]])24; MDEP-NEXT: br label %[[LOOP]]25;26; MSSA-LABEL: define hidden void @test_01(27; MSSA-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {28; MSSA-NEXT: [[ENTRY:.*:]]29; MSSA-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]])30; MSSA-NEXT: br label %[[LOOP:.*]]31; MSSA: [[LOOP]]:32; MSSA-NEXT: [[VAL:%.*]] = load i32, ptr null, align 833; MSSA-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[VAL]])34; MSSA-NEXT: br label %[[LOOP]]35;36 37entry:38 %c1 = call i32 @foo(i32 %x)39 br label %loop40 41loop:42 %c2 = call i32 @foo(i32 %x)43 %val = load i32, ptr null, align 844 %c3 = call i32 @foo(i32 %val)45 br label %loop46}47 48define hidden void @test_02(i32 %x, i32 %y) {49; PRE is not allowed because c2 may throw.50; CHECK-LABEL: define hidden void @test_02(51; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {52; CHECK-NEXT: [[ENTRY:.*:]]53; CHECK-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]])54; CHECK-NEXT: br label %[[LOOP:.*]]55; CHECK: [[LOOP]]:56; CHECK-NEXT: [[C2:%.*]] = call i32 @foo(i32 [[Y]])57; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr null, align 858; CHECK-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[VAL]])59; CHECK-NEXT: br label %[[LOOP]]60;61 62entry:63 %c1 = call i32 @foo(i32 %x)64 br label %loop65 66loop:67 %c2 = call i32 @foo(i32 %y)68 %val = load i32, ptr null, align 869 %c3 = call i32 @foo(i32 %val)70 br label %loop71}72 73define hidden void @test_03(i32 %x, i32 %y) {74; PRE of load is allowed because c2 only throws if c1 throws. c3 should75; not be eliminated. c4 is eliminated because it only throws if c3 throws.76; MDEP-LABEL: define hidden void @test_03(77; MDEP-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {78; MDEP-NEXT: [[ENTRY:.*:]]79; MDEP-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]])80; MDEP-NEXT: [[VAL_PRE:%.*]] = load i32, ptr null, align 881; MDEP-NEXT: br label %[[LOOP:.*]]82; MDEP: [[LOOP]]:83; MDEP-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[Y]])84; MDEP-NEXT: [[C5:%.*]] = call i32 @foo(i32 [[VAL_PRE]])85; MDEP-NEXT: br label %[[LOOP]]86;87; MSSA-LABEL: define hidden void @test_03(88; MSSA-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {89; MSSA-NEXT: [[ENTRY:.*:]]90; MSSA-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]])91; MSSA-NEXT: br label %[[LOOP:.*]]92; MSSA: [[LOOP]]:93; MSSA-NEXT: [[VAL:%.*]] = load i32, ptr null, align 894; MSSA-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[Y]])95; MSSA-NEXT: [[VAL2:%.*]] = load i32, ptr null, align 896; MSSA-NEXT: [[C5:%.*]] = call i32 @foo(i32 [[VAL]])97; MSSA-NEXT: br label %[[LOOP]]98;99 100entry:101 %c1 = call i32 @foo(i32 %x)102 br label %loop103 104loop:105 %c2 = call i32 @foo(i32 %x)106 %val = load i32, ptr null, align 8107 %c3 = call i32 @foo(i32 %y)108 %val2 = load i32, ptr null, align 8109 %c4 = call i32 @foo(i32 %y)110 %c5 = call i32 @foo(i32 %val)111 br label %loop112}113 114define hidden void @test_04(i32 %x, i32 %y) {115; PRE is not allowed even after we remove c2 because now c3 prevents us from it.116; CHECK-LABEL: define hidden void @test_04(117; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {118; CHECK-NEXT: [[ENTRY:.*:]]119; CHECK-NEXT: [[C1:%.*]] = call i32 @foo(i32 [[X]])120; CHECK-NEXT: br label %[[LOOP:.*]]121; CHECK: [[LOOP]]:122; CHECK-NEXT: [[C3:%.*]] = call i32 @foo(i32 [[Y]])123; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr null, align 8124; CHECK-NEXT: [[C5:%.*]] = call i32 @foo(i32 [[VAL]])125; CHECK-NEXT: br label %[[LOOP]]126;127 128entry:129 %c1 = call i32 @foo(i32 %x)130 br label %loop131 132loop:133 %c2 = call i32 @foo(i32 %x)134 %c3 = call i32 @foo(i32 %y)135 %val = load i32, ptr null, align 8136 %c4 = call i32 @foo(i32 %y)137 %c5 = call i32 @foo(i32 %val)138 br label %loop139}140 141attributes #0 = { readnone }142