brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.1 KiB · 49cffe2 Raw
419 lines · plain
1; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' -mtriple=thumbv7m -disable-complex-addr-modes=false -addr-sink-new-select=true -addr-sink-new-phis=true < %s | FileCheck %s2 3target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"4 5@gv1 = common global i32 0, align 46@gv2 = common global i32 0, align 47 8; Phi selects between ptr and gep with ptr as base and constant offset9define void @test_phi_onegep_offset(ptr %ptr, i32 %value) {10; CHECK-LABEL: @test_phi_onegep_offset11; CHECK-NOT: phi ptr [ %ptr, %entry ], [ %gep, %if.then ]12; CHECK: phi i32 [ 4, %if.then ], [ 0, %entry ]13entry:14  %cmp = icmp sgt i32 %value, 015  br i1 %cmp, label %if.then, label %if.end16 17if.then:18  %gep = getelementptr inbounds i32, ptr %ptr, i32 119  br label %if.end20 21if.end:22  %phi = phi ptr [ %ptr, %entry ], [ %gep, %if.then ]23  store i32 %value, ptr %phi, align 424  ret void25}26 27; Phi selects between two geps with same base, different constant offsets28define void @test_phi_twogep_offset(ptr %ptr, i32 %value) {29; CHECK-LABEL: @test_phi_twogep_offset30; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]31; CHECK: phi i32 [ 8, %if.else ], [ 4, %if.then ]32entry:33  %cmp = icmp sgt i32 %value, 034  br i1 %cmp, label %if.then, label %if.else35 36if.then:37  %gep1 = getelementptr inbounds i32, ptr %ptr, i32 138  br label %if.end39 40if.else:41  %gep2 = getelementptr inbounds i32, ptr %ptr, i32 242  br label %if.end43 44if.end:45  %phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]46  store i32 %value, ptr %phi, align 447  ret void48}49 50; Phi selects between ptr and gep with ptr as base and nonconstant offset51define void @test_phi_onegep_nonconst_offset(ptr %ptr, i32 %value, i32 %off) {52; CHECK-LABEL: @test_phi_onegep_nonconst_offset53; CHECK-NOT: phi ptr [ %ptr, %entry ], [ %gep, %if.then ]54; CHECK: phi i32 [ %off, %if.then ], [ 0, %entry ]55entry:56  %cmp = icmp sgt i32 %value, 057  br i1 %cmp, label %if.then, label %if.end58 59if.then:60  %gep = getelementptr inbounds i32, ptr %ptr, i32 %off61  br label %if.end62 63if.end:64  %phi = phi ptr [ %ptr, %entry ], [ %gep, %if.then ]65  store i32 %value, ptr %phi, align 466  ret void67}68 69; Phi selects between two geps with same base, different nonconstant offsets70define void @test_phi_twogep_nonconst_offset(ptr %ptr, i32 %value, i32 %off1, i32 %off2) {71; CHECK-LABEL: @test_phi_twogep_nonconst_offset72; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]73; CHECK: phi i32 [ %off2, %if.else ], [ %off1, %if.then ]74entry:75  %cmp = icmp sgt i32 %value, 076  br i1 %cmp, label %if.then, label %if.else77 78if.then:79  %gep1 = getelementptr inbounds i32, ptr %ptr, i32 %off180  br label %if.end81 82if.else:83  %gep2 = getelementptr inbounds i32, ptr %ptr, i32 %off284  br label %if.end85 86if.end:87  %phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]88  store i32 %value, ptr %phi, align 489  ret void90}91 92; Phi selects between two geps with different base, same constant offset93define void @test_phi_twogep_base(ptr %ptr1, ptr %ptr2, i32 %value) {94; CHECK-LABEL: @test_phi_twogep_base95; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]96; CHECK: phi ptr [ %ptr2, %if.else ], [ %ptr1, %if.then ]97entry:98  %cmp = icmp sgt i32 %value, 099  br i1 %cmp, label %if.then, label %if.else100 101if.then:102  %gep1 = getelementptr inbounds i32, ptr %ptr1, i32 1103  br label %if.end104 105if.else:106  %gep2 = getelementptr inbounds i32, ptr %ptr2, i32 1107  br label %if.end108 109if.end:110  %phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]111  store i32 %value, ptr %phi, align 4112  ret void113}114 115; Phi selects between two geps with different base global variables, same constant offset116define void @test_phi_twogep_base_gv(i32 %value) {117; CHECK-LABEL: @test_phi_twogep_base_gv118; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]119; CHECK: phi ptr [ @gv2, %if.else ], [ @gv1, %if.then ]120entry:121  %cmp = icmp sgt i32 %value, 0122  br i1 %cmp, label %if.then, label %if.else123 124if.then:125  %gep1 = getelementptr inbounds i32, ptr @gv1, i32 1126  br label %if.end127 128if.else:129  %gep2 = getelementptr inbounds i32, ptr @gv2, i32 1130  br label %if.end131 132if.end:133  %phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]134  store i32 %value, ptr %phi, align 4135  ret void136}137 138; Phi selects between ptr and gep with ptr as base and constant offset139define void @test_select_onegep_offset(ptr %ptr, i32 %value) {140; CHECK-LABEL: @test_select_onegep_offset141; CHECK-NOT: select i1 %cmp, ptr %ptr, ptr %gep142; CHECK: select i1 %cmp, i32 0, i32 4143entry:144  %cmp = icmp sgt i32 %value, 0145  %gep = getelementptr inbounds i32, ptr %ptr, i32 1146  %select = select i1 %cmp, ptr %ptr, ptr %gep147  store i32 %value, ptr %select, align 4148  ret void149}150 151; Select between two geps with same base, different constant offsets152define void @test_select_twogep_offset(ptr %ptr, i32 %value) {153; CHECK-LABEL: @test_select_twogep_offset154; CHECK-NOT: select i1 %cmp, ptr %gep1, ptr %gep2155; CHECK: select i1 %cmp, i32 4, i32 8156entry:157  %cmp = icmp sgt i32 %value, 0158  %gep1 = getelementptr inbounds i32, ptr %ptr, i32 1159  %gep2 = getelementptr inbounds i32, ptr %ptr, i32 2160  %select = select i1 %cmp, ptr %gep1, ptr %gep2161  store i32 %value, ptr %select, align 4162  ret void163}164 165; Select between ptr and gep with ptr as base and nonconstant offset166define void @test_select_onegep_nonconst_offset(ptr %ptr, i32 %value, i32 %off) {167; CHECK-LABEL: @test_select_onegep_nonconst_offset168; CHECK-NOT: select i1 %cmp, ptr %ptr, ptr %gep169; CHECK: select i1 %cmp, i32 0, i32 %off170entry:171  %cmp = icmp sgt i32 %value, 0172  %gep = getelementptr inbounds i32, ptr %ptr, i32 %off173  %select = select i1 %cmp, ptr %ptr, ptr %gep174  store i32 %value, ptr %select, align 4175  ret void176}177 178; Select between two geps with same base, different nonconstant offsets179define void @test_select_twogep_nonconst_offset(ptr %ptr, i32 %value, i32 %off1, i32 %off2) {180; CHECK-LABEL: @test_select_twogep_nonconst_offset181; CHECK-NOT: select i1 %cmp, ptr %gep1, ptr %gep2182; CHECK: select i1 %cmp, i32 %off1, i32 %off2183entry:184  %cmp = icmp sgt i32 %value, 0185  %gep1 = getelementptr inbounds i32, ptr %ptr, i32 %off1186  %gep2 = getelementptr inbounds i32, ptr %ptr, i32 %off2187  %select = select i1 %cmp, ptr %gep1, ptr %gep2188  store i32 %value, ptr %select, align 4189  ret void190}191 192; Select between two geps with different base, same constant offset193define void @test_select_twogep_base(ptr %ptr1, ptr %ptr2, i32 %value) {194; CHECK-LABEL: @test_select_twogep_base195; CHECK-NOT: select i1 %cmp, ptr %gep1, ptr %gep2196; CHECK: select i1 %cmp, ptr %ptr1, ptr %ptr2197entry:198  %cmp = icmp sgt i32 %value, 0199  %gep1 = getelementptr inbounds i32, ptr %ptr1, i32 1200  %gep2 = getelementptr inbounds i32, ptr %ptr2, i32 1201  %select = select i1 %cmp, ptr %gep1, ptr %gep2202  store i32 %value, ptr %select, align 4203  ret void204}205 206; Select between two geps with different base global variables, same constant offset207define void @test_select_twogep_base_gv(i32 %value) {208; CHECK-LABEL: @test_select_twogep_base_gv209; CHECK-NOT: select i1 %cmp, ptr %gep1, ptr %gep2210; CHECK: select i1 %cmp, ptr @gv1, ptr @gv2211entry:212  %cmp = icmp sgt i32 %value, 0213  %gep1 = getelementptr inbounds i32, ptr @gv1, i32 1214  %gep2 = getelementptr inbounds i32, ptr @gv2, i32 1215  %select = select i1 %cmp, ptr %gep1, ptr %gep2216  store i32 %value, ptr %select, align 4217  ret void218}219 220; If the phi is in a different block to where the gep will be, the phi goes where221; the original phi was not where the gep is.222; CHECK-LABEL: @test_phi_different_block223; CHECK-LABEL: if1.end224; CHECK-NOT: phi ptr [ %ptr, %entry ], [ %gep, %if1.then ]225; CHECK: phi i32 [ 4, %if1.then ], [ 0, %entry ]226define void @test_phi_different_block(ptr %ptr, i32 %value1, i32 %value2) {227entry:228  %cmp1 = icmp sgt i32 %value1, 0229  br i1 %cmp1, label %if1.then, label %if1.end230 231if1.then:232  %gep = getelementptr inbounds i32, ptr %ptr, i32 1233  br label %if1.end234 235if1.end:236  %phi = phi ptr [ %ptr, %entry ], [ %gep, %if1.then ]237  %cmp2 = icmp sgt i32 %value2, 0238  br i1 %cmp2, label %if2.then, label %if2.end239 240if2.then:241  store i32 %value1, ptr %ptr, align 4242  br label %if2.end243 244if2.end:245  store i32 %value2, ptr %phi, align 4246  ret void247}248 249; A phi with three incoming values should be optimised250; CHECK-LABEL: @test_phi_threegep251; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]252; CHECK: phi i32 [ 12, %if.else.else ], [ 8, %if.else.then ], [ 4, %if.then ]253define void @test_phi_threegep(ptr %ptr, i32 %value1, i32 %value2) {254entry:255  %cmp1 = icmp sgt i32 %value1, 0256  br i1 %cmp1, label %if.then, label %if.else257 258if.then:259  %gep1 = getelementptr inbounds i32, ptr %ptr, i32 1260  br label %if.end261 262if.else:263  %cmp2 = icmp sgt i32 %value2, 0264  br i1 %cmp2, label %if.else.then, label %if.else.else265 266if.else.then:267  %gep2 = getelementptr inbounds i32, ptr %ptr, i32 2268  br label %if.end269 270if.else.else:271  %gep3 = getelementptr inbounds i32, ptr %ptr, i32 3272  br label %if.end273 274if.end:275  %phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]276  store i32 %value1, ptr %phi, align 4277  ret void278}279 280; A phi with two incoming values but three geps due to nesting should be281; optimised282; CHECK-LABEL: @test_phi_threegep_nested283; CHECK: %[[PHI:[a-z0-9_]+]] = phi i32 [ 12, %if.else.else ], [ 8, %if.else.then ]284; CHECK: phi i32 [ %[[PHI]], %if.else.end ], [ 4, %if.then ]285define void @test_phi_threegep_nested(ptr %ptr, i32 %value1, i32 %value2) {286entry:287  %cmp1 = icmp sgt i32 %value1, 0288  br i1 %cmp1, label %if.then, label %if.else289 290if.then:291  %gep1 = getelementptr inbounds i32, ptr %ptr, i32 1292  br label %if.end293 294if.else:295  %cmp2 = icmp sgt i32 %value2, 0296  br i1 %cmp2, label %if.else.then, label %if.else.else297 298if.else.then:299  %gep2 = getelementptr inbounds i32, ptr %ptr, i32 2300  br label %if.else.end301 302if.else.else:303  %gep3 = getelementptr inbounds i32, ptr %ptr, i32 3304  br label %if.else.end305 306if.else.end:307  %gep4 = phi ptr [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]308  store i32 %value2, ptr %ptr, align 4309  br label %if.end310 311if.end:312  %phi = phi ptr [ %gep1, %if.then ], [ %gep4, %if.else.end ]313  store i32 %value1, ptr %phi, align 4314  ret void315}316 317; A nested select is expected to be optimised318; CHECK-LABEL: @test_nested_select319; CHECK: %[[SELECT:[a-z0-9_]+]] = select i1 %cmp2, i32 4, i32 8320; CHECK: select i1 %cmp1, i32 4, i32 %[[SELECT]]321define void @test_nested_select(ptr %ptr, i32 %value1, i32 %value2) {322entry:323  %gep1 = getelementptr inbounds i32, ptr %ptr, i32 1324  %gep2 = getelementptr inbounds i32, ptr %ptr, i32 2325  %cmp1 = icmp sgt i32 %value1, 0326  %cmp2 = icmp sgt i32 %value2, 0327  %select1 = select i1 %cmp2, ptr %gep1, ptr %gep2328  %select2 = select i1 %cmp1, ptr %gep1, ptr %select1329  store i32 %value1, ptr %select2, align 4330  ret void331}332 333; Scaling the offset by a different amount is expected not to be optimised334; CHECK-LABEL: @test_select_different_scale335; CHECK: select i1 %cmp, ptr %gep1, ptr %gep2336define void @test_select_different_scale(ptr %ptr, i32 %value, i32 %off) {337entry:338  %cmp = icmp sgt i32 %value, 0339  %gep1 = getelementptr inbounds i32, ptr %ptr, i32 %off340  %gep2 = getelementptr inbounds i16, ptr %ptr, i32 %off341  %select = select i1 %cmp, ptr %gep1, ptr %gep2342  store i32 %value, ptr %select, align 4343  ret void344}345 346; A select between two values is already the best we can do347; CHECK-LABEL: @test_select_trivial348; CHECK: select i1 %cmp, ptr %ptr1, ptr %ptr2349define void @test_select_trivial(ptr %ptr1, ptr %ptr2, i32 %value) {350entey:351  %cmp = icmp sgt i32 %value, 0352  %select = select i1 %cmp, ptr %ptr1, ptr %ptr2353  store i32 %value, ptr %select, align 4354  ret void355}356 357; A select between two global variables is already the best we can do358; CHECK-LABEL: @test_select_trivial_gv359; CHECK: select i1 %cmp, ptr @gv1, ptr @gv2360define void @test_select_trivial_gv(i32 %value) {361entey:362  %cmp = icmp sgt i32 %value, 0363  %select = select i1 %cmp, ptr @gv1, ptr @gv2364  store i32 %value, ptr %select, align 4365  ret void366}367 368; Same for a select between a value and global variable369; CHECK-LABEL: @test_select_trivial_ptr_gv370; CHECK: select i1 %cmp, ptr %ptr, ptr @gv2371define void @test_select_trivial_ptr_gv(ptr %ptr, i32 %value) {372entry:373  %cmp = icmp sgt i32 %value, 0374  %select = select i1 %cmp, ptr %ptr, ptr @gv2375  store i32 %value, ptr %select, align 4376  ret void377}378 379; Same for a select between a global variable and null, though the test needs to380; be a little more complicated to avoid dereferencing a potential null pointer381; CHECK-LABEL: @test_select_trivial_gv_null382; CHECK: select i1 %cmp.i, ptr @gv1, ptr null383define void @test_select_trivial_gv_null(){384entry:385  %gv1_val = load i32, ptr @gv1, align 4386  %cmp.i = icmp eq i32 %gv1_val, 0387  %spec.select.i = select i1 %cmp.i, ptr @gv1, ptr null388  br i1 %cmp.i, label %if.then, label %if.end389 390if.then:391  %val = load i32, ptr %spec.select.i, align 4392  %inc = add nsw i32 %val, 1393  store i32 %inc, ptr %spec.select.i, align 4394  br label %if.end395 396if.end:397  ret void398}399 400; Same for a select between a value and null401; CHECK-LABEL: @test_select_trivial_ptr_null402; CHECK: select i1 %cmp.i, ptr %ptr, ptr null403define void @test_select_trivial_ptr_null(ptr %ptr){404entry:405  %gv1_val = load i32, ptr %ptr, align 4406  %cmp.i = icmp eq i32 %gv1_val, 0407  %spec.select.i = select i1 %cmp.i, ptr %ptr, ptr null408  br i1 %cmp.i, label %if.then, label %if.end409 410if.then:411  %val = load i32, ptr %spec.select.i, align 4412  %inc = add nsw i32 %val, 1413  store i32 %inc, ptr %spec.select.i, align 4414  br label %if.end415 416if.end:417  ret void418}419