diff --git a/llvm/include/llvm/IR/IntrinsicsARM.td b/llvm/include/llvm/IR/IntrinsicsARM.td index bc5cbf144e11..ce758e257312 100644 --- a/llvm/include/llvm/IR/IntrinsicsARM.td +++ b/llvm/include/llvm/IR/IntrinsicsARM.td @@ -20,6 +20,11 @@ let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; +// A space-consuming intrinsic primarily for testing ARMConstantIslands. The +// first argument is the number of bytes this "instruction" takes up, the second +// and return value are essentially chains, used to force ordering during ISel. +def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; + //===----------------------------------------------------------------------===// // Saturating Arithmetic diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index f8e32634c74f..695fd4d16c56 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1592,6 +1592,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { EmitJumpTable(MI); return; } + case ARM::SPACE: + OutStreamer.EmitZeros(MI->getOperand(1).getImm()); + return; case ARM::TRAP: { // Non-Darwin binutils don't yet support the "trap" mnemonic. // FIXME: Remove this special case when they do. diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index 4ab05f910ff3..7a315c4b2ef5 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -674,6 +674,8 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { ++NumEntries; return NumEntries * EntrySize + InstSize; } + case ARM::SPACE: + return MI->getOperand(1).getImm(); } } diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index c03901cb5e5a..317711446120 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -5621,3 +5621,8 @@ def : InstAlias<"umull${s}${p} $RdLo, $RdHi, $Rn, $Rm", // is discarded. def ITasm : ARMAsmPseudo<"it$mask $cc", (ins it_pred:$cc, it_mask:$mask)>, ComplexDeprecationPredicate<"IT">; + +let mayLoad = 1, mayStore =1, hasSideEffects = 1 in +def SPACE : PseudoInst<(outs GPR:$Rd), (ins i32imm:$size, GPR:$Rn), + NoItinerary, + [(set GPR:$Rd, (int_arm_space imm:$size, GPR:$Rn))]>; diff --git a/llvm/test/CodeGen/ARM/space-directive.ll b/llvm/test/CodeGen/ARM/space-directive.ll new file mode 100644 index 000000000000..55be1991fe82 --- /dev/null +++ b/llvm/test/CodeGen/ARM/space-directive.ll @@ -0,0 +1,19 @@ +; RUN: llc -mtriple=armv7 -o - %s | FileCheck %s + +define i32 @test_space() minsize { +; CHECK-LABEL: test_space: +; CHECK: ldr {{r[0-9]+}}, [[CPENTRY:.?LCPI[0-9]+_[0-9]+]] +; CHECK: b [[PAST_CP:.?LBB[0-9]+_[0-9]+]] + +; CHECK: [[CPENTRY]]: +; CHECK-NEXT: 12345678 + +; CHECK: [[PAST_CP]]: +; CHECK: .zero 10000 + %addr = inttoptr i32 12345678 to i32* + %val = load i32* %addr + call i32 @llvm.arm.space(i32 10000, i32 undef) + ret i32 %val +} + +declare i32 @llvm.arm.space(i32, i32)