// operand no. of the operand to be converted in 'MemOp'. Remember, PIC16 has
// no instruction that can operation on two registers. Most insns take
// one register and one memory operand (addwf) / Constant (addlw).
-bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp) {
+bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp,
+ SelectionDAG &DAG) {
// If one of the operand is a constant, return false.
if (Op.getOperand(0).getOpcode() == ISD::Constant ||
Op.getOperand(1).getOpcode() == ISD::Constant)
// Return false if one of the operands is already a direct
// load and that operand has only one use.
if (isDirectLoad(Op.getOperand(0))) {
- if (Op.getOperand(0).hasOneUse())
- return false;
- else
- MemOp = 0;
+ if (Op.getOperand(0).hasOneUse()) {
+ // Legal and profitable folding check uses the NodeId of DAG nodes.
+ // This NodeId is assigned by topological order. Therefore first
+ // assign topological order then perform legal and profitable check.
+ // Note:- Though this ordering is done before begining with legalization,
+ // newly added node during legalization process have NodeId=-1 (NewNode)
+ // therefore before performing any check proper ordering of the node is
+ // required.
+ DAG.AssignTopologicalOrder();
+
+ // Direct load operands are folded in binary operations. But before folding
+ // verify if this folding is legal. Fold only if it is legal otherwise
+ // convert this direct load to a separate memory operation.
+ if(ISel->IsLegalAndProfitableToFold(Op.getOperand(0).getNode(),
+ Op.getNode(), Op.getNode()))
+ return false;
+ else
+ MemOp = 0;
+ }
}
+
+ // For operations that are non-cummutative there is no need to check
+ // for right operand because folding right operand may result in
+ // incorrect operation.
+ if (! SelectionDAG::isCommutativeBinOp(Op.getOpcode()))
+ return true;
+
if (isDirectLoad(Op.getOperand(1))) {
if (Op.getOperand(1).hasOneUse())
return false;
assert (Op.getValueType() == MVT::i8 && "illegal Op to lower");
unsigned MemOp = 1;
- if (NeedToConvertToMemOp(Op, MemOp)) {
+ if (NeedToConvertToMemOp(Op, MemOp, DAG)) {
// Put one value on stack.
SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl);
assert (Op.getValueType() == MVT::i8 && "illegal add to lower");
DebugLoc dl = Op.getDebugLoc();
unsigned MemOp = 1;
- if (NeedToConvertToMemOp(Op, MemOp)) {
+ if (NeedToConvertToMemOp(Op, MemOp, DAG)) {
// Put one value on stack.
SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl);
DAG.getConstant(0-(C->getZExtValue()), MVT::i8));
}
- if (NeedToConvertToMemOp(Op, MemOp) ||
+ if (NeedToConvertToMemOp(Op, MemOp, DAG) ||
(isDirectLoad(Op.getOperand(1)) &&
(!isDirectLoad(Op.getOperand(0))) &&
(Op.getOperand(0).getOpcode() != ISD::Constant)))
#include "PIC16.h"
#include "PIC16Subtarget.h"
#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include <map>
// This function checks if we need to put an operand of an operation on
// stack and generate a load or not.
- bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp);
+ // DAG parameter is required to access DAG information during
+ // analysis.
+ bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp, SelectionDAG &DAG);
/// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
/// make the right decision when generating code for different targets.
// Check if operation has a direct load operand.
inline bool isDirectLoad(const SDValue Op);
+ public:
+ // Keep a pointer to SelectionDAGISel to access its public
+ // interface (It is required during legalization)
+ SelectionDAGISel *ISel;
+
private:
// The frameindexes generated for spill/reload are stack based.
// This maps maintain zero based indexes for these FIs.
--- /dev/null
+;RUN: llvm-as < %s | llc -march=pic16
+
+@aa = global i16 55, align 1 ; <i16*> [#uses=1]
+@bb = global i16 44, align 1 ; <i16*> [#uses=1]
+@PORTD = external global i8 ; <i8*> [#uses=1]
+
+define void @foo() nounwind {
+entry:
+ %tmp = volatile load i16* @aa ; <i16> [#uses=1]
+ %tmp1 = volatile load i16* @bb ; <i16> [#uses=1]
+ %sub = sub i16 %tmp, %tmp1 ; <i16> [#uses=1]
+ %conv = trunc i16 %sub to i8 ; <i8> [#uses=1]
+ store i8 %conv, i8* @PORTD
+ ret void
+}