@ RUN: llvm-mc -triple thumbv7a--none-eabi -arm-implicit-it=always < %s -show-encoding | FileCheck %s @ Single instruction .section test1 @ CHECK-LABEL: test1 addeq r0, #1 @ CHECK: it eq @ CHECK: addeq @ Multiple instructions, same condition .section test2 @ CHECK-LABEL: test2 addeq r0, #1 addeq r0, #1 addeq r0, #1 addeq r0, #1 @ CHECK: itttt eq @ CHECK: addeq @ CHECK: addeq @ CHECK: addeq @ CHECK: addeq @ Multiple instructions, equal but opposite conditions .section test3 @ CHECK-LABEL: test3 addeq r0, #1 addne r0, #1 addeq r0, #1 addne r0, #1 @ CHECK: itete eq @ CHECK: addeq @ CHECK: addne @ CHECK: addeq @ CHECK: addne @ Multiple instructions, unrelated conditions .section test4 @ CHECK-LABEL: test4 addeq r0, #1 addlt r0, #1 addeq r0, #1 addge r0, #1 @ CHECK: it eq @ CHECK: addeq @ CHECK: it lt @ CHECK: addlt @ CHECK: it eq @ CHECK: addeq @ CHECK: it ge @ CHECK: addge @ More than 4 instructions eligible for a block .section test5 @ CHECK-LABEL: test5 addeq r0, #1 addeq r0, #1 addeq r0, #1 addeq r0, #1 addeq r0, #1 addeq r0, #1 @ CHECK: itttt eq @ CHECK: addeq @ CHECK: addeq @ CHECK: addeq @ CHECK: addeq @ CHECK: itt eq @ CHECK: addeq @ CHECK: addeq @ Flush on a label .section test6 @ CHECK-LABEL: test6 addeq r0, #1 label: addeq r0, #1 5: addeq r0, #1 @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ Flush on a section-change directive .section test7a @ CHECK-LABEL: test7a addeq r0, #1 .section test7b addeq r0, #1 .previous addeq r0, #1 .pushsection test7c addeq r0, #1 .popsection addeq r0, #1 @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ Flush on an ISA change (even to the same ISA) .section test8 @ CHECK-LABEL: test8 addeq r0, #1 .thumb addeq r0, #1 .arm addeq r0, #1 .thumb addeq r0, #1 @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ Flush on an arch, cpu or fpu change .section test9 @ CHECK-LABEL: test9 addeq r0, #1 .arch armv7-a addeq r0, #1 .cpu cortex-a15 addeq r0, #1 .fpu vfpv3 addeq r0, #1 @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ Flush on an unpredicable instruction .section test10 @ CHECK-LABEL: test10 addeq r0, #1 setend le addeq r0, #1 hvc #0 addeq r0, #1 @ CHECK: it eq @ CHECK: addeq @ CHECK: setend le @ CHECK: it eq @ CHECK: addeq @ CHECK: hvc.w #0 @ CHECK: it eq @ CHECK: addeq @ Flush when reaching an explicit IT instruction .section test11 @ CHECK-LABEL: test11 addeq r0, #1 it eq addeq r0, #1 @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ Don't extend an explicit IT instruction .section test12 @ CHECK-LABEL: test12 it eq addeq r0, #1 addeq r0, #1 @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ Branch-like instructions can only be used at the end of an IT block, so @ terminate it. .section test13 @ CHECK-LABEL: test13 .cpu cortex-a15 addeq pc, r0 addeq pc, sp, pc ldreq pc, [r0, #4] ldreq pc, [r0, #-4] ldreq pc, [r0, r1] ldreq pc, [pc, #-0] moveq pc, r0 bleq #4 blxeq #4 blxeq r0 bxeq r0 bxjeq r0 tbbeq [r0, r1] tbheq [r0, r1, lsl #1] ereteq rfeiaeq r0 rfeiaeq r0! rfedbeq r0 rfedbeq r0! smceq #0 ldmiaeq r0, {pc} ldmiaeq r0!, {r1, pc} ldmdbeq r0, {pc} ldmdbeq r0!, {r1, pc} popeq {pc} .arch armv8-m.main bxnseq r0 blxnseq r0 @ CHECK: it eq @ CHECK: addeq pc, r0 @ CHECK: it eq @ CHECK: addeq pc, sp, pc @ CHECK: it eq @ CHECK: ldreq.w pc, [r0, #4] @ CHECK: it eq @ CHECK: ldreq pc, [r0, #-4] @ CHECK: it eq @ CHECK: ldreq.w pc, [r0, r1] @ CHECK: it eq @ CHECK: ldreq.w pc, [pc, #-0] @ CHECK: it eq @ CHECK: moveq pc, r0 @ CHECK: it eq @ CHECK: bleq #4 @ CHECK: it eq @ CHECK: blxeq #4 @ CHECK: it eq @ CHECK: blxeq r0 @ CHECK: it eq @ CHECK: bxeq r0 @ CHECK: it eq @ CHECK: bxjeq r0 @ CHECK: it eq @ CHECK: tbbeq [r0, r1] @ CHECK: it eq @ CHECK: tbheq [r0, r1, lsl #1] @ CHECK: it eq @ CHECK: ereteq @ CHECK: it eq @ CHECK: rfeiaeq r0 @ CHECK: it eq @ CHECK: rfeiaeq r0! @ CHECK: it eq @ CHECK: rfedbeq r0 @ CHECK: it eq @ CHECK: rfedbeq r0! @ CHECK: it eq @ CHECK: smceq #0 @ CHECK: it eq @ CHECK: ldmeq.w r0, {pc} @ CHECK: it eq @ CHECK: ldmeq.w r0!, {r1, pc} @ CHECK: it eq @ CHECK: ldmdbeq r0, {pc} @ CHECK: it eq @ CHECK: ldmdbeq r0!, {r1, pc} @ CHECK: it eq @ CHECK: popeq {pc} @ CHECK: it eq @ CHECK: bxnseq r0 @ CHECK: it eq @ CHECK: blxnseq r0 @ Thumb 16-bit ALU instructions set the flags iff they are not in an IT block, @ so instruction matching must change when generating an implicit IT block. .section test14 @ CHECK-LABEL: test14 @ Outside an IT block, the 16-bit encoding must set flags add r0, #1 @ CHECK:add.w r0, r0, #1 @ encoding: [0x00,0xf1,0x01,0x00] adds r0, #1 @ CHECK: adds r0, #1 @ encoding: [0x01,0x30] @ Inside an IT block, the 16-bit encoding can not set flags addeq r0, #1 @ CHECK: itt eq @ CHECK: addeq r0, #1 @ encoding: [0x01,0x30] addseq r0, #1 @ CHECK: addseq.w r0, r0, #1 @ encoding: [0x10,0xf1,0x01,0x00] @ Some variants of the B instruction have their own condition code field, and @ are not valid in IT blocks. .section test15 @ CHECK-LABEL: test15 @ Outside of an IT block, the 4 variants (narrow/wide, @ predicated/non-predicated) are selected as normal, and the predicated @ encodings are used instead of opening a new IT block: b #0x100 @ CHECK: b #256 @ encoding: [0x80,0xe0] b #0x800 @ CHECK: b.w #2048 @ encoding: [0x00,0xf0,0x00,0xbc] beq #0x4 @ CHECK-NOT: it @ CHECK: beq #4 @ encoding: [0x02,0xd0] beq #0x100 @ CHECK-NOT: it @ CHECK: beq.w #256 @ encoding: [0x00,0xf0,0x80,0x80] @ We could support "beq #0x100000" to "beq #0x1fffffc" by using t2Bcc in @ an IT block (these currently fail as the target is out of range). However, long @ ranges like this are rarely assembly-time constants, so this probably isn't @ worth doing. @ If we already have an open IT block, we can use the non-predicated encodings, @ which have a greater range: addeq r0, r1 beq #0x4 @ CHECK: itt eq @ CHECK: addeq r0, r1 @ CHECK: beq #4 @ encoding: [0x02,0xe0] addeq r0, r1 beq #0x100 @ CHECK: itt eq @ CHECK: addeq r0, r1 @ CHECK: beq #256 @ encoding: [0x80,0xe0] addeq r0, r1 beq #0x800 @ CHECK: itt eq @ CHECK: addeq r0, r1 @ CHECK: beq.w #2048 @ encoding: [0x00,0xf0,0x00,0xbc] @ If we have an open but incompatible IT block, we close it and use the @ self-predicated encodings, without an IT block: addeq r0, r1 bgt #0x4 @ CHECK: it eq @ CHECK: addeq r0, r1 @ CHECK: bgt #4 @ encoding: [0x02,0xdc] addeq r0, r1 bgt #0x100 @ CHECK: it eq @ CHECK: addeq r0, r1 @ CHECK: bgt.w #256 @ encoding: [0x00,0xf3,0x80,0x80] @ Breakpoint instructions are allowed in IT blocks, but are always executed @ regardless of the condition flags. We could continue an IT block through @ them, but currently do not. .section test16 @ CHECK-LABEL: test16 addeq r0, r1 bkpt #0 addeq r0, r1 @ CHECK: it eq @ CHECK: addeq r0, r1 @ CHECK: bkpt #0 @ CHECK: it eq @ CHECK: addeq r0, r1 @ The .if directive causes entire assembly statments to be dropped before they @ reach the IT block generation code. This happens to be exactly what we want, @ and allows IT blocks to extend into and out of .if blocks. Only one arm of the @ .if will be seen by the IT state tracking code, so the subeq shouldn't have @ any effect here. .section test17 @ CHECK-LABEL: test17 addeq r0, r1 .if 1 addeq r0, r1 .else subeq r0, r1 .endif addeq r0, r1 @ CHECK: ittt eq @ CHECK: addeq @ CHECK: addeq @ CHECK: addeq @ TODO: There are some other directives which we could continue through, such @ as .set and .global, but we currently conservatively flush the IT block before @ every directive (except for .if and friends, which are handled separately). .section test18 @ CHECK-LABEL: test18 addeq r0, r1 .set s, 1 addeq r0, r1 @ CHECK: it eq @ CHECK: addeq @ CHECK: it eq @ CHECK: addeq @ The .rept directive can be used to create long IT blocks. .section test19 @ CHECK-LABEL: test19 .rept 3 addeq r0, r1 subne r0, r1 .endr @ CHECK: itete eq @ CHECK: addeq r0, r1 @ CHECK: subne r0, r0, r1 @ CHECK: addeq r0, r1 @ CHECK: subne r0, r0, r1 @ CHECK: ite eq @ CHECK: addeq r0, r1 @ CHECK: subne r0, r0, r1 @ Flush at end of file .section test99 @ CHECK-LABEL: test99 addeq r0, #1 @ CHECK: it eq @ CHECK: addeq