1; Tests the branch optimizations under O2 (against a lack of 2; optimizations under Om1). 3 4; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ 5; RUN: --target x8632 -i %s --args -O2 -allow-externally-defined-symbols \ 6; RUN: | %if --need=target_X8632 --command FileCheck --check-prefix=O2 %s 7 8; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ 9; RUN: --target x8632 -i %s --args -Om1 -allow-externally-defined-symbols \ 10; RUN: | %if --need=target_X8632 --command FileCheck --check-prefix=OM1 %s 11 12; RUN: %if --need=target_ARM32_dump \ 13; RUN: --command %p2i --filetype=obj \ 14; RUN: --disassemble --target arm32 -i %s --args -O2 \ 15; RUN: -allow-externally-defined-symbols \ 16; RUN: | %if --need=target_ARM32_dump \ 17; RUN: --command FileCheck --check-prefix ARM32O2 %s 18 19; RUN: %if --need=target_ARM32 \ 20; RUN: --command %p2i --filetype=obj \ 21; RUN: --disassemble --target arm32 -i %s --args -Om1 \ 22; RUN: -allow-externally-defined-symbols \ 23; RUN: | %if --need=target_ARM32 \ 24; RUN: --command FileCheck \ 25; RUN: --check-prefix ARM32OM1 %s 26 27; RUN: %if --need=target_MIPS32 --need=allow_dump \ 28; RUN: --command %p2i --filetype=asm --assemble \ 29; RUN: --disassemble --target mips32 -i %s --args -O2 \ 30; RUN: -allow-externally-defined-symbols \ 31; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 32; RUN: --command FileCheck --check-prefix MIPS32O2 %s 33 34; RUN: %if --need=target_MIPS32 --need=allow_dump \ 35; RUN: --command %p2i --filetype=asm --assemble \ 36; RUN: --disassemble --target mips32 -i %s --args -Om1 \ 37; RUN: -allow-externally-defined-symbols \ 38; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 39; RUN: --command FileCheck \ 40; RUN: --check-prefix MIPS32OM1 %s 41 42declare void @dummy() 43 44; An unconditional branch to the next block should be removed. 45define internal void @testUncondToNextBlock() { 46entry: 47 call void @dummy() 48 br label %next 49next: 50 call void @dummy() 51 ret void 52} 53; O2-LABEL: testUncondToNextBlock 54; O2: call 55; There will be nops for bundle align to end (for NaCl), but there should 56; not be a branch. 57; O2-NOT: j 58; O2: call 59 60; OM1-LABEL: testUncondToNextBlock 61; OM1: call 62; OM1-NEXT: jmp 63; OM1: call 64 65; ARM32O2-LABEL: testUncondToNextBlock 66; ARM32O2: bl {{.*}} dummy 67; ARM32O2-NEXT: bl {{.*}} dummy 68 69; ARM32OM1-LABEL: testUncondToNextBlock 70; ARM32OM1: bl {{.*}} dummy 71; ARM32OM1-NEXT: b 72; ARM32OM1-NEXT: bl {{.*}} dummy 73 74; MIPS32O2-LABEL: testUncondToNextBlock 75; MIPS32O2: jal {{.*}} dummy 76; MIPS32O2-NEXT: nop 77; MIPS32O2-LABEL: <.LtestUncondToNextBlock$next>: 78; MIPS32O2-NEXT: jal {{.*}} dummy 79; MIPS32O2-NEXT: nop 80 81; MIPS32OM1-LABEL: testUncondToNextBlock 82; MIPS32OM1: jal {{.*}} dummy 83; MIPS32OM1-NEXT: nop 84; MIPS32OM1-NEXT: b {{.*}} <.LtestUncondToNextBlock$next> 85; MIPS32OM1-NEXT: nop 86; MIPS32OM1-LABEL: <.LtestUncondToNextBlock$next>: 87; MIPS32OM1-NEXT: jal {{.*}} dummy 88; MIPS32OM1-NEXT: nop 89 90; For a conditional branch with a fallthrough to the next block, the 91; fallthrough branch should be removed. 92define internal void @testCondFallthroughToNextBlock(i32 %arg) { 93entry: 94 %cmp = icmp sge i32 %arg, 123 95 br i1 %cmp, label %target, label %fallthrough 96fallthrough: 97 call void @dummy() 98 ret void 99target: 100 call void @dummy() 101 ret void 102} 103; O2-LABEL: testCondFallthroughToNextBlock 104; O2: cmp {{.*}},0x7b 105; O2-NEXT: jge 106; O2-NOT: j 107; O2: call 108; O2: ret 109; O2: call 110; O2: ret 111 112; OM1-LABEL: testCondFallthroughToNextBlock 113; OM1: cmp {{.*}},0x7b 114; OM1: setge 115; OM1: cmp 116; OM1: jne 117; OM1: jmp 118; OM1: call 119; OM1: ret 120; OM1: call 121; OM1: ret 122 123; ARM32O2-LABEL: testCondFallthroughToNextBlock 124; ARM32O2: cmp {{.*}}, #123 125; ARM32O2-NEXT: bge 126; ARM32O2-NEXT: bl 127; ARM32O2: bx lr 128; ARM32O2: bl 129; ARM32O2: bx lr 130 131; ARM32OM1-LABEL: testCondFallthroughToNextBlock 132; ARM32OM1: mov {{.*}}, #0 133; ARM32OM1: cmp {{.*}}, #123 134; ARM32OM1: movge {{.*}}, #1 135; ARM32OM1: tst {{.*}}, #1 136; ARM32OM1: bne 137; ARM32OM1: b 138; ARM32OM1: bl 139; ARM32OM1: bx lr 140; ARM32OM1: bl 141; ARM32OM1: bx lr 142 143; MIPS32O2-LABEL: testCondFallthroughToNextBlock 144; MIPS32O2: li {{.*}},123 145; MIPS32O2: slt {{.*}},{{.*}},{{.*}} 146; MIPS32O2: beqz 147; MIPS32O2: nop 148; MIPS32O2: .LtestCondFallthroughToNextBlock$fallthrough 149; MIPS32O2: jal {{.*}} dummy 150; MIPS32O2: nop 151; MIPS32O2: jr 152; MIPS32O2: nop 153; MIPS32O2: .LtestCondFallthroughToNextBlock$target 154; MIPS32O2: jal {{.*}} dummy 155; MIPS32O2: nop 156; MIPS32O2: jr 157; MIPS32O2: nop 158 159; MIPS32OM1-LABEL: testCondFallthroughToNextBlock 160; MIPS32OM1: li {{.*}},123 161; MIPS32OM1: slt {{.*}},{{.*}},{{.*}} 162; MIPS32OM1: xori {{.*}},{{.*}},{{.*}} 163; MIPS32OM1: beqz 164; MIPS32OM1: nop 165; MIPS32OM1: b 166; MIPS32OM1: nop 167; MIPS32OM1: .LtestCondFallthroughToNextBlock$fallthrough 168; MIPS32OM1: jal {{.*}} dummy 169; MIPS32OM1: nop 170; MIPS32OM1: jr 171; MIPS32OM1: nop 172; MIPS32OM1: .LtestCondFallthroughToNextBlock$target 173; MIPS32OM1: jal {{.*}} dummy 174; MIPS32OM1: nop 175; MIPS32OM1: jr 176; MIPS32OM1: nop 177 178; For a conditional branch with the next block as the target and a 179; different block as the fallthrough, the branch condition should be 180; inverted, the fallthrough block changed to the target, and the 181; branch to the next block removed. 182define internal void @testCondTargetNextBlock(i32 %arg) { 183entry: 184 %cmp = icmp sge i32 %arg, 123 185 br i1 %cmp, label %fallthrough, label %target 186fallthrough: 187 call void @dummy() 188 ret void 189target: 190 call void @dummy() 191 ret void 192} 193; O2-LABEL: testCondTargetNextBlock 194; O2: cmp {{.*}},0x7b 195; O2-NEXT: jl 196; O2-NOT: j 197; O2: call 198; O2: ret 199; O2: call 200; O2: ret 201 202; OM1-LABEL: testCondTargetNextBlock 203; OM1: cmp {{.*}},0x7b 204; OM1: setge 205; OM1: cmp 206; OM1: jne 207; OM1: jmp 208; OM1: call 209; OM1: ret 210; OM1: call 211; OM1: ret 212 213; Note that compare and branch folding isn't implemented yet 214; (compared to x86-32). 215; ARM32O2-LABEL: testCondTargetNextBlock 216; ARM32O2: cmp {{.*}}, #123 217; ARM32O2-NEXT: blt 218; ARM32O2-NEXT: bl 219; ARM32O2: bx lr 220; ARM32O2: bl 221; ARM32O2: bx lr 222 223; ARM32OM1-LABEL: testCondTargetNextBlock 224; ARM32OM1: cmp {{.*}}, #123 225; ARM32OM1: movge {{.*}}, #1 226; ARM32OM1: tst {{.*}}, #1 227; ARM32OM1: bne 228; ARM32OM1: b 229; ARM32OM1: bl 230; ARM32OM1: bx lr 231; ARM32OM1: bl 232; ARM32OM1: bx lr 233 234; MIPS32O2-LABEL: testCondTargetNextBlock 235; MIPS32O2: li {{.*}},123 236; MIPS32O2: slt {{.*}},{{.*}},{{.*}} 237; MIPS32O2: bnez 238; MIPS32O2: nop 239; MIPS32O2: .LtestCondTargetNextBlock$fallthrough 240; MIPS32O2: jal {{.*}} dummy 241; MIPS32O2: nop 242; MIPS32O2: jr 243; MIPS32O2: nop 244; MIPS32O2: .LtestCondTargetNextBlock$target 245; MIPS32O2: jal {{.*}} dummy 246; MIPS32O2: nop 247; MIPS32O2: jr 248; MIPS32O2: nop 249 250; MIPS32OM1-LABEL: testCondTargetNextBlock 251; MIPS32OM1: li {{.*}},123 252; MIPS32OM1: slt {{.*}},{{.*}},{{.*}} 253; MIPS32OM1: xori {{.*}},{{.*}},{{.*}} 254; MIPS32OM1: beqz 255; MIPS32OM1: nop 256; MIPS32OM1: b 257; MIPS32OM1: nop 258; MIPS32OM1: .LtestCondTargetNextBlock$fallthrough 259; MIPS32OM1: jal {{.*}} dummy 260; MIPS32OM1: nop 261; MIPS32OM1: jr 262; MIPS32OM1: nop 263; MIPS32OM1: .LtestCondTargetNextBlock$target 264; MIPS32OM1: jal {{.*}} dummy 265; MIPS32OM1: nop 266; MIPS32OM1: jr 267; MIPS32OM1: nop 268 269; Unconditional branches to the block after a contracted block should be 270; removed. 271define internal void @testUncondToBlockAfterContract() { 272entry: 273 call void @dummy() 274 br label %target 275contract: 276 br label %target 277target: 278 call void @dummy() 279 ret void 280} 281 282; O2-LABEL: testUncondToBlockAfterContract 283; O2: call 284; There will be nops for bundle align to end (for NaCl), but there should 285; not be a branch. 286; O2-NOT: j 287; O2: call 288 289; OM1-LABEL: testUncondToBlockAfterContract 290; OM1: call 291; OM1-NEXT: jmp 292; OM1: call 293 294; ARM32O2-LABEL: testUncondToBlockAfterContract 295; ARM32O2: bl {{.*}} dummy 296; ARM32O2-NEXT: bl {{.*}} dummy 297 298; ARM32OM1-LABEL: testUncondToBlockAfterContract 299; ARM32OM1: bl {{.*}} dummy 300; ARM32OM1-NEXT: b 301; ARM32OM1-NEXT: bl {{.*}} dummy 302 303; MIPS32O2-LABEL: testUncondToBlockAfterContract 304; MIPS32O2: jal {{.*}} dummy 305; MIPS32O2: .LtestUncondToBlockAfterContract$target 306 307; MIPS32OM1-LABEL: testUncondToBlockAfterContract 308; MIPS32OM1: jal {{.*}} dummy 309; MIPS32OM1: b 310; MIPS32OM1: .LtestUncondToBlockAfterContract$target 311