408 lines · plain
1;; Test that correct clones are generated and reached when we need to2;; re-merge clone nodes before function assignment.3;;4;; The code is similar to that of basic.ll, but with a second allocation.5 6; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \7;; Disable merge iteration for now as it causes spurious diffs due to different8;; iteration order (but the same ultimate hinting of the contexts).9; RUN: -memprof-merge-iteration=false \10; RUN: -memprof-verify-ccg -memprof-dump-ccg %s -S 2>&1 | FileCheck %s \11; RUN: --check-prefix=IR --check-prefix=DUMP12 13;; Make sure the option to disable merging causes the expected regression.14; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \15; RUN: -memprof-merge-clones=false %s -S 2>&1 | FileCheck %s --check-prefix=NOMERGE16;; main should incorrectly call the same clone of foo.17; NOMERGE: define {{.*}} @main18; NOMERGE-NEXT: entry:19; NOMERGE-NEXT: call {{.*}} @_Z3foov.memprof.1()20; NOMERGE-NEXT: call {{.*}} @_Z3foov.memprof.1()21 22target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"23target triple = "x86_64-unknown-linux-gnu"24 25define i32 @main() {26entry:27 ;; Ultimately calls bar and allocates notcold memory from first call to new28 ;; and cold memory from second call to new.29 %call = call noundef ptr @_Z3foov(), !callsite !030 ;; Ultimately calls bar and allocates cold memory from first call to new31 ;; and notcold memory from second call to new.32 %call1 = call noundef ptr @_Z3foov(), !callsite !133 ret i32 034}35 36define internal ptr @_Z3barv() {37entry:38 ;; notcold when called from first call to foo from main, cold when called from second.39 %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0, !memprof !2, !callsite !740 ;; cold when called from first call to foo from main, notcold when called from second.41 %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0, !memprof !13, !callsite !1842 ret ptr null43}44 45declare ptr @_Znam(i64)46 47define internal ptr @_Z3bazv() {48entry:49 %call = call noundef ptr @_Z3barv(), !callsite !850 ret ptr null51}52 53; Function Attrs: noinline54define internal ptr @_Z3foov() {55entry:56 %call = call noundef ptr @_Z3bazv(), !callsite !957 ret ptr null58}59 60attributes #0 = { builtin }61 62!0 = !{i64 8632435727821051414}63!1 = !{i64 -3421689549917153178}64!2 = !{!3, !5}65!3 = !{!4, !"notcold"}66!4 = !{i64 9086428284934609951, i64 -5964873800580613432, i64 2732490490862098848, i64 8632435727821051414}67!5 = !{!6, !"cold"}68!6 = !{i64 9086428284934609951, i64 -5964873800580613432, i64 2732490490862098848, i64 -3421689549917153178}69!7 = !{i64 9086428284934609951}70!8 = !{i64 -5964873800580613432}71!9 = !{i64 2732490490862098848}72!13 = !{!14, !16}73!14 = !{!15, !"cold"}74!15 = !{i64 123, i64 -5964873800580613432, i64 2732490490862098848, i64 8632435727821051414}75!16 = !{!17, !"notcold"}76!17 = !{i64 123, i64 -5964873800580613432, i64 2732490490862098848, i64 -3421689549917153178}77!18 = !{i64 123}78 79;; After cloning, each callsite in main calls different clones of foo with80;; different allocaton types, and ditto all the way through the leaf81;; allocation callsites. The single allocation-type clones are shared between82;; the two callsites in main. This would lead to incorrect assignment of83;; the leaf allocations to function clones as is, since we have lost the84;; information that each callsite in main ultimately reaches two allocation85;; callsites with *different* allocation types.86; DUMP: CCG after cloning:87; DUMP: Callsite Context Graph:88; DUMP: Node [[BAR1ALLOC1:0x[a-f0-9]+]]89; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)90; DUMP: AllocTypes: NotCold91; DUMP: ContextIds: 192; DUMP: CalleeEdges:93; DUMP: CallerEdges:94; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ1:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 195; DUMP: Clones: [[BAR2ALLOC1:0x[a-f0-9]+]]96 97; DUMP: Node [[BAZ1]]98; DUMP: %call = call noundef ptr @_Z3barv() (clone 0)99; DUMP: AllocTypes: NotCold100; DUMP: ContextIds: 1 4101; DUMP: CalleeEdges:102; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ1]] AllocTypes: NotCold ContextIds: 1103; DUMP: Edge from Callee [[BAR1ALLOC2:0x[a-f0-9]+]] to Caller: [[BAZ1]] AllocTypes: NotCold ContextIds: 4104; DUMP: CallerEdges:105; DUMP: Edge from Callee [[BAZ1]] to Caller: [[FOO1:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 1 4106; DUMP: Clones: [[BAZ2:0x[a-f0-9]+]]107 108; DUMP: Node [[FOO1]]109; DUMP: %call = call noundef ptr @_Z3bazv() (clone 0)110; DUMP: AllocTypes: NotCold111; DUMP: ContextIds: 1 4112; DUMP: CalleeEdges:113; DUMP: Edge from Callee [[BAZ1]] to Caller: [[FOO1]] AllocTypes: NotCold ContextIds: 1 4114; DUMP: CallerEdges:115; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN1:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 1116; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN2:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 4117; DUMP: Clones: [[FOO2:0x[a-f0-9]+]]118 119; DUMP: Node [[MAIN1]]120; DUMP: %call = call noundef ptr @_Z3foov() (clone 0)121; DUMP: AllocTypes: NotColdCold122; DUMP: ContextIds: 1 3123; DUMP: CalleeEdges:124; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN1]] AllocTypes: NotCold ContextIds: 1125; DUMP: Edge from Callee [[FOO2:0x[a-f0-9]+]] to Caller: [[MAIN1]] AllocTypes: Cold ContextIds: 3126; DUMP: CallerEdges:127 128; DUMP: Node [[MAIN2]]129; DUMP: %call1 = call noundef ptr @_Z3foov() (clone 0)130; DUMP: AllocTypes: NotColdCold131; DUMP: ContextIds: 2 4132; DUMP: CalleeEdges:133; DUMP: Edge from Callee [[FOO1]] to Caller: [[MAIN2]] AllocTypes: NotCold ContextIds: 4134; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: Cold ContextIds: 2135; DUMP: CallerEdges:136 137; DUMP: Node [[BAR1ALLOC2]]138; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)139; DUMP: AllocTypes: NotCold140; DUMP: ContextIds: 4141; DUMP: CalleeEdges:142; DUMP: CallerEdges:143; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ1]] AllocTypes: NotCold ContextIds: 4144; DUMP: Clones: [[BAR2ALLOC2:0x[a-f0-9]+]]145 146; DUMP: Node [[FOO2]]147; DUMP: %call = call noundef ptr @_Z3bazv() (clone 0)148; DUMP: AllocTypes: Cold149; DUMP: ContextIds: 2 3150; DUMP: CalleeEdges:151; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO2]] AllocTypes: Cold ContextIds: 2 3152; DUMP: CallerEdges:153; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: Cold ContextIds: 2154; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN1]] AllocTypes: Cold ContextIds: 3155; DUMP: Clone of [[FOO1]]156 157; DUMP: Node [[BAZ2]]158; DUMP: %call = call noundef ptr @_Z3barv() (clone 0)159; DUMP: AllocTypes: Cold160; DUMP: ContextIds: 2 3161; DUMP: CalleeEdges:162; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 2163; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 3164; DUMP: CallerEdges:165; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO2]] AllocTypes: Cold ContextIds: 2 3166; DUMP: Clone of [[BAZ1]]167 168; DUMP: Node [[BAR2ALLOC1]]169; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)170; DUMP: AllocTypes: Cold171; DUMP: ContextIds: 2172; DUMP: CalleeEdges:173; DUMP: CallerEdges:174; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 2175; DUMP: Clone of [[BAR1ALLOC1]]176 177; DUMP: Node [[BAR2ALLOC2]]178; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)179; DUMP: AllocTypes: Cold180; DUMP: ContextIds: 3181; DUMP: CalleeEdges:182; DUMP: CallerEdges:183; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 3184; DUMP: Clone of [[BAR1ALLOC2]]185 186;; After merging, each callsite in main calls a different single clone of foo187;; with both cold and not cold allocation types, but ultimately reaches two188;; single allocation type allocation callsite clones of the correct189;; combination. The graph after assigning function clones is the same, but190;; with function calls updated to the new function clones.191; DUMP: CCG after merging:192; DUMP: Callsite Context Graph:193; DUMP: Node [[BAR1ALLOC1]]194; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)195; DUMP: AllocTypes: NotCold196; DUMP: ContextIds: 1197; DUMP: CalleeEdges:198; DUMP: CallerEdges:199; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ2]] AllocTypes: NotCold ContextIds: 1200; DUMP: Clones: [[BAR2ALLOC1]]201 202; DUMP: Node [[MAIN1]]203; DUMP: %call = call noundef ptr @_Z3foov() (clone 0)204; DUMP: AllocTypes: NotColdCold205; DUMP: ContextIds: 1 3206; DUMP: CalleeEdges:207; DUMP: Edge from Callee [[FOO3:0x[a-f0-9]+]] to Caller: [[MAIN1]] AllocTypes: NotColdCold ContextIds: 1 3208; DUMP: CallerEdges:209 210; DUMP: Node [[MAIN2]]211; DUMP: %call1 = call noundef ptr @_Z3foov() (clone 0)212; DUMP: AllocTypes: NotColdCold213; DUMP: ContextIds: 2 4214; DUMP: CalleeEdges:215; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: NotColdCold ContextIds: 2 4216; DUMP: CallerEdges:217 218; DUMP: Node [[BAR1ALLOC2]]219; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)220; DUMP: AllocTypes: NotCold221; DUMP: ContextIds: 4222; DUMP: CalleeEdges:223; DUMP: CallerEdges:224; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ3:0x[a-f0-9]+]] AllocTypes: NotCold ContextIds: 4225; DUMP: Clones: [[BAR2ALLOC2]]226 227; DUMP: Node [[FOO2]]228; DUMP: %call = call noundef ptr @_Z3bazv() (clone 0)229; DUMP: AllocTypes: NotColdCold230; DUMP: ContextIds: 2 4231; DUMP: CalleeEdges:232; DUMP: Edge from Callee [[BAZ3]] to Caller: [[FOO2]] AllocTypes: NotColdCold ContextIds: 2 4233; DUMP: CallerEdges:234; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: NotColdCold ContextIds: 2 4235; DUMP: Clone of [[FOO1]]236 237; DUMP: Node [[BAZ2]]238; DUMP: %call = call noundef ptr @_Z3barv() (clone 0)239; DUMP: AllocTypes: NotColdCold240; DUMP: ContextIds: 1 3241; DUMP: CalleeEdges:242; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 3243; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ2]] AllocTypes: NotCold ContextIds: 1244; DUMP: CallerEdges:245; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO3]] AllocTypes: NotColdCold ContextIds: 1 3246; DUMP: Clone of [[BAZ1]]247 248; DUMP: Node [[BAR2ALLOC1]]249; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)250; DUMP: AllocTypes: Cold251; DUMP: ContextIds: 2252; DUMP: CalleeEdges:253; DUMP: CallerEdges:254; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ3]] AllocTypes: Cold ContextIds: 2255; DUMP: Clone of [[BAR1ALLOC1]]256 257; DUMP: Node [[BAR2ALLOC2]]258; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)259; DUMP: AllocTypes: Cold260; DUMP: ContextIds: 3261; DUMP: CalleeEdges:262; DUMP: CallerEdges:263; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 3264; DUMP: Clone of [[BAR1ALLOC2]]265 266; DUMP: Node [[FOO3]]267; DUMP: %call = call noundef ptr @_Z3bazv() (clone 0)268; DUMP: AllocTypes: NotColdCold269; DUMP: ContextIds: 1 3270; DUMP: CalleeEdges:271; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO3]] AllocTypes: NotColdCold ContextIds: 1 3272; DUMP: CallerEdges:273; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN1]] AllocTypes: NotColdCold ContextIds: 1 3274; DUMP: Clone of [[FOO1]]275 276; DUMP: Node [[BAZ3]]277; DUMP: %call = call noundef ptr @_Z3barv() (clone 0)278; DUMP: AllocTypes: NotColdCold279; DUMP: ContextIds: 2 4280; DUMP: CalleeEdges:281; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ3]] AllocTypes: Cold ContextIds: 2282; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ3]] AllocTypes: NotCold ContextIds: 4283; DUMP: CallerEdges:284; DUMP: Edge from Callee [[BAZ3]] to Caller: [[FOO2]] AllocTypes: NotColdCold ContextIds: 2 4285; DUMP: Clone of [[BAZ1]]286 287; DUMP: CCG after assigning function clones:288; DUMP: Callsite Context Graph:289; DUMP: Node [[BAR1ALLOC1]]290; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 0)291; DUMP: AllocTypes: NotCold292; DUMP: ContextIds: 1293; DUMP: CalleeEdges:294; DUMP: CallerEdges:295; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ2]] AllocTypes: NotCold ContextIds: 1296; DUMP: Clones: [[BAR2ALLOC1]]297 298; DUMP: Node [[MAIN1]]299; DUMP: %call = call noundef ptr @_Z3foov.memprof.1() (clone 0)300; DUMP: AllocTypes: NotColdCold301; DUMP: ContextIds: 1 3302; DUMP: CalleeEdges:303; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN1]] AllocTypes: NotColdCold ContextIds: 1 3304; DUMP: CallerEdges:305 306; DUMP: Node [[MAIN2]]307; DUMP: %call1 = call noundef ptr @_Z3foov() (clone 0)308; DUMP: AllocTypes: NotColdCold309; DUMP: ContextIds: 2 4310; DUMP: CalleeEdges:311; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: NotColdCold ContextIds: 2 4312; DUMP: CallerEdges:313 314; DUMP: Node [[BAR1ALLOC2]]315; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #1 (clone 1)316; DUMP: AllocTypes: NotCold317; DUMP: ContextIds: 4318; DUMP: CalleeEdges:319; DUMP: CallerEdges:320; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ3]] AllocTypes: NotCold ContextIds: 4321; DUMP: Clones: [[BAR2ALLOC2]]322 323; DUMP: Node [[FOO2]]324; DUMP: %call = call noundef ptr @_Z3bazv.memprof.1() (clone 0)325; DUMP: AllocTypes: NotColdCold326; DUMP: ContextIds: 2 4327; DUMP: CalleeEdges:328; DUMP: Edge from Callee [[BAZ3]] to Caller: [[FOO2]] AllocTypes: NotColdCold ContextIds: 2 4329; DUMP: CallerEdges:330; DUMP: Edge from Callee [[FOO2]] to Caller: [[MAIN2]] AllocTypes: NotColdCold ContextIds: 2 4331; DUMP: Clone of [[FOO1]]332 333; DUMP: Node [[BAZ2]]334; DUMP: %call = call noundef ptr @_Z3barv() (clone 0)335; DUMP: AllocTypes: NotColdCold336; DUMP: ContextIds: 1 3337; DUMP: CalleeEdges:338; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 3339; DUMP: Edge from Callee [[BAR1ALLOC1]] to Caller: [[BAZ2]] AllocTypes: NotCold ContextIds: 1340; DUMP: CallerEdges:341; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO3]] AllocTypes: NotColdCold ContextIds: 1 3342; DUMP: Clone of [[BAZ1]]343 344; DUMP: Node [[BAR2ALLOC1]]345; DUMP: %call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #0 (clone 1)346; DUMP: AllocTypes: Cold347; DUMP: ContextIds: 2348; DUMP: CalleeEdges:349; DUMP: CallerEdges:350; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ3]] AllocTypes: Cold ContextIds: 2351; DUMP: Clone of [[BAR1ALLOC1]]352 353; DUMP: Node [[BAR2ALLOC2]]354; DUMP: %call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #1 (clone 0)355; DUMP: AllocTypes: Cold356; DUMP: ContextIds: 3357; DUMP: CalleeEdges:358; DUMP: CallerEdges:359; DUMP: Edge from Callee [[BAR2ALLOC2]] to Caller: [[BAZ2]] AllocTypes: Cold ContextIds: 3360; DUMP: Clone of [[BAR1ALLOC2]]361 362; DUMP: Node [[FOO3]]363; DUMP: %call = call noundef ptr @_Z3bazv() (clone 1)364; DUMP: AllocTypes: NotColdCold365; DUMP: ContextIds: 1 3366; DUMP: CalleeEdges:367; DUMP: Edge from Callee [[BAZ2]] to Caller: [[FOO3]] AllocTypes: NotColdCold ContextIds: 1 3368; DUMP: CallerEdges:369; DUMP: Edge from Callee [[FOO3]] to Caller: [[MAIN1]] AllocTypes: NotColdCold ContextIds: 1 3370; DUMP: Clone of [[FOO1]]371 372; DUMP: Node [[BAZ3]]373; DUMP: %call = call noundef ptr @_Z3barv.memprof.1() (clone 1)374; DUMP: AllocTypes: NotColdCold375; DUMP: ContextIds: 2 4376; DUMP: CalleeEdges:377; DUMP: Edge from Callee [[BAR2ALLOC1]] to Caller: [[BAZ3]] AllocTypes: Cold ContextIds: 2378; DUMP: Edge from Callee [[BAR1ALLOC2]] to Caller: [[BAZ3]] AllocTypes: NotCold ContextIds: 4379; DUMP: CallerEdges:380; DUMP: Edge from Callee [[BAZ3]] to Caller: [[FOO2]] AllocTypes: NotColdCold ContextIds: 2 4381; DUMP: Clone of [[BAZ1]]382 383; IR: define {{.*}} @main384;; The first call to foo should now call foo.memprof.1 that ultimately385;; calls bar with the first allocation hinted notcold and the second cold386;; (via call chain foo.memprof.1 -> baz -> bar).387; IR: call {{.*}} @_Z3foov.memprof.1()388;; The second call to foo still calls the original foo, but ultimately389;; reaches a clone of bar with the first allocation hinted cold and the390;; second notcold.391; IR: call {{.*}} @_Z3foov()392; IR: define internal {{.*}} @_Z3barv()393; IR: call {{.*}} @_Znam(i64 noundef 10) #[[NOTCOLD:[0-9]+]]394; IR: call {{.*}} @_Znam(i64 noundef 10) #[[COLD:[0-9]+]]395; IR: define internal {{.*}} @_Z3bazv()396; IR: call {{.*}} @_Z3barv()397; IR: define internal {{.*}} @_Z3foov()398; IR: call {{.*}} @_Z3bazv.memprof.1()399; IR: define internal {{.*}} @_Z3barv.memprof.1()400; IR: call {{.*}} @_Znam(i64 noundef 10) #[[COLD]]401; IR: call {{.*}} @_Znam(i64 noundef 10) #[[NOTCOLD]]402; IR: define internal {{.*}} @_Z3bazv.memprof.1()403; IR: call {{.*}} @_Z3barv.memprof.1()404; IR: define internal {{.*}} @_Z3foov.memprof.1()405; IR: call {{.*}} @_Z3bazv()406; IR: attributes #[[NOTCOLD]] = { builtin "memprof"="notcold" }407; IR: attributes #[[COLD]] = { builtin "memprof"="cold" }408