Peter Collingbourne | 9421c2d | 2017-02-15 21:10:09 +0000 | [diff] [blame] | 1 | ; RUN: opt -o %t %s -instcombine -simplifycfg -thinlto-bc -verify-assumption-cache |
Peter Collingbourne | 0609acc | 2017-02-15 03:01:11 +0000 | [diff] [blame] | 2 | ; RUN: llvm-dis -o - %t | FileCheck %s |
| 3 | |
| 4 | ; Test that the simplifycfg pass correctly updates the assumption cache |
| 5 | ; when it clones the llvm.assume call as part of creating a critical |
| 6 | ; edge. To do that, we set up a pass pipeline such that (1) an assumption |
| 7 | ; cache is created for foo before simplifycfg updates it, and (2) foo's |
| 8 | ; assumption cache is verified after simplifycfg has run. To satisfy 1, we |
| 9 | ; run the instcombine pass first in our pipeline. To satisfy 2, we use the |
| 10 | ; ThinLTOBitcodeWriter pass to write bitcode (that pass uses the assumption |
| 11 | ; cache). That ensures that the pass manager does not call releaseMemory() |
| 12 | ; on the AssumptionCacheTracker before the end of the pipeline, which would |
| 13 | ; wipe out the bad assumption cache before it is verified. |
| 14 | |
| 15 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| 16 | target triple = "x86_64-unknown-linux-gnu" |
| 17 | |
| 18 | %class.F = type { i8 } |
| 19 | %class.B = type { i8 } |
| 20 | %class.A = type { %class.C } |
| 21 | %class.C = type { i32 (...)** } |
| 22 | |
| 23 | define void @foo(%class.F* %this, %class.B* %out) { |
| 24 | entry: |
| 25 | %call = tail call i32 @_ZNK1F5beginEv(%class.F* %this) |
| 26 | %call2 = tail call i32 @_ZNK1F3endEv(%class.F* %this) |
| 27 | %cmp.i22 = icmp eq i32 %call, %call2 |
| 28 | br i1 %cmp.i22, label %while.end, label %while.body.preheader |
| 29 | |
| 30 | while.body.preheader: |
| 31 | br label %while.body |
| 32 | |
| 33 | while.body: |
| 34 | %frame_node.sroa.0.023 = phi i32 [ %inc.i, %_ZN10unique_ptrD2Ev.exit ], [ %call, %while.body.preheader ] |
| 35 | %call8 = tail call i8* @_Znwm(i64 8) |
| 36 | %inc.i = add nsw i32 %frame_node.sroa.0.023, 1 |
| 37 | %cmp = icmp eq i32 %inc.i, %call2 |
| 38 | br i1 %cmp, label %_ZN10unique_ptrD2Ev.exit, label %if.then |
| 39 | |
| 40 | if.then: |
| 41 | tail call void @_ZN1B6appendEv(%class.B* %out) |
| 42 | br label %_ZN10unique_ptrD2Ev.exit |
| 43 | |
| 44 | _ZN10unique_ptrD2Ev.exit: |
| 45 | %x1 = bitcast i8* %call8 to void (%class.A*)*** |
| 46 | %vtable.i.i = load void (%class.A*)**, void (%class.A*)*** %x1, align 8 |
| 47 | %x2 = bitcast void (%class.A*)** %vtable.i.i to i8* |
| 48 | %x3 = tail call i1 @llvm.type.test(i8* %x2, metadata !"foo") |
| 49 | ; CHECK: call void @llvm.assume |
| 50 | ; CHECK: call void @llvm.assume |
| 51 | tail call void @llvm.assume(i1 %x3) #5 |
| 52 | br i1 %cmp, label %while.end.loopexit, label %while.body |
| 53 | |
| 54 | while.end.loopexit: |
| 55 | br label %while.end |
| 56 | |
| 57 | while.end: |
| 58 | ret void |
| 59 | } |
| 60 | |
Matt Arsenault | f10061e | 2017-04-10 20:18:21 +0000 | [diff] [blame] | 61 | declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) |
Peter Collingbourne | 0609acc | 2017-02-15 03:01:11 +0000 | [diff] [blame] | 62 | |
| 63 | declare i32 @_ZNK1F5beginEv(%class.F*) |
| 64 | |
| 65 | declare i32 @_ZNK1F3endEv(%class.F*) |
| 66 | |
| 67 | declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) |
| 68 | |
| 69 | declare noalias nonnull i8* @_Znwm(i64) |
| 70 | |
| 71 | declare void @_ZN1B6appendEv(%class.B*) |
| 72 | |
Matt Arsenault | f10061e | 2017-04-10 20:18:21 +0000 | [diff] [blame] | 73 | declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) |
Peter Collingbourne | 0609acc | 2017-02-15 03:01:11 +0000 | [diff] [blame] | 74 | |
| 75 | declare i1 @llvm.type.test(i8*, metadata) |
| 76 | |
| 77 | declare void @llvm.assume(i1) |
| 78 | |
| 79 | !llvm.module.flags = !{!0} |
| 80 | !llvm.ident = !{!1} |
| 81 | |
| 82 | !0 = !{i32 1, !"PIC Level", i32 2} |
| 83 | !1 = !{!"clang version 5.0.0 "} |