Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -139,6 +139,7 @@ StringRef StringValue = ""); virtual void emitFPU(unsigned FPU); virtual void emitArch(unsigned Arch); + virtual void emitArchExtension(StringRef StringValue); virtual void emitObjectArch(unsigned Arch); virtual void finishAttributeSection(); virtual void emitInst(uint32_t Inst, char Suffix = '\0'); Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -635,9 +635,13 @@ std::string CPUString = Subtarget->getCPUString(); - // FIXME: remove krait check when GNU tools support krait cpu - if (CPUString != "generic" && CPUString != "krait") - ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString); + if (CPUString != "generic") { + // FIXME: remove krait check when GNU tools support krait cpu + if (Subtarget->isKrait()) + ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a9"); + else + ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString); + } ATS.emitAttribute(ARMBuildAttrs::CPU_arch, getArchForCPU(CPUString, Subtarget)); @@ -667,6 +671,12 @@ ARMBuildAttrs::AllowThumb32); } + // We consider krait as a "cortex-a9" + hwdiv CPU + // Enable hwdiv through ".arch_extension idiv" + if (Subtarget->isKrait() && (Subtarget->hasDivide() + || Subtarget->hasDivideInARMMode())) + ATS.emitArchExtension("idiv"); + if (Subtarget->hasNEON()) { /* NEON is not exactly a VFP architecture, but GAS emit one of * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */ Index: lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -134,6 +134,7 @@ void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, StringRef StrinValue) override; void emitArch(unsigned Arch) override; + void emitArchExtension(StringRef StringValue) override; void emitObjectArch(unsigned Arch) override; void emitFPU(unsigned FPU) override; void emitInst(uint32_t Inst, char Suffix = '\0') override; @@ -249,6 +250,9 @@ void ARMTargetAsmStreamer::emitArch(unsigned Arch) { OS << "\t.arch\t" << GetArchName(Arch) << "\n"; } +void ARMTargetAsmStreamer::emitArchExtension(StringRef StringValue) { + OS << "\t.arch_extension\t" << StringValue << "\n"; +} void ARMTargetAsmStreamer::emitObjectArch(unsigned Arch) { OS << "\t.object_arch\t" << GetArchName(Arch) << '\n'; } Index: lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp +++ lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp @@ -63,6 +63,7 @@ unsigned IntValue, StringRef StringValue) {} void ARMTargetStreamer::emitArch(unsigned Arch) {} +void ARMTargetStreamer::emitArchExtension(StringRef StringValue) {} void ARMTargetStreamer::emitObjectArch(unsigned Arch) {} void ARMTargetStreamer::emitFPU(unsigned FPU) {} void ARMTargetStreamer::finishAttributeSection() {} Index: test/CodeGen/ARM/krait-cpu-div-attribute.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/krait-cpu-div-attribute.ll @@ -0,0 +1,37 @@ +; Tests the genration of ".arch_extension" attribute for hardware +; division on krait CPU. For now, krait is recognized as "cortex-a9" + hwdiv +; Also, tests for the hwdiv instruction on krait CPU + +; check for arch_extension/cpu directive +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=krait | FileCheck %s --check-prefix=DIV_EXTENSION +; RUN: llc < %s -mtriple=thumbv7-linux-gnueabi -mcpu=krait | FileCheck %s --check-prefix=DIV_EXTENSION +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a9 | FileCheck %s --check-prefix=NODIV_KRAIT +; RUN: llc < %s -mtriple=thumbv7-linux-gnueabi -mcpu=cortex-a9 | FileCheck %s --check-prefix=NODIV_KRAIT +; RUN: llc < %s -mcpu=krait -mattr=+v7,+thumb-mode,-vfp4,-hwdiv,+vfp3,-hwdiv-arm | FileCheck %s --check-prefix=NODIV_KRAIT +; RUN: llc <%s -mcpu=krait -mattr=-v7,+v6,-hwdiv,-hwdiv-arm,-vfp4,-vfp3,+vfp2,-neon,-t2dsp,+slowfpvmlx,-aclass,-trustzone | FileCheck %s --check-prefix=NODIV_KRAIT + +; check if correct instruction is emitted by integrated assembler +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=krait -filetype=obj | llvm-objdump -mcpu=krait -triple armv7-linux-gnueabi -d - | FileCheck %s --check-prefix=HWDIV +; RUN: llc < %s -mtriple=thumbv7-linux-gnueabi -mcpu=krait -filetype=obj | llvm-objdump -mcpu=krait -triple thumbv7-linux-gnueabi -d - | FileCheck %s --check-prefix=HWDIV + +; arch_extension attribute +; DIV_EXTENSION: .cpu cortex-a9 +; DIV_EXTENSION: .arch_extension idiv +; NODIV_KRAIT-NOT: .arch_extension idiv +; HWDIV: sdiv + +define i32 @main() #0 { +entry: + %retval = alloca i32, align 4 + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %c = alloca i32, align 4 + store i32 0, i32* %retval + store volatile i32 100, i32* %b, align 4 + store volatile i32 32, i32* %c, align 4 + %0 = load volatile i32* %b, align 4 + %1 = load volatile i32* %c, align 4 + %div = sdiv i32 %0, %1 + store volatile i32 %div, i32* %a, align 4 + ret i32 0 +}