brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.8 KiB · 826e27d Raw
434 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt %s -callbrprepare -S -o - | FileCheck %s3; RUN: opt %s -passes=callbr-prepare -S -o - | FileCheck %s4 5define i32 @test0() {6; CHECK-LABEL: @test0(7; CHECK-NEXT:  entry:8; CHECK-NEXT:    [[OUT:%.*]] = callbr i32 asm "# $0", "=r,!i"()9; CHECK-NEXT:            to label [[DIRECT:%.*]] [label %entry.indirect_crit_edge]10; CHECK:       entry.indirect_crit_edge:11; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[OUT]])12; CHECK-NEXT:    br label [[INDIRECT:%.*]]13; CHECK:       direct:14; CHECK-NEXT:    [[OUT2:%.*]] = callbr i32 asm "# $0", "=r,!i"()15; CHECK-NEXT:            to label [[DIRECT2:%.*]] [label %direct.indirect_crit_edge]16; CHECK:       direct.indirect_crit_edge:17; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[OUT2]])18; CHECK-NEXT:    br label [[INDIRECT]]19; CHECK:       direct2:20; CHECK-NEXT:    ret i32 021; CHECK:       indirect:22; CHECK-NEXT:    [[OUT3:%.*]] = phi i32 [ [[TMP0]], [[ENTRY_INDIRECT_CRIT_EDGE:%.*]] ], [ [[TMP1]], [[DIRECT_INDIRECT_CRIT_EDGE:%.*]] ]23; CHECK-NEXT:    ret i32 [[OUT3]]24;25entry:26  %out = callbr i32 asm "# $0", "=r,!i"()27  to label %direct [label %indirect]28direct:29  %out2 = callbr i32 asm "# $0", "=r,!i"()30  to label %direct2 [label %indirect]31direct2:32  ret i32 033indirect:34  %out3 = phi i32 [%out, %entry], [%out2, %direct]35  ret i32 %out336}37 38; Don't split edges unless they are critical, and callbr produces output, and39; that output is used.40; Here we have none of the above.41define i32 @dont_split0() {42; CHECK-LABEL: @dont_split0(43; CHECK-NEXT:  entry:44; CHECK-NEXT:    callbr void asm "", "!i"()45; CHECK-NEXT:            to label [[X:%.*]] [label %y]46; CHECK:       x:47; CHECK-NEXT:    ret i32 4248; CHECK:       y:49; CHECK-NEXT:    ret i32 050;51entry:52  callbr void asm "", "!i"()53  to label %x [label %y]54 55x:56  ret i32 4257 58y:59  ret i32 060}61 62; Don't split edges unless they are critical, and callbr produces output, and63; that output is used.64; Here we have output, but no critical edge.65; That said, we ought to insert a callbr landing pad intrinsic call and update66; to use the correct SSA value.67define i32 @dont_split1() {68; CHECK-LABEL: @dont_split1(69; CHECK-NEXT:  entry:70; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()71; CHECK-NEXT:            to label [[X:%.*]] [label %y]72; CHECK:       x:73; CHECK-NEXT:    ret i32 4274; CHECK:       y:75; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])76; CHECK-NEXT:    ret i32 [[TMP1]]77;78entry:79  %0 = callbr i32 asm "", "=r,!i"()80  to label %x [label %y]81 82x:83  ret i32 4284 85y:86  ret i32 %087}88 89; Don't split edges unless they are critical, and callbr produces output, and90; that output is used.91; Here we have a critical edge along an indirect branch, but no output.92define i32 @dont_split2() {93; CHECK-LABEL: @dont_split2(94; CHECK-NEXT:  entry:95; CHECK-NEXT:    callbr void asm "", "!i"()96; CHECK-NEXT:            to label [[X:%.*]] [label %y]97; CHECK:       x:98; CHECK-NEXT:    br label [[Y:%.*]]99; CHECK:       y:100; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ 0, [[X]] ], [ 42, [[ENTRY:%.*]] ]101; CHECK-NEXT:    ret i32 [[TMP0]]102;103entry:104  callbr void asm "", "!i"()105  to label %x [label %y]106 107x:108  br label %y109 110y:111  %0 = phi i32 [ 0, %x ], [ 42, %entry ]112  ret i32 %0113}114 115; Don't split edges unless they are critical, and callbr produces output, and116; that output is used.117; Here we're missing a use.118define i32 @dont_split3() {119; CHECK-LABEL: @dont_split3(120; CHECK-NEXT:  entry:121; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()122; CHECK-NEXT:            to label [[X:%.*]] [label %v]123; CHECK:       x:124; CHECK-NEXT:    br label [[V:%.*]]125; CHECK:       v:126; CHECK-NEXT:    ret i32 42127;128entry:129  %0 = callbr i32 asm "", "=r,!i"() to label %x [label %v]130 131x:132  br label %v133 134v:135  ret i32 42136}137 138; Don't split edges unless they are critical, and callbr produces output, and139; that output is used.140; Here we have output and a critical edge along an indirect branch.141define i32 @split_me0() {142; CHECK-LABEL: @split_me0(143; CHECK-NEXT:  entry:144; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()145; CHECK-NEXT:            to label [[X:%.*]] [label %entry.y_crit_edge]146; CHECK:       entry.y_crit_edge:147; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])148; CHECK-NEXT:    br label [[Y:%.*]]149; CHECK:       x:150; CHECK-NEXT:    br label [[Y]]151; CHECK:       y:152; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_Y_CRIT_EDGE:%.*]] ], [ 42, [[X]] ]153; CHECK-NEXT:    ret i32 [[TMP2]]154;155entry:156  %0 = callbr i32 asm "", "=r,!i"()157  to label %x [label %y]158 159x:160  br label %y161 162y:163  %1 = phi i32 [ %0, %entry ], [ 42, %x ]164  ret i32 %1165}166 167; Here we have output and a critical edge along an indirect branch.168; Ensure that if we repeat the indirect destination, that we only split it169; once.170define i32 @split_me1(i1 %z) {171; CHECK-LABEL: @split_me1(172; CHECK-NEXT:  entry:173; CHECK-NEXT:    br i1 [[Z:%.*]], label [[W:%.*]], label [[V:%.*]]174; CHECK:       w:175; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,!i"()176; CHECK-NEXT:            to label [[X:%.*]] [label [[W_V_CRIT_EDGE:%.*]], label %w.v_crit_edge]177; CHECK:       w.v_crit_edge:178; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])179; CHECK-NEXT:    br label [[V]]180; CHECK:       x:181; CHECK-NEXT:    ret i32 42182; CHECK:       v:183; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[W_V_CRIT_EDGE]] ], [ undef, [[ENTRY:%.*]] ]184; CHECK-NEXT:    ret i32 [[TMP2]]185;186entry:187  br i1 %z, label %w, label %v188 189w:190  %0 = callbr i32 asm "", "=r,!i,!i"()191  to label %x [label %v, label %v]192 193x:194  ret i32 42195 196v:197  %1 = phi i32 [%0, %w], [%0, %w], [undef, %entry]198  ret i32 %1199}200 201; A more interessting case of @split_me1. Check that we still only split the202; critical edge from w to v once.203define i32 @split_me2(i1 %z) {204; CHECK-LABEL: @split_me2(205; CHECK-NEXT:  entry:206; CHECK-NEXT:    br i1 [[Z:%.*]], label [[W:%.*]], label [[V:%.*]]207; CHECK:       w:208; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i,!i"()209; CHECK-NEXT:            to label [[X:%.*]] [label [[W_V_CRIT_EDGE:%.*]], label %w.v_crit_edge]210; CHECK:       w.v_crit_edge:211; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])212; CHECK-NEXT:    br label [[V]]213; CHECK:       x:214; CHECK-NEXT:    ret i32 42215; CHECK:       v:216; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[W_V_CRIT_EDGE]] ], [ 42, [[ENTRY:%.*]] ]217; CHECK-NEXT:    ret i32 [[TMP2]]218;219entry:220  br i1 %z, label %w, label %v221 222w:223  %0 = callbr i32 asm "", "=r,!i,!i"()224  to label %x [label %v, label %v]225 226x:227  ret i32 42228 229v:230  %1 = phi i32 [ %0, %w ], [ 42, %entry ], [ %0, %w ]231  ret i32 %1232}233 234; Here we have a diamond with no phi.235define i32 @dont_split4() {236; CHECK-LABEL: @dont_split4(237; CHECK-NEXT:  entry:238; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()239; CHECK-NEXT:            to label [[X:%.*]] [label %y]240; CHECK:       x:241; CHECK-NEXT:    br label [[OUT:%.*]]242; CHECK:       y:243; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])244; CHECK-NEXT:    br label [[OUT]]245; CHECK:       out:246; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[Y:%.*]] ], [ [[TMP0]], [[X]] ]247; CHECK-NEXT:    ret i32 [[TMP2]]248;249entry:250  %0 = callbr i32 asm "", "=r,!i"()251  to label %x [label %y]252 253x:254  br label %out255 256y:257  br label %out258 259out:260  ret i32 %0261}262 263; Triangle with no phi.264define i32 @dont_split5() {265; CHECK-LABEL: @dont_split5(266; CHECK-NEXT:  entry:267; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()268; CHECK-NEXT:            to label [[OUT:%.*]] [label %y]269; CHECK:       y:270; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])271; CHECK-NEXT:    br label [[OUT]]272; CHECK:       out:273; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[Y:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]274; CHECK-NEXT:    ret i32 [[TMP2]]275;276entry:277  %0 = callbr i32 asm "", "=r,!i"()278  to label %out [label %y]279 280y:281  br label %out282 283out:284  ret i32 %0285}286 287; Triangle the other way with no phi.288define i32 @split_me3() {289; CHECK-LABEL: @split_me3(290; CHECK-NEXT:  entry:291; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()292; CHECK-NEXT:            to label [[Y:%.*]] [label %entry.out_crit_edge]293; CHECK:       entry.out_crit_edge:294; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])295; CHECK-NEXT:    br label [[OUT:%.*]]296; CHECK:       y:297; CHECK-NEXT:    br label [[OUT]]298; CHECK:       out:299; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_OUT_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[Y]] ]300; CHECK-NEXT:    ret i32 [[TMP2]]301;302entry:303  %0 = callbr i32 asm "", "=r,!i"()304  to label %y [label %out]305 306y:307  br label %out308 309out:310  ret i32 %0311}312 313; Test callbr looping back on itself.314define i32 @dont_split6(i32 %0) {315; CHECK-LABEL: @dont_split6(316; CHECK-NEXT:  entry:317; CHECK-NEXT:    br label [[LOOP:%.*]]318; CHECK:       loop:319; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[TMP0:%.*]], [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ]320; CHECK-NEXT:    [[TMP2:%.*]] = callbr i32 asm "", "=r,0,!i"(i32 [[TMP1]])321; CHECK-NEXT:            to label [[EXIT:%.*]] [label %loop.loop_crit_edge]322; CHECK:       loop.loop_crit_edge:323; CHECK-NEXT:    [[TMP3]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP2]])324; CHECK-NEXT:    br label [[LOOP]]325; CHECK:       exit:326; CHECK-NEXT:    ret i32 0327;328entry:329  br label %loop330loop:331  %1 = phi i32 [%0, %entry], [%2, %loop]332  %2 = callbr i32 asm "", "=r,0,!i"(i32 %1) to label %exit [label %loop]333exit:334  ret i32 0335}336 337; Test same direct+indirect dest no phi.338define i32 @split_me4() {339; CHECK-LABEL: @split_me4(340; CHECK-NEXT:  entry:341; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()342; CHECK-NEXT:            to label [[SAME:%.*]] [label %entry.same_crit_edge]343; CHECK:       entry.same_crit_edge:344; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])345; CHECK-NEXT:    br label [[SAME]]346; CHECK:       same:347; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_SAME_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]348; CHECK-NEXT:    ret i32 [[TMP2]]349;350entry:351  %0 = callbr i32 asm "", "=r,!i"() to label %same [label %same]352same:353  ret i32 %0354}355 356; Test same direct+indirect dest w/ phi.357define i32 @split_me5() {358; CHECK-LABEL: @split_me5(359; CHECK-NEXT:  entry:360; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()361; CHECK-NEXT:            to label [[SAME:%.*]] [label %entry.same_crit_edge]362; CHECK:       entry.same_crit_edge:363; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])364; CHECK-NEXT:    br label [[SAME]]365; CHECK:       same:366; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[ENTRY_SAME_CRIT_EDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ]367; CHECK-NEXT:    ret i32 [[TMP2]]368;369entry:370  %0 = callbr i32 asm "", "=r,!i"() to label %same [label %same]371same:372  %1 = phi i32 [%0, %entry], [%0, %entry]373  ret i32 %1374}375 376; "The Devil's cross" (i.e. two asm goto with conflicting physreg constraints377; going to the same destination).378define i64 @split_me6() {379; CHECK-LABEL: @split_me6(380; CHECK-NEXT:  entry:381; CHECK-NEXT:    [[TMP0:%.*]] = callbr i64 asm "# $0 $1", "={dx},!i"()382; CHECK-NEXT:            to label [[ASM_FALLTHROUGH:%.*]] [label %entry.foo_crit_edge]383; CHECK:       entry.foo_crit_edge:384; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.callbr.landingpad.i64(i64 [[TMP0]])385; CHECK-NEXT:    br label [[FOO:%.*]]386; CHECK:       asm.fallthrough:387; CHECK-NEXT:    [[TMP2:%.*]] = callbr i64 asm "# $0 $1", "={bx},!i"()388; CHECK-NEXT:            to label [[FOO]] [label %asm.fallthrough.foo_crit_edge]389; CHECK:       asm.fallthrough.foo_crit_edge:390; CHECK-NEXT:    [[TMP3:%.*]] = call i64 @llvm.callbr.landingpad.i64(i64 [[TMP2]])391; CHECK-NEXT:    br label [[FOO]]392; CHECK:       foo:393; CHECK-NEXT:    [[X_0:%.*]] = phi i64 [ [[TMP1]], [[ENTRY_FOO_CRIT_EDGE:%.*]] ], [ [[TMP3]], [[ASM_FALLTHROUGH_FOO_CRIT_EDGE:%.*]] ], [ [[TMP2]], [[ASM_FALLTHROUGH]] ]394; CHECK-NEXT:    ret i64 [[X_0]]395;396entry:397  %0 = callbr i64 asm "# $0 $1", "={dx},!i"()398  to label %asm.fallthrough [label %foo]399 400asm.fallthrough:401  %1 = callbr i64 asm "# $0 $1", "={bx},!i"()402  to label %foo [label %foo]403 404foo:405  %x.0 = phi i64 [ %0, %entry ], [ %1, %asm.fallthrough ], [ %1, %asm.fallthrough ]406  ret i64 %x.0407}408 409; Test the result of the callbr having multiple uses to avoid iterator410; invalidation bugs in CallBrPrepare::UpdateSSA.411define i32 @multiple_split() {412; CHECK-LABEL: @multiple_split(413; CHECK-NEXT:  entry:414; CHECK-NEXT:    [[TMP0:%.*]] = callbr i32 asm "", "=r,!i"()415; CHECK-NEXT:            to label [[X:%.*]] [label %y]416; CHECK:       x:417; CHECK-NEXT:    ret i32 42418; CHECK:       y:419; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[TMP0]])420; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[TMP1]]421; CHECK-NEXT:    ret i32 [[TMP2]]422;423entry:424  %0 = callbr i32 asm "", "=r,!i"()425  to label %x [label %y]426 427x:428  ret i32 42429 430y:431  %1 = add nsw i32 %0, %0432  ret i32 %1433}434