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 42 declare void @dummy() 43 44 ; An unconditional branch to the next block should be removed. 45 define internal void @testUncondToNextBlock() { 46 entry: 47 call void @dummy() 48 br label %next 49 next: 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. 92 define internal void @testCondFallthroughToNextBlock(i32 %arg) { 93 entry: 94 %cmp = icmp sge i32 %arg, 123 95 br i1 %cmp, label %target, label %fallthrough 96 fallthrough: 97 call void @dummy() 98 ret void 99 target: 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. 182 define internal void @testCondTargetNextBlock(i32 %arg) { 183 entry: 184 %cmp = icmp sge i32 %arg, 123 185 br i1 %cmp, label %fallthrough, label %target 186 fallthrough: 187 call void @dummy() 188 ret void 189 target: 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. 271 define internal void @testUncondToBlockAfterContract() { 272 entry: 273 call void @dummy() 274 br label %target 275 contract: 276 br label %target 277 target: 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