mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 17:36:05 +00:00
[ARM] Undeprecate complex IT blocks
AArch32/Armv8A introduced the performance deprecation of certain patterns of IT instructions. After some debate internal to ARM, this is now being reverted; i.e. no IT instruction patterns are performance deprecated anymore, as the perfomance degredation is not significant enough. This reverts the following: "ARMv8-A deprecates some uses of the T32 IT instruction. All uses of IT that apply to instructions other than a single subsequent 16-bit instruction from a restricted set are deprecated, as are explicit references to the PC within that single 16-bit instruction. This permits the non-deprecated forms of IT and subsequent instructions to be treated as a single 32-bit conditional instruction." The deprecation no longer applies, but the behaviour may be controlled by the -arm-restrict-it and -arm-no-restrict-it command-line options, with the latter being the default. No warnings about complex IT blocks will be generated. Reviewed By: dmgreen Differential Revision: https://reviews.llvm.org/D118044
This commit is contained in:
parent
cdc0573f75
commit
3d7662142d
@ -3313,7 +3313,7 @@ Disallow use of CRC instructions (ARM only)
|
||||
|
||||
.. option:: -mrestrict-it, -mno-restrict-it
|
||||
|
||||
Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode.
|
||||
Disallow generation of complex IT blocks. It is off by default.
|
||||
|
||||
.. option:: -mtp=<arg>
|
||||
|
||||
|
@ -3325,9 +3325,9 @@ def mstrict_align : Flag<["-"], "mstrict-align">, Alias<mno_unaligned_access>, F
|
||||
HelpText<"Force all memory accesses to be aligned (same as mno-unaligned-access)">;
|
||||
def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>;
|
||||
def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>,
|
||||
HelpText<"Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode.">;
|
||||
HelpText<"Disallow generation of complex IT blocks.">;
|
||||
def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group<m_arm_Features_Group>,
|
||||
HelpText<"Allow generation of deprecated IT blocks for ARMv8. It is off by default for ARMv8 Thumb mode">;
|
||||
HelpText<"Allow generation of complex IT blocks.">;
|
||||
def marm : Flag<["-"], "marm">, Alias<mno_thumb>;
|
||||
def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>,
|
||||
HelpText<"Reserve the r9 register (ARM only)">;
|
||||
|
@ -6129,14 +6129,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
CmdArgs.push_back("-arm-restrict-it");
|
||||
} else {
|
||||
CmdArgs.push_back("-mllvm");
|
||||
CmdArgs.push_back("-arm-no-restrict-it");
|
||||
CmdArgs.push_back("-arm-default-it");
|
||||
}
|
||||
} else if (Triple.isOSWindows() &&
|
||||
(Triple.getArch() == llvm::Triple::arm ||
|
||||
Triple.getArch() == llvm::Triple::thumb)) {
|
||||
// Windows on ARM expects restricted IT blocks
|
||||
CmdArgs.push_back("-mllvm");
|
||||
CmdArgs.push_back("-arm-restrict-it");
|
||||
}
|
||||
|
||||
// Forward -cl options to -cc1
|
||||
|
@ -12,4 +12,4 @@
|
||||
// RUN: %clang -target armv8a-none-gnueabi -mno-restrict-it -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-NO-RESTRICTED < %t %s
|
||||
|
||||
// CHECK-NO-RESTRICTED: "-mllvm" "-arm-no-restrict-it"
|
||||
// CHECK-NO-RESTRICTED: "-mllvm" "-arm-default-it"
|
||||
|
@ -1,4 +0,0 @@
|
||||
// RUN: %clang -target armv7-windows -### %s 2>&1 | FileCheck %s
|
||||
|
||||
// CHECK: "-mllvm" "-arm-restrict-it"
|
||||
|
@ -70,6 +70,15 @@ Changes to the AArch64 Backend
|
||||
Changes to the ARM Backend
|
||||
--------------------------
|
||||
|
||||
* Added support for the Armv9-A, Armv9.1-A and Armv9.2-A architectures.
|
||||
* Added support for the Armv8.1-M PACBTI-M extension.
|
||||
* Added support for the Armv9-A, Armv9.1-A and Armv9.2-A architectures.
|
||||
* Added support for the Armv8.1-M PACBTI-M extension.
|
||||
* Removed the deprecation of ARMv8-A T32 Complex IT blocks. No deprecation
|
||||
warnings will be generated and -mrestrict-it is now always off by default.
|
||||
Previously it was on by default for Armv8 and off for all other architecture
|
||||
versions.
|
||||
|
||||
Changes to the MIPS Target
|
||||
--------------------------
|
||||
|
||||
|
@ -6415,8 +6415,7 @@ def : InstAlias<"umull${s}${p} $RdLo, $RdHi, $Rn, $Rm",
|
||||
|
||||
// 'it' blocks in ARM mode just validate the predicates. The IT itself
|
||||
// is discarded.
|
||||
def ITasm : ARMAsmPseudo<"it$mask $cc", (ins it_pred:$cc, it_mask:$mask)>,
|
||||
ComplexDeprecationPredicate<"IT">;
|
||||
def ITasm : ARMAsmPseudo<"it$mask $cc", (ins it_pred:$cc, it_mask:$mask)>;
|
||||
|
||||
let mayLoad = 1, mayStore =1, hasSideEffects = 1, hasNoSchedulingInfo = 1 in
|
||||
def SPACE : PseudoInst<(outs GPR:$Rd), (ins i32imm:$size, GPR:$Rn),
|
||||
|
@ -3964,8 +3964,7 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
||||
let Defs = [ITSTATE] in
|
||||
def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask),
|
||||
AddrModeNone, 2, IIC_iALUx,
|
||||
"it$mask\t$cc", "", []>,
|
||||
ComplexDeprecationPredicate<"IT"> {
|
||||
"it$mask\t$cc", "", []> {
|
||||
// 16-bit instruction.
|
||||
let Inst{31-16} = 0x0000;
|
||||
let Inst{15-8} = 0b10111111;
|
||||
|
@ -52,19 +52,16 @@ UseFusedMulOps("arm-use-mulops",
|
||||
|
||||
enum ITMode {
|
||||
DefaultIT,
|
||||
RestrictedIT,
|
||||
NoRestrictedIT
|
||||
RestrictedIT
|
||||
};
|
||||
|
||||
static cl::opt<ITMode>
|
||||
IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),
|
||||
cl::ZeroOrMore,
|
||||
cl::values(clEnumValN(DefaultIT, "arm-default-it",
|
||||
"Generate IT block based on arch"),
|
||||
"Generate any type of IT block"),
|
||||
clEnumValN(RestrictedIT, "arm-restrict-it",
|
||||
"Disallow deprecated IT based on ARMv8"),
|
||||
clEnumValN(NoRestrictedIT, "arm-no-restrict-it",
|
||||
"Allow IT blocks based on ARMv7")));
|
||||
"Disallow complex IT blocks")));
|
||||
|
||||
/// ForceFastISel - Use the fast-isel, even for subtargets where it is not
|
||||
/// currently supported (for testing only).
|
||||
@ -237,14 +234,11 @@ void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
|
||||
|
||||
switch (IT) {
|
||||
case DefaultIT:
|
||||
RestrictIT = hasV8Ops() && !hasMinSize();
|
||||
RestrictIT = false;
|
||||
break;
|
||||
case RestrictedIT:
|
||||
RestrictIT = true;
|
||||
break;
|
||||
case NoRestrictedIT:
|
||||
RestrictIT = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
|
||||
|
@ -453,8 +453,8 @@ protected:
|
||||
/// ARMTargetLowering::allowsMisalignedMemoryAccesses().
|
||||
bool StrictAlign = false;
|
||||
|
||||
/// RestrictIT - If true, the subtarget disallows generation of deprecated IT
|
||||
/// blocks to conform to ARMv8 rule.
|
||||
/// RestrictIT - If true, the subtarget disallows generation of complex IT
|
||||
/// blocks.
|
||||
bool RestrictIT = false;
|
||||
|
||||
/// HasDSP - If true, the subtarget supports the DSP (saturating arith
|
||||
|
@ -10958,9 +10958,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
return true;
|
||||
}
|
||||
|
||||
{ // processInstruction() updates inITBlock state, we need to save it away
|
||||
bool wasInITBlock = inITBlock();
|
||||
|
||||
{
|
||||
// Some instructions need post-processing to, for example, tweak which
|
||||
// encoding is selected. Loop on it while changes happen so the
|
||||
// individual transformations can chain off each other. E.g.,
|
||||
@ -10969,12 +10967,6 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
LLVM_DEBUG(dbgs() << "Changed to: ";
|
||||
Inst.dump_pretty(dbgs(), MII.getName(Inst.getOpcode()));
|
||||
dbgs() << "\n");
|
||||
|
||||
// Only after the instruction is fully processed, we can validate it
|
||||
if (wasInITBlock && hasV8Ops() && isThumb() &&
|
||||
!isV8EligibleForIT(&Inst) && !getTargetOptions().MCNoDeprecatedWarn) {
|
||||
Warning(IDLoc, "deprecated instruction in IT block");
|
||||
}
|
||||
}
|
||||
|
||||
// Only move forward at the very end so that everything in validate
|
||||
|
@ -87,18 +87,6 @@ static bool getMRCDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getITDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
|
||||
std::string &Info) {
|
||||
if (STI.getFeatureBits()[llvm::ARM::HasV8Ops] && MI.getOperand(1).isImm() &&
|
||||
MI.getOperand(1).getImm() != 8) {
|
||||
Info = "applying IT instruction to more than one subsequent instruction is "
|
||||
"deprecated";
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getARMStoreDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI,
|
||||
std::string &Info) {
|
||||
assert(!STI.getFeatureBits()[llvm::ARM::ModeThumb] &&
|
||||
|
@ -226,9 +226,10 @@ bool Thumb2ITBlock::InsertITInstructions(MachineBasicBlock &MBB) {
|
||||
ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
|
||||
unsigned Mask = 0, Pos = 3;
|
||||
|
||||
// v8 IT blocks are limited to one conditional op unless -arm-no-restrict-it
|
||||
// IT blocks are limited to one conditional op if -arm-restrict-it
|
||||
// is set: skip the loop
|
||||
if (!restrictIT) {
|
||||
LLVM_DEBUG(dbgs() << "Allowing complex IT block\n";);
|
||||
// Branches, including tricky ones like LDM_RET, need to end an IT
|
||||
// block so check the instruction we just put in the block.
|
||||
for (; MBBI != E && Pos &&
|
||||
|
@ -1,11 +1,63 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mtriple=thumbv7-apple-ios -mcpu=cortex-a8 | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8 | FileCheck -check-prefix=CHECK-V8 %s
|
||||
; RUN: llc < %s -mtriple=thumbv7 -arm-restrict-it | FileCheck -check-prefix=CHECK-V8 %s
|
||||
; RUN: llc < %s -mtriple=thumbv7 -arm-restrict-it | FileCheck -check-prefix=CHECK-RESTRICT-IT %s
|
||||
|
||||
define i32 @t1(i32 %a, i32 %b, i8** %retaddr) {
|
||||
; CHECK-LABEL: t1:
|
||||
; CHECK: Block address taken
|
||||
; CHECK-NOT: Address of block that was removed by CodeGen
|
||||
; CHECK: @ %bb.0:
|
||||
; CHECK-NEXT: ldr r3, LCPI0_0
|
||||
; CHECK-NEXT: cmp r0, #0
|
||||
; CHECK-NEXT: LPC0_0:
|
||||
; CHECK-NEXT: add r3, pc
|
||||
; CHECK-NEXT: str r3, [r2]
|
||||
; CHECK-NEXT: mov.w r2, #1
|
||||
; CHECK-NEXT: it eq
|
||||
; CHECK-NEXT: moveq.w r2, #-1
|
||||
; CHECK-NEXT: Ltmp0: @ Block address taken
|
||||
; CHECK-NEXT: @ %bb.1: @ %common.ret
|
||||
; CHECK-NEXT: adds r0, r1, r2
|
||||
; CHECK-NEXT: bx lr
|
||||
; CHECK-NEXT: .p2align 2
|
||||
; CHECK-NEXT: @ %bb.2:
|
||||
; CHECK-NEXT: .data_region
|
||||
; CHECK-NEXT: LCPI0_0:
|
||||
; CHECK-NEXT: .long Ltmp0-(LPC0_0+4)
|
||||
; CHECK-NEXT: .end_data_region
|
||||
;
|
||||
; CHECK-V8-LABEL: t1:
|
||||
; CHECK-V8: @ %bb.0:
|
||||
; CHECK-V8-NEXT: ldr r3, .LCPI0_0
|
||||
; CHECK-V8-NEXT: cmp r0, #0
|
||||
; CHECK-V8-NEXT: str r3, [r2]
|
||||
; CHECK-V8-NEXT: mov.w r2, #1
|
||||
; CHECK-V8-NEXT: it eq
|
||||
; CHECK-V8-NEXT: moveq.w r2, #-1
|
||||
; CHECK-V8-NEXT: .Ltmp0: @ Block address taken
|
||||
; CHECK-V8-NEXT: @ %bb.1: @ %common.ret
|
||||
; CHECK-V8-NEXT: adds r0, r1, r2
|
||||
; CHECK-V8-NEXT: bx lr
|
||||
; CHECK-V8-NEXT: .p2align 2
|
||||
; CHECK-V8-NEXT: @ %bb.2:
|
||||
; CHECK-V8-NEXT: .LCPI0_0:
|
||||
; CHECK-V8-NEXT: .long .Ltmp0
|
||||
;
|
||||
; CHECK-RESTRICT-IT-LABEL: t1:
|
||||
; CHECK-RESTRICT-IT: @ %bb.0:
|
||||
; CHECK-RESTRICT-IT-NEXT: ldr r3, .LCPI0_0
|
||||
; CHECK-RESTRICT-IT-NEXT: str r3, [r2]
|
||||
; CHECK-RESTRICT-IT-NEXT: movs r2, #1
|
||||
; CHECK-RESTRICT-IT-NEXT: cmp r0, #0
|
||||
; CHECK-RESTRICT-IT-NEXT: it eq
|
||||
; CHECK-RESTRICT-IT-NEXT: moveq.w r2, #-1
|
||||
; CHECK-RESTRICT-IT-NEXT: .Ltmp0: @ Block address taken
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.1: @ %common.ret
|
||||
; CHECK-RESTRICT-IT-NEXT: adds r0, r1, r2
|
||||
; CHECK-RESTRICT-IT-NEXT: bx lr
|
||||
; CHECK-RESTRICT-IT-NEXT: .p2align 2
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.2:
|
||||
; CHECK-RESTRICT-IT-NEXT: .LCPI0_0:
|
||||
; CHECK-RESTRICT-IT-NEXT: .long .Ltmp0
|
||||
store i8* blockaddress(@t1, %cond_true), i8** %retaddr
|
||||
%tmp2 = icmp eq i32 %a, 0
|
||||
br i1 %tmp2, label %cond_false, label %cond_true
|
||||
@ -21,10 +73,78 @@ cond_false:
|
||||
|
||||
define i32 @t2(i32 %a, i32 %b, i32 %c, i32 %d, i8** %retaddr) {
|
||||
; CHECK-LABEL: t2:
|
||||
; CHECK: Block address taken
|
||||
; CHECK: %cond_true
|
||||
; CHECK: add
|
||||
; CHECK: bx lr
|
||||
; CHECK: @ %bb.0:
|
||||
; CHECK-NEXT: ldr.w r9, [sp]
|
||||
; CHECK-NEXT: add r0, r1
|
||||
; CHECK-NEXT: ldr.w r12, LCPI1_0
|
||||
; CHECK-NEXT: cmp r3, #3
|
||||
; CHECK-NEXT: LPC1_0:
|
||||
; CHECK-NEXT: add r12, pc
|
||||
; CHECK-NEXT: str.w r12, [r9]
|
||||
; CHECK-NEXT: it gt
|
||||
; CHECK-NEXT: bxgt lr
|
||||
; CHECK-NEXT: LBB1_1:
|
||||
; CHECK-NEXT: cmp r2, #10
|
||||
; CHECK-NEXT: ble LBB1_3
|
||||
; CHECK-NEXT: Ltmp1: @ Block address taken
|
||||
; CHECK-NEXT: @ %bb.2: @ %cond_true
|
||||
; CHECK-NEXT: add r0, r2
|
||||
; CHECK-NEXT: subs r0, r0, r3
|
||||
; CHECK-NEXT: LBB1_3: @ %common.ret
|
||||
; CHECK-NEXT: bx lr
|
||||
; CHECK-NEXT: .p2align 2
|
||||
; CHECK-NEXT: @ %bb.4:
|
||||
; CHECK-NEXT: .data_region
|
||||
; CHECK-NEXT: LCPI1_0:
|
||||
; CHECK-NEXT: .long Ltmp1-(LPC1_0+4)
|
||||
; CHECK-NEXT: .end_data_region
|
||||
;
|
||||
; CHECK-V8-LABEL: t2:
|
||||
; CHECK-V8: @ %bb.0:
|
||||
; CHECK-V8-NEXT: push {r7, lr}
|
||||
; CHECK-V8-NEXT: ldr.w r12, [sp, #8]
|
||||
; CHECK-V8-NEXT: add r0, r1
|
||||
; CHECK-V8-NEXT: ldr.w lr, .LCPI1_0
|
||||
; CHECK-V8-NEXT: cmp r3, #3
|
||||
; CHECK-V8-NEXT: str.w lr, [r12]
|
||||
; CHECK-V8-NEXT: it gt
|
||||
; CHECK-V8-NEXT: popgt {r7, pc}
|
||||
; CHECK-V8-NEXT: .LBB1_1:
|
||||
; CHECK-V8-NEXT: cmp r2, #10
|
||||
; CHECK-V8-NEXT: ble .LBB1_3
|
||||
; CHECK-V8-NEXT: .Ltmp1: @ Block address taken
|
||||
; CHECK-V8-NEXT: @ %bb.2: @ %cond_true
|
||||
; CHECK-V8-NEXT: add r0, r2
|
||||
; CHECK-V8-NEXT: subs r0, r0, r3
|
||||
; CHECK-V8-NEXT: .LBB1_3: @ %common.ret
|
||||
; CHECK-V8-NEXT: pop {r7, pc}
|
||||
; CHECK-V8-NEXT: .p2align 2
|
||||
; CHECK-V8-NEXT: @ %bb.4:
|
||||
; CHECK-V8-NEXT: .LCPI1_0:
|
||||
; CHECK-V8-NEXT: .long .Ltmp1
|
||||
;
|
||||
; CHECK-RESTRICT-IT-LABEL: t2:
|
||||
; CHECK-RESTRICT-IT: @ %bb.0:
|
||||
; CHECK-RESTRICT-IT-NEXT: push {r7, lr}
|
||||
; CHECK-RESTRICT-IT-NEXT: ldr.w r12, [sp, #8]
|
||||
; CHECK-RESTRICT-IT-NEXT: add r0, r1
|
||||
; CHECK-RESTRICT-IT-NEXT: ldr.w lr, .LCPI1_0
|
||||
; CHECK-RESTRICT-IT-NEXT: cmp r3, #3
|
||||
; CHECK-RESTRICT-IT-NEXT: str.w lr, [r12]
|
||||
; CHECK-RESTRICT-IT-NEXT: bgt .LBB1_3
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.1:
|
||||
; CHECK-RESTRICT-IT-NEXT: cmp r2, #10
|
||||
; CHECK-RESTRICT-IT-NEXT: ble .LBB1_3
|
||||
; CHECK-RESTRICT-IT-NEXT: .Ltmp1: @ Block address taken
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.2: @ %cond_true
|
||||
; CHECK-RESTRICT-IT-NEXT: add r0, r2
|
||||
; CHECK-RESTRICT-IT-NEXT: subs r0, r0, r3
|
||||
; CHECK-RESTRICT-IT-NEXT: .LBB1_3: @ %common.ret
|
||||
; CHECK-RESTRICT-IT-NEXT: pop {r7, pc}
|
||||
; CHECK-RESTRICT-IT-NEXT: .p2align 2
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.4:
|
||||
; CHECK-RESTRICT-IT-NEXT: .LCPI1_0:
|
||||
; CHECK-RESTRICT-IT-NEXT: .long .Ltmp1
|
||||
store i8* blockaddress(@t2, %cond_true), i8** %retaddr
|
||||
%tmp2 = icmp sgt i32 %c, 10
|
||||
%tmp5 = icmp slt i32 %d, 4
|
||||
@ -43,8 +163,44 @@ UnifiedReturnBlock:
|
||||
|
||||
define hidden fastcc void @t3(i8** %retaddr, i1 %tst, i8* %p8) {
|
||||
; CHECK-LABEL: t3:
|
||||
; CHECK: Block address taken
|
||||
; CHECK-NOT: Address of block that was removed by CodeGen
|
||||
; CHECK: @ %bb.0: @ %bb
|
||||
; CHECK-NEXT: ldr r1, LCPI2_0
|
||||
; CHECK-NEXT: LPC2_0:
|
||||
; CHECK-NEXT: add r1, pc
|
||||
; CHECK-NEXT: str r1, [r0]
|
||||
; CHECK-NEXT: Ltmp2: @ Block address taken
|
||||
; CHECK-NEXT: @ %bb.1: @ %common.ret
|
||||
; CHECK-NEXT: bx lr
|
||||
; CHECK-NEXT: .p2align 2
|
||||
; CHECK-NEXT: @ %bb.2:
|
||||
; CHECK-NEXT: .data_region
|
||||
; CHECK-NEXT: LCPI2_0:
|
||||
; CHECK-NEXT: .long Ltmp2-(LPC2_0+4)
|
||||
; CHECK-NEXT: .end_data_region
|
||||
;
|
||||
; CHECK-V8-LABEL: t3:
|
||||
; CHECK-V8: @ %bb.0: @ %bb
|
||||
; CHECK-V8-NEXT: ldr r1, .LCPI2_0
|
||||
; CHECK-V8-NEXT: str r1, [r0]
|
||||
; CHECK-V8-NEXT: .Ltmp2: @ Block address taken
|
||||
; CHECK-V8-NEXT: @ %bb.1: @ %common.ret
|
||||
; CHECK-V8-NEXT: bx lr
|
||||
; CHECK-V8-NEXT: .p2align 2
|
||||
; CHECK-V8-NEXT: @ %bb.2:
|
||||
; CHECK-V8-NEXT: .LCPI2_0:
|
||||
; CHECK-V8-NEXT: .long .Ltmp2
|
||||
;
|
||||
; CHECK-RESTRICT-IT-LABEL: t3:
|
||||
; CHECK-RESTRICT-IT: @ %bb.0: @ %bb
|
||||
; CHECK-RESTRICT-IT-NEXT: ldr r1, .LCPI2_0
|
||||
; CHECK-RESTRICT-IT-NEXT: str r1, [r0]
|
||||
; CHECK-RESTRICT-IT-NEXT: .Ltmp2: @ Block address taken
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.1: @ %common.ret
|
||||
; CHECK-RESTRICT-IT-NEXT: bx lr
|
||||
; CHECK-RESTRICT-IT-NEXT: .p2align 2
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.2:
|
||||
; CHECK-RESTRICT-IT-NEXT: .LCPI2_0:
|
||||
; CHECK-RESTRICT-IT-NEXT: .long .Ltmp2
|
||||
bb:
|
||||
store i8* blockaddress(@t3, %KBBlockZero_return_1), i8** %retaddr
|
||||
br i1 %tst, label %bb77, label %bb7.i
|
||||
@ -73,9 +229,53 @@ KBBlockZero.exit: ; preds = %bb2.i
|
||||
|
||||
@foo = global i32 ()* null
|
||||
define i32 @t4(i32 %x, i32 ()* %p_foo) {
|
||||
; CHECK-LABEL: t4:
|
||||
; CHECK: @ %bb.0: @ %entry
|
||||
; CHECK-NEXT: push {r4, lr}
|
||||
; CHECK-NEXT: mov r4, r0
|
||||
; CHECK-NEXT: cmp r0, #59
|
||||
; CHECK-NEXT: ittt gt
|
||||
; CHECK-NEXT: mvngt r0, #119
|
||||
; CHECK-NEXT: addgt r0, r4
|
||||
; CHECK-NEXT: popgt {r4, pc}
|
||||
; CHECK-NEXT: LBB3_1: @ %if.then
|
||||
; CHECK-NEXT: blx r1
|
||||
; CHECK-NEXT: mov.w r0, #-1
|
||||
; CHECK-NEXT: add r0, r4
|
||||
; CHECK-NEXT: pop {r4, pc}
|
||||
;
|
||||
; CHECK-V8-LABEL: t4:
|
||||
; CHECK-V8: @ %bb.0: @ %entry
|
||||
; CHECK-V8-NEXT: push {r4, lr}
|
||||
; CHECK-V8-NEXT: mov r4, r0
|
||||
; CHECK-V8-NEXT: cmp r0, #59
|
||||
; CHECK-V8-NEXT: bgt .LBB3_2
|
||||
; CHECK-V8-NEXT: @ %bb.1: @ %if.then
|
||||
; CHECK-V8-NEXT: blx r1
|
||||
; CHECK-V8-NEXT: mov.w r0, #-1
|
||||
; CHECK-V8-NEXT: add r0, r4
|
||||
; CHECK-V8-NEXT: pop {r4, pc}
|
||||
; CHECK-V8-NEXT: .LBB3_2:
|
||||
; CHECK-V8-NEXT: mvn r0, #119
|
||||
; CHECK-V8-NEXT: add r0, r4
|
||||
; CHECK-V8-NEXT: pop {r4, pc}
|
||||
;
|
||||
; CHECK-RESTRICT-IT-LABEL: t4:
|
||||
; CHECK-RESTRICT-IT: @ %bb.0: @ %entry
|
||||
; CHECK-RESTRICT-IT-NEXT: push {r4, lr}
|
||||
; CHECK-RESTRICT-IT-NEXT: mov r4, r0
|
||||
; CHECK-RESTRICT-IT-NEXT: cmp r0, #59
|
||||
; CHECK-RESTRICT-IT-NEXT: bgt .LBB3_2
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.1: @ %if.then
|
||||
; CHECK-RESTRICT-IT-NEXT: blx r1
|
||||
; CHECK-RESTRICT-IT-NEXT: mov.w r0, #-1
|
||||
; CHECK-RESTRICT-IT-NEXT: add r0, r4
|
||||
; CHECK-RESTRICT-IT-NEXT: pop {r4, pc}
|
||||
; CHECK-RESTRICT-IT-NEXT: .LBB3_2:
|
||||
; CHECK-RESTRICT-IT-NEXT: mvn r0, #119
|
||||
; CHECK-RESTRICT-IT-NEXT: add r0, r4
|
||||
; CHECK-RESTRICT-IT-NEXT: pop {r4, pc}
|
||||
entry:
|
||||
;CHECK-LABEL: t4:
|
||||
;CHECK-V8-LABEL: t4:
|
||||
%cmp = icmp slt i32 %x, 60
|
||||
br i1 %cmp, label %if.then, label %if.else
|
||||
|
||||
@ -99,51 +299,67 @@ return: ; preds = %if.end5, %if.then4,
|
||||
; predicated block.
|
||||
; B can be predicated with A.BrToBPredicate into A iff B.Predicate is less
|
||||
; "permissive" than A.BrToBPredicate, i.e., iff A.BrToBPredicate subsumes
|
||||
; B.Predicate.
|
||||
|
||||
; Hard-coded registers comes from the ABI.
|
||||
; CHECK-LABEL: wrapDistance:
|
||||
; CHECK: cmp r1, #59
|
||||
; CHECK-NEXT: itt le
|
||||
; CHECK-NEXT: suble r0, r2, #1
|
||||
; CHECK-NEXT: bxle lr
|
||||
; CHECK-NEXT: LBB{{.*}}:
|
||||
; CHECK-NEXT: subs [[REG:r[0-9]+]], #120
|
||||
; CHECK-NEXT: cmp [[REG]], r1
|
||||
; CHECK-NOT: it lt
|
||||
; CHECK-NEXT: bge [[LABEL:.+]]
|
||||
; Next BB
|
||||
; CHECK-NOT: cmplt
|
||||
; CHECK: cmp r0, #119
|
||||
; CHECK-NEXT: itt le
|
||||
; CHECK-NEXT: addle r0, r1, #1
|
||||
; CHECK-NEXT: bxle lr
|
||||
; Next BB
|
||||
; CHECK: [[LABEL]]:
|
||||
; CHECK-NEXT: subs r0, r1, r0
|
||||
; CHECK-NEXT: bx lr
|
||||
|
||||
; CHECK-V8-LABEL: wrapDistance:
|
||||
; CHECK-V8: cmp r1, #59
|
||||
; CHECK-V8-NEXT: bgt
|
||||
; CHECK-V8-NEXT: %if.then
|
||||
; CHECK-V8-NEXT: subs r0, r2, #1
|
||||
; CHECK-V8-NEXT: bx lr
|
||||
; CHECK-V8-NEXT: %if.else
|
||||
; CHECK-V8-NEXT: subs [[REG:r[0-9]+]], #120
|
||||
; CHECK-V8-NEXT: cmp [[REG]], r1
|
||||
; CHECK-V8-NEXT: bge
|
||||
; CHECK-V8-NEXT: %if.else
|
||||
; CHECK-V8-NEXT: cmp r0, #119
|
||||
; CHECK-V8-NEXT: bgt
|
||||
; CHECK-V8-NEXT: %if.then4
|
||||
; CHECK-V8-NEXT: adds r0, r1, #1
|
||||
; CHECK-V8-NEXT: bx lr
|
||||
; CHECK-V8-NEXT: %if.end5
|
||||
; CHECK-V8-NEXT: subs r0, r1, r0
|
||||
; CHECK-V8-NEXT: bx lr
|
||||
; B.Predicate.
|
||||
|
||||
define i32 @wrapDistance(i32 %tx, i32 %sx, i32 %w) {
|
||||
; CHECK-LABEL: wrapDistance:
|
||||
; CHECK: @ %bb.0: @ %entry
|
||||
; CHECK-NEXT: cmp r1, #59
|
||||
; CHECK-NEXT: itt le
|
||||
; CHECK-NEXT: suble r0, r2, #1
|
||||
; CHECK-NEXT: bxle lr
|
||||
; CHECK-NEXT: LBB4_1: @ %if.else
|
||||
; CHECK-NEXT: subs r2, #120
|
||||
; CHECK-NEXT: cmp r2, r1
|
||||
; CHECK-NEXT: bge LBB4_3
|
||||
; CHECK-NEXT: @ %bb.2: @ %if.else
|
||||
; CHECK-NEXT: cmp r0, #119
|
||||
; CHECK-NEXT: itt le
|
||||
; CHECK-NEXT: addle r0, r1, #1
|
||||
; CHECK-NEXT: bxle lr
|
||||
; CHECK-NEXT: LBB4_3: @ %if.end5
|
||||
; CHECK-NEXT: subs r0, r1, r0
|
||||
; CHECK-NEXT: bx lr
|
||||
;
|
||||
; CHECK-V8-LABEL: wrapDistance:
|
||||
; CHECK-V8: @ %bb.0: @ %entry
|
||||
; CHECK-V8-NEXT: cmp r1, #59
|
||||
; CHECK-V8-NEXT: itt le
|
||||
; CHECK-V8-NEXT: suble r0, r2, #1
|
||||
; CHECK-V8-NEXT: bxle lr
|
||||
; CHECK-V8-NEXT: .LBB4_1: @ %if.else
|
||||
; CHECK-V8-NEXT: subs r2, #120
|
||||
; CHECK-V8-NEXT: cmp r2, r1
|
||||
; CHECK-V8-NEXT: bge .LBB4_3
|
||||
; CHECK-V8-NEXT: @ %bb.2: @ %if.else
|
||||
; CHECK-V8-NEXT: cmp r0, #119
|
||||
; CHECK-V8-NEXT: itt le
|
||||
; CHECK-V8-NEXT: addle r0, r1, #1
|
||||
; CHECK-V8-NEXT: bxle lr
|
||||
; CHECK-V8-NEXT: .LBB4_3: @ %if.end5
|
||||
; CHECK-V8-NEXT: subs r0, r1, r0
|
||||
; CHECK-V8-NEXT: bx lr
|
||||
;
|
||||
; CHECK-RESTRICT-IT-LABEL: wrapDistance:
|
||||
; CHECK-RESTRICT-IT: @ %bb.0: @ %entry
|
||||
; CHECK-RESTRICT-IT-NEXT: cmp r1, #59
|
||||
; CHECK-RESTRICT-IT-NEXT: bgt .LBB4_2
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.1: @ %if.then
|
||||
; CHECK-RESTRICT-IT-NEXT: subs r0, r2, #1
|
||||
; CHECK-RESTRICT-IT-NEXT: bx lr
|
||||
; CHECK-RESTRICT-IT-NEXT: .LBB4_2: @ %if.else
|
||||
; CHECK-RESTRICT-IT-NEXT: subs r2, #120
|
||||
; CHECK-RESTRICT-IT-NEXT: cmp r2, r1
|
||||
; CHECK-RESTRICT-IT-NEXT: bge .LBB4_5
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.3: @ %if.else
|
||||
; CHECK-RESTRICT-IT-NEXT: cmp r0, #119
|
||||
; CHECK-RESTRICT-IT-NEXT: bgt .LBB4_5
|
||||
; CHECK-RESTRICT-IT-NEXT: @ %bb.4: @ %if.then4
|
||||
; CHECK-RESTRICT-IT-NEXT: adds r0, r1, #1
|
||||
; CHECK-RESTRICT-IT-NEXT: bx lr
|
||||
; CHECK-RESTRICT-IT-NEXT: .LBB4_5: @ %if.end5
|
||||
; CHECK-RESTRICT-IT-NEXT: subs r0, r1, r0
|
||||
; CHECK-RESTRICT-IT-NEXT: bx lr
|
||||
entry:
|
||||
%cmp = icmp slt i32 %sx, 60
|
||||
br i1 %cmp, label %if.then, label %if.else
|
||||
|
@ -1,3 +1,4 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=arm-eabi -arm-atomic-cfg-tidy=0 %s -o - | FileCheck -check-prefix=ARM %s
|
||||
; RUN: llc -mtriple=thumb-eabi -arm-atomic-cfg-tidy=0 %s -o - | FileCheck -check-prefix=THUMB %s
|
||||
; RUN: llc -mtriple=thumb-eabi -arm-atomic-cfg-tidy=0 -mcpu=arm1156t2-s -mattr=+thumb2 %s -o - | FileCheck -check-prefix=T2 %s
|
||||
@ -11,6 +12,152 @@
|
||||
; THUMB-LABEL: foo:
|
||||
; T2-LABEL: foo:
|
||||
define %struct.Foo* @foo(%struct.Foo* %this, i32 %acc) nounwind readonly align 2 {
|
||||
; ARM: @ %bb.0: @ %entry
|
||||
; ARM-NEXT: add r2, r0, #4
|
||||
; ARM-NEXT: mov r12, #1
|
||||
; ARM-NEXT: b .LBB0_3
|
||||
; ARM-NEXT: .LBB0_1: @ %tailrecurse.switch
|
||||
; ARM-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; ARM-NEXT: cmp r3, #1
|
||||
; ARM-NEXT: movne pc, lr
|
||||
; ARM-NEXT: .LBB0_2: @ %sw.bb
|
||||
; ARM-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; ARM-NEXT: orr r1, r3, r1, lsl #1
|
||||
; ARM-NEXT: add r2, r2, #4
|
||||
; ARM-NEXT: add r12, r12, #1
|
||||
; ARM-NEXT: .LBB0_3: @ %tailrecurse
|
||||
; ARM-NEXT: @ =>This Inner Loop Header: Depth=1
|
||||
; ARM-NEXT: ldr r3, [r2, #-4]
|
||||
; ARM-NEXT: ands r3, r3, #3
|
||||
; ARM-NEXT: beq .LBB0_2
|
||||
; ARM-NEXT: @ %bb.4: @ %tailrecurse.switch
|
||||
; ARM-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; ARM-NEXT: cmp r3, #3
|
||||
; ARM-NEXT: moveq r0, r2
|
||||
; ARM-NEXT: moveq pc, lr
|
||||
; ARM-NEXT: .LBB0_5: @ %tailrecurse.switch
|
||||
; ARM-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; ARM-NEXT: cmp r3, #2
|
||||
; ARM-NEXT: bne .LBB0_1
|
||||
; ARM-NEXT: @ %bb.6: @ %sw.bb8
|
||||
; ARM-NEXT: add r1, r1, r12
|
||||
; ARM-NEXT: add r0, r0, r1, lsl #2
|
||||
; ARM-NEXT: mov pc, lr
|
||||
;
|
||||
; THUMB: @ %bb.0: @ %entry
|
||||
; THUMB-NEXT: .save {r4, r5, r7, lr}
|
||||
; THUMB-NEXT: push {r4, r5, r7, lr}
|
||||
; THUMB-NEXT: movs r2, #1
|
||||
; THUMB-NEXT: movs r3, r0
|
||||
; THUMB-NEXT: .LBB0_1: @ %tailrecurse
|
||||
; THUMB-NEXT: @ =>This Inner Loop Header: Depth=1
|
||||
; THUMB-NEXT: ldr r5, [r3]
|
||||
; THUMB-NEXT: movs r4, #3
|
||||
; THUMB-NEXT: ands r4, r5
|
||||
; THUMB-NEXT: beq .LBB0_5
|
||||
; THUMB-NEXT: @ %bb.2: @ %tailrecurse.switch
|
||||
; THUMB-NEXT: @ in Loop: Header=BB0_1 Depth=1
|
||||
; THUMB-NEXT: cmp r4, #3
|
||||
; THUMB-NEXT: beq .LBB0_6
|
||||
; THUMB-NEXT: @ %bb.3: @ %tailrecurse.switch
|
||||
; THUMB-NEXT: @ in Loop: Header=BB0_1 Depth=1
|
||||
; THUMB-NEXT: cmp r4, #2
|
||||
; THUMB-NEXT: beq .LBB0_7
|
||||
; THUMB-NEXT: @ %bb.4: @ %tailrecurse.switch
|
||||
; THUMB-NEXT: @ in Loop: Header=BB0_1 Depth=1
|
||||
; THUMB-NEXT: cmp r4, #1
|
||||
; THUMB-NEXT: bne .LBB0_9
|
||||
; THUMB-NEXT: .LBB0_5: @ %sw.bb
|
||||
; THUMB-NEXT: @ in Loop: Header=BB0_1 Depth=1
|
||||
; THUMB-NEXT: lsls r1, r1, #1
|
||||
; THUMB-NEXT: orrs r4, r1
|
||||
; THUMB-NEXT: adds r3, r3, #4
|
||||
; THUMB-NEXT: adds r2, r2, #1
|
||||
; THUMB-NEXT: movs r1, r4
|
||||
; THUMB-NEXT: b .LBB0_1
|
||||
; THUMB-NEXT: .LBB0_6: @ %sw.bb6
|
||||
; THUMB-NEXT: adds r0, r3, #4
|
||||
; THUMB-NEXT: b .LBB0_8
|
||||
; THUMB-NEXT: .LBB0_7: @ %sw.bb8
|
||||
; THUMB-NEXT: adds r1, r1, r2
|
||||
; THUMB-NEXT: lsls r1, r1, #2
|
||||
; THUMB-NEXT: adds r0, r0, r1
|
||||
; THUMB-NEXT: .LBB0_8: @ %sw.bb6
|
||||
; THUMB-NEXT: pop {r4, r5, r7}
|
||||
; THUMB-NEXT: pop {r1}
|
||||
; THUMB-NEXT: bx r1
|
||||
; THUMB-NEXT: .LBB0_9: @ %sw.epilog
|
||||
; THUMB-NEXT: pop {r4, r5, r7}
|
||||
; THUMB-NEXT: pop {r0}
|
||||
; THUMB-NEXT: bx r0
|
||||
;
|
||||
; T2: @ %bb.0: @ %entry
|
||||
; T2-NEXT: adds r2, r0, #4
|
||||
; T2-NEXT: mov.w r12, #1
|
||||
; T2-NEXT: b .LBB0_3
|
||||
; T2-NEXT: .LBB0_1: @ %tailrecurse.switch
|
||||
; T2-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; T2-NEXT: cmp r3, #1
|
||||
; T2-NEXT: it ne
|
||||
; T2-NEXT: bxne lr
|
||||
; T2-NEXT: .LBB0_2: @ %sw.bb
|
||||
; T2-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; T2-NEXT: orr.w r1, r3, r1, lsl #1
|
||||
; T2-NEXT: adds r2, #4
|
||||
; T2-NEXT: add.w r12, r12, #1
|
||||
; T2-NEXT: .LBB0_3: @ %tailrecurse
|
||||
; T2-NEXT: @ =>This Inner Loop Header: Depth=1
|
||||
; T2-NEXT: ldr r3, [r2, #-4]
|
||||
; T2-NEXT: ands r3, r3, #3
|
||||
; T2-NEXT: beq .LBB0_2
|
||||
; T2-NEXT: @ %bb.4: @ %tailrecurse.switch
|
||||
; T2-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; T2-NEXT: cmp r3, #3
|
||||
; T2-NEXT: itt eq
|
||||
; T2-NEXT: moveq r0, r2
|
||||
; T2-NEXT: bxeq lr
|
||||
; T2-NEXT: .LBB0_5: @ %tailrecurse.switch
|
||||
; T2-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; T2-NEXT: cmp r3, #2
|
||||
; T2-NEXT: bne .LBB0_1
|
||||
; T2-NEXT: @ %bb.6: @ %sw.bb8
|
||||
; T2-NEXT: add r1, r12
|
||||
; T2-NEXT: add.w r0, r0, r1, lsl #2
|
||||
; T2-NEXT: bx lr
|
||||
;
|
||||
; V8: @ %bb.0: @ %entry
|
||||
; V8-NEXT: adds r2, r0, #4
|
||||
; V8-NEXT: mov.w r12, #1
|
||||
; V8-NEXT: b .LBB0_3
|
||||
; V8-NEXT: .LBB0_1: @ %tailrecurse.switch
|
||||
; V8-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; V8-NEXT: cmp r3, #1
|
||||
; V8-NEXT: it ne
|
||||
; V8-NEXT: bxne lr
|
||||
; V8-NEXT: .LBB0_2: @ %sw.bb
|
||||
; V8-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; V8-NEXT: orr.w r1, r3, r1, lsl #1
|
||||
; V8-NEXT: adds r2, #4
|
||||
; V8-NEXT: add.w r12, r12, #1
|
||||
; V8-NEXT: .LBB0_3: @ %tailrecurse
|
||||
; V8-NEXT: @ =>This Inner Loop Header: Depth=1
|
||||
; V8-NEXT: ldr r3, [r2, #-4]
|
||||
; V8-NEXT: ands r3, r3, #3
|
||||
; V8-NEXT: beq .LBB0_2
|
||||
; V8-NEXT: @ %bb.4: @ %tailrecurse.switch
|
||||
; V8-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; V8-NEXT: cmp r3, #3
|
||||
; V8-NEXT: itt eq
|
||||
; V8-NEXT: moveq r0, r2
|
||||
; V8-NEXT: bxeq lr
|
||||
; V8-NEXT: .LBB0_5: @ %tailrecurse.switch
|
||||
; V8-NEXT: @ in Loop: Header=BB0_3 Depth=1
|
||||
; V8-NEXT: cmp r3, #2
|
||||
; V8-NEXT: bne .LBB0_1
|
||||
; V8-NEXT: @ %bb.6: @ %sw.bb8
|
||||
; V8-NEXT: add r1, r12
|
||||
; V8-NEXT: add.w r0, r0, r1, lsl #2
|
||||
; V8-NEXT: bx lr
|
||||
entry:
|
||||
%scevgep = getelementptr %struct.Foo, %struct.Foo* %this, i32 1
|
||||
br label %tailrecurse
|
||||
@ -24,31 +171,15 @@ tailrecurse: ; preds = %sw.bb, %entry
|
||||
%tmp2 = load i8*, i8** %scevgep5
|
||||
%0 = ptrtoint i8* %tmp2 to i32
|
||||
|
||||
; ARM: ands {{r[0-9]+}}, {{r[0-9]+}}, #3
|
||||
; ARM-NEXT: beq
|
||||
|
||||
; THUMB: movs r[[R0:[0-9]+]], #3
|
||||
; THUMB-NEXT: ands r[[R0]], r
|
||||
; THUMB-NEXT: beq
|
||||
|
||||
; T2: ands {{r[0-9]+}}, {{r[0-9]+}}, #3
|
||||
; T2-NEXT: beq
|
||||
|
||||
%and = and i32 %0, 3
|
||||
%tst = icmp eq i32 %and, 0
|
||||
br i1 %tst, label %sw.bb, label %tailrecurse.switch
|
||||
|
||||
tailrecurse.switch: ; preds = %tailrecurse
|
||||
; V8-LABEL: %tailrecurse.switch
|
||||
; V8: cmp
|
||||
; V8-NEXT: beq
|
||||
; V8-NEXT: %tailrecurse.switch
|
||||
; V8: cmp
|
||||
; V8-NEXT: beq
|
||||
; V8-NEXT: %tailrecurse.switch
|
||||
; V8: cmp
|
||||
; V8-NEXT: bne
|
||||
; V8-NEXT: %sw.bb
|
||||
|
||||
switch i32 %and, label %sw.epilog [
|
||||
i32 1, label %sw.bb
|
||||
i32 3, label %sw.bb6
|
||||
@ -85,39 +216,94 @@ sw.epilog: ; preds = %tailrecurse.switch
|
||||
; T2-LABEL: bar:
|
||||
; V8-LABEL: bar:
|
||||
define internal zeroext i8 @bar(%struct.S* %x, %struct.S* nocapture %y) nounwind readonly {
|
||||
; ARM: @ %bb.0: @ %entry
|
||||
; ARM-NEXT: ldrb r2, [r0, #4]
|
||||
; ARM-NEXT: ands r2, r2, #112
|
||||
; ARM-NEXT: ldrbne r1, [r1, #4]
|
||||
; ARM-NEXT: andsne r1, r1, #112
|
||||
; ARM-NEXT: beq .LBB1_2
|
||||
; ARM-NEXT: @ %bb.1: @ %bb2
|
||||
; ARM-NEXT: cmp r2, #16
|
||||
; ARM-NEXT: cmpne r1, #16
|
||||
; ARM-NEXT: andeq r0, r0, #255
|
||||
; ARM-NEXT: moveq pc, lr
|
||||
; ARM-NEXT: .LBB1_2: @ %return
|
||||
; ARM-NEXT: mov r0, #1
|
||||
; ARM-NEXT: mov pc, lr
|
||||
;
|
||||
; THUMB: @ %bb.0: @ %entry
|
||||
; THUMB-NEXT: ldrb r2, [r0, #4]
|
||||
; THUMB-NEXT: movs r3, #112
|
||||
; THUMB-NEXT: ands r2, r3
|
||||
; THUMB-NEXT: beq .LBB1_4
|
||||
; THUMB-NEXT: @ %bb.1: @ %bb
|
||||
; THUMB-NEXT: ldrb r1, [r1, #4]
|
||||
; THUMB-NEXT: ands r1, r3
|
||||
; THUMB-NEXT: beq .LBB1_4
|
||||
; THUMB-NEXT: @ %bb.2: @ %bb2
|
||||
; THUMB-NEXT: cmp r2, #16
|
||||
; THUMB-NEXT: beq .LBB1_5
|
||||
; THUMB-NEXT: @ %bb.3: @ %bb2
|
||||
; THUMB-NEXT: cmp r1, #16
|
||||
; THUMB-NEXT: beq .LBB1_5
|
||||
; THUMB-NEXT: .LBB1_4: @ %return
|
||||
; THUMB-NEXT: movs r0, #1
|
||||
; THUMB-NEXT: bx lr
|
||||
; THUMB-NEXT: .LBB1_5: @ %bb4
|
||||
; THUMB-NEXT: movs r1, #255
|
||||
; THUMB-NEXT: ands r0, r1
|
||||
; THUMB-NEXT: bx lr
|
||||
;
|
||||
; T2: @ %bb.0: @ %entry
|
||||
; T2-NEXT: ldrb r2, [r0, #4]
|
||||
; T2-NEXT: ands r2, r2, #112
|
||||
; T2-NEXT: itt ne
|
||||
; T2-NEXT: ldrbne r1, [r1, #4]
|
||||
; T2-NEXT: andsne r1, r1, #112
|
||||
; T2-NEXT: beq .LBB1_2
|
||||
; T2-NEXT: @ %bb.1: @ %bb2
|
||||
; T2-NEXT: cmp r2, #16
|
||||
; T2-NEXT: itee ne
|
||||
; T2-NEXT: cmpne r1, #16
|
||||
; T2-NEXT: uxtbeq r0, r0
|
||||
; T2-NEXT: bxeq lr
|
||||
; T2-NEXT: .LBB1_2: @ %return
|
||||
; T2-NEXT: movs r0, #1
|
||||
; T2-NEXT: bx lr
|
||||
;
|
||||
; V8: @ %bb.0: @ %entry
|
||||
; V8-NEXT: ldrb r2, [r0, #4]
|
||||
; V8-NEXT: ands r2, r2, #112
|
||||
; V8-NEXT: itt ne
|
||||
; V8-NEXT: ldrbne r1, [r1, #4]
|
||||
; V8-NEXT: andsne r1, r1, #112
|
||||
; V8-NEXT: beq .LBB1_2
|
||||
; V8-NEXT: @ %bb.1: @ %bb2
|
||||
; V8-NEXT: cmp r2, #16
|
||||
; V8-NEXT: itee ne
|
||||
; V8-NEXT: cmpne r1, #16
|
||||
; V8-NEXT: uxtbeq r0, r0
|
||||
; V8-NEXT: bxeq lr
|
||||
; V8-NEXT: .LBB1_2: @ %return
|
||||
; V8-NEXT: movs r0, #1
|
||||
; V8-NEXT: bx lr
|
||||
entry:
|
||||
%0 = getelementptr inbounds %struct.S, %struct.S* %x, i32 0, i32 1, i32 0
|
||||
%1 = load i8, i8* %0, align 1
|
||||
%2 = zext i8 %1 to i32
|
||||
; ARM: ands
|
||||
; THUMB: ands
|
||||
; T2: ands
|
||||
; V8: ands
|
||||
; V8-NEXT: beq
|
||||
%3 = and i32 %2, 112
|
||||
%4 = icmp eq i32 %3, 0
|
||||
br i1 %4, label %return, label %bb
|
||||
|
||||
bb: ; preds = %entry
|
||||
; V8-NEXT: %bb
|
||||
%5 = getelementptr inbounds %struct.S, %struct.S* %y, i32 0, i32 1, i32 0
|
||||
%6 = load i8, i8* %5, align 1
|
||||
%7 = zext i8 %6 to i32
|
||||
; ARM: andsne
|
||||
; THUMB: ands
|
||||
; T2: andsne
|
||||
; V8: ands
|
||||
; V8-NEXT: beq
|
||||
%8 = and i32 %7, 112
|
||||
%9 = icmp eq i32 %8, 0
|
||||
br i1 %9, label %return, label %bb2
|
||||
|
||||
bb2: ; preds = %bb
|
||||
; V8-NEXT: %bb2
|
||||
; V8-NEXT: cmp
|
||||
; V8-NEXT: it ne
|
||||
; V8-NEXT: cmpne
|
||||
; V8-NEXT: bne
|
||||
%10 = icmp eq i32 %3, 16
|
||||
%11 = icmp eq i32 %8, 16
|
||||
%or.cond = or i1 %10, %11
|
||||
@ -168,11 +354,10 @@ define i32 @test_tst_assessment(i32 %a, i32 %b) {
|
||||
;
|
||||
; V8-LABEL: test_tst_assessment:
|
||||
; V8: @ %bb.0:
|
||||
; V8-NEXT: and r2, r0, #1
|
||||
; V8-NEXT: subs r0, r2, #1
|
||||
; V8-NEXT: and r0, r0, #1
|
||||
; V8-NEXT: lsls r1, r1, #31
|
||||
; V8-NEXT: it eq
|
||||
; V8-NEXT: moveq r0, r2
|
||||
; V8-NEXT: it ne
|
||||
; V8-NEXT: subne r0, #1
|
||||
; V8-NEXT: bx lr
|
||||
%and1 = and i32 %a, 1
|
||||
%sub = sub i32 %and1, 1
|
||||
|
@ -186,8 +186,8 @@ define bfloat @test_fncall_soft(bfloat %bf, bfloat (bfloat, bfloat)* %f) {
|
||||
; BASE-THUMB-NEXT: mov r0, r5
|
||||
; BASE-THUMB-NEXT: mov r1, r5
|
||||
; BASE-THUMB-NEXT: blx r4
|
||||
; BASE-THUMB-NEXT: uxth r1, r0
|
||||
; BASE-THUMB-NEXT: strh.w r0, [sp, #6]
|
||||
; BASE-THUMB-NEXT: uxth r1, r0
|
||||
; BASE-THUMB-NEXT: mov r0, r5
|
||||
; BASE-THUMB-NEXT: blx r4
|
||||
; BASE-THUMB-NEXT: ldrh.w r0, [sp, #6]
|
||||
|
@ -1045,21 +1045,19 @@ define i8 @test_atomic_cmpxchg_i8(i8 zeroext %wanted, i8 zeroext %new) nounwind
|
||||
; function there.
|
||||
; CHECK-ARM-NEXT: cmp r[[OLD]], r0
|
||||
; CHECK-THUMB-NEXT: cmp r[[OLD]], r[[WANTED]]
|
||||
; CHECK-NEXT: bne .LBB{{[0-9]+}}_4
|
||||
; CHECK-NEXT: bne .LBB{{[0-9]+}}_{{[0-9]}}
|
||||
; CHECK-NEXT: %bb.2:
|
||||
; As above, r1 is a reasonable guess.
|
||||
; CHECK: strexb [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
|
||||
; CHECK-NEXT: cmp [[STATUS]], #0
|
||||
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||||
; CHECK-ARM-NEXT: bne .LBB{{[0-9]+}}_{{[0-9]}}
|
||||
; CHECK-THUMB-NEXT: it eq
|
||||
; CHECK-THUMB-NEXT: bxeq lr
|
||||
; CHECK-ARM: mov r0, r[[OLD]]
|
||||
; CHECK-ARM: clrex
|
||||
; CHECK: bx lr
|
||||
; CHECK-NEXT: .LBB{{[0-9]+}}_4:
|
||||
; CHECK-NEXT: clrex
|
||||
; CHECK-NOT: dmb
|
||||
; CHECK-NOT: mcr
|
||||
|
||||
; CHECK-ARM: mov r0, r[[OLD]]
|
||||
; CHECK-ARM-NEXT: bx lr
|
||||
ret i8 %old
|
||||
}
|
||||
|
||||
@ -1079,16 +1077,18 @@ define i16 @test_atomic_cmpxchg_i16(i16 zeroext %wanted, i16 zeroext %new) nounw
|
||||
; function there.
|
||||
; CHECK-ARM-NEXT: cmp r[[OLD]], r0
|
||||
; CHECK-THUMB-NEXT: cmp r[[OLD]], r[[WANTED]]
|
||||
; CHECK-NEXT: bne .LBB{{[0-9]+}}_4
|
||||
; CHECK-NEXT: bne .LBB{{[0-9]+}}_{{[0-9]}}
|
||||
; CHECK-NEXT: %bb.2:
|
||||
; As above, r1 is a reasonable guess.
|
||||
; CHECK: stlexh [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
|
||||
; CHECK-NEXT: cmp [[STATUS]], #0
|
||||
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||||
; CHECK-ARM-NEXT: bne .LBB{{[0-9]+}}_{{[0-9]}}
|
||||
; CHECK-THUMB-NEXT: it eq
|
||||
; CHECK-THUMB-NEXT: bxeq lr
|
||||
; CHECK-ARM: mov r0, r[[OLD]]
|
||||
; CHECK: bx lr
|
||||
; CHECK-NEXT: .LBB{{[0-9]+}}_4:
|
||||
; CHECK-NEXT: clrex
|
||||
; CHECK-ARM-NEXT: .LBB{{[0-9]+}}_{{[0-9]}}
|
||||
; CHECK-ARM-NEXT: clrex
|
||||
; CHECK-NOT: dmb
|
||||
; CHECK-NOT: mcr
|
||||
|
||||
|
@ -192,11 +192,11 @@ body: |
|
||||
; CHECK-V7: tTAILJMPdND @extfunc, 14 /* CC::al */, $noreg, implicit $sp, implicit $sp
|
||||
; CHECK-V8-LABEL: name: test_nosize
|
||||
; CHECK-V8: bb.0 (%ir-block.0):
|
||||
; CHECK-V8: successors: %bb.1(0x50000000), %bb.6(0x30000000)
|
||||
; CHECK-V8: successors: %bb.1(0x80000000)
|
||||
; CHECK-V8: liveins: $lr, $r7
|
||||
; CHECK-V8: renamable $r0 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg
|
||||
; CHECK-V8: t2CMPri killed renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
|
||||
; CHECK-V8: t2Bcc %bb.6, 1 /* CC::ne */, killed $cpsr
|
||||
; CHECK-V8: tTAILJMPdND @extfunc, 1 /* CC::ne */, killed $cpsr, implicit $sp, implicit $sp
|
||||
; CHECK-V8: bb.1.b1:
|
||||
; CHECK-V8: successors: %bb.3(0x40000000), %bb.2(0x40000000)
|
||||
; CHECK-V8: liveins: $r7, $lr
|
||||
@ -216,15 +216,12 @@ body: |
|
||||
; CHECK-V8: renamable $r0 = t2LDRi12 undef renamable $r0, 0, 14 /* CC::al */, $noreg :: (load (s32) from `i32* undef`)
|
||||
; CHECK-V8: renamable $r0 = t2ANDri killed renamable $r0, 256, 14 /* CC::al */, $noreg, $noreg
|
||||
; CHECK-V8: bb.4.b5:
|
||||
; CHECK-V8: successors: %bb.5(0x30000000), %bb.6(0x50000000)
|
||||
; CHECK-V8: successors: %bb.5(0x50000000)
|
||||
; CHECK-V8: liveins: $r0
|
||||
; CHECK-V8: t2CMPri killed renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
|
||||
; CHECK-V8: $sp = t2LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r7, def $lr
|
||||
; CHECK-V8: t2Bcc %bb.6, 1 /* CC::ne */, killed $cpsr
|
||||
; CHECK-V8: bb.5.b8:
|
||||
; CHECK-V8: liveins: $lr, $r7
|
||||
; CHECK-V8: tBX_RET 14 /* CC::al */, $noreg
|
||||
; CHECK-V8: bb.6.b7:
|
||||
; CHECK-V8: tBX_RET 0 /* CC::eq */, killed $cpsr
|
||||
; CHECK-V8: bb.5.b7:
|
||||
; CHECK-V8: liveins: $lr, $r7
|
||||
; CHECK-V8: tTAILJMPdND @extfunc, 14 /* CC::al */, $noreg, implicit $sp, implicit $sp
|
||||
bb.0 (%ir-block.0):
|
||||
|
@ -1,5 +1,5 @@
|
||||
; RUN: llc -O3 -mtriple=armv8a-none-eabi -mattr=+fullfp16 -o - %s | FileCheck %s
|
||||
; RUN: llc -O3 -mtriple=thumbv8a-none-eabi -mattr=+fullfp16 -arm-no-restrict-it -o - %s | FileCheck %s
|
||||
; RUN: llc -O3 -mtriple=armv8a-none-eabi -mattr=+fullfp16 -arm-restrict-it -o - %s | FileCheck %s
|
||||
; RUN: llc -O3 -mtriple=thumbv8a-none-eabi -mattr=+fullfp16 -o - %s | FileCheck %s
|
||||
|
||||
; Require the vmul.f16 not to be predicated, because it's illegal to
|
||||
; do so with fp16 instructions
|
||||
|
@ -3,8 +3,8 @@
|
||||
; RUN: llc -mtriple=armv7 < %s | FileCheck %s --check-prefixes=ARM,ARM78
|
||||
; RUN: llc -mtriple=armv8a < %s | FileCheck %s --check-prefixes=ARM,ARM78
|
||||
; RUN: llc -mtriple=thumbv6 < %s | FileCheck %s --check-prefixes=THUMB,THUMB6
|
||||
; RUN: llc -mtriple=thumbv7 < %s | FileCheck %s --check-prefixes=THUMB,THUMB78,THUMB7
|
||||
; RUN: llc -mtriple=thumbv8-eabi < %s | FileCheck %s --check-prefixes=THUMB,THUMB78,THUMB8
|
||||
; RUN: llc -mtriple=thumbv7 < %s | FileCheck %s --check-prefixes=THUMB,THUMB78
|
||||
; RUN: llc -mtriple=thumbv8-eabi < %s | FileCheck %s --check-prefixes=THUMB,THUMB78
|
||||
|
||||
; We are looking for the following pattern here:
|
||||
; (X & (C l>> Y)) ==/!= 0
|
||||
@ -350,32 +350,18 @@ define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
|
||||
; THUMB6-NEXT: adcs r0, r2
|
||||
; THUMB6-NEXT: pop {r7, pc}
|
||||
;
|
||||
; THUMB7-LABEL: scalar_i64_signbit_eq:
|
||||
; THUMB7: @ %bb.0:
|
||||
; THUMB7-NEXT: rsb.w r3, r2, #32
|
||||
; THUMB7-NEXT: lsls r1, r2
|
||||
; THUMB7-NEXT: subs r2, #32
|
||||
; THUMB7-NEXT: lsr.w r3, r0, r3
|
||||
; THUMB7-NEXT: orr.w r1, r1, r3
|
||||
; THUMB7-NEXT: it pl
|
||||
; THUMB7-NEXT: lslpl.w r1, r0, r2
|
||||
; THUMB7-NEXT: mvns r0, r1
|
||||
; THUMB7-NEXT: lsrs r0, r0, #31
|
||||
; THUMB7-NEXT: bx lr
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i64_signbit_eq:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: rsb.w r3, r2, #32
|
||||
; THUMB8-NEXT: lsls r1, r2
|
||||
; THUMB8-NEXT: lsr.w r3, r0, r3
|
||||
; THUMB8-NEXT: orrs r1, r3
|
||||
; THUMB8-NEXT: subs r2, #32
|
||||
; THUMB8-NEXT: lsl.w r0, r0, r2
|
||||
; THUMB8-NEXT: it mi
|
||||
; THUMB8-NEXT: movmi r0, r1
|
||||
; THUMB8-NEXT: mvns r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r0, #31
|
||||
; THUMB8-NEXT: bx lr
|
||||
; THUMB78-LABEL: scalar_i64_signbit_eq:
|
||||
; THUMB78: @ %bb.0:
|
||||
; THUMB78-NEXT: rsb.w r3, r2, #32
|
||||
; THUMB78-NEXT: lsls r1, r2
|
||||
; THUMB78-NEXT: subs r2, #32
|
||||
; THUMB78-NEXT: lsr.w r3, r0, r3
|
||||
; THUMB78-NEXT: orr.w r1, r1, r3
|
||||
; THUMB78-NEXT: it pl
|
||||
; THUMB78-NEXT: lslpl.w r1, r0, r2
|
||||
; THUMB78-NEXT: mvns r0, r1
|
||||
; THUMB78-NEXT: lsrs r0, r0, #31
|
||||
; THUMB78-NEXT: bx lr
|
||||
%t0 = lshr i64 9223372036854775808, %y
|
||||
%t1 = and i64 %t0, %x
|
||||
%res = icmp eq i64 %t1, 0
|
||||
@ -471,40 +457,22 @@ define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
|
||||
; THUMB6-NEXT: .LCPI11_0:
|
||||
; THUMB6-NEXT: .long 4294901760 @ 0xffff0000
|
||||
;
|
||||
; THUMB7-LABEL: scalar_i64_bitsinmiddle_eq:
|
||||
; THUMB7: @ %bb.0:
|
||||
; THUMB7-NEXT: rsb.w r3, r2, #32
|
||||
; THUMB7-NEXT: lsls r1, r2
|
||||
; THUMB7-NEXT: lsr.w r3, r0, r3
|
||||
; THUMB7-NEXT: orrs r1, r3
|
||||
; THUMB7-NEXT: subs.w r3, r2, #32
|
||||
; THUMB7-NEXT: it pl
|
||||
; THUMB7-NEXT: lslpl.w r1, r0, r3
|
||||
; THUMB7-NEXT: lsl.w r0, r0, r2
|
||||
; THUMB7-NEXT: it pl
|
||||
; THUMB7-NEXT: movpl r0, #0
|
||||
; THUMB7-NEXT: pkhbt r0, r1, r0
|
||||
; THUMB7-NEXT: clz r0, r0
|
||||
; THUMB7-NEXT: lsrs r0, r0, #5
|
||||
; THUMB7-NEXT: bx lr
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i64_bitsinmiddle_eq:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: rsb.w r3, r2, #32
|
||||
; THUMB8-NEXT: lsls r1, r2
|
||||
; THUMB8-NEXT: lsr.w r3, r0, r3
|
||||
; THUMB8-NEXT: orrs r1, r3
|
||||
; THUMB8-NEXT: subs.w r3, r2, #32
|
||||
; THUMB8-NEXT: lsl.w r3, r0, r3
|
||||
; THUMB8-NEXT: lsl.w r0, r0, r2
|
||||
; THUMB8-NEXT: it mi
|
||||
; THUMB8-NEXT: movmi r3, r1
|
||||
; THUMB8-NEXT: it pl
|
||||
; THUMB8-NEXT: movpl r0, #0
|
||||
; THUMB8-NEXT: pkhbt r0, r3, r0
|
||||
; THUMB8-NEXT: clz r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r0, #5
|
||||
; THUMB8-NEXT: bx lr
|
||||
; THUMB78-LABEL: scalar_i64_bitsinmiddle_eq:
|
||||
; THUMB78: @ %bb.0:
|
||||
; THUMB78-NEXT: rsb.w r3, r2, #32
|
||||
; THUMB78-NEXT: lsls r1, r2
|
||||
; THUMB78-NEXT: lsr.w r3, r0, r3
|
||||
; THUMB78-NEXT: orrs r1, r3
|
||||
; THUMB78-NEXT: subs.w r3, r2, #32
|
||||
; THUMB78-NEXT: it pl
|
||||
; THUMB78-NEXT: lslpl.w r1, r0, r3
|
||||
; THUMB78-NEXT: lsl.w r0, r0, r2
|
||||
; THUMB78-NEXT: it pl
|
||||
; THUMB78-NEXT: movpl r0, #0
|
||||
; THUMB78-NEXT: pkhbt r0, r1, r0
|
||||
; THUMB78-NEXT: clz r0, r0
|
||||
; THUMB78-NEXT: lsrs r0, r0, #5
|
||||
; THUMB78-NEXT: bx lr
|
||||
%t0 = lshr i64 281474976645120, %y
|
||||
%t1 = and i64 %t0, %x
|
||||
%res = icmp eq i64 %t1, 0
|
||||
|
@ -49,8 +49,8 @@ define i1 @scalar_i8_signbit_eq(i8 %x, i8 %y) nounwind {
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i8_signbit_eq:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: uxtb r0, r0
|
||||
; THUMB8-NEXT: uxtb r1, r1
|
||||
; THUMB8-NEXT: uxtb r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r1
|
||||
; THUMB8-NEXT: movs r1, #1
|
||||
; THUMB8-NEXT: eor.w r0, r1, r0, lsr #7
|
||||
@ -92,8 +92,8 @@ define i1 @scalar_i8_lowestbit_eq(i8 %x, i8 %y) nounwind {
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i8_lowestbit_eq:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: uxtb r0, r0
|
||||
; THUMB8-NEXT: uxtb r1, r1
|
||||
; THUMB8-NEXT: uxtb r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r1
|
||||
; THUMB8-NEXT: movs r1, #1
|
||||
; THUMB8-NEXT: bic.w r0, r1, r0
|
||||
@ -138,8 +138,8 @@ define i1 @scalar_i8_bitsinmiddle_eq(i8 %x, i8 %y) nounwind {
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i8_bitsinmiddle_eq:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: uxtb r0, r0
|
||||
; THUMB8-NEXT: uxtb r1, r1
|
||||
; THUMB8-NEXT: uxtb r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r1
|
||||
; THUMB8-NEXT: and r0, r0, #24
|
||||
; THUMB8-NEXT: clz r0, r0
|
||||
@ -186,8 +186,8 @@ define i1 @scalar_i16_signbit_eq(i16 %x, i16 %y) nounwind {
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i16_signbit_eq:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: uxth r0, r0
|
||||
; THUMB8-NEXT: uxth r1, r1
|
||||
; THUMB8-NEXT: uxth r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r1
|
||||
; THUMB8-NEXT: movs r1, #1
|
||||
; THUMB8-NEXT: eor.w r0, r1, r0, lsr #15
|
||||
@ -229,8 +229,8 @@ define i1 @scalar_i16_lowestbit_eq(i16 %x, i16 %y) nounwind {
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i16_lowestbit_eq:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: uxth r0, r0
|
||||
; THUMB8-NEXT: uxth r1, r1
|
||||
; THUMB8-NEXT: uxth r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r1
|
||||
; THUMB8-NEXT: movs r1, #1
|
||||
; THUMB8-NEXT: bic.w r0, r1, r0
|
||||
@ -276,8 +276,8 @@ define i1 @scalar_i16_bitsinmiddle_eq(i16 %x, i16 %y) nounwind {
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i16_bitsinmiddle_eq:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: uxth r0, r0
|
||||
; THUMB8-NEXT: uxth r1, r1
|
||||
; THUMB8-NEXT: uxth r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r1
|
||||
; THUMB8-NEXT: and r0, r0, #4080
|
||||
; THUMB8-NEXT: clz r0, r0
|
||||
@ -481,14 +481,13 @@ define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) nounwind {
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: rsb.w r3, r2, #32
|
||||
; THUMB8-NEXT: lsrs r0, r2
|
||||
; THUMB8-NEXT: lsl.w r3, r1, r3
|
||||
; THUMB8-NEXT: orrs r0, r3
|
||||
; THUMB8-NEXT: subs r2, #32
|
||||
; THUMB8-NEXT: lsr.w r1, r1, r2
|
||||
; THUMB8-NEXT: it mi
|
||||
; THUMB8-NEXT: movmi r1, r0
|
||||
; THUMB8-NEXT: movs r0, #1
|
||||
; THUMB8-NEXT: bics r0, r1
|
||||
; THUMB8-NEXT: lsl.w r3, r1, r3
|
||||
; THUMB8-NEXT: orr.w r0, r0, r3
|
||||
; THUMB8-NEXT: it pl
|
||||
; THUMB8-NEXT: lsrpl.w r0, r1, r2
|
||||
; THUMB8-NEXT: movs r1, #1
|
||||
; THUMB8-NEXT: bic.w r0, r1, r0
|
||||
; THUMB8-NEXT: bx lr
|
||||
%t0 = shl i64 1, %y
|
||||
%t1 = and i64 %t0, %x
|
||||
@ -565,13 +564,12 @@ define i1 @scalar_i64_bitsinmiddle_eq(i64 %x, i64 %y) nounwind {
|
||||
; THUMB8-NEXT: lsl.w r3, r1, r3
|
||||
; THUMB8-NEXT: orrs r0, r3
|
||||
; THUMB8-NEXT: subs.w r3, r2, #32
|
||||
; THUMB8-NEXT: lsr.w r3, r1, r3
|
||||
; THUMB8-NEXT: it mi
|
||||
; THUMB8-NEXT: movmi r3, r0
|
||||
; THUMB8-NEXT: lsr.w r0, r1, r2
|
||||
; THUMB8-NEXT: it pl
|
||||
; THUMB8-NEXT: movpl r0, #0
|
||||
; THUMB8-NEXT: pkhbt r0, r0, r3
|
||||
; THUMB8-NEXT: lsrpl.w r0, r1, r3
|
||||
; THUMB8-NEXT: lsr.w r1, r1, r2
|
||||
; THUMB8-NEXT: it pl
|
||||
; THUMB8-NEXT: movpl r1, #0
|
||||
; THUMB8-NEXT: pkhbt r0, r1, r0
|
||||
; THUMB8-NEXT: clz r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r0, #5
|
||||
; THUMB8-NEXT: bx lr
|
||||
@ -988,8 +986,8 @@ define i1 @scalar_i8_signbit_ne(i8 %x, i8 %y) nounwind {
|
||||
;
|
||||
; THUMB8-LABEL: scalar_i8_signbit_ne:
|
||||
; THUMB8: @ %bb.0:
|
||||
; THUMB8-NEXT: uxtb r0, r0
|
||||
; THUMB8-NEXT: uxtb r1, r1
|
||||
; THUMB8-NEXT: uxtb r0, r0
|
||||
; THUMB8-NEXT: lsrs r0, r1
|
||||
; THUMB8-NEXT: lsrs r0, r0, #7
|
||||
; THUMB8-NEXT: bx lr
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: llc < %s -mtriple=thumbv8 -stop-after=if-converter -arm-atomic-cfg-tidy=0 | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8 -stop-after=if-converter -arm-atomic-cfg-tidy=0 -arm-restrict-it | FileCheck %s
|
||||
|
||||
%struct.S = type { i8* (i8*)*, [1 x i8] }
|
||||
define internal zeroext i8 @bar(%struct.S* %x, %struct.S* nocapture %y) nounwind readonly {
|
||||
@ -18,7 +18,7 @@ bb:
|
||||
%9 = icmp eq i32 %8, 0
|
||||
br i1 %9, label %return, label %bb2
|
||||
|
||||
; CHECK: bb.2.bb2:
|
||||
; CHECK: bb.1.bb:
|
||||
; CHECK: successors: %bb.4(0x40000000), %bb.3(0x40000000)
|
||||
|
||||
bb2:
|
||||
|
@ -35,7 +35,7 @@ if.then: ; preds = %entry
|
||||
; CHECK-LABEL: double_return:
|
||||
; HARDEN: {{bx lr$}}
|
||||
; NOHARDENARM: {{bxgt lr$}}
|
||||
; NOHARDENTHUMB: {{bx lr$}}
|
||||
; NOHARDENTHUMB: {{bxgt lr$}}
|
||||
; ISBDSB-NEXT: dsb sy
|
||||
; ISBDSB-NEXT: isb
|
||||
; SB-NEXT: {{ sb$}}
|
||||
|
@ -19,9 +19,8 @@ while.cond38: ; preds = %if.end111, %entry
|
||||
; CHECK: %cond.true77
|
||||
; CHECK-NEXT: @ in Loop
|
||||
; CHECK-NEXT: cmp.w {{r[0-9]+}}, #0
|
||||
; CHECK-NEXT: it eq
|
||||
; CHECK-NEXT: ite eq
|
||||
; CHECK-NEXT: ldreq
|
||||
; CHECK-NEXT: it ne
|
||||
; N.b. 16-bit mov instruction in IT block does not set flags.
|
||||
; CHECK-NEXT: movne
|
||||
; CHECK-NEXT: mvns
|
||||
|
@ -1,8 +1,8 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mtriple=thumbv7-apple-darwin | FileCheck %s --check-prefixes=ALL,V01
|
||||
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -arm-default-it | FileCheck %s --check-prefixes=ALL,V01
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-no-restrict-it | FileCheck %s --check-prefixes=ALL,V23,V2
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-no-restrict-it -enable-tail-merge=0 | FileCheck %s --check-prefixes=ALL,V23,V3
|
||||
; RUN: llc < %s -mtriple=thumbv8 | FileCheck %s --check-prefixes=ALL,V23,V2
|
||||
; RUN: llc < %s -mtriple=thumbv8 -enable-tail-merge=0 | FileCheck %s --check-prefixes=ALL,V23,V3
|
||||
|
||||
define i32 @t1(i32 %a, i32 %b, i32 %c, i32 %d) nounwind {
|
||||
; ALL-LABEL: t1:
|
||||
|
@ -1,6 +1,6 @@
|
||||
; RUN: llc < %s -mtriple=thumbv7-apple-ios -arm-atomic-cfg-tidy=0 | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv7-apple-ios -arm-atomic-cfg-tidy=0 -arm-default-it | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8-apple-ios -arm-atomic-cfg-tidy=0 -arm-no-restrict-it | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8-apple-ios -arm-atomic-cfg-tidy=0 | FileCheck %s
|
||||
|
||||
define void @foo(i32 %X, i32 %Y) {
|
||||
entry:
|
||||
|
@ -1,6 +1,6 @@
|
||||
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -arm-atomic-cfg-tidy=0 | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -arm-atomic-cfg-tidy=0 -arm-default-it | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8-apple-darwin -arm-atomic-cfg-tidy=0 -arm-no-restrict-it | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8-apple-darwin -arm-atomic-cfg-tidy=0 | FileCheck %s
|
||||
|
||||
; There shouldn't be a unconditional branch at end of bb52.
|
||||
; rdar://7184787
|
||||
|
@ -1,6 +1,6 @@
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-atomic-cfg-tidy=0 | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-atomic-cfg-tidy=0 -arm-restrict-it | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv7 -arm-atomic-cfg-tidy=0 -arm-restrict-it | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-atomic-cfg-tidy=0 -relocation-model=pic | FileCheck %s --check-prefix=CHECK-PIC
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-atomic-cfg-tidy=0 -arm-restrict-it -relocation-model=pic | FileCheck %s --check-prefix=CHECK-PIC
|
||||
; RUN: llc < %s -mtriple=thumbv7 -arm-atomic-cfg-tidy=0 -arm-restrict-it -relocation-model=pic | FileCheck %s --check-prefix=CHECK-PIC
|
||||
|
||||
%struct.FF = type { i32 (i32*)*, i32 (i32*, i32*, i32, i32, i32, i32)*, i32 (i32, i32, i8*)*, void ()*, i32 (i32, i8*, i32*)*, i32 ()* }
|
||||
@ -36,9 +36,9 @@ bb:
|
||||
|
||||
bb1:
|
||||
; CHECK: %entry
|
||||
; CHECK: it eq
|
||||
; CHECK: it eq
|
||||
; CHECK-NEXT: ldreq
|
||||
; CHECK-NEXT: it eq
|
||||
; CHECK-NEXT: it eq
|
||||
; CHECK-NEXT: cmpeq
|
||||
; CHECK: %bb1
|
||||
%tmp5 = load i32, i32* %block_size, align 4
|
||||
|
@ -1,7 +1,7 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mtriple=thumbv8-eabi -float-abi=hard | FileCheck --check-prefixes=P01 %s
|
||||
; RUN: llc < %s -mtriple=thumbv8-eabi -float-abi=hard -arm-restrict-it | FileCheck --check-prefixes=P01 %s
|
||||
; RUN: llc < %s -mtriple=thumbv7-eabi -float-abi=hard -arm-restrict-it | FileCheck --check-prefixes=P01 %s
|
||||
; RUN: llc < %s -mtriple=thumbv8-eabi -float-abi=hard -regalloc=basic | FileCheck --check-prefixes=P23 %s
|
||||
; RUN: llc < %s -mtriple=thumbv8-eabi -float-abi=hard -regalloc=basic -arm-restrict-it | FileCheck --check-prefixes=P23 %s
|
||||
; RUN: llc < %s -mtriple=thumbv7-eabi -float-abi=hard -regalloc=basic -arm-restrict-it | FileCheck --check-prefixes=P23 %s
|
||||
|
||||
%"struct.__gnu_cxx::__normal_iterator<char*,std::basic_string<char, std::char_traits<char>, std::allocator<char> > >" = type { i8* }
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-atomic-cfg-tidy=0 | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-atomic-cfg-tidy=0 -arm-restrict-it | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=thumbv7 -arm-atomic-cfg-tidy=0 -arm-restrict-it | FileCheck %s
|
||||
; CHECK: it ne
|
||||
; CHECK-NEXT: cmpne
|
||||
|
@ -1,32 +0,0 @@
|
||||
; RUN: llc < %s -mtriple=thumbv7 -o - | llvm-mc -triple thumbv7 --show-encoding 2>&1 | FileCheck %s --check-prefix=V7
|
||||
; RUN: llc < %s -mtriple=thumbv7 -arm-restrict-it -o - | llvm-mc -triple thumbv7 --show-encoding 2>&1 | FileCheck %s --check-prefix=V7_RESTRICT_IT
|
||||
; RUN: llc < %s -mtriple=thumbv8 -o - | llvm-mc -triple thumbv8 --show-encoding 2>&1 | FileCheck %s --check-prefix=V8
|
||||
; RUN: llc < %s -mtriple=thumbv8 -arm-no-restrict-it -o - | llvm-mc -triple thumbv8 --show-encoding 2>&1 | FileCheck %s --check-prefix=V8_NO_RESTRICT_IT
|
||||
|
||||
|
||||
; V7-NOT: warning
|
||||
; V7_RESTRICT_IT-NOT: warning
|
||||
; V8-NOT: warning
|
||||
; V8_NO_RESTRICT_IT: warning: deprecated instruction in IT block
|
||||
; it ge @ encoding: [0xa8,0xbf]
|
||||
; lslge.w r3, r12, lr @ encoding: [0x0c,0xfa,0x0e,0xf3] ; deprecated in ARMv8 thumb mode
|
||||
define i1 @scalar_i64_lowestbit_eq(i64 %x, i64 %y) {
|
||||
%t0 = shl i64 1, %y
|
||||
%t1 = and i64 %t0, %x
|
||||
%res = icmp eq i64 %t1, 0
|
||||
ret i1 %res
|
||||
}
|
||||
|
||||
; V7-NOT: warning
|
||||
; V7_RESTRICT_IT-NOT: warning
|
||||
; V8-NOT: warning
|
||||
; V8_NO_RESTRICT_IT: warning: deprecated instruction in IT block
|
||||
; it ne @ encoding: [0x18,0xbf]
|
||||
; movne.w r0, #-1 @ encoding: [0x4f,0xf0,0xff,0x30] ; deprecated in ARMv8 thumb mode
|
||||
define i32 @icmp_eq_minus_one(i8* %ptr) {
|
||||
%load = load i8, i8* %ptr, align 1
|
||||
%conv = zext i8 %load to i32
|
||||
%cmp = icmp eq i8 %load, -1
|
||||
%ret = select i1 %cmp, i32 %conv, i32 -1
|
||||
ret i32 %ret
|
||||
}
|
@ -33,28 +33,28 @@ mcr p15, #0, r5, c7, c10, #5
|
||||
@ CHECK-NO-WARN-NOT: warning: deprecated since v7, use 'dmb'
|
||||
it ge
|
||||
movge r0, #4096
|
||||
@ CHECK-THUMBV8: warning: deprecated instruction in IT block
|
||||
@ CHECK-THUMBV8-NOT: warning
|
||||
@ CHECK-THUMBV7-NOT: warning
|
||||
@ CHECK-NO-WARN-NOT: warning
|
||||
ite ge
|
||||
addge r0, r1
|
||||
addlt r0, r2
|
||||
@ CHECK-ARMV8: warning: applying IT instruction to more than one subsequent instruction is deprecated
|
||||
@ CHECK-THUMBV8: warning: applying IT instruction to more than one subsequent instruction is deprecated
|
||||
@ CHECK-ARMV8-NOT: warning
|
||||
@ CHECK-THUMBV8-NOT: warning
|
||||
@ CHECK-THUMBV7-NOT: warning
|
||||
@ CHECK-NO-WARN-NOT: warning
|
||||
it ge
|
||||
movge r0, pc // invalid operand
|
||||
@ CHECK-THUMBV8: warning: deprecated instruction in IT block
|
||||
@ CHECK-THUMBV8-NOT: warning
|
||||
@ CHECK-THUMBV7-NOT: warning
|
||||
@ CHECK-NO-WARN-NOT: warning
|
||||
it ge
|
||||
revge r0, r0 // invalid instruction
|
||||
@ CHECK-THUMBV8: warning: deprecated instruction in IT block
|
||||
@ CHECK-THUMBV8-NOT: warning
|
||||
@ CHECK-THUMBV7-NOT: warning
|
||||
@ CHECK-NO-WARN-NOT: warning
|
||||
it ge
|
||||
clzge r0, r0 // only has 32-bit form
|
||||
@ CHECK-THUMBV8: warning: deprecated instruction in IT block
|
||||
@ CHECK-THUMBV8-NOT: warning
|
||||
@ CHECK-THUMBV7-NOT: warning
|
||||
@ CHECK-NO-WARN-NOT: warning
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user