llvm-project/llvm/test/MC/ARM/implicit-it-generation.s

410 lines
8.7 KiB
ArmAsm

@ 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.w r0, r0, r1
@ CHECK: addeq r0, r1
@ CHECK: subne.w r0, r0, r1
@ CHECK: ite eq
@ CHECK: addeq r0, r1
@ CHECK: subne.w r0, r0, r1
@ Flush at end of file
.section test99
@ CHECK-LABEL: test99
addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq