254 lines · plain
1; RUN: opt -S -passes=callsite-splitting < %s | FileCheck --check-prefix=CHECK %s2; RUN: opt -S -passes=callsite-splitting -callsite-splitting-duplication-threshold=0 < %s | FileCheck --check-prefix=NODUP %s3 4; Instructions before a call that will be pushed to its predecessors5; with uses after the callsite, must be patched up as PHI nodes in6; the join block.7define ptr @test_split_branch_phi(ptr %ptrarg, i32 %i) {8Header:9 %tobool = icmp ne ptr %ptrarg, null10 br i1 %tobool, label %TBB, label %CallSite11 12TBB: ; preds = %Header13 %arrayidx = getelementptr inbounds i32, ptr %ptrarg, i64 4214 %0 = load i32, ptr %arrayidx, align 415 %tobool1 = icmp ne i32 %0, 016 br i1 %tobool1, label %CallSite, label %End17 18CallSite: ; preds = %TBB, %Header19 %somepointer = getelementptr i32, ptr %ptrarg, i64 1820 call void @bar(ptr %ptrarg, i32 %i)21 br label %End22 23End: ; preds = %CallSite, %TBB24 %somepointerphi = phi ptr [ %somepointer, %CallSite ], [ null, %TBB ]25 ret ptr %somepointerphi26}27; NODUP-LABEL: test_split_branch_phi28; NODUP-NOT: split29; CHECK-LABEL: Header.split30; CHECK: %[[V1:somepointer[0-9]+]] = getelementptr i32, ptr %ptrarg, i64 1831; CHECK: call void @bar(ptr null, i32 %i)32; CHECK: br label %CallSite33; CHECK-LABEL: TBB.split:34; CHECK: %[[V2:somepointer[0-9]+]] = getelementptr i32, ptr %ptrarg, i64 1835; CHECK: call void @bar(ptr nonnull %ptrarg, i32 %i)36; CHECK: br label %CallSite37; CHECK: CallSite:38; CHECK: phi ptr [ %[[V1]], %Header.split ], [ %[[V2]], %TBB.split ]39 40 41define void @split_branch_no_extra_phi(ptr %ptrarg, i32 %i) {42Header:43 %tobool = icmp ne ptr %ptrarg, null44 br i1 %tobool, label %TBB, label %CallSite45 46TBB: ; preds = %Header47 %arrayidx = getelementptr inbounds i32, ptr %ptrarg, i64 4248 %0 = load i32, ptr %arrayidx, align 449 %tobool1 = icmp ne i32 %0, 050 br i1 %tobool1, label %CallSite, label %End51 52CallSite: ; preds = %TBB, %Header53 %i.add = add i32 %i, 9954 call void @bar(ptr %ptrarg, i32 %i.add)55 br label %End56 57End: ; preds = %CallSite, %TBB58 ret void59}60; NODUP-LABEL: split_branch_no_extra_phi61; NODUP-NOT: split62; CHECK-LABEL: split_branch_no_extra_phi63; CHECK-LABEL: Header.split64; CHECK: %[[V1:.+]] = add i32 %i, 9965; CHECK: call void @bar(ptr null, i32 %[[V1]])66; CHECK: br label %CallSite67; CHECK-LABEL: TBB.split:68; CHECK: %[[V2:.+]] = add i32 %i, 9969; CHECK: call void @bar(ptr nonnull %ptrarg, i32 %[[V2]])70; CHECK: br label %CallSite71; CHECK: CallSite:72; CHECK-NOT: phi73 74 75; In this test case, the codesize cost of the instructions before the call to76; bar() is equal to the default DuplicationThreshold of 5, because calls are77; more expensive.78define void @test_no_split_threshold(ptr %ptrarg, i32 %i) {79Header:80 %tobool = icmp ne ptr %ptrarg, null81 br i1 %tobool, label %TBB, label %CallSite82 83TBB: ; preds = %Header84 %arrayidx = getelementptr inbounds i32, ptr %ptrarg, i64 4285 %0 = load i32, ptr %arrayidx, align 486 %tobool1 = icmp ne i32 %0, 087 br i1 %tobool1, label %CallSite, label %End88 89CallSite: ; preds = %TBB, %Header90 %i2 = add i32 %i, 1091 call void @bari(i32 %i2)92 call void @bari(i32 %i2)93 call void @bar(ptr %ptrarg, i32 %i2)94 br label %End95 96End: ; preds = %CallSite, %TBB97 ret void98}99; NODUP-LABEL: test_no_split_threshold100; NODUP-NOT: split101; CHECK-LABEL: test_no_split_threshold102; CHECK-NOT: split103; CHECK-LABEL: CallSite:104; CHECK: call void @bar(ptr %ptrarg, i32 %i2)105 106; In this test case, the phi node %l in CallSite should be removed, as after107; moving the call to the split blocks we can use the values directly.108define void @test_remove_unused_phi(ptr %ptrarg, i32 %i) {109Header:110 %l1 = load i32, ptr undef, align 16111 %tobool = icmp ne ptr %ptrarg, null112 br i1 %tobool, label %TBB, label %CallSite113 114TBB: ; preds = %Header115 %arrayidx = getelementptr inbounds i32, ptr %ptrarg, i64 42116 %0 = load i32, ptr %arrayidx, align 4117 %l2 = load i32, ptr undef, align 16118 %tobool1 = icmp ne i32 %0, 0119 br i1 %tobool1, label %CallSite, label %End120 121CallSite: ; preds = %TBB, %Header122 %l = phi i32 [ %l1, %Header ], [ %l2, %TBB ]123 call void @bar(ptr %ptrarg, i32 %l)124 br label %End125 126End: ; preds = %CallSite, %TBB127 ret void128}129; NODUP-LABEL: test_remove_unused_phi130; NODUP-NOT: split131; CHECK-LABEL: test_remove_unused_phi132; CHECK-LABEL: Header.split133; CHECK: call void @bar(ptr null, i32 %l1)134; CHECK: br label %CallSite135; CHECK-LABEL: TBB.split:136; CHECK: call void @bar(ptr nonnull %ptrarg, i32 %l2)137; CHECK: br label %CallSite138; CHECK-LABEL: CallSite:139; CHECK-NOT: phi140 141; In this test case, we need to insert a new PHI node in TailBB to combine142; the loads we moved to the predecessors.143define void @test_add_new_phi(ptr %ptrarg, i32 %i, i1 %arg) {144Header:145 %tobool = icmp ne ptr %ptrarg, null146 br i1 %tobool, label %TBB, label %CallSite147 148TBB:149 br i1 %arg, label %CallSite, label %End150 151CallSite:152 %arrayidx112 = getelementptr inbounds i32, ptr undef, i64 1153 %0 = load i32, ptr %arrayidx112, align 4154 call void @bar(ptr %ptrarg, i32 %i)155 %sub = sub nsw i32 %0, undef156 br label %End157 158End: ; preds = %CallSite, %TBB159 ret void160}161; NODUP-LABEL: test_add_new_phi162; NODUP-NOT: split163; CHECK-LABEL: test_add_new_phi164; CHECK-LABEL: Header.split165; CHECK: %[[V1:.+]] = load i32, ptr166; CHECK: call void @bar(ptr null, i32 %i)167; CHECK: br label %CallSite168; CHECK-LABEL: TBB.split:169; CHECK: %[[V2:.+]] = load i32, ptr170; CHECK: call void @bar(ptr nonnull %ptrarg, i32 %i)171; CHECK: br label %CallSite172; CHECK-LABEL: CallSite:173; CHECK-NEXT: %[[V3:.+]] = phi i32 [ %[[V1]], %Header.split ], [ %[[V2]], %TBB.split ]174; CHECK: %sub = sub nsw i32 %[[V3]], undef175 176define i32 @test_firstnophi(ptr %a, i32 %v) {177Header:178 %tobool1 = icmp eq ptr %a, null179 br i1 %tobool1, label %Tail, label %TBB180 181TBB:182 %cmp = icmp eq i32 %v, 1183 br i1 %cmp, label %Tail, label %End184 185Tail:186 %p = phi i32[1,%Header], [2, %TBB]187 store i32 %v, ptr %a188 %r = call i32 @callee(ptr %a, i32 %v, i32 %p)189 ret i32 %r190 191End:192 ret i32 %v193}194; NODUP-LABEL: @test_firstnophi195; NODUP-NOT: split:196; CHECK-LABEL: @test_firstnophi197; CHECK-LABEL: Header.split:198; CHECK-NEXT: store i32 %v, ptr %a199; CHECK-NEXT: %[[CALL1:.*]] = call i32 @callee(ptr null, i32 %v, i32 1)200; CHECK-NEXT: br label %Tail201; CHECK-LABEL: TBB.split:202; CHECK-NEXT: store i32 %v, ptr %a203; CHECK-NEXT: %[[CALL2:.*]] = call i32 @callee(ptr nonnull %a, i32 1, i32 2)204; CHECK-NEXT: br label %Tail205; CHECK-LABEL: Tail:206; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]207; CHECK: ret i32 %[[MERGED]]208define i32 @callee(ptr %a, i32 %v, i32 %p) {209 ret i32 0210}211 212define void @test_no_remove_used_phi(ptr %ptrarg, i32 %i) {213Header:214 %l1 = load i32, ptr undef, align 16215 %tobool = icmp ne ptr %ptrarg, null216 br i1 %tobool, label %TBB, label %CallSite217 218TBB: ; preds = %Header219 %arrayidx = getelementptr inbounds i32, ptr %ptrarg, i64 42220 %0 = load i32, ptr %arrayidx, align 4221 %l2 = load i32, ptr undef, align 16222 %tobool1 = icmp ne i32 %0, 0223 br i1 %tobool1, label %CallSite, label %End224 225CallSite: ; preds = %TBB, %Header226 %l = phi i32 [ %l1, %Header ], [ %l2, %TBB ]227 call void @bar(ptr %ptrarg, i32 %l)228 call void @bari(i32 %l)229 br label %End230 231End: ; preds = %CallSite, %TBB232 ret void233}234; NODUP-LABEL: @test_no_remove_used_phi235; NODUP-NOT: split236; CHECK-LABEL: @test_no_remove_used_phi237; CHECK-LABEL: Header.split:238; CHECK: call void @bar(ptr null, i32 %l1)239; CHECK-NEXT: br label %CallSite240; CHECK-LABEL: TBB.split:241; CHECK: call void @bar(ptr nonnull %ptrarg, i32 %l2)242; CHECK-NEXT: br label %CallSite243; CHECK-LABEL: CallSite:244; CHECK-NEXT: %l = phi i32 [ %l1, %Header.split ], [ %l2, %TBB.split ]245; CHECK: call void @bari(i32 %l)246 247define void @bar(ptr, i32) {248 ret void249}250 251define void @bari(i32) {252 ret void253}254