brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.7 KiB · 4e44c08 Raw
360 lines · plain
1; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -win-eh-prepare  < %s | FileCheck %s2; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -passes=win-eh-prepare  < %s | FileCheck %s3; RUN: %if aarch64-registered-target %{ opt -mtriple=aarch64-pc-windows-msvc -S -win-eh-prepare  < %s | FileCheck %s %}4; RUN: %if aarch64-registered-target %{ opt -mtriple=aarch64-pc-windows-msvc -S -passes=win-eh-prepare  < %s | FileCheck %s %}5 6declare i32 @__CxxFrameHandler3(...)7 8declare void @f()9 10declare i32 @g()11 12declare void @h(i32)13 14declare i1 @i()15 16declare void @llvm.bar() nounwind17 18; CHECK-LABEL: @test1(19define void @test1(i1 %B) personality ptr @__CxxFrameHandler3 {20entry:21  ; Spill slot should be inserted here22  ; CHECK: [[Slot:%[^ ]+]] = alloca23  ; Can't store for %phi at these defs because the lifetimes overlap24  ; CHECK-NOT: store25  %x = call i32 @g()26  %y = call i32 @g()27  br i1 %B, label %left, label %right28left:29  ; CHECK: left:30  ; CHECK-NEXT: store i32 %x, ptr [[Slot]]31  ; CHECK-NEXT: invoke void @f32  invoke void @f()33          to label %exit unwind label %merge34right:35  ; CHECK: right:36  ; CHECK-NEXT: store i32 %y, ptr [[Slot]]37  ; CHECK-NEXT: invoke void @f38  invoke void @f()39          to label %exit unwind label %merge40merge:41  ; CHECK: merge:42  ; CHECK-NOT: = phi43  %phi = phi i32 [ %x, %left ], [ %y, %right ]44  %cs1 = catchswitch within none [label %catch] unwind to caller45 46catch:47  %cp = catchpad within %cs1 []48  ; CHECK: catch:49  ; CHECK: [[Reload:%[^ ]+]] = load i32, ptr [[Slot]]50  ; CHECK-NEXT: call void @h(i32 [[Reload]])51  call void @h(i32 %phi) [ "funclet"(token %cp) ]52  catchret from %cp to label %exit53 54exit:55  ret void56}57 58; CHECK-LABEL: @test2(59define void @test2(i1 %B) personality ptr @__CxxFrameHandler3 {60entry:61  br i1 %B, label %left, label %right62left:63  ; Need two stores here because %x and %y interfere so they need 2 slots64  ; CHECK: left:65  ; CHECK:   store i32 1, ptr [[Slot1:%[^ ]+]]66  ; CHECK:   store i32 1, ptr [[Slot2:%[^ ]+]]67  ; CHECK-NEXT: invoke void @f68  invoke void @f()69          to label %exit unwind label %merge.inner70right:71  ; Need two stores here because %x and %y interfere so they need 2 slots72  ; CHECK: right:73  ; CHECK-DAG:   store i32 2, ptr [[Slot1]]74  ; CHECK-DAG:   store i32 2, ptr [[Slot2]]75  ; CHECK: invoke void @f76  invoke void @f()77          to label %exit unwind label %merge.inner78merge.inner:79  ; CHECK: merge.inner:80  ; CHECK-NOT: = phi81  ; CHECK: catchswitch within none82  %x = phi i32 [ 1, %left ], [ 2, %right ]83  %cs1 = catchswitch within none [label %catch.inner] unwind label %merge.outer84 85catch.inner:86  %cpinner = catchpad within %cs1 []87  ; Need just one store here because only %y is affected88  ; CHECK: catch.inner:89  %z = call i32 @g() [ "funclet"(token %cpinner) ]90  ; CHECK:   store i32 %z91  ; CHECK-NEXT: invoke void @f92  invoke void @f() [ "funclet"(token %cpinner) ]93          to label %catchret.inner unwind label %merge.outer94 95catchret.inner:96  catchret from %cpinner to label %exit97 98merge.outer:99  %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]100  ; CHECK: merge.outer:101  ; CHECK-NOT: = phi102  ; CHECK: catchswitch within none103  %cs2 = catchswitch within none [label %catch.outer] unwind to caller104 105catch.outer:106  %cpouter = catchpad within %cs2 []107  ; CHECK: catch.outer:108  ; CHECK: [[CatchPad:%[^ ]+]] = catchpad within %cs2 []109  ; Need to load x and y from two different slots since they're both live110  ; and can have different values (if we came from catch.inner)111  ; CHECK-DAG: load i32, ptr [[Slot1]]112  ; CHECK-DAG: load i32, ptr [[Slot2]]113  ; CHECK: catchret from [[CatchPad]] to label114  call void @h(i32 %x) [ "funclet"(token %cpouter) ]115  call void @h(i32 %y) [ "funclet"(token %cpouter) ]116  catchret from %cpouter to label %exit117 118exit:119  ret void120}121 122; test4: don't need stores for %phi.inner, as its only use is to feed %phi.outer123;        %phi.outer needs stores in %left, %right, and %join124; CHECK-LABEL: @test4(125define void @test4(i1 %B) personality ptr @__CxxFrameHandler3 {126entry:127  ; CHECK:      entry:128  ; CHECK:        [[Slot:%[^ ]+]] = alloca129  ; CHECK-NEXT:   br130  br i1 %B, label %left, label %right131left:132  ; CHECK: left:133  ; CHECK-NOT: store134  ; CHECK: store i32 %l, ptr [[Slot]]135  ; CHECK-NEXT: invoke void @f136  %l = call i32 @g()137  invoke void @f()138          to label %join unwind label %catchpad.inner139right:140  ; CHECK: right:141  ; CHECK-NOT: store142  ; CHECK: store i32 %r, ptr [[Slot]]143  ; CHECK-NEXT: invoke void @f144  %r = call i32 @g()145  invoke void @f()146          to label %join unwind label %catchpad.inner147catchpad.inner:148   ; CHECK: catchpad.inner:149   ; CHECK-NEXT: catchswitch within none150   %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]151   %cs1 = catchswitch within none [label %catch.inner] unwind label %catchpad.outer152catch.inner:153   %cp1 = catchpad within %cs1 []154   catchret from %cp1 to label %join155join:156  ; CHECK: join:157  ; CHECK-NOT: store158  ; CHECK: store i32 %j, ptr [[Slot]]159  ; CHECK-NEXT: invoke void @f160   %j = call i32 @g()161   invoke void @f()162           to label %exit unwind label %catchpad.outer163 164catchpad.outer:165   ; CHECK: catchpad.outer:166   ; CHECK-NEXT: catchswitch within none167   %phi.outer = phi i32 [ %phi.inner, %catchpad.inner ], [ %j, %join ]168   %cs2 = catchswitch within none [label %catch.outer] unwind to caller169catch.outer:170   ; CHECK: catch.outer:171   ; CHECK:   [[Reload:%[^ ]+]] = load i32, ptr [[Slot]]172   ; CHECK:   call void @h(i32 [[Reload]])173   %cp2 = catchpad within %cs2 []174   call void @h(i32 %phi.outer) [ "funclet"(token %cp2) ]175   catchret from %cp2 to label %exit176exit:177   ret void178}179 180; CHECK-LABEL: @test5(181define void @test5() personality ptr @__CxxFrameHandler3 {182entry:183  ; need store for %phi.cleanup184  ; CHECK:      entry:185  ; CHECK:        store i32 1, ptr [[CleanupSlot:%[^ ]+]]186  ; CHECK-NEXT:   invoke void @f187  invoke void @f()188          to label %invoke.cont unwind label %cleanup189 190invoke.cont:191  ; need store for %phi.cleanup192  ; CHECK:      invoke.cont:193  ; CHECK-NEXT:   store i32 2, ptr [[CleanupSlot]]194  ; CHECK-NEXT:   invoke void @f195  invoke void @f()196          to label %invoke.cont2 unwind label %cleanup197 198cleanup:199  ; cleanup phi can be loaded at cleanup entry200  ; CHECK: cleanup:201  ; CHECK-NEXT: cleanuppad within none []202  ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, ptr [[CleanupSlot]]203  %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]204  %cp = cleanuppad within none []205  %b = call i1 @i() [ "funclet"(token %cp) ]206  br i1 %b, label %left, label %right207 208left:209  ; CHECK: left:210  ; CHECK:   call void @h(i32 [[CleanupReload]]211  call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]212  br label %merge213 214right:215  ; CHECK: right:216  ; CHECK:   call void @h(i32 [[CleanupReload]]217  call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]218  br label %merge219 220merge:221  ; need store for %phi.catch222  ; CHECK:      merge:223  ; CHECK-NEXT:   store i32 [[CleanupReload]], ptr [[CatchSlot:%[^ ]+]]224  ; CHECK-NEXT:   cleanupret225  cleanupret from %cp unwind label %catchswitch226 227invoke.cont2:228  ; need store for %phi.catch229  ; CHECK:      invoke.cont2:230  ; CHECK-NEXT:   store i32 3, ptr [[CatchSlot]]231  ; CHECK-NEXT:   invoke void @f232  invoke void @f()233          to label %exit unwind label %catchswitch234 235catchswitch:236  ; CHECK: catchswitch:237  ; CHECK-NEXT: catchswitch within none238  %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]239  %cs1 = catchswitch within none [label %catch] unwind to caller240 241catch:242  ; CHECK: catch:243  ; CHECK:   catchpad within %cs1244  ; CHECK:   [[CatchReload:%[^ ]+]] = load i32, ptr [[CatchSlot]]245  ; CHECK:   call void @h(i32 [[CatchReload]]246  %cp2 = catchpad within %cs1 []247  call void @h(i32 %phi.catch) [ "funclet"(token %cp2) ]248  catchret from %cp2 to label %exit249 250exit:251  ret void252}253 254; We used to demote %x, but we don't need to anymore.255; CHECK-LABEL: @test6(256define void @test6() personality ptr @__CxxFrameHandler3 {257entry:258  ; CHECK: entry:259  ; CHECK: %x = invoke i32 @g()260  ; CHECK-NEXT: to label %loop unwind label %to_caller261  %x = invoke i32 @g()262          to label %loop unwind label %to_caller263to_caller:264  %cp1 = cleanuppad within none []265  cleanupret from %cp1 unwind to caller266loop:267  invoke void @f()268          to label %loop unwind label %cleanup269cleanup:270  ; CHECK: cleanup:271  ; CHECK:   call void @h(i32 %x)272  %cp2 = cleanuppad within none []273  call void @h(i32 %x) [ "funclet"(token %cp2) ]274  cleanupret from %cp2 unwind to caller275}276 277; CHECK-LABEL: @test7(278define void @test7() personality ptr @__CxxFrameHandler3 {279entry:280  ; %x is an EH pad phi, so gets stored in pred here281  ; CHECK: entry:282  ; CHECK:   store i32 1, ptr [[SlotX:%[^ ]+]]283  ; CHECK:   invoke void @f()284  invoke void @f()285     to label %invoke.cont unwind label %catchpad286invoke.cont:287  ; %x is an EH pad phi, so gets stored in pred here288  ; CHECK: invoke.cont:289  ; CHECK:   store i32 2, ptr [[SlotX]]290  ; CHECK:   invoke void @f()291  invoke void @f()292    to label %exit unwind label %catchpad293catchpad:294  ; %x phi should be eliminated295  ; CHECK: catchpad:296  ; CHECK-NEXT: catchswitch within none297  %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]298  %cs1 = catchswitch within none [label %catch] unwind to caller299catch:300  ; CHECK: catch:301  ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []302  %cp = catchpad within %cs1 []303  %b = call i1 @i() [ "funclet"(token %cp) ]304  br i1 %b, label %left, label %right305left:306  ; Edge from %left to %join needs to be split so that307  ; the load of %x can be inserted *after* the catchret308  ; CHECK: left:309  ; CHECK-NEXT: catchret from %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]310  catchret from %cp to label %join311  ; CHECK: [[SplitLeft]]:312  ; CHECK:   [[LoadX:%[^ ]+]] = load i32, ptr [[SlotX]]313  ; CHECK:   br label %join314right:315  ; Edge from %right to %join needs to be split so that316  ; the load of %y can be inserted *after* the catchret317  ; CHECK: right:318  ; CHECK:   %y = call i32 @g()319  ; CHECK:   catchret from %[[CatchPad]] to label %join320  %y = call i32 @g() [ "funclet"(token %cp) ]321  catchret from %cp to label %join322join:323  ; CHECK: join:324  ; CHECK:   %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]325  %phi = phi i32 [ %x, %left ], [ %y, %right ]326  call void @h(i32 %phi)327  br label %exit328exit:329  ret void330}331 332; CHECK-LABEL: @test8(333define void @test8() personality ptr @__CxxFrameHandler3 { entry:334  invoke void @f()335          to label %done unwind label %cleanup1336  invoke void @f()337          to label %done unwind label %cleanup2338 339done:340  ret void341 342cleanup1:343  ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []344  ; CHECK-NEXT: call void @llvm.bar()345  ; CHECK-NEXT: cleanupret from [[CleanupPad1]]346  %cp0 = cleanuppad within none []347  br label %cleanupexit348 349cleanup2:350  ; CHECK: cleanuppad within none []351  ; CHECK-NEXT: call void @llvm.bar()352  ; CHECK-NEXT: unreachable353  %cp1 = cleanuppad within none []354  br label %cleanupexit355 356cleanupexit:357  call void @llvm.bar()358  cleanupret from %cp0 unwind label %cleanup2359}360