diff --git a/lib/Target/Hexagon/Hexagon.td b/lib/Target/Hexagon/Hexagon.td index cacf9fb9d13..92a7e554e36 100644 --- a/lib/Target/Hexagon/Hexagon.td +++ b/lib/Target/Hexagon/Hexagon.td @@ -49,10 +49,14 @@ def ExtensionHVXDbl : SubtargetFeature<"hvx-double", "UseHVX128BOps", "true", "Hexagon HVX 128B instructions", [ExtensionHVX128B]>; +def FeaturePackets: SubtargetFeature<"packets", "UsePackets", "true", + "Support for instruction packets">; def FeatureLongCalls: SubtargetFeature<"long-calls", "UseLongCalls", "true", "Use constant-extended calls">; def FeatureMemNoShuf: SubtargetFeature<"mem_noshuf", "HasMemNoShuf", "false", "Supports mem_noshuf feature">; +def FeatureNVJ : SubtargetFeature<"nvj", "UseNewValueJumps", "true", + "Support for new-value jumps", [FeaturePackets]>; def FeatureDuplex : SubtargetFeature<"duplex", "EnableDuplex", "true", "Enable generation of duplex instruction">; def FeatureReservedR19: SubtargetFeature<"reserved-r19", "ReservedR19", @@ -323,18 +327,21 @@ class Proc; def : Proc<"hexagonv4", HexagonModelV4, - [ArchV4, FeatureDuplex]>; + [ArchV4, FeaturePackets, FeatureNVJ, FeatureDuplex]>; def : Proc<"hexagonv5", HexagonModelV4, - [ArchV4, ArchV5, FeatureDuplex]>; + [ArchV4, ArchV5, FeaturePackets, FeatureNVJ, FeatureDuplex]>; def : Proc<"hexagonv55", HexagonModelV55, - [ArchV4, ArchV5, ArchV55, FeatureDuplex]>; + [ArchV4, ArchV5, ArchV55, FeaturePackets, FeatureNVJ, + FeatureDuplex]>; def : Proc<"hexagonv60", HexagonModelV60, - [ArchV4, ArchV5, ArchV55, ArchV60, FeatureDuplex]>; + [ArchV4, ArchV5, ArchV55, ArchV60, FeaturePackets, FeatureNVJ, + FeatureDuplex]>; def : Proc<"hexagonv62", HexagonModelV62, - [ArchV4, ArchV5, ArchV55, ArchV60, ArchV62, FeatureDuplex]>; + [ArchV4, ArchV5, ArchV55, ArchV60, ArchV62, FeaturePackets, + FeatureNVJ, FeatureDuplex]>; def : Proc<"hexagonv65", HexagonModelV65, [ArchV4, ArchV5, ArchV55, ArchV60, ArchV62, ArchV65, - FeatureMemNoShuf, FeatureDuplex]>; + FeatureMemNoShuf, FeaturePackets, FeatureNVJ, FeatureDuplex]>; //===----------------------------------------------------------------------===// // Declare the target which we are implementing diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/lib/Target/Hexagon/HexagonAsmPrinter.cpp index 68b1fe6bf4b..3a1821bf265 100644 --- a/lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ b/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -748,6 +748,7 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCInstrInfo &MCII = *Subtarget->getInstrInfo(); if (MI->isBundle()) { + assert(Subtarget->usePackets() && "Support for packets is disabled"); const MachineBasicBlock* MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator MII = MI->getIterator(); diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp index 46f5bb4de8a..97d5565d059 100644 --- a/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp +++ b/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp @@ -2035,6 +2035,10 @@ void HexagonDAGToDAGISel::SelectHvxVAlign(SDNode *N) { } void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) { + if (!HST->usePackets()) { + report_fatal_error("Support for gather requires packets, " + "which are disabled"); + } const SDLoc &dl(N); SDValue Chain = N->getOperand(0); SDValue Address = N->getOperand(2); @@ -2075,6 +2079,10 @@ void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) { } void HexagonDAGToDAGISel::SelectV65Gather(SDNode *N) { + if (!HST->usePackets()) { + report_fatal_error("Support for gather requires packets, " + "which are disabled"); + } const SDLoc &dl(N); SDValue Chain = N->getOperand(0); SDValue Address = N->getOperand(2); diff --git a/lib/Target/Hexagon/HexagonNewValueJump.cpp b/lib/Target/Hexagon/HexagonNewValueJump.cpp index bb733fed044..2608096b87d 100644 --- a/lib/Target/Hexagon/HexagonNewValueJump.cpp +++ b/lib/Target/Hexagon/HexagonNewValueJump.cpp @@ -24,6 +24,7 @@ #include "Hexagon.h" #include "HexagonInstrInfo.h" #include "HexagonRegisterInfo.h" +#include "HexagonSubtarget.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" @@ -461,9 +462,9 @@ bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { MF.getSubtarget().getRegisterInfo()); MBPI = &getAnalysis(); - if (DisableNewValueJumps) { + if (DisableNewValueJumps || + !MF.getSubtarget().useNewValueJumps()) return false; - } int nvjCount = DbgNVJCount; int nvjGenerated = 0; diff --git a/lib/Target/Hexagon/HexagonSubtarget.h b/lib/Target/Hexagon/HexagonSubtarget.h index 87121b30906..9076b1d7fd6 100644 --- a/lib/Target/Hexagon/HexagonSubtarget.h +++ b/lib/Target/Hexagon/HexagonSubtarget.h @@ -48,6 +48,8 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo { bool UseMemOps, UseHVX64BOps, UseHVX128BOps; bool UseLongCalls; + bool UsePackets = false; + bool UseNewValueJumps = false; bool ModeIEEERndNear; bool HasMemNoShuf = false; @@ -153,6 +155,9 @@ public: bool useHVXOps() const { return HexagonHVXVersion > Hexagon::ArchEnum::V4; } bool useHVX128BOps() const { return useHVXOps() && UseHVX128BOps; } bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; } + bool usePackets() const { return UsePackets; } + bool useNewValueJumps() const { return UseNewValueJumps; } + bool hasMemNoShuf() const { return HasMemNoShuf; } bool hasReservedR19() const { return ReservedR19; } bool useLongCalls() const { return UseLongCalls; } diff --git a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp index c2404235091..16d3733b92e 100644 --- a/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp +++ b/lib/Target/Hexagon/HexagonVLIWPacketizer.cpp @@ -199,11 +199,12 @@ static MachineBasicBlock::iterator moveInstrOut(MachineInstr &MI, } bool HexagonPacketizer::runOnMachineFunction(MachineFunction &MF) { - if (DisablePacketizer || skipFunction(MF.getFunction())) + auto &HST = MF.getSubtarget(); + if (DisablePacketizer || !HST.usePackets() || skipFunction(MF.getFunction())) return false; - HII = MF.getSubtarget().getInstrInfo(); - HRI = MF.getSubtarget().getRegisterInfo(); + HII = HST.getInstrInfo(); + HRI = HST.getRegisterInfo(); auto &MLI = getAnalysis(); auto *AA = &getAnalysis().getAAResults(); auto *MBPI = &getAnalysis(); diff --git a/test/CodeGen/Hexagon/no-packets-gather.ll b/test/CodeGen/Hexagon/no-packets-gather.ll new file mode 100644 index 00000000000..516419b7372 --- /dev/null +++ b/test/CodeGen/Hexagon/no-packets-gather.ll @@ -0,0 +1,27 @@ +; RUN: llc -march=hexagon -mattr=+hvxv60,hvx-length64b < %s | FileCheck %s --check-prefix=CHECK-GATHER +; RUN: not llc -march=hexagon -mattr=+hvxv60,hvx-length64b,-packets %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR + +target triple = "hexagon" + +; CHECK-GATHER-LABEL: fred: +; CHECK-GATHER: vgather +; CHECK-ERROR: LLVM ERROR: Support for gather requires packets, which are disabled + +define void @fred(i8* %p, i32 %x, i32 %y) local_unnamed_addr #0 { +entry: + %v = alloca <16 x i32>, align 64 + %0 = bitcast <16 x i32>* %v to i8* + call void @llvm.lifetime.start(i64 64, i8* nonnull %0) #3 + tail call void @llvm.hexagon.V6.vgathermw(i8* %p, i32 %x, i32 %y, <16 x i32> undef) + call void @foo(i8* nonnull %0) #0 + call void @llvm.lifetime.end(i64 64, i8* nonnull %0) #3 + ret void +} + +declare void @llvm.lifetime.start(i64, i8* nocapture) #1 +declare void @llvm.hexagon.V6.vgathermw(i8*, i32, i32, <16 x i32>) #1 +declare void @foo(i8*) local_unnamed_addr #0 +declare void @llvm.lifetime.end(i64, i8* nocapture) #1 + +attributes #0 = { nounwind "target-cpu"="hexagonv65" } +attributes #1 = { argmemonly nounwind } diff --git a/test/CodeGen/Hexagon/no-packets.ll b/test/CodeGen/Hexagon/no-packets.ll new file mode 100644 index 00000000000..de58a204f40 --- /dev/null +++ b/test/CodeGen/Hexagon/no-packets.ll @@ -0,0 +1,82 @@ +; RUN: llc -march=hexagon < %s | FileCheck %s +; Check that there are no packets with two or more instructions, except +; for the endloop packet. + +; This is the expected code: +; +; p0 = cmp.gt(r3,#0) +; if (!p0) jump:nt .LBB0_3 +; loop0(.LBB0_2,r3) +; r3 = memw(r1++#4) +; r4 = memw(r2++#4) +; r3 = add(r4,r3) +; memw(r0++#4) = r3 +; { nop; nop }:endloop0 +; jumpr r31 + +; CHECK-LABEL: fred: +; CHECK: { +; CHECK-NEXT: cmp +; CHECK-NEXT: } +; CHECK: { +; CHECK-NEXT: jump +; CHECK-NEXT: } +; CHECK: { +; CHECK-NEXT: loop0 +; CHECK-NEXT: } +; CHECK: { +; CHECK-NEXT: memw +; CHECK-NEXT: } +; CHECK: { +; CHECK-NEXT: memw +; CHECK-NEXT: } +; CHECK: { +; CHECK-NEXT: add +; CHECK-NEXT: } +; CHECK: { +; CHECK-NEXT: memw +; CHECK-NEXT: } +; CHECK: { +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: }{{[ \t]*}}:endloop0 +; CHECK: { +; CHECK-NEXT: jumpr r31 +; CHECK-NEXT: } + +target triple = "hexagon" + + +define void @fred(i32* nocapture %a0, i32* nocapture readonly %a1, i32* nocapture readonly %a2, i32 %a3) local_unnamed_addr #0 { +b4: + %v5 = icmp sgt i32 %a3, 0 + br i1 %v5, label %b6, label %b21 + +b6: ; preds = %b4 + br label %b7 + +b7: ; preds = %b7, %b6 + %v8 = phi i32 [ %v18, %b7 ], [ 0, %b6 ] + %v9 = phi i32* [ %v17, %b7 ], [ %a0, %b6 ] + %v10 = phi i32* [ %v14, %b7 ], [ %a2, %b6 ] + %v11 = phi i32* [ %v12, %b7 ], [ %a1, %b6 ] + %v12 = getelementptr inbounds i32, i32* %v11, i32 1 + %v13 = load i32, i32* %v11, align 4 + %v14 = getelementptr inbounds i32, i32* %v10, i32 1 + %v15 = load i32, i32* %v10, align 4 + %v16 = add nsw i32 %v15, %v13 + %v17 = getelementptr inbounds i32, i32* %v9, i32 1 + store i32 %v16, i32* %v9, align 4 + %v18 = add nuw nsw i32 %v8, 1 + %v19 = icmp eq i32 %v18, %a3 + br i1 %v19, label %b20, label %b7 + +b20: ; preds = %b7 + br label %b21 + +b21: ; preds = %b20, %b4 + ret void +} + +attributes #0 = { norecurse nounwind "target-cpu"="hexagonv60" "target-features"="-packets" } +