diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2660,13 +2660,9 @@ // those, the target's already in a register, so we don't need to do // anything extra. if (isa(Callee)) { - // When generating execute-only code we use movw movt pair. - // Currently execute-only is only available for architectures that - // support movw movt, so we are safe to assume that. if (Subtarget->genExecuteOnly()) { - assert(Subtarget->useMovt() && - "long-calls with execute-only requires movt and movw!"); - ++NumMovwMovt; + if (Subtarget->useMovt()) + ++NumMovwMovt; Callee = DAG.getNode(ARMISD::Wrapper, dl, PtrVt, DAG.getTargetGlobalAddress(GVal, dl, PtrVt)); } else { @@ -2685,13 +2681,9 @@ } else if (ExternalSymbolSDNode *S=dyn_cast(Callee)) { const char *Sym = S->getSymbol(); - // When generating execute-only code we use movw movt pair. - // Currently execute-only is only available for architectures that - // support movw movt, so we are safe to assume that. if (Subtarget->genExecuteOnly()) { - assert(Subtarget->useMovt() && - "long-calls with execute-only requires movt and movw!"); - ++NumMovwMovt; + if (Subtarget->useMovt()) + ++NumMovwMovt; Callee = DAG.getNode(ARMISD::Wrapper, dl, PtrVt, DAG.getTargetGlobalAddress(GVal, dl, PtrVt)); } else { diff --git a/llvm/test/CodeGen/ARM/large-stack.ll b/llvm/test/CodeGen/ARM/large-stack.ll --- a/llvm/test/CodeGen/ARM/large-stack.ll +++ b/llvm/test/CodeGen/ARM/large-stack.ll @@ -1,4 +1,5 @@ ; RUN: llc -mtriple=arm-eabi %s -o /dev/null +; RUN: llc -mtriple=thumbv6m-eabi -mattr=+execute-only %s -o - define void @test1() { %tmp = alloca [ 64 x i32 ] , align 4 diff --git a/llvm/test/CodeGen/Thumb/thumb-execute-only-long-calls.ll b/llvm/test/CodeGen/Thumb/thumb-execute-only-long-calls.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Thumb/thumb-execute-only-long-calls.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s -mtriple=thumbv6m-arm-none-eabi -relocation-model=static | FileCheck %s -check-prefixes=CHECK + +define void @fn() #0 { +entry: +; CHECK-LABEL: fn: +; CHECK: ldr [[REG:r[0-9]+]], .LCPI0_0 +; CHECK-NEXT: blx [[REG]] +; CHECK: .LCPI0_0: +; CHECK-NEXT: .long bar + call void @bar() + ret void +} + +define void @execute_only_fn() #1 { +; CHECK-LABEL: execute_only_fn: +; CHECK: movs [[REG0:r[0-9]+]], :upper8_15:bar +; CHECK-NEXT: lsls [[REG0]], r0, #8 +; CHECK-NEXT: adds [[REG0]], :upper0_7:bar +; CHECK-NEXT: lsls [[REG0]], r0, #8 +; CHECK-NEXT: adds [[REG0]], :lower8_15:bar +; CHECK-NEXT: lsls [[REG0]], r0, #8 +; CHECK-NEXT: adds [[REG0]], :lower0_7:bar +; CHECK-NEXT: blx [[REG0]] +; CHECK-NOT: .LCPI1_0: + +entry: + call void @bar() + ret void +} + +attributes #0 = { noinline optnone "target-features"="+thumb-mode,+long-calls" } +attributes #1 = { noinline optnone "target-features"="+execute-only,+thumb-mode,+long-calls" } + +declare dso_local void @bar() diff --git a/llvm/test/CodeGen/Thumb2/thumb2-execute-only-long-calls.ll b/llvm/test/CodeGen/Thumb2/thumb2-execute-only-long-calls.ll --- a/llvm/test/CodeGen/Thumb2/thumb2-execute-only-long-calls.ll +++ b/llvm/test/CodeGen/Thumb2/thumb2-execute-only-long-calls.ll @@ -23,7 +23,7 @@ ; RWPI: movw [[REG0:r[0-9]+]], :lower16:bar ; RWPI-NEXT: movt [[REG0]], :upper16:bar ; RWPI-NEXT: blx [[REG0]] -; RWPI-NOT: .LCPI0_0: +; RWPI-NOT: .LCPI1_0: entry: call void @bar() ret void