mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
Hexagon: Add constant extender support framework.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176358 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ae1dbb39f7
commit
ef94c6c85e
@ -2800,7 +2800,26 @@ isConditionalStore (const MachineInstr* MI) const {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned HexagonInstrInfo::getAddrMode(const MachineInstr* MI) const {
|
||||
const uint64_t F = MI->getDesc().TSFlags;
|
||||
|
||||
return((F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask);
|
||||
}
|
||||
|
||||
/// immediateExtend - Changes the instruction in place to one using an immediate
|
||||
/// extender.
|
||||
void HexagonInstrInfo::immediateExtend(MachineInstr *MI) const {
|
||||
assert((isExtendable(MI)||isConstExtended(MI)) &&
|
||||
"Instruction must be extendable");
|
||||
// Find which operand is extendable.
|
||||
short ExtOpNum = getCExtOpNum(MI);
|
||||
MachineOperand &MO = MI->getOperand(ExtOpNum);
|
||||
// This needs to be something we understand.
|
||||
assert((MO.isMBB() || MO.isImm()) &&
|
||||
"Branch with unknown extendable field type");
|
||||
// Mark given operand as extended.
|
||||
MO.addTargetFlag(HexagonII::HMOTF_ConstExtended);
|
||||
}
|
||||
|
||||
DFAPacketizer *HexagonInstrInfo::
|
||||
CreateTargetScheduleState(const TargetMachine *TM,
|
||||
@ -2827,3 +2846,155 @@ bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr *MI,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HexagonInstrInfo::isConstExtended(MachineInstr *MI) const {
|
||||
|
||||
// Constant extenders are allowed only for V4 and above.
|
||||
if (!Subtarget.hasV4TOps())
|
||||
return false;
|
||||
|
||||
const uint64_t F = MI->getDesc().TSFlags;
|
||||
unsigned isExtended = (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
|
||||
if (isExtended) // Instruction must be extended.
|
||||
return true;
|
||||
|
||||
unsigned isExtendable = (F >> HexagonII::ExtendablePos)
|
||||
& HexagonII::ExtendableMask;
|
||||
if (!isExtendable)
|
||||
return false;
|
||||
|
||||
short ExtOpNum = getCExtOpNum(MI);
|
||||
const MachineOperand &MO = MI->getOperand(ExtOpNum);
|
||||
// Use MO operand flags to determine if MO
|
||||
// has the HMOTF_ConstExtended flag set.
|
||||
if (MO.getTargetFlags() && HexagonII::HMOTF_ConstExtended)
|
||||
return true;
|
||||
// If this is a Machine BB address we are talking about, and it is
|
||||
// not marked as extended, say so.
|
||||
if (MO.isMBB())
|
||||
return false;
|
||||
|
||||
// We could be using an instruction with an extendable immediate and shoehorn
|
||||
// a global address into it. If it is a global address it will be constant
|
||||
// extended. We do this for COMBINE.
|
||||
// We currently only handle isGlobal() because it is the only kind of
|
||||
// object we are going to end up with here for now.
|
||||
// In the future we probably should add isSymbol(), etc.
|
||||
if (MO.isGlobal() || MO.isSymbol())
|
||||
return true;
|
||||
|
||||
// If the extendable operand is not 'Immediate' type, the instruction should
|
||||
// have 'isExtended' flag set.
|
||||
assert(MO.isImm() && "Extendable operand must be Immediate type");
|
||||
|
||||
int MinValue = getMinValue(MI);
|
||||
int MaxValue = getMaxValue(MI);
|
||||
int ImmValue = MO.getImm();
|
||||
|
||||
return (ImmValue < MinValue || ImmValue > MaxValue);
|
||||
}
|
||||
|
||||
// Returns true if a particular operand is extendable for an instruction.
|
||||
bool HexagonInstrInfo::isOperandExtended(const MachineInstr *MI,
|
||||
unsigned short OperandNum) const {
|
||||
// Constant extenders are allowed only for V4 and above.
|
||||
if (!Subtarget.hasV4TOps())
|
||||
return false;
|
||||
|
||||
const uint64_t F = MI->getDesc().TSFlags;
|
||||
|
||||
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask)
|
||||
== OperandNum;
|
||||
}
|
||||
|
||||
// Returns Operand Index for the constant extended instruction.
|
||||
unsigned short HexagonInstrInfo::getCExtOpNum(const MachineInstr *MI) const {
|
||||
const uint64_t F = MI->getDesc().TSFlags;
|
||||
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask);
|
||||
}
|
||||
|
||||
// Returns the min value that doesn't need to be extended.
|
||||
int HexagonInstrInfo::getMinValue(const MachineInstr *MI) const {
|
||||
const uint64_t F = MI->getDesc().TSFlags;
|
||||
unsigned isSigned = (F >> HexagonII::ExtentSignedPos)
|
||||
& HexagonII::ExtentSignedMask;
|
||||
unsigned bits = (F >> HexagonII::ExtentBitsPos)
|
||||
& HexagonII::ExtentBitsMask;
|
||||
|
||||
if (isSigned) // if value is signed
|
||||
return -1 << (bits - 1);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the max value that doesn't need to be extended.
|
||||
int HexagonInstrInfo::getMaxValue(const MachineInstr *MI) const {
|
||||
const uint64_t F = MI->getDesc().TSFlags;
|
||||
unsigned isSigned = (F >> HexagonII::ExtentSignedPos)
|
||||
& HexagonII::ExtentSignedMask;
|
||||
unsigned bits = (F >> HexagonII::ExtentBitsPos)
|
||||
& HexagonII::ExtentBitsMask;
|
||||
|
||||
if (isSigned) // if value is signed
|
||||
return ~(-1 << (bits - 1));
|
||||
else
|
||||
return ~(-1 << bits);
|
||||
}
|
||||
|
||||
// Returns true if an instruction can be converted into a non-extended
|
||||
// equivalent instruction.
|
||||
bool HexagonInstrInfo::NonExtEquivalentExists (const MachineInstr *MI) const {
|
||||
|
||||
short NonExtOpcode;
|
||||
// Check if the instruction has a register form that uses register in place
|
||||
// of the extended operand, if so return that as the non-extended form.
|
||||
if (Hexagon::getRegForm(MI->getOpcode()) >= 0)
|
||||
return true;
|
||||
|
||||
if (MI->getDesc().mayLoad() || MI->getDesc().mayStore()) {
|
||||
// Check addressing mode and retreive non-ext equivalent instruction.
|
||||
|
||||
switch (getAddrMode(MI)) {
|
||||
case HexagonII::Absolute :
|
||||
// Load/store with absolute addressing mode can be converted into
|
||||
// base+offset mode.
|
||||
NonExtOpcode = Hexagon::getBasedWithImmOffset(MI->getOpcode());
|
||||
break;
|
||||
case HexagonII::BaseImmOffset :
|
||||
// Load/store with base+offset addressing mode can be converted into
|
||||
// base+register offset addressing mode. However left shift operand should
|
||||
// be set to 0.
|
||||
NonExtOpcode = Hexagon::getBaseWithRegOffset(MI->getOpcode());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (NonExtOpcode < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns opcode of the non-extended equivalent instruction.
|
||||
short HexagonInstrInfo::getNonExtOpcode (const MachineInstr *MI) const {
|
||||
|
||||
// Check if the instruction has a register form that uses register in place
|
||||
// of the extended operand, if so return that as the non-extended form.
|
||||
short NonExtOpcode = Hexagon::getRegForm(MI->getOpcode());
|
||||
if (NonExtOpcode >= 0)
|
||||
return NonExtOpcode;
|
||||
|
||||
if (MI->getDesc().mayLoad() || MI->getDesc().mayStore()) {
|
||||
// Check addressing mode and retreive non-ext equivalent instruction.
|
||||
switch (getAddrMode(MI)) {
|
||||
case HexagonII::Absolute :
|
||||
return Hexagon::getBasedWithImmOffset(MI->getOpcode());
|
||||
case HexagonII::BaseImmOffset :
|
||||
return Hexagon::getBaseWithRegOffset(MI->getOpcode());
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -180,6 +180,17 @@ public:
|
||||
unsigned getImmExtForm(const MachineInstr* MI) const;
|
||||
unsigned getNormalBranchForm(const MachineInstr* MI) const;
|
||||
|
||||
|
||||
void immediateExtend(MachineInstr *MI) const;
|
||||
bool isConstExtended(MachineInstr *MI) const;
|
||||
unsigned getAddrMode(const MachineInstr* MI) const;
|
||||
bool isOperandExtended(const MachineInstr *MI,
|
||||
unsigned short OperandNum) const;
|
||||
unsigned short getCExtOpNum(const MachineInstr *MI) const;
|
||||
int getMinValue(const MachineInstr *MI) const;
|
||||
int getMaxValue(const MachineInstr *MI) const;
|
||||
bool NonExtEquivalentExists (const MachineInstr *MI) const;
|
||||
short getNonExtOpcode(const MachineInstr *MI) const;
|
||||
private:
|
||||
int getMatchingCondBranchOpcode(int Opc, bool sense) const;
|
||||
|
||||
|
@ -17,35 +17,36 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#define DEBUG_TYPE "packets"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "HexagonRegisterInfo.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/DFAPacketizer.h"
|
||||
#include "llvm/CodeGen/LatencyPriorityQueue.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||
#include "llvm/CodeGen/ScheduleDAG.h"
|
||||
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
|
||||
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
||||
#include "llvm/CodeGen/LatencyPriorityQueue.h"
|
||||
#include "llvm/CodeGen/SchedulerRegistry.h"
|
||||
#include "llvm/MC/MCInstrItineraries.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
||||
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/MC/MCInstrItineraries.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonRegisterInfo.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace llvm;
|
||||
@ -257,7 +258,7 @@ void HexagonPacketizerList::reserveResourcesForConstExt(MachineInstr* MI) {
|
||||
|
||||
bool HexagonPacketizerList::canReserveResourcesForConstExt(MachineInstr *MI) {
|
||||
const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII;
|
||||
assert(QII->isExtended(MI) &&
|
||||
assert((QII->isExtended(MI) || QII->isConstExtended(MI)) &&
|
||||
"Should only be called for constant extended instructions");
|
||||
MachineFunction *MF = MI->getParent()->getParent();
|
||||
MachineInstr *PseudoMI = MF->CreateMachineInstr(QII->get(Hexagon::IMMEXT_i),
|
||||
@ -3196,7 +3197,7 @@ HexagonPacketizerList::addToPacket(MachineInstr *MI) {
|
||||
MachineInstr *nvjMI = MII;
|
||||
assert(ResourceTracker->canReserveResources(MI));
|
||||
ResourceTracker->reserveResources(MI);
|
||||
if (QII->isExtended(MI) &&
|
||||
if ((QII->isExtended(MI) || QII->isConstExtended(MI)) &&
|
||||
!tryAllocateResourcesForConstExt(MI)) {
|
||||
endPacket(MBB, MI);
|
||||
ResourceTracker->reserveResources(MI);
|
||||
@ -3216,7 +3217,7 @@ HexagonPacketizerList::addToPacket(MachineInstr *MI) {
|
||||
&& (!tryAllocateResourcesForConstExt(nvjMI)
|
||||
|| !ResourceTracker->canReserveResources(nvjMI)))
|
||||
|| // For non-extended instruction, no need to allocate extra 4 bytes.
|
||||
(!QII->isExtended(nvjMI) &&
|
||||
(!QII->isExtended(nvjMI) &&
|
||||
!ResourceTracker->canReserveResources(nvjMI)))
|
||||
{
|
||||
endPacket(MBB, MI);
|
||||
@ -3232,7 +3233,7 @@ HexagonPacketizerList::addToPacket(MachineInstr *MI) {
|
||||
CurrentPacketMIs.push_back(MI);
|
||||
CurrentPacketMIs.push_back(nvjMI);
|
||||
} else {
|
||||
if ( QII->isExtended(MI)
|
||||
if ( (QII->isExtended(MI) || QII->isConstExtended(MI))
|
||||
&& ( !tryAllocateResourcesForConstExt(MI)
|
||||
|| !ResourceTracker->canReserveResources(MI)))
|
||||
{
|
||||
|
@ -154,6 +154,28 @@ namespace HexagonII {
|
||||
|
||||
// *** The code above must match HexagonInstrFormat*.td *** //
|
||||
|
||||
// Hexagon specific MO operand flag mask.
|
||||
enum HexagonMOTargetFlagVal {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Hexagon Specific MachineOperand flags.
|
||||
MO_NO_FLAG,
|
||||
|
||||
HMOTF_ConstExtended = 1,
|
||||
|
||||
/// MO_PCREL - On a symbol operand, indicates a PC-relative relocation
|
||||
/// Used for computing a global address for PIC compilations
|
||||
MO_PCREL,
|
||||
|
||||
/// MO_GOT - Indicates a GOT-relative relocation
|
||||
MO_GOT,
|
||||
|
||||
// Low or high part of a symbol.
|
||||
MO_LO16, MO_HI16,
|
||||
|
||||
// Offset from the base of the SDA.
|
||||
MO_GPREL
|
||||
};
|
||||
|
||||
} // End namespace HexagonII.
|
||||
|
||||
} // End namespace llvm.
|
||||
|
18
test/CodeGen/Hexagon/cext-valid-packet1.ll
Normal file
18
test/CodeGen/Hexagon/cext-valid-packet1.ll
Normal file
@ -0,0 +1,18 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
|
||||
; Check that the packetizer generates valid packets with constant
|
||||
; extended instructions.
|
||||
; CHECK: {
|
||||
; CHECK-NEXT: r{{[0-9]+}}{{ *}}={{ *}}add(r{{[0-9]+}}, ##{{[0-9]+}})
|
||||
; CHECK-NEXT: r{{[0-9]+}}{{ *}}={{ *}}add(r{{[0-9]+}}, ##{{[0-9]+}})
|
||||
; CHECK-NEXT: }
|
||||
|
||||
define i32 @check-packet1(i32 %a, i32 %b, i32 %c) nounwind readnone {
|
||||
entry:
|
||||
%add = add nsw i32 %a, 200000
|
||||
%add1 = add nsw i32 %b, 200001
|
||||
%add2 = add nsw i32 %c, 200002
|
||||
%cmp = icmp sgt i32 %add, %add1
|
||||
%b.addr.0 = select i1 %cmp, i32 %add1, i32 %add2
|
||||
ret i32 %b.addr.0
|
||||
}
|
43
test/CodeGen/Hexagon/cext-valid-packet2.ll
Normal file
43
test/CodeGen/Hexagon/cext-valid-packet2.ll
Normal file
@ -0,0 +1,43 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; Check that the packetizer generates valid packets with constant
|
||||
; extended add and base+offset store instructions.
|
||||
|
||||
; CHECK: {
|
||||
; CHECK-NEXT: r{{[0-9]+}}{{ *}}={{ *}}add(r{{[0-9]+}}, ##{{[0-9]+}})
|
||||
; CHECK-NEXT: memw(r{{[0-9]+}}+{{ *}}##{{[0-9]+}}){{ *}}={{ *}}r{{[0-9]+}}.new
|
||||
; CHECK-NEXT: }
|
||||
|
||||
define i32 @test(i32* nocapture %a, i32* nocapture %b, i32 %c) nounwind {
|
||||
entry:
|
||||
%add = add nsw i32 %c, 200002
|
||||
%0 = load i32* %a, align 4
|
||||
%add1 = add nsw i32 %0, 200000
|
||||
%arrayidx2 = getelementptr inbounds i32* %a, i32 3000
|
||||
store i32 %add1, i32* %arrayidx2, align 4
|
||||
%1 = load i32* %b, align 4
|
||||
%add4 = add nsw i32 %1, 200001
|
||||
%arrayidx5 = getelementptr inbounds i32* %a, i32 1
|
||||
store i32 %add4, i32* %arrayidx5, align 4
|
||||
%arrayidx7 = getelementptr inbounds i32* %b, i32 1
|
||||
%2 = load i32* %arrayidx7, align 4
|
||||
%cmp = icmp sgt i32 %add4, %2
|
||||
br i1 %cmp, label %if.then, label %if.else
|
||||
|
||||
if.then: ; preds = %entry
|
||||
%arrayidx8 = getelementptr inbounds i32* %a, i32 2
|
||||
%3 = load i32* %arrayidx8, align 4
|
||||
%arrayidx9 = getelementptr inbounds i32* %b, i32 2000
|
||||
%4 = load i32* %arrayidx9, align 4
|
||||
%sub = sub nsw i32 %3, %4
|
||||
%arrayidx10 = getelementptr inbounds i32* %a, i32 4000
|
||||
store i32 %sub, i32* %arrayidx10, align 4
|
||||
br label %if.end
|
||||
|
||||
if.else: ; preds = %entry
|
||||
%arrayidx11 = getelementptr inbounds i32* %b, i32 3200
|
||||
store i32 %add, i32* %arrayidx11, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.else, %if.then
|
||||
ret i32 %add
|
||||
}
|
Loading…
Reference in New Issue
Block a user