1; RUN: opt -S -callsite-splitting < %s | FileCheck --check-prefix=CHECK %s 2; RUN: opt -S -callsite-splitting -callsite-splitting-duplication-threshold=0 < %s | FileCheck --check-prefix=NODUP %s 3 4; Instructions before a call that will be pushed to its predecessors 5; with uses after the callsite, must be patched up as PHI nodes in 6; the join block. 7define i32* @test_split_branch_phi(i32* %ptrarg, i32 %i) { 8Header: 9 %tobool = icmp ne i32* %ptrarg, null 10 br i1 %tobool, label %TBB, label %CallSite 11 12TBB: ; preds = %Header 13 %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42 14 %0 = load i32, i32* %arrayidx, align 4 15 %tobool1 = icmp ne i32 %0, 0 16 br i1 %tobool1, label %CallSite, label %End 17 18CallSite: ; preds = %TBB, %Header 19 %somepointer = getelementptr i32, i32* %ptrarg, i64 18 20 call void @bar(i32* %ptrarg, i32 %i) 21 br label %End 22 23End: ; preds = %CallSite, %TBB 24 %somepointerphi = phi i32* [ %somepointer, %CallSite ], [ null, %TBB ] 25 ret i32* %somepointerphi 26} 27; NODUP-LABEL: test_split_branch_phi 28; NODUP-NOT: split 29; CHECK-LABEL: Header.split 30; CHECK: %[[V1:somepointer[0-9]+]] = getelementptr i32, i32* %ptrarg, i64 18 31; CHECK: call void @bar(i32* null, i32 %i) 32; CHECK: br label %CallSite 33; CHECK-LABEL: TBB.split: 34; CHECK: %[[V2:somepointer[0-9]+]] = getelementptr i32, i32* %ptrarg, i64 18 35; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %i) 36; CHECK: br label %CallSite 37; CHECK: CallSite: 38; CHECK: phi i32* [ %[[V1]], %Header.split ], [ %[[V2]], %TBB.split ] 39 40 41define void @split_branch_no_extra_phi(i32* %ptrarg, i32 %i) { 42Header: 43 %tobool = icmp ne i32* %ptrarg, null 44 br i1 %tobool, label %TBB, label %CallSite 45 46TBB: ; preds = %Header 47 %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42 48 %0 = load i32, i32* %arrayidx, align 4 49 %tobool1 = icmp ne i32 %0, 0 50 br i1 %tobool1, label %CallSite, label %End 51 52CallSite: ; preds = %TBB, %Header 53 %i.add = add i32 %i, 99 54 call void @bar(i32* %ptrarg, i32 %i.add) 55 br label %End 56 57End: ; preds = %CallSite, %TBB 58 ret void 59} 60; NODUP-LABEL: split_branch_no_extra_phi 61; NODUP-NOT: split 62; CHECK-LABEL: split_branch_no_extra_phi 63; CHECK-LABEL: Header.split 64; CHECK: %[[V1:.+]] = add i32 %i, 99 65; CHECK: call void @bar(i32* null, i32 %[[V1]]) 66; CHECK: br label %CallSite 67; CHECK-LABEL: TBB.split: 68; CHECK: %[[V2:.+]] = add i32 %i, 99 69; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %[[V2]]) 70; CHECK: br label %CallSite 71; CHECK: CallSite: 72; CHECK-NOT: phi 73 74 75; In this test case, the codesize cost of the instructions before the call to 76; bar() is equal to the default DuplicationThreshold of 5, because calls are 77; more expensive. 78define void @test_no_split_threshold(i32* %ptrarg, i32 %i) { 79Header: 80 %tobool = icmp ne i32* %ptrarg, null 81 br i1 %tobool, label %TBB, label %CallSite 82 83TBB: ; preds = %Header 84 %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42 85 %0 = load i32, i32* %arrayidx, align 4 86 %tobool1 = icmp ne i32 %0, 0 87 br i1 %tobool1, label %CallSite, label %End 88 89CallSite: ; preds = %TBB, %Header 90 %i2 = add i32 %i, 10 91 call void @bari(i32 %i2) 92 call void @bari(i32 %i2) 93 call void @bar(i32* %ptrarg, i32 %i2) 94 br label %End 95 96End: ; preds = %CallSite, %TBB 97 ret void 98} 99; NODUP-LABEL: test_no_split_threshold 100; NODUP-NOT: split 101; CHECK-LABEL: test_no_split_threshold 102; CHECK-NOT: split 103; CHECK-LABEL: CallSite: 104; CHECK: call void @bar(i32* %ptrarg, i32 %i2) 105 106; In this test case, the phi node %l in CallSite should be removed, as after 107; moving the call to the split blocks we can use the values directly. 108define void @test_remove_unused_phi(i32* %ptrarg, i32 %i) { 109Header: 110 %l1 = load i32, i32* undef, align 16 111 %tobool = icmp ne i32* %ptrarg, null 112 br i1 %tobool, label %TBB, label %CallSite 113 114TBB: ; preds = %Header 115 %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42 116 %0 = load i32, i32* %arrayidx, align 4 117 %l2 = load i32, i32* undef, align 16 118 %tobool1 = icmp ne i32 %0, 0 119 br i1 %tobool1, label %CallSite, label %End 120 121CallSite: ; preds = %TBB, %Header 122 %l = phi i32 [ %l1, %Header ], [ %l2, %TBB ] 123 call void @bar(i32* %ptrarg, i32 %l) 124 br label %End 125 126End: ; preds = %CallSite, %TBB 127 ret void 128} 129; NODUP-LABEL: test_remove_unused_phi 130; NODUP-NOT: split 131; CHECK-LABEL: test_remove_unused_phi 132; CHECK-LABEL: Header.split 133; CHECK: call void @bar(i32* null, i32 %l1) 134; CHECK: br label %CallSite 135; CHECK-LABEL: TBB.split: 136; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %l2) 137; CHECK: br label %CallSite 138; CHECK-LABEL: CallSite: 139; CHECK-NOT: phi 140 141; In this test case, we need to insert a new PHI node in TailBB to combine 142; the loads we moved to the predecessors. 143define void @test_add_new_phi(i32* %ptrarg, i32 %i) { 144Header: 145 %tobool = icmp ne i32* %ptrarg, null 146 br i1 %tobool, label %TBB, label %CallSite 147 148TBB: 149 br i1 undef, label %CallSite, label %End 150 151CallSite: 152 %arrayidx112 = getelementptr inbounds i32, i32* undef, i64 1 153 %0 = load i32, i32* %arrayidx112, align 4 154 call void @bar(i32* %ptrarg, i32 %i) 155 %sub = sub nsw i32 %0, undef 156 br label %End 157 158End: ; preds = %CallSite, %TBB 159 ret void 160} 161; NODUP-LABEL: test_add_new_phi 162; NODUP-NOT: split 163; CHECK-LABEL: test_add_new_phi 164; CHECK-LABEL: Header.split 165; CHECK: %[[V1:.+]] = load i32, i32* 166; CHECK: call void @bar(i32* null, i32 %i) 167; CHECK: br label %CallSite 168; CHECK-LABEL: TBB.split: 169; CHECK: %[[V2:.+]] = load i32, i32* 170; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %i) 171; CHECK: br label %CallSite 172; CHECK-LABEL: CallSite: 173; CHECK-NEXT: %[[V3:.+]] = phi i32 [ %[[V1]], %Header.split ], [ %[[V2]], %TBB.split ] 174; CHECK: %sub = sub nsw i32 %[[V3]], undef 175 176define i32 @test_firstnophi(i32* %a, i32 %v) { 177Header: 178 %tobool1 = icmp eq i32* %a, null 179 br i1 %tobool1, label %Tail, label %TBB 180 181TBB: 182 %cmp = icmp eq i32 %v, 1 183 br i1 %cmp, label %Tail, label %End 184 185Tail: 186 %p = phi i32[1,%Header], [2, %TBB] 187 store i32 %v, i32* %a 188 %r = call i32 @callee(i32* %a, i32 %v, i32 %p) 189 ret i32 %r 190 191End: 192 ret i32 %v 193} 194; NODUP-LABEL: @test_firstnophi 195; NODUP-NOT: split: 196; CHECK-LABEL: @test_firstnophi 197; CHECK-LABEL: Header.split: 198; CHECK-NEXT: store i32 %v, i32* %a 199; CHECK-NEXT: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1) 200; CHECK-NEXT: br label %Tail 201; CHECK-LABEL: TBB.split: 202; CHECK-NEXT: store i32 %v, i32* %a 203; CHECK-NEXT: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2) 204; CHECK-NEXT: br label %Tail 205; CHECK-LABEL: Tail: 206; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ] 207; CHECK: ret i32 %[[MERGED]] 208define i32 @callee(i32* %a, i32 %v, i32 %p) { 209 ret i32 0 210} 211 212define void @test_no_remove_used_phi(i32* %ptrarg, i32 %i) { 213Header: 214 %l1 = load i32, i32* undef, align 16 215 %tobool = icmp ne i32* %ptrarg, null 216 br i1 %tobool, label %TBB, label %CallSite 217 218TBB: ; preds = %Header 219 %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42 220 %0 = load i32, i32* %arrayidx, align 4 221 %l2 = load i32, i32* undef, align 16 222 %tobool1 = icmp ne i32 %0, 0 223 br i1 %tobool1, label %CallSite, label %End 224 225CallSite: ; preds = %TBB, %Header 226 %l = phi i32 [ %l1, %Header ], [ %l2, %TBB ] 227 call void @bar(i32* %ptrarg, i32 %l) 228 call void @bari(i32 %l) 229 br label %End 230 231End: ; preds = %CallSite, %TBB 232 ret void 233} 234; NODUP-LABEL: @test_no_remove_used_phi 235; NODUP-NOT: split 236; CHECK-LABEL: @test_no_remove_used_phi 237; CHECK-LABEL: Header.split: 238; CHECK: call void @bar(i32* null, i32 %l1) 239; CHECK-NEXT: br label %CallSite 240; CHECK-LABEL: TBB.split: 241; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %l2) 242; CHECK-NEXT: br label %CallSite 243; 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(i32*, i32) { 248 ret void 249} 250 251define void @bari(i32) { 252 ret void 253} 254