summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorJacques Pienaar <jpienaar@google.com>2016-07-07 23:36:04 +0000
committerJacques Pienaar <jpienaar@google.com>2016-07-07 23:36:04 +0000
commit6d3eecc84304c0b36ed5f1ababa22cd974de1f5b (patch)
tree7754b66e6fb7eb27a95f26e03c130a403b878559 /llvm/lib/Target
parent3f36781dec71788e87779005d7c18cb78c6f163d (diff)
downloadbcm5719-llvm-6d3eecc84304c0b36ed5f1ababa22cd974de1f5b.tar.gz
bcm5719-llvm-6d3eecc84304c0b36ed5f1ababa22cd974de1f5b.zip
[lanai] Use peephole optimizer to generate more conditional ALU operations.
Summary: * Similiar to the ARM backend yse the peephole optimizer to generate more conditional ALU operations; * Add predicated type with default always true to RR instructions in LanaiInstrInfo.td; * Move LanaiSetflagAluCombiner into optimizeCompare; * The ASM parser can currently only handle explicitly specified CC, so specify ".t" (true) where needed in the ASM test; * Remove unused MachineOperand flags; Reviewers: eliben Subscribers: aemerson Differential Revision: http://reviews.llvm.org/D22072 llvm-svn: 274807
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp30
-rw-r--r--llvm/lib/Target/Lanai/CMakeLists.txt1
-rw-r--r--llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp13
-rw-r--r--llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.cpp20
-rw-r--r--llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.h1
-rw-r--r--llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp12
-rw-r--r--llvm/lib/Target/Lanai/LanaiISelLowering.cpp170
-rw-r--r--llvm/lib/Target/Lanai/LanaiISelLowering.h2
-rw-r--r--llvm/lib/Target/Lanai/LanaiInstrInfo.cpp395
-rw-r--r--llvm/lib/Target/Lanai/LanaiInstrInfo.h47
-rw-r--r--llvm/lib/Target/Lanai/LanaiInstrInfo.td43
-rw-r--r--llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp15
-rw-r--r--llvm/lib/Target/Lanai/LanaiSetflagAluCombiner.cpp294
-rw-r--r--llvm/lib/Target/Lanai/LanaiTargetMachine.cpp2
-rw-r--r--llvm/lib/Target/Lanai/MCTargetDesc/LanaiBaseInfo.h26
15 files changed, 707 insertions, 364 deletions
diff --git a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
index 799f587ff3f..c3c4468d54c 100644
--- a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
+++ b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
@@ -357,6 +357,20 @@ public:
return isInt<10>(Value);
}
+ bool isCondCode() {
+ if (!isImm())
+ return false;
+
+ const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
+ if (!ConstExpr)
+ return false;
+ uint64_t Value = ConstExpr->getValue();
+ // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
+ // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
+ // value corresponds to a valid condition code.
+ return Value < LPCC::UNKNOWN;
+ }
+
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediates where possible. Null MCExpr = 0
if (Expr == nullptr)
@@ -388,6 +402,11 @@ public:
addExpr(Inst, getImm());
}
+ void addCondCodeOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
void addMemImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCExpr *Expr = getMemOffset();
@@ -1031,7 +1050,16 @@ StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
if (CondCode != LPCC::UNKNOWN) {
size_t Next = Mnemonic.rfind('.', Name.size());
- Mnemonic = Mnemonic.substr(0, Next + 1);
+ // 'sel' doesn't use a predicate operand whose printer adds the period,
+ // but instead has the period as part of the identifier (i.e., 'sel.' is
+ // expected by the generated matcher). If the mnemonic starts with 'sel'
+ // then include the period as part of the mnemonic, else don't include it
+ // as part of the mnemonic.
+ if (Mnemonic.startswith("sel")) {
+ Mnemonic = Mnemonic.substr(0, Next + 1);
+ } else {
+ Mnemonic = Mnemonic.substr(0, Next);
+ }
Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
Operands->push_back(LanaiOperand::createImm(
MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
diff --git a/llvm/lib/Target/Lanai/CMakeLists.txt b/llvm/lib/Target/Lanai/CMakeLists.txt
index e5aec96e476..867f6165c25 100644
--- a/llvm/lib/Target/Lanai/CMakeLists.txt
+++ b/llvm/lib/Target/Lanai/CMakeLists.txt
@@ -23,7 +23,6 @@ add_llvm_target(LanaiCodeGen
LanaiMemAluCombiner.cpp
LanaiRegisterInfo.cpp
LanaiSelectionDAGInfo.cpp
- LanaiSetflagAluCombiner.cpp
LanaiSubtarget.cpp
LanaiTargetMachine.cpp
LanaiTargetObjectFile.cpp
diff --git a/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp b/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
index 3a71b80b2ba..d8ead5d67bc 100644
--- a/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
+++ b/llvm/lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
@@ -62,6 +62,10 @@ static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder);
+static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
@@ -226,3 +230,12 @@ static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
return MCDisassembler::Success;
}
+
+static DecodeStatus decodePredicateOperand(MCInst &Inst, unsigned Val,
+ uint64_t Address,
+ const void *Decoder) {
+ if (Val >= LPCC::UNKNOWN)
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::createImm(Val));
+ return MCDisassembler::Success;
+}
diff --git a/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.cpp b/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.cpp
index 4a1dcd881b5..82b720cea8d 100644
--- a/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.cpp
+++ b/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.cpp
@@ -284,6 +284,22 @@ void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
raw_ostream &OS) {
- const int CC = static_cast<const int>(MI->getOperand(OpNo).getImm());
- OS << lanaiCondCodeToString(static_cast<LPCC::CondCode>(CC));
+ LPCC::CondCode CC =
+ static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
+ // Handle the undefined value here for printing so we don't abort().
+ if (CC >= LPCC::UNKNOWN)
+ OS << "<und>";
+ else
+ OS << lanaiCondCodeToString(CC);
+}
+
+void LanaiInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &OS) {
+ LPCC::CondCode CC =
+ static_cast<LPCC::CondCode>(MI->getOperand(OpNo).getImm());
+ // Handle the undefined value here for printing so we don't abort().
+ if (CC >= LPCC::UNKNOWN)
+ OS << "<und>";
+ else if (CC != LPCC::ICC_T)
+ OS << "." << lanaiCondCodeToString(CC);
}
diff --git a/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.h b/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.h
index 4bd5bb0e7fc..1c9d186ad81 100644
--- a/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.h
+++ b/llvm/lib/Target/Lanai/InstPrinter/LanaiInstPrinter.h
@@ -29,6 +29,7 @@ public:
const MCSubtargetInfo &STI) override;
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
const char *Modifier = 0);
+ void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printMemRiOperand(const MCInst *MI, int OpNo, raw_ostream &O,
const char *Modifier = 0);
void printMemRrOperand(const MCInst *MI, int OpNo, raw_ostream &O,
diff --git a/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp b/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp
index 0effa5cc653..d3ff9e8668d 100644
--- a/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp
+++ b/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp
@@ -65,7 +65,6 @@ private:
void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
raw_ostream &O, const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNum);
- unsigned TF = MO.getTargetFlags();
switch (MO.getType()) {
case MachineOperand::MO_Register:
@@ -81,10 +80,7 @@ void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
break;
case MachineOperand::MO_GlobalAddress:
- if (TF == LanaiII::MO_PLT)
- O << "plt(" << *getSymbol(MO.getGlobal()) << ")";
- else
- O << *getSymbol(MO.getGlobal());
+ O << *getSymbol(MO.getGlobal());
break;
case MachineOperand::MO_BlockAddress: {
@@ -94,10 +90,7 @@ void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
}
case MachineOperand::MO_ExternalSymbol:
- if (TF == LanaiII::MO_PLT)
- O << "plt(" << *GetExternalSymbolSymbol(MO.getSymbolName()) << ")";
- else
- O << *GetExternalSymbolSymbol(MO.getSymbolName());
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
break;
case MachineOperand::MO_JumpTableIndex:
@@ -116,7 +109,6 @@ void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
}
// PrintAsmOperand - Print out an operand for an inline asm expression.
-//
bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode, raw_ostream &O) {
diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
index fd2d7fffd0e..a383cf844b6 100644
--- a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
+++ b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp
@@ -124,6 +124,12 @@ LanaiTargetLowering::LanaiTargetLowering(const TargetMachine &TM,
setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
}
+ setTargetDAGCombine(ISD::ADD);
+ setTargetDAGCombine(ISD::SUB);
+ setTargetDAGCombine(ISD::AND);
+ setTargetDAGCombine(ISD::OR);
+ setTargetDAGCombine(ISD::XOR);
+
// Function alignments (log2)
setMinFunctionAlignment(2);
setPrefFunctionAlignment(2);
@@ -1268,3 +1274,167 @@ SDValue LanaiTargetLowering::LowerSRL_PARTS(SDValue Op,
SDValue Ops[2] = {Lo, Hi};
return DAG.getMergeValues(Ops, dl);
}
+
+// Helper function that checks if N is a null or all ones constant.
+static inline bool isZeroOrAllOnes(SDValue N, bool AllOnes) {
+ return AllOnes ? isAllOnesConstant(N) : isNullConstant(N);
+}
+
+// Return true if N is conditionally 0 or all ones.
+// Detects these expressions where cc is an i1 value:
+//
+// (select cc 0, y) [AllOnes=0]
+// (select cc y, 0) [AllOnes=0]
+// (zext cc) [AllOnes=0]
+// (sext cc) [AllOnes=0/1]
+// (select cc -1, y) [AllOnes=1]
+// (select cc y, -1) [AllOnes=1]
+//
+// * AllOnes determines whether to check for an all zero (AllOnes false) or an
+// all ones operand (AllOnes true).
+// * Invert is set when N is the all zero/ones constant when CC is false.
+// * OtherOp is set to the alternative value of N.
+//
+// For example, for (select cc X, Y) and AllOnes = 0 if:
+// * X = 0, Invert = False and OtherOp = Y
+// * Y = 0, Invert = True and OtherOp = X
+static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC,
+ bool &Invert, SDValue &OtherOp,
+ SelectionDAG &DAG) {
+ switch (N->getOpcode()) {
+ default:
+ return false;
+ case ISD::SELECT: {
+ CC = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ SDValue N2 = N->getOperand(2);
+ if (isZeroOrAllOnes(N1, AllOnes)) {
+ Invert = false;
+ OtherOp = N2;
+ return true;
+ }
+ if (isZeroOrAllOnes(N2, AllOnes)) {
+ Invert = true;
+ OtherOp = N1;
+ return true;
+ }
+ return false;
+ }
+ case ISD::ZERO_EXTEND: {
+ // (zext cc) can never be the all ones value.
+ if (AllOnes)
+ return false;
+ CC = N->getOperand(0);
+ if (CC.getValueType() != MVT::i1)
+ return false;
+ SDLoc dl(N);
+ EVT VT = N->getValueType(0);
+ OtherOp = DAG.getConstant(1, dl, VT);
+ Invert = true;
+ return true;
+ }
+ case ISD::SIGN_EXTEND: {
+ CC = N->getOperand(0);
+ if (CC.getValueType() != MVT::i1)
+ return false;
+ SDLoc dl(N);
+ EVT VT = N->getValueType(0);
+ Invert = !AllOnes;
+ if (AllOnes)
+ // When looking for an AllOnes constant, N is an sext, and the 'other'
+ // value is 0.
+ OtherOp = DAG.getConstant(0, dl, VT);
+ else
+ OtherOp =
+ DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), dl, VT);
+ return true;
+ }
+ }
+}
+
+// Combine a constant select operand into its use:
+//
+// (add (select cc, 0, c), x) -> (select cc, x, (add, x, c))
+// (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c))
+// (and (select cc, -1, c), x) -> (select cc, x, (and, x, c)) [AllOnes=1]
+// (or (select cc, 0, c), x) -> (select cc, x, (or, x, c))
+// (xor (select cc, 0, c), x) -> (select cc, x, (xor, x, c))
+//
+// The transform is rejected if the select doesn't have a constant operand that
+// is null, or all ones when AllOnes is set.
+//
+// Also recognize sext/zext from i1:
+//
+// (add (zext cc), x) -> (select cc (add x, 1), x)
+// (add (sext cc), x) -> (select cc (add x, -1), x)
+//
+// These transformations eventually create predicated instructions.
+static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
+ TargetLowering::DAGCombinerInfo &DCI,
+ bool AllOnes) {
+ SelectionDAG &DAG = DCI.DAG;
+ EVT VT = N->getValueType(0);
+ SDValue NonConstantVal;
+ SDValue CCOp;
+ bool SwapSelectOps;
+ if (!isConditionalZeroOrAllOnes(Slct.getNode(), AllOnes, CCOp, SwapSelectOps,
+ NonConstantVal, DAG))
+ return SDValue();
+
+ // Slct is now know to be the desired identity constant when CC is true.
+ SDValue TrueVal = OtherOp;
+ SDValue FalseVal =
+ DAG.getNode(N->getOpcode(), SDLoc(N), VT, OtherOp, NonConstantVal);
+ // Unless SwapSelectOps says CC should be false.
+ if (SwapSelectOps)
+ std::swap(TrueVal, FalseVal);
+
+ return DAG.getNode(ISD::SELECT, SDLoc(N), VT, CCOp, TrueVal, FalseVal);
+}
+
+// Attempt combineSelectAndUse on each operand of a commutative operator N.
+static SDValue
+combineSelectAndUseCommutative(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
+ bool AllOnes) {
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ if (N0.getNode()->hasOneUse())
+ if (SDValue Result = combineSelectAndUse(N, N0, N1, DCI, AllOnes))
+ return Result;
+ if (N1.getNode()->hasOneUse())
+ if (SDValue Result = combineSelectAndUse(N, N1, N0, DCI, AllOnes))
+ return Result;
+ return SDValue();
+}
+
+// PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
+static SDValue PerformSUBCombine(SDNode *N,
+ TargetLowering::DAGCombinerInfo &DCI) {
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+
+ // fold (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c))
+ if (N1.getNode()->hasOneUse())
+ if (SDValue Result = combineSelectAndUse(N, N1, N0, DCI, /*AllOnes=*/false))
+ return Result;
+
+ return SDValue();
+}
+
+SDValue LanaiTargetLowering::PerformDAGCombine(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ switch (N->getOpcode()) {
+ default:
+ break;
+ case ISD::ADD:
+ case ISD::OR:
+ case ISD::XOR:
+ return combineSelectAndUseCommutative(N, DCI, /*AllOnes=*/false);
+ case ISD::AND:
+ return combineSelectAndUseCommutative(N, DCI, /*AllOnes=*/true);
+ case ISD::SUB:
+ return PerformSUBCombine(N, DCI);
+ }
+
+ return SDValue();
+}
diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.h b/llvm/lib/Target/Lanai/LanaiISelLowering.h
index 20ca9a01684..16ce8edd27c 100644
--- a/llvm/lib/Target/Lanai/LanaiISelLowering.h
+++ b/llvm/lib/Target/Lanai/LanaiISelLowering.h
@@ -103,6 +103,8 @@ public:
std::vector<SDValue> &Ops,
SelectionDAG &DAG) const override;
+ SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
+
private:
SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
CallingConv::ID CallConv, bool IsVarArg,
diff --git a/llvm/lib/Target/Lanai/LanaiInstrInfo.cpp b/llvm/lib/Target/Lanai/LanaiInstrInfo.cpp
index 797fd8e5c53..861604266cd 100644
--- a/llvm/lib/Target/Lanai/LanaiInstrInfo.cpp
+++ b/llvm/lib/Target/Lanai/LanaiInstrInfo.cpp
@@ -122,7 +122,7 @@ bool LanaiInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
return false;
}
-static LPCC::CondCode GetOppositeBranchCondition(LPCC::CondCode CC) {
+static LPCC::CondCode getOppositeCondition(LPCC::CondCode CC) {
switch (CC) {
case LPCC::ICC_T: // true
return LPCC::ICC_F;
@@ -161,6 +161,397 @@ static LPCC::CondCode GetOppositeBranchCondition(LPCC::CondCode CC) {
}
}
+std::pair<unsigned, unsigned>
+LanaiInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
+ return std::make_pair(TF, 0u);
+}
+
+ArrayRef<std::pair<unsigned, const char *>>
+LanaiInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
+ using namespace LanaiII;
+ static const std::pair<unsigned, const char *> TargetFlags[] = {
+ {MO_ABS_HI, "lanai-hi"},
+ {MO_ABS_LO, "lanai-lo"},
+ {MO_NO_FLAG, "lanai-nf"}};
+ return makeArrayRef(TargetFlags);
+}
+
+bool LanaiInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
+ unsigned &SrcReg2, int &CmpMask,
+ int &CmpValue) const {
+ switch (MI.getOpcode()) {
+ default:
+ break;
+ case Lanai::SFSUB_F_RI_LO:
+ case Lanai::SFSUB_F_RI_HI:
+ SrcReg = MI.getOperand(0).getReg();
+ SrcReg2 = 0;
+ CmpMask = ~0;
+ CmpValue = MI.getOperand(1).getImm();
+ return true;
+ case Lanai::SFSUB_F_RR:
+ SrcReg = MI.getOperand(0).getReg();
+ SrcReg2 = MI.getOperand(1).getReg();
+ CmpMask = ~0;
+ CmpValue = 0;
+ return true;
+ }
+
+ return false;
+}
+
+// isRedundantFlagInstr - check whether the first instruction, whose only
+// purpose is to update flags, can be made redundant.
+// * SFSUB_F_RR can be made redundant by SUB_RI if the operands are the same.
+// * SFSUB_F_RI can be made redundant by SUB_I if the operands are the same.
+inline static bool isRedundantFlagInstr(MachineInstr *CmpI, unsigned SrcReg,
+ unsigned SrcReg2, int ImmValue,
+ MachineInstr *OI) {
+ if (CmpI->getOpcode() == Lanai::SFSUB_F_RR &&
+ OI->getOpcode() == Lanai::SUB_R &&
+ ((OI->getOperand(1).getReg() == SrcReg &&
+ OI->getOperand(2).getReg() == SrcReg2) ||
+ (OI->getOperand(1).getReg() == SrcReg2 &&
+ OI->getOperand(2).getReg() == SrcReg)))
+ return true;
+
+ if (((CmpI->getOpcode() == Lanai::SFSUB_F_RI_LO &&
+ OI->getOpcode() == Lanai::SUB_I_LO) ||
+ (CmpI->getOpcode() == Lanai::SFSUB_F_RI_HI &&
+ OI->getOpcode() == Lanai::SUB_I_HI)) &&
+ OI->getOperand(1).getReg() == SrcReg &&
+ OI->getOperand(2).getImm() == ImmValue)
+ return true;
+ return false;
+}
+
+inline static unsigned flagSettingOpcodeVariant(unsigned OldOpcode) {
+ switch (OldOpcode) {
+ case Lanai::ADD_I_HI:
+ return Lanai::ADD_F_I_HI;
+ case Lanai::ADD_I_LO:
+ return Lanai::ADD_F_I_LO;
+ case Lanai::ADD_R:
+ return Lanai::ADD_F_R;
+ case Lanai::ADDC_I_HI:
+ return Lanai::ADDC_F_I_HI;
+ case Lanai::ADDC_I_LO:
+ return Lanai::ADDC_F_I_LO;
+ case Lanai::ADDC_R:
+ return Lanai::ADDC_F_R;
+ case Lanai::AND_I_HI:
+ return Lanai::AND_F_I_HI;
+ case Lanai::AND_I_LO:
+ return Lanai::AND_F_I_LO;
+ case Lanai::AND_R:
+ return Lanai::AND_F_R;
+ case Lanai::OR_I_HI:
+ return Lanai::OR_F_I_HI;
+ case Lanai::OR_I_LO:
+ return Lanai::OR_F_I_LO;
+ case Lanai::OR_R:
+ return Lanai::OR_F_R;
+ case Lanai::SL_I:
+ return Lanai::SL_F_I;
+ case Lanai::SRL_R:
+ return Lanai::SRL_F_R;
+ case Lanai::SA_I:
+ return Lanai::SA_F_I;
+ case Lanai::SRA_R:
+ return Lanai::SRA_F_R;
+ case Lanai::SUB_I_HI:
+ return Lanai::SUB_F_I_HI;
+ case Lanai::SUB_I_LO:
+ return Lanai::SUB_F_I_LO;
+ case Lanai::SUB_R:
+ return Lanai::SUB_F_R;
+ case Lanai::SUBB_I_HI:
+ return Lanai::SUBB_F_I_HI;
+ case Lanai::SUBB_I_LO:
+ return Lanai::SUBB_F_I_LO;
+ case Lanai::SUBB_R:
+ return Lanai::SUBB_F_R;
+ case Lanai::XOR_I_HI:
+ return Lanai::XOR_F_I_HI;
+ case Lanai::XOR_I_LO:
+ return Lanai::XOR_F_I_LO;
+ case Lanai::XOR_R:
+ return Lanai::XOR_F_R;
+ default:
+ return Lanai::NOP;
+ }
+}
+
+bool LanaiInstrInfo::optimizeCompareInstr(
+ MachineInstr &CmpInstr, unsigned SrcReg, unsigned SrcReg2, int CmpMask,
+ int CmpValue, const MachineRegisterInfo *MRI) const {
+ // Get the unique definition of SrcReg.
+ MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
+ if (!MI)
+ return false;
+
+ // Get ready to iterate backward from CmpInstr.
+ MachineBasicBlock::iterator I = CmpInstr, E = MI,
+ B = CmpInstr.getParent()->begin();
+
+ // Early exit if CmpInstr is at the beginning of the BB.
+ if (I == B)
+ return false;
+
+ // There are two possible candidates which can be changed to set SR:
+ // One is MI, the other is a SUB instruction.
+ // * For SFSUB_F_RR(r1,r2), we are looking for SUB(r1,r2) or SUB(r2,r1).
+ // * For SFSUB_F_RI(r1, CmpValue), we are looking for SUB(r1, CmpValue).
+ MachineInstr *Sub = nullptr;
+ if (SrcReg2 != 0)
+ // MI is not a candidate to transform into a flag setting instruction.
+ MI = nullptr;
+ else if (MI->getParent() != CmpInstr.getParent() || CmpValue != 0) {
+ // Conservatively refuse to convert an instruction which isn't in the same
+ // BB as the comparison. Don't return if SFSUB_F_RI and CmpValue != 0 as Sub
+ // may still be a candidate.
+ if (CmpInstr.getOpcode() == Lanai::SFSUB_F_RI_LO)
+ MI = nullptr;
+ else
+ return false;
+ }
+
+ // Check that SR isn't set between the comparison instruction and the
+ // instruction we want to change while searching for Sub.
+ const TargetRegisterInfo *TRI = &getRegisterInfo();
+ for (--I; I != E; --I) {
+ const MachineInstr &Instr = *I;
+
+ if (Instr.modifiesRegister(Lanai::SR, TRI) ||
+ Instr.readsRegister(Lanai::SR, TRI))
+ // This instruction modifies or uses SR after the one we want to change.
+ // We can't do this transformation.
+ return false;
+
+ // Check whether CmpInstr can be made redundant by the current instruction.
+ if (isRedundantFlagInstr(&CmpInstr, SrcReg, SrcReg2, CmpValue, &*I)) {
+ Sub = &*I;
+ break;
+ }
+
+ // Don't search outside the containing basic block.
+ if (I == B)
+ return false;
+ }
+
+ // Return false if no candidates exist.
+ if (!MI && !Sub)
+ return false;
+
+ // The single candidate is called MI.
+ if (!MI)
+ MI = Sub;
+
+ if (flagSettingOpcodeVariant(MI->getOpcode()) != Lanai::NOP) {
+ bool isSafe = false;
+
+ SmallVector<std::pair<MachineOperand *, LPCC::CondCode>, 4>
+ OperandsToUpdate;
+ I = CmpInstr;
+ E = CmpInstr.getParent()->end();
+ while (!isSafe && ++I != E) {
+ const MachineInstr &Instr = *I;
+ for (unsigned IO = 0, EO = Instr.getNumOperands(); !isSafe && IO != EO;
+ ++IO) {
+ const MachineOperand &MO = Instr.getOperand(IO);
+ if (MO.isRegMask() && MO.clobbersPhysReg(Lanai::SR)) {
+ isSafe = true;
+ break;
+ }
+ if (!MO.isReg() || MO.getReg() != Lanai::SR)
+ continue;
+ if (MO.isDef()) {
+ isSafe = true;
+ break;
+ }
+ // Condition code is after the operand before SR.
+ LPCC::CondCode CC;
+ CC = (LPCC::CondCode)Instr.getOperand(IO - 1).getImm();
+
+ if (Sub) {
+ LPCC::CondCode NewCC = getOppositeCondition(CC);
+ if (NewCC == LPCC::ICC_T)
+ return false;
+ // If we have SUB(r1, r2) and CMP(r2, r1), the condition code based on
+ // CMP needs to be updated to be based on SUB. Push the condition
+ // code operands to OperandsToUpdate. If it is safe to remove
+ // CmpInstr, the condition code of these operands will be modified.
+ if (SrcReg2 != 0 && Sub->getOperand(1).getReg() == SrcReg2 &&
+ Sub->getOperand(2).getReg() == SrcReg) {
+ OperandsToUpdate.push_back(
+ std::make_pair(&((*I).getOperand(IO - 1)), NewCC));
+ }
+ } else {
+ // No Sub, so this is x = <op> y, z; cmp x, 0.
+ switch (CC) {
+ case LPCC::ICC_EQ: // Z
+ case LPCC::ICC_NE: // Z
+ case LPCC::ICC_MI: // N
+ case LPCC::ICC_PL: // N
+ case LPCC::ICC_F: // none
+ case LPCC::ICC_T: // none
+ // SR can be used multiple times, we should continue.
+ break;
+ case LPCC::ICC_CS: // C
+ case LPCC::ICC_CC: // C
+ case LPCC::ICC_VS: // V
+ case LPCC::ICC_VC: // V
+ case LPCC::ICC_HI: // C Z
+ case LPCC::ICC_LS: // C Z
+ case LPCC::ICC_GE: // N V
+ case LPCC::ICC_LT: // N V
+ case LPCC::ICC_GT: // Z N V
+ case LPCC::ICC_LE: // Z N V
+ // The instruction uses the V bit or C bit which is not safe.
+ return false;
+ case LPCC::UNKNOWN:
+ return false;
+ }
+ }
+ }
+ }
+
+ // If SR is not killed nor re-defined, we should check whether it is
+ // live-out. If it is live-out, do not optimize.
+ if (!isSafe) {
+ MachineBasicBlock *MBB = CmpInstr.getParent();
+ for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
+ SE = MBB->succ_end();
+ SI != SE; ++SI)
+ if ((*SI)->isLiveIn(Lanai::SR))
+ return false;
+ }
+
+ // Toggle the optional operand to SR.
+ MI->setDesc(get(flagSettingOpcodeVariant(MI->getOpcode())));
+ MI->addRegisterDefined(Lanai::SR);
+ CmpInstr.eraseFromParent();
+ return true;
+ }
+
+ return false;
+}
+
+bool LanaiInstrInfo::analyzeSelect(const MachineInstr &MI,
+ SmallVectorImpl<MachineOperand> &Cond,
+ unsigned &TrueOp, unsigned &FalseOp,
+ bool &Optimizable) const {
+ assert(MI.getOpcode() == Lanai::SELECT && "unknown select instruction");
+ // Select operands:
+ // 0: Def.
+ // 1: True use.
+ // 2: False use.
+ // 3: Condition code.
+ TrueOp = 1;
+ FalseOp = 2;
+ Cond.push_back(MI.getOperand(3));
+ Optimizable = true;
+ return false;
+}
+
+// Identify instructions that can be folded into a SELECT instruction, and
+// return the defining instruction.
+static MachineInstr *canFoldIntoSelect(unsigned Reg,
+ const MachineRegisterInfo &MRI,
+ const TargetInstrInfo *TII) {
+ if (!TargetRegisterInfo::isVirtualRegister(Reg))
+ return nullptr;
+ if (!MRI.hasOneNonDBGUse(Reg))
+ return nullptr;
+ MachineInstr *MI = MRI.getVRegDef(Reg);
+ if (!MI)
+ return nullptr;
+ // MI is folded into the SELECT by predicating it.
+ if (!MI->isPredicable())
+ return nullptr;
+ // Check if MI has any non-dead defs or physreg uses. This also detects
+ // predicated instructions which will be reading SR.
+ for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ // Reject frame index operands.
+ if (MO.isFI() || MO.isCPI() || MO.isJTI())
+ return nullptr;
+ if (!MO.isReg())
+ continue;
+ // MI can't have any tied operands, that would conflict with predication.
+ if (MO.isTied())
+ return nullptr;
+ if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
+ return nullptr;
+ if (MO.isDef() && !MO.isDead())
+ return nullptr;
+ }
+ bool DontMoveAcrossStores = true;
+ if (!MI->isSafeToMove(/*AliasAnalysis=*/nullptr, DontMoveAcrossStores))
+ return nullptr;
+ return MI;
+}
+
+MachineInstr *
+LanaiInstrInfo::optimizeSelect(MachineInstr &MI,
+ SmallPtrSetImpl<MachineInstr *> &SeenMIs,
+ bool PreferFalse) const {
+ assert(MI.getOpcode() == Lanai::SELECT && "unknown select instruction");
+ MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+ MachineInstr *DefMI = canFoldIntoSelect(MI.getOperand(1).getReg(), MRI, this);
+ bool Invert = !DefMI;
+ if (!DefMI)
+ DefMI = canFoldIntoSelect(MI.getOperand(2).getReg(), MRI, this);
+ if (!DefMI)
+ return nullptr;
+
+ // Find new register class to use.
+ MachineOperand FalseReg = MI.getOperand(Invert ? 1 : 2);
+ unsigned DestReg = MI.getOperand(0).getReg();
+ const TargetRegisterClass *PreviousClass = MRI.getRegClass(FalseReg.getReg());
+ if (!MRI.constrainRegClass(DestReg, PreviousClass))
+ return nullptr;
+
+ // Create a new predicated version of DefMI.
+ MachineInstrBuilder NewMI =
+ BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), DefMI->getDesc(), DestReg);
+
+ // Copy all the DefMI operands, excluding its (null) predicate.
+ const MCInstrDesc &DefDesc = DefMI->getDesc();
+ for (unsigned i = 1, e = DefDesc.getNumOperands();
+ i != e && !DefDesc.OpInfo[i].isPredicate(); ++i)
+ NewMI.addOperand(DefMI->getOperand(i));
+
+ unsigned CondCode = MI.getOperand(3).getImm();
+ if (Invert)
+ NewMI.addImm(getOppositeCondition(LPCC::CondCode(CondCode)));
+ else
+ NewMI.addImm(CondCode);
+ NewMI.copyImplicitOps(MI);
+
+ // The output register value when the predicate is false is an implicit
+ // register operand tied to the first def. The tie makes the register
+ // allocator ensure the FalseReg is allocated the same register as operand 0.
+ FalseReg.setImplicit();
+ NewMI.addOperand(FalseReg);
+ NewMI->tieOperands(0, NewMI->getNumOperands() - 1);
+
+ // Update SeenMIs set: register newly created MI and erase removed DefMI.
+ SeenMIs.insert(NewMI);
+ SeenMIs.erase(DefMI);
+
+ // If MI is inside a loop, and DefMI is outside the loop, then kill flags on
+ // DefMI would be invalid when transferred inside the loop. Checking for a
+ // loop is expensive, but at least remove kill flags if they are in different
+ // BBs.
+ if (DefMI->getParent() != MI.getParent())
+ NewMI->clearKillInfo();
+
+ // The caller will erase MI, but not DefMI.
+ DefMI->eraseFromParent();
+ return NewMI;
+}
+
// The AnalyzeBranch function is used to examine conditional instructions and
// remove unnecessary instructions. This method is used by BranchFolder and
// IfConverter machine function passes to improve the CFG.
@@ -262,7 +653,7 @@ bool LanaiInstrInfo::ReverseBranchCondition(
LPCC::CondCode BranchCond =
static_cast<LPCC::CondCode>(Condition[0].getImm());
- Condition[0].setImm(GetOppositeBranchCondition(BranchCond));
+ Condition[0].setImm(getOppositeCondition(BranchCond));
return false;
}
diff --git a/llvm/lib/Target/Lanai/LanaiInstrInfo.h b/llvm/lib/Target/Lanai/LanaiInstrInfo.h
index ff2a51a26df..2d12d3d2228 100644
--- a/llvm/lib/Target/Lanai/LanaiInstrInfo.h
+++ b/llvm/lib/Target/Lanai/LanaiInstrInfo.h
@@ -75,6 +75,12 @@ public:
int64_t &Offset, unsigned &Width,
const TargetRegisterInfo *TRI) const;
+ std::pair<unsigned, unsigned>
+ decomposeMachineOperandsTargetFlags(unsigned TF) const override;
+
+ ArrayRef<std::pair<unsigned, const char *>>
+ getSerializableDirectMachineOperandTargetFlags() const override;
+
bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TrueBlock,
MachineBasicBlock *&FalseBlock,
SmallVectorImpl<MachineOperand> &Condition,
@@ -82,6 +88,47 @@ public:
unsigned RemoveBranch(MachineBasicBlock &MBB) const override;
+ // For a comparison instruction, return the source registers in SrcReg and
+ // SrcReg2 if having two register operands, and the value it compares against
+ // in CmpValue. Return true if the comparison instruction can be analyzed.
+ bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
+ unsigned &SrcReg2, int &CmpMask,
+ int &CmpValue) const override;
+
+ // See if the comparison instruction can be converted into something more
+ // efficient. E.g., on Lanai register-register instructions can set the flag
+ // register, obviating the need for a separate compare.
+ bool optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
+ unsigned SrcReg2, int CmpMask, int CmpValue,
+ const MachineRegisterInfo *MRI) const override;
+
+ // Analyze the given select instruction, returning true if it cannot be
+ // understood. It is assumed that MI->isSelect() is true.
+ //
+ // When successful, return the controlling condition and the operands that
+ // determine the true and false result values.
+ //
+ // Result = SELECT Cond, TrueOp, FalseOp
+ //
+ // Lanai can optimize certain select instructions, for example by predicating
+ // the instruction defining one of the operands and sets Optimizable to true.
+ bool analyzeSelect(const MachineInstr &MI,
+ SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp,
+ unsigned &FalseOp, bool &Optimizable) const override;
+
+ // Given a select instruction that was understood by analyzeSelect and
+ // returned Optimizable = true, attempt to optimize MI by merging it with one
+ // of its operands. Returns NULL on failure.
+ //
+ // When successful, returns the new select instruction. The client is
+ // responsible for deleting MI.
+ //
+ // If both sides of the select can be optimized, the TrueOp is modifed.
+ // PreferFalse is not used.
+ MachineInstr *optimizeSelect(MachineInstr &MI,
+ SmallPtrSetImpl<MachineInstr *> &SeenMIs,
+ bool PreferFalse) const override;
+
bool ReverseBranchCondition(
SmallVectorImpl<MachineOperand> &Condition) const override;
diff --git a/llvm/lib/Target/Lanai/LanaiInstrInfo.td b/llvm/lib/Target/Lanai/LanaiInstrInfo.td
index 20dd4ee58fa..05f4f75b9c7 100644
--- a/llvm/lib/Target/Lanai/LanaiInstrInfo.td
+++ b/llvm/lib/Target/Lanai/LanaiInstrInfo.td
@@ -235,6 +235,15 @@ def CCOp : Operand<i32> {
let PrintMethod = "printCCOperand";
}
+// Predicate operand. Default to 0 = true.
+def CondCodeOperand : AsmOperandClass { let Name = "CondCode"; }
+
+def pred : PredicateOperand<i32, (ops i32imm), (ops (i32 0))> {
+ let PrintMethod = "printPredicateOperand";
+ let ParserMatchClass = CondCodeOperand;
+ let DecoderMethod = "decodePredicateOperand";
+}
+
let hasSideEffects = 0, Inst = 0x00000001 in
def NOP : InstLanai<(outs), (ins), "nop", []>;
@@ -283,16 +292,10 @@ multiclass ALUarith<bits<3> subOp, string AsmStr, SDNode OpNode,
defm I_ : ALUbase<subOp, AsmStr, OpNode, LoExt, HiExt, [], []>;
// Register Register
- let JJJJJ = 0, DDDI = 0 in
- def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2),
- !strconcat(AsmStr, "\t$Rs1, $Rs2, $Rd"),
+ let JJJJJ = 0 in
+ def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2, pred:$DDDI),
+ !strconcat(AsmStr, "$DDDI\t$Rs1, $Rs2, $Rd"),
[(set GPR:$Rd, (OpNode GPR:$Rs1, GPR:$Rs2))]>;
- // RR Conditional
- let JJJJJ = 0, Uses = [SR] in
- def R_CC : InstRR<subOp, (outs GPR:$Rd),
- (ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI),
- !strconcat(AsmStr, ".$DDDI\t$Rs1, $Rs2, $Rd"),
- []>;
}
multiclass ALUlogic<bits<3> subOp, string AsmStr, SDNode OpNode,
@@ -302,16 +305,10 @@ multiclass ALUlogic<bits<3> subOp, string AsmStr, SDNode OpNode,
[(set GPR:$Rd, (OpNode GPR:$Rs1, HiExt:$imm16))]>;
// Register Register
- let JJJJJ = 0, DDDI = 0 in
- def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2),
- !strconcat(AsmStr, "\t$Rs1, $Rs2, $Rd"),
+ let JJJJJ = 0 in
+ def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2, pred:$DDDI),
+ !strconcat(AsmStr, "$DDDI\t$Rs1, $Rs2, $Rd"),
[(set GPR:$Rd, (OpNode GPR:$Rs1, GPR:$Rs2))]>;
- // RR Conditional
- let JJJJJ = 0, Uses = [SR] in
- def R_CC : InstRR<subOp, (outs GPR:$Rd),
- (ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI),
- !strconcat(AsmStr, ".$DDDI\t$Rs1, $Rs2, $Rd"),
- []>;
}
// Non flag setting ALU operations
@@ -407,7 +404,7 @@ def : Pat<(LanaiSubbF GPR:$Rs1, i32lo16z:$imm),
def : Pat<(LanaiSubbF GPR:$Rs1, i32hi16:$imm),
(SUBB_F_I_HI GPR:$Rs1, i32hi16:$imm)>;
-def : InstAlias<"mov $src, $dst", (ADD_R GPR:$dst, GPR:$src, R0)>;
+def : InstAlias<"mov $src, $dst", (ADD_R GPR:$dst, GPR:$src, R0, 0)>;
let isAsCheapAsAMove = 1, Rs1 = R0.Num, isCodeGenOnly = 1, H = 1, F = 0,
isReMaterializable = 1 in
@@ -716,11 +713,15 @@ multiclass SF<bits<3> op2Val, string AsmStr> {
!strconcat(AsmStr, "\t$Rs1, $Rs2, %r0"),
[(LanaiSetFlag (i32 GPR:$Rs1), (i32 GPR:$Rs2))]>;
let F = 1, Rd = R0.Num, H = 0, Defs = [SR] in
- def _RI : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32lo16z:$imm16),
+ def _RI_LO : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32lo16z:$imm16),
!strconcat(AsmStr, "\t$Rs1, $imm16, %r0"),
[(LanaiSetFlag (i32 GPR:$Rs1), i32lo16z:$imm16)]>;
+ let F = 1, Rd = R0.Num, H = 1, Defs = [SR] in
+ def _RI_HI : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32hi16:$imm16),
+ !strconcat(AsmStr, "\t$Rs1, $imm16, %r0"),
+ [(LanaiSetFlag (i32 GPR:$Rs1), i32hi16:$imm16)]>;
}
-let isCodeGenOnly = 1 in {
+let isCodeGenOnly = 1, isCompare = 1 in {
defm SFSUB_F : SF<0b010, "sub.f">;
}
diff --git a/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp b/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp
index 5d99f12d7a0..7bfe992d1d5 100644
--- a/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp
+++ b/llvm/lib/Target/Lanai/LanaiRegisterInfo.cpp
@@ -197,11 +197,16 @@ void LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
}
// Reg = FrameReg OP Reg
if (MI.getOpcode() == Lanai::ADD_I_LO) {
- if (HasNegOffset)
- MI.setDesc(TII->get(Lanai::SUB_R));
- else
- MI.setDesc(TII->get(Lanai::ADD_R));
- } else if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) {
+ BuildMI(*MI.getParent(), II, DL,
+ HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R),
+ MI.getOperand(0).getReg())
+ .addReg(FrameReg)
+ .addReg(Reg)
+ .addImm(LPCC::ICC_T);
+ MI.eraseFromParent();
+ return;
+ }
+ if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) {
MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode())));
if (HasNegOffset) {
// Change the ALU op (operand 3) from LPAC::ADD (the default) to
diff --git a/llvm/lib/Target/Lanai/LanaiSetflagAluCombiner.cpp b/llvm/lib/Target/Lanai/LanaiSetflagAluCombiner.cpp
deleted file mode 100644
index cd728778a65..00000000000
--- a/llvm/lib/Target/Lanai/LanaiSetflagAluCombiner.cpp
+++ /dev/null
@@ -1,294 +0,0 @@
-//===-- LanaiSetflagAluCombiner.cpp - Pass to combine set flag & ALU ops --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Lanai.h"
-#include "LanaiTargetMachine.h"
-#include "llvm/ADT/SmallSet.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/RegisterScavenging.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Target/TargetInstrInfo.h"
-
-using namespace llvm;
-
-#define DEBUG_TYPE "lanai-setflag-alu-combiner"
-
-STATISTIC(NumSetflagAluCombined,
- "Number of SET_FLAG and ALU instructions combined");
-
-static llvm::cl::opt<bool> DisableSetflagAluCombiner(
- "disable-lanai-setflag-alu-combiner", llvm::cl::init(false),
- llvm::cl::desc("Do not combine SET_FLAG and ALU operators"),
- llvm::cl::Hidden);
-
-namespace llvm {
-void initializeLanaiSetflagAluCombinerPass(PassRegistry &);
-} // namespace llvm
-
-namespace {
-typedef MachineBasicBlock::iterator MbbIterator;
-typedef MachineFunction::iterator MfIterator;
-
-class LanaiSetflagAluCombiner : public MachineFunctionPass {
-public:
- static char ID;
- LanaiSetflagAluCombiner() : MachineFunctionPass(ID) {
- initializeLanaiSetflagAluCombinerPass(*PassRegistry::getPassRegistry());
- }
-
- const char *getPassName() const override {
- return "Lanai SET_FLAG ALU combiner pass";
- }
-
- bool runOnMachineFunction(MachineFunction &F) override;
-
- MachineFunctionProperties getRequiredProperties() const override {
- return MachineFunctionProperties().set(
- MachineFunctionProperties::Property::AllVRegsAllocated);
- }
-
-private:
- bool CombineSetflagAluInBasicBlock(MachineFunction *MF,
- MachineBasicBlock *BB);
-};
-} // namespace
-
-char LanaiSetflagAluCombiner::ID = 0;
-
-INITIALIZE_PASS(LanaiSetflagAluCombiner, DEBUG_TYPE,
- "Lanai SET_FLAG ALU combiner pass", false, false)
-
-namespace {
-
-const unsigned kInvalid = -1;
-
-static unsigned flagSettingOpcodeVariant(unsigned OldOpcode) {
- switch (OldOpcode) {
- case Lanai::ADD_I_HI:
- return Lanai::ADD_F_I_HI;
- case Lanai::ADD_I_LO:
- return Lanai::ADD_F_I_LO;
- case Lanai::ADD_R:
- return Lanai::ADD_F_R;
- case Lanai::ADD_R_CC:
- return Lanai::ADD_F_R_CC;
- case Lanai::ADDC_I_HI:
- return Lanai::ADDC_F_I_HI;
- case Lanai::ADDC_I_LO:
- return Lanai::ADDC_F_I_LO;
- case Lanai::ADDC_R:
- return Lanai::ADDC_F_R;
- case Lanai::ADDC_R_CC:
- return Lanai::ADDC_F_R_CC;
- case Lanai::AND_I_HI:
- return Lanai::AND_F_I_HI;
- case Lanai::AND_I_LO:
- return Lanai::AND_F_I_LO;
- case Lanai::AND_R:
- return Lanai::AND_F_R;
- case Lanai::AND_R_CC:
- return Lanai::AND_F_R_CC;
- case Lanai::OR_I_HI:
- return Lanai::OR_F_I_HI;
- case Lanai::OR_I_LO:
- return Lanai::OR_F_I_LO;
- case Lanai::OR_R:
- return Lanai::OR_F_R;
- case Lanai::OR_R_CC:
- return Lanai::OR_F_R_CC;
- case Lanai::SL_I:
- return Lanai::SL_F_I;
- case Lanai::SRL_R:
- return Lanai::SRL_F_R;
- case Lanai::SA_I:
- return Lanai::SA_F_I;
- case Lanai::SRA_R:
- return Lanai::SRA_F_R;
- case Lanai::SUB_I_HI:
- return Lanai::SUB_F_I_HI;
- case Lanai::SUB_I_LO:
- return Lanai::SUB_F_I_LO;
- case Lanai::SUB_R:
- return Lanai::SUB_F_R;
- case Lanai::SUB_R_CC:
- return Lanai::SUB_F_R_CC;
- case Lanai::SUBB_I_HI:
- return Lanai::SUBB_F_I_HI;
- case Lanai::SUBB_I_LO:
- return Lanai::SUBB_F_I_LO;
- case Lanai::SUBB_R:
- return Lanai::SUBB_F_R;
- case Lanai::SUBB_R_CC:
- return Lanai::SUBB_F_R_CC;
- case Lanai::XOR_I_HI:
- return Lanai::XOR_F_I_HI;
- case Lanai::XOR_I_LO:
- return Lanai::XOR_F_I_LO;
- case Lanai::XOR_R:
- return Lanai::XOR_F_R;
- case Lanai::XOR_R_CC:
- return Lanai::XOR_F_R_CC;
- default:
- return kInvalid;
- }
-}
-
-// Returns whether opcode corresponds to instruction that sets flags.
-static bool isFlagSettingInstruction(MbbIterator Instruction) {
- return Instruction->killsRegister(Lanai::SR);
-}
-
-// Return the Conditional Code operand for a given instruction kind. For
-// example, operand at index 1 of a BRIND_CC instruction is the conditional code
-// (eq, ne, etc.). Returns -1 if the instruction does not have a conditional
-// code.
-static int getCCOperandPosition(unsigned Opcode) {
- switch (Opcode) {
- case Lanai::BRIND_CC:
- case Lanai::BRIND_CCA:
- case Lanai::BRR:
- case Lanai::BRCC:
- case Lanai::SCC:
- return 1;
- case Lanai::SELECT:
- case Lanai::ADDC_F_R_CC:
- case Lanai::ADDC_R_CC:
- case Lanai::ADD_F_R_CC:
- case Lanai::ADD_R_CC:
- case Lanai::AND_F_R_CC:
- case Lanai::AND_R_CC:
- case Lanai::OR_F_R_CC:
- case Lanai::OR_R_CC:
- case Lanai::SUBB_F_R_CC:
- case Lanai::SUBB_R_CC:
- case Lanai::SUB_F_R_CC:
- case Lanai::SUB_R_CC:
- case Lanai::XOR_F_R_CC:
- case Lanai::XOR_R_CC:
- return 3;
- default:
- return -1;
- }
-}
-
-// Returns true if instruction is a lowered SET_FLAG instruction with 0/R0 as
-// the first operand and whose conditional code is such that it can be merged
-// (i.e., EQ, NE, PL and MI).
-static bool isSuitableSetflag(MbbIterator Instruction, MbbIterator End) {
- unsigned Opcode = Instruction->getOpcode();
- if (Opcode == Lanai::SFSUB_F_RI || Opcode == Lanai::SFSUB_F_RR) {
- const MachineOperand &Operand = Instruction->getOperand(1);
- if (Operand.isReg() && Operand.getReg() != Lanai::R0)
- return false;
- if (Operand.isImm() && Operand.getImm() != 0)
- return false;
-
- MbbIterator SCCUserIter = Instruction;
- while (SCCUserIter != End) {
- ++SCCUserIter;
- if (SCCUserIter == End)
- break;
- // Skip debug instructions. Debug instructions don't affect codegen.
- if (SCCUserIter->isDebugValue())
- continue;
- // Early exit when encountering flag setting or return instruction.
- if (isFlagSettingInstruction(SCCUserIter))
- // Only return true if flags are set post the flag setting instruction
- // tested or a return is executed.
- return true;
- int CCIndex = getCCOperandPosition(SCCUserIter->getOpcode());
- if (CCIndex != -1) {
- LPCC::CondCode CC = static_cast<LPCC::CondCode>(
- SCCUserIter->getOperand(CCIndex).getImm());
- // Return false if the flag is used outside of a EQ, NE, PL and MI.
- if (CC != LPCC::ICC_EQ && CC != LPCC::ICC_NE && CC != LPCC::ICC_PL &&
- CC != LPCC::ICC_MI)
- return false;
- }
- }
- }
-
- return false;
-}
-
-// Combines a SET_FLAG instruction comparing a register with 0 and an ALU
-// operation that sets the same register used in the comparison into a single
-// flag setting ALU instruction (both instructions combined are removed and new
-// flag setting ALU operation inserted where ALU instruction was).
-bool LanaiSetflagAluCombiner::CombineSetflagAluInBasicBlock(
- MachineFunction *MF, MachineBasicBlock *BB) {
- bool Modified = false;
- const TargetInstrInfo *TII =
- MF->getSubtarget<LanaiSubtarget>().getInstrInfo();
-
- MbbIterator SetflagIter = BB->begin();
- MbbIterator End = BB->end();
- MbbIterator Begin = BB->begin();
- while (SetflagIter != End) {
- bool Replaced = false;
- if (isSuitableSetflag(SetflagIter, End)) {
- MbbIterator AluIter = SetflagIter;
- while (AluIter != Begin) {
- --AluIter;
- // Skip debug instructions. Debug instructions don't affect codegen.
- if (AluIter->isDebugValue())
- continue;
- // Early exit when encountering flag setting instruction.
- if (isFlagSettingInstruction(AluIter))
- break;
- // Check that output of AluIter is equal to input of SetflagIter.
- if (AluIter->getNumOperands() > 1 && AluIter->getOperand(0).isReg() &&
- (AluIter->getOperand(0).getReg() ==
- SetflagIter->getOperand(0).getReg())) {
- unsigned NewOpc = flagSettingOpcodeVariant(AluIter->getOpcode());
- if (NewOpc == kInvalid)
- break;
-
- // Change the ALU instruction to the flag setting variant.
- AluIter->setDesc(TII->get(NewOpc));
- AluIter->addImplicitDefUseOperands(*MF);
-
- Replaced = true;
- ++NumSetflagAluCombined;
- break;
- }
- }
- // Erase the setflag instruction if merged.
- if (Replaced)
- BB->erase(SetflagIter++);
- }
-
- Modified |= Replaced;
- if (!Replaced)
- ++SetflagIter;
- }
-
- return Modified;
-}
-
-// Driver function that iterates over the machine basic building blocks of a
-// machine function
-bool LanaiSetflagAluCombiner::runOnMachineFunction(MachineFunction &MF) {
- if (DisableSetflagAluCombiner)
- return false;
-
- bool Modified = false;
- MfIterator End = MF.end();
- for (MfIterator MFI = MF.begin(); MFI != End; ++MFI) {
- Modified |= CombineSetflagAluInBasicBlock(&MF, &*MFI);
- }
- return Modified;
-}
-} // namespace
-
-FunctionPass *llvm::createLanaiSetflagAluCombinerPass() {
- return new LanaiSetflagAluCombiner();
-}
diff --git a/llvm/lib/Target/Lanai/LanaiTargetMachine.cpp b/llvm/lib/Target/Lanai/LanaiTargetMachine.cpp
index b43e9702f2b..2d1846c9874 100644
--- a/llvm/lib/Target/Lanai/LanaiTargetMachine.cpp
+++ b/llvm/lib/Target/Lanai/LanaiTargetMachine.cpp
@@ -28,7 +28,6 @@ using namespace llvm;
namespace llvm {
void initializeLanaiMemAluCombinerPass(PassRegistry &);
-void initializeLanaiSetflagAluCombinerPass(PassRegistry &);
} // namespace llvm
extern "C" void LLVMInitializeLanaiTarget() {
@@ -112,5 +111,4 @@ void LanaiPassConfig::addPreEmitPass() {
// scheduling pass.
void LanaiPassConfig::addPreSched2() {
addPass(createLanaiMemAluCombinerPass());
- addPass(createLanaiSetflagAluCombinerPass());
}
diff --git a/llvm/lib/Target/Lanai/MCTargetDesc/LanaiBaseInfo.h b/llvm/lib/Target/Lanai/MCTargetDesc/LanaiBaseInfo.h
index 42bda1e894f..ce7f83509c9 100644
--- a/llvm/lib/Target/Lanai/MCTargetDesc/LanaiBaseInfo.h
+++ b/llvm/lib/Target/Lanai/MCTargetDesc/LanaiBaseInfo.h
@@ -24,7 +24,6 @@ namespace llvm {
// LanaiII - This namespace holds all of the target specific flags that
// instruction info tracks.
-//
namespace LanaiII {
// Target Operand Flag enum.
enum TOF {
@@ -36,31 +35,6 @@ enum TOF {
// address.
MO_ABS_HI,
MO_ABS_LO,
-
- // MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the
- // immediate should get the value of the symbol minus the PIC base label:
- // SYMBOL_LABEL - PICBASELABEL
- MO_PIC_BASE_OFFSET,
-
- // MO_GOT - On a symbol operand this indicates that the immediate is the
- // offset to the GOT entry for the symbol name from the base of the GOT.
- MO_GOT,
-
- // MO_GOTOFFHI/MO_GOTOFFLO - On a symbol operand this indicates that the
- // immediate is the offset to the location of the symbol name from the
- // base of the GOT.
- MO_GOTOFFHI,
- MO_GOTOFFLO,
-
- // MO_GOTPCHI/MO_GOTPCLO - On a symbol operand this indicates that
- // the immediate is an offset to the GOT entry for the symbol name
- // from the current code location.
- MO_GOTPCHI,
- MO_GOTPCLO,
-
- // MO_PLT - On a symbol operand this indicates that the immediate is
- // offset to the PLT entry of symbol name from the current code location.
- MO_PLT
};
} // namespace LanaiII
OpenPOWER on IntegriCloud