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:
Jyotsna Verma 2013-03-01 17:37:13 +00:00
parent ae1dbb39f7
commit ef94c6c85e
6 changed files with 292 additions and 26 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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)))
{

View File

@ -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.

View 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
}

View 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
}