Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/LivePhysRegs.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ void addLiveIns(MachineBasicBlock &MBB, const LivePhysRegs &LiveRegs);
void computeAndAddLiveIns(LivePhysRegs &LiveRegs,
MachineBasicBlock &MBB);

/// Check if physical register \p Reg is alive after \p MBI.
bool isPhysRegLiveAfter(Register Reg, MachineBasicBlock::iterator MBI);

/// Convenience function for recomputing live-in's for a MBB. Returns true if
/// any changes were made.
static inline bool recomputeLiveIns(MachineBasicBlock &MBB) {
Expand Down
22 changes: 22 additions & 0 deletions llvm/lib/CodeGen/LivePhysRegs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,25 @@ void llvm::computeAndAddLiveIns(LivePhysRegs &LiveRegs,
computeLiveIns(LiveRegs, MBB);
addLiveIns(MBB, LiveRegs);
}

bool llvm::isPhysRegLiveAfter(Register Reg, MachineBasicBlock::iterator MBI) {
assert(Reg.isPhysical() && "Apply to physical register only");

MachineBasicBlock *MBB = MBI->getParent();
// Scan forward through BB for a use/def of Reg
for (const MachineInstr &MI : llvm::make_range(std::next(MBI), MBB->end())) {
if (MI.readsRegister(Reg, /*TRI=*/nullptr))
return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it return true if a Reg is being read here but then being redefined later in this MBB?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add some comment for the function ,the function name is not precise, I also change the function name to isPhysRegUsedAfter

// If we found a def, we can stop searching.
if (MI.definesRegister(Reg, /*TRI=*/nullptr))
return false;
}

// If we hit the end of the block, check whether Reg is live into a
// successor.
for (MachineBasicBlock *Succ : MBB->successors())
if (Succ->isLiveIn(Reg))
return true;

return false;
}
192 changes: 137 additions & 55 deletions llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
Expand Down Expand Up @@ -197,6 +198,11 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
}

setOperationAction(ISD::UADDO, RegVT, Custom);
setOperationAction(ISD::USUBO, RegVT, Custom);

// PowerPC uses addo_carry,subo_carry to propagate carry.
setOperationAction(ISD::UADDO_CARRY, RegVT, Custom);
setOperationAction(ISD::USUBO_CARRY, RegVT, Custom);

// On P10, the default lowering generates better code using the
// setbc instruction.
Expand Down Expand Up @@ -266,15 +272,6 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setIndexedStoreAction(ISD::PRE_INC, MVT::f64, Legal);
}

// PowerPC uses ADDC/ADDE/SUBC/SUBE to propagate carry.
const MVT ScalarIntVTs[] = { MVT::i32, MVT::i64 };
for (MVT VT : ScalarIntVTs) {
setOperationAction(ISD::ADDC, VT, Legal);
setOperationAction(ISD::ADDE, VT, Legal);
setOperationAction(ISD::SUBC, VT, Legal);
setOperationAction(ISD::SUBE, VT, Legal);
}

if (Subtarget.useCRBits()) {
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);

Expand Down Expand Up @@ -1864,6 +1861,14 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
return "PPCISD::SETBC";
case PPCISD::SETBCR:
return "PPCISD::SETBCR";
case PPCISD::ADDC:
return "PPCISD::ADDC";
case PPCISD::ADDE:
return "PPCISD::ADDE";
case PPCISD::SUBC:
return "PPCISD::SUBC";
case PPCISD::SUBE:
return "PPCISD::SUBE";
}
return nullptr;
}
Expand Down Expand Up @@ -12150,43 +12155,74 @@ SDValue PPCTargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
llvm_unreachable("ERROR:Should return for all cases within swtich.");
}

SDValue PPCTargetLowering::LowerUaddo(SDValue Op, SelectionDAG &DAG) const {
// Default to target independent lowering if there is a logical user of the
// carry-bit.
for (SDNode *U : Op->users()) {
if (U->getOpcode() == ISD::SELECT)
return SDValue();
if (ISD::isBitwiseLogicOp(U->getOpcode())) {
for (unsigned i = 0, ie = U->getNumOperands(); i != ie; ++i) {
if (U->getOperand(i).getOpcode() != ISD::UADDO &&
U->getOperand(i).getOpcode() != ISD::MERGE_VALUES)
return SDValue();
}
}
}
SDValue LHS = Op.getOperand(0);
SDValue RHS = Op.getOperand(1);
SDLoc dl(Op);

// Default to target independent lowering for special cases handled there.
if (isOneConstant(RHS) || isAllOnesConstant(RHS))
return SDValue();
static SDValue ConvertCarryValueToCarryFlag(EVT SumType, SDValue Value,
SelectionDAG &DAG,
const PPCSubtarget &STI) {
SDLoc DL(Value);
if (STI.useCRBits())
Value = DAG.getNode(ISD::SELECT, DL, SumType, Value,
DAG.getConstant(1, DL, SumType),
DAG.getConstant(0, DL, SumType));
else
Value = DAG.getZExtOrTrunc(Value, DL, SumType);
SDValue Sum = DAG.getNode(PPCISD::ADDC, DL, DAG.getVTList(SumType, MVT::i32),
Value, DAG.getAllOnesConstant(DL, SumType));
return Sum.getValue(1);
}

EVT VT = Op.getNode()->getValueType(0);
static SDValue ConvertCarryFlagToCarryValue(EVT SumType, SDValue Flag,
EVT CarryType, SelectionDAG &DAG,
const PPCSubtarget &STI) {
SDLoc DL(Flag);
SDValue Zero = DAG.getConstant(0, DL, SumType);
SDValue Carry = DAG.getNode(
PPCISD::ADDE, DL, DAG.getVTList(SumType, MVT::i32), Zero, Zero, Flag);
if (STI.useCRBits())
return DAG.getSetCC(DL, CarryType, Carry, Zero, ISD::SETNE);
return DAG.getZExtOrTrunc(Carry, DL, CarryType);
}

SDValue ADDC;
SDValue Overflow;
SDVTList VTs = Op.getNode()->getVTList();
SDValue PPCTargetLowering::LowerADDSUBO(SDValue Op, SelectionDAG &DAG) const {

ADDC = DAG.getNode(ISD::ADDC, dl, DAG.getVTList(VT, MVT::Glue), LHS, RHS);
Overflow = DAG.getNode(ISD::ADDE, dl, DAG.getVTList(VT, MVT::Glue),
DAG.getConstant(0, dl, VT), DAG.getConstant(0, dl, VT),
ADDC.getValue(1));
SDValue OverflowTrunc =
DAG.getNode(ISD::TRUNCATE, dl, Op.getNode()->getValueType(1), Overflow);
SDValue Res =
DAG.getNode(ISD::MERGE_VALUES, dl, VTs, ADDC.getValue(0), OverflowTrunc);
return Res;
SDLoc DL(Op);
SDNode *N = Op.getNode();
EVT VT = N->getValueType(0);
EVT CarryType = N->getValueType(1);
unsigned Opc = N->getOpcode();
bool IsAdd = Opc == ISD::UADDO;
Opc = IsAdd ? PPCISD::ADDC : PPCISD::SUBC;
SDValue Sum = DAG.getNode(Opc, DL, DAG.getVTList(VT, MVT::i32),
N->getOperand(0), N->getOperand(1));
SDValue Carry = ConvertCarryFlagToCarryValue(VT, Sum.getValue(1), CarryType,
DAG, Subtarget);
if (!IsAdd)
Carry = DAG.getNode(ISD::XOR, DL, CarryType, Carry,
DAG.getConstant(1UL, DL, CarryType));
return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Sum, Carry);
}

SDValue PPCTargetLowering::LowerADDSUBO_CARRY(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
SDNode *N = Op.getNode();
unsigned Opc = N->getOpcode();
EVT VT = N->getValueType(0);
EVT CarryType = N->getValueType(1);
SDValue CarryOp = N->getOperand(2);
bool IsAdd = Opc == ISD::UADDO_CARRY;
Opc = IsAdd ? PPCISD::ADDE : PPCISD::SUBE;
if (!IsAdd)
CarryOp = DAG.getNode(ISD::XOR, DL, CarryOp.getValueType(), CarryOp,
DAG.getAllOnesConstant(DL, CarryOp.getValueType()));
CarryOp = ConvertCarryValueToCarryFlag(VT, CarryOp, DAG, Subtarget);
SDValue Sum = DAG.getNode(Opc, DL, DAG.getVTList(VT, MVT::i32),
Op.getOperand(0), Op.getOperand(1), CarryOp);
CarryOp = ConvertCarryFlagToCarryValue(VT, Sum.getValue(1), CarryType, DAG,
Subtarget);
if (!IsAdd)
CarryOp = DAG.getNode(ISD::XOR, DL, CarryOp.getValueType(), CarryOp,
DAG.getConstant(1UL, DL, CarryOp.getValueType()));
return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Sum, CarryOp);
}

SDValue PPCTargetLowering::LowerSSUBO(SDValue Op, SelectionDAG &DAG) const {
Expand Down Expand Up @@ -12217,8 +12253,8 @@ SDValue PPCTargetLowering::LowerSSUBO(SDValue Op, SelectionDAG &DAG) const {
///
SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
default: llvm_unreachable("Wasn't expecting to be able to lower this!");
case ISD::UADDO: return LowerUaddo(Op, DAG);
default:
llvm_unreachable("Wasn't expecting to be able to lower this!");
case ISD::FPOW: return lowerPow(Op, DAG);
case ISD::FSIN: return lowerSin(Op, DAG);
case ISD::FCOS: return lowerCos(Op, DAG);
Expand Down Expand Up @@ -12311,6 +12347,12 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
return LowerATOMIC_LOAD_STORE(Op, DAG);
case ISD::IS_FPCLASS:
return LowerIS_FPCLASS(Op, DAG);
case ISD::UADDO:
case ISD::USUBO:
return LowerADDSUBO(Op, DAG);
case ISD::UADDO_CARRY:
case ISD::USUBO_CARRY:
return LowerADDSUBO_CARRY(Op, DAG);
}
}

Expand Down Expand Up @@ -13393,6 +13435,11 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
F->insert(It, copy0MBB);
F->insert(It, sinkMBB);

if (isPhysRegLiveAfter(PPC::CARRY, MI.getIterator())) {
copy0MBB->addLiveIn(PPC::CARRY);
sinkMBB->addLiveIn(PPC::CARRY);
}

// Set the call frame size on entry to the new basic blocks.
// See https://reviews.llvm.org/D156113.
unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
Expand Down Expand Up @@ -16246,6 +16293,21 @@ static bool isStoreConditional(SDValue Intrin, unsigned &StoreWidth) {
return true;
}

static SDValue DAGCombineAddc(SDNode *N,
llvm::PPCTargetLowering::DAGCombinerInfo &DCI) {
if (N->getOpcode() == PPCISD::ADDC && N->hasAnyUseOfValue(1)) {
// (ADDC (ADDE 0, 0, C), -1) -> C
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
if (LHS->getOpcode() == PPCISD::ADDE &&
isNullConstant(LHS->getOperand(0)) &&
isNullConstant(LHS->getOperand(1)) && isAllOnesConstant(RHS)) {
return DCI.CombineTo(N, SDValue(N, 0), LHS->getOperand(2));
}
}
return SDValue();
}

SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
SelectionDAG &DAG = DCI.DAG;
Expand Down Expand Up @@ -17034,6 +17096,8 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
}
case ISD::BUILD_VECTOR:
return DAGCombineBuildVector(N, DCI);
case PPCISD::ADDC:
return DAGCombineAddc(N, DCI);
}

return SDValue();
Expand Down Expand Up @@ -17087,6 +17151,16 @@ void PPCTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
Known.Zero = 0xFFFF0000;
break;
}
case PPCISD::ADDE: {
if (Op.getResNo() == 0) {
// (0|1), _ = ADDE 0, 0, CARRY
SDValue LHS = Op.getOperand(0);
SDValue RHS = Op.getOperand(1);
if (isNullConstant(LHS) && isNullConstant(RHS))
Known.Zero = ~1ULL;
}
break;
}
case ISD::INTRINSIC_WO_CHAIN: {
switch (Op.getConstantOperandVal(0)) {
default: break;
Expand Down Expand Up @@ -18356,7 +18430,8 @@ static SDValue combineADDToADDZE(SDNode *N, SelectionDAG &DAG,
return SDValue();

SDLoc DL(N);
SDVTList VTs = DAG.getVTList(MVT::i64, MVT::Glue);
EVT CarryType = Subtarget.useCRBits() ? MVT::i1 : MVT::i32;
SDVTList VTs = DAG.getVTList(MVT::i64, CarryType);
SDValue Cmp = RHS.getOperand(0);
SDValue Z = Cmp.getOperand(0);
auto *Constant = cast<ConstantSDNode>(Cmp.getOperand(1));
Expand All @@ -18374,11 +18449,14 @@ static SDValue combineADDToADDZE(SDNode *N, SelectionDAG &DAG,
SDValue Add = DAG.getNode(ISD::ADD, DL, MVT::i64, Z,
DAG.getConstant(NegConstant, DL, MVT::i64));
SDValue AddOrZ = NegConstant != 0 ? Add : Z;
SDValue Addc = DAG.getNode(ISD::ADDC, DL, DAG.getVTList(MVT::i64, MVT::Glue),
AddOrZ, DAG.getAllOnesConstant(DL, MVT::i64));
return DAG.getNode(ISD::ADDE, DL, VTs, LHS, DAG.getConstant(0, DL, MVT::i64),
SDValue Addc =
DAG.getNode(ISD::UADDO_CARRY, DL, DAG.getVTList(MVT::i64, CarryType),
AddOrZ, DAG.getAllOnesConstant(DL, MVT::i64),
DAG.getConstant(0, DL, CarryType));
return DAG.getNode(ISD::UADDO_CARRY, DL, VTs, LHS,
DAG.getConstant(0, DL, MVT::i64),
SDValue(Addc.getNode(), 1));
}
}
case ISD::SETEQ: {
// when C == 0
// --> addze X, (subfic Z, 0).carry
Expand All @@ -18389,11 +18467,15 @@ static SDValue combineADDToADDZE(SDNode *N, SelectionDAG &DAG,
SDValue Add = DAG.getNode(ISD::ADD, DL, MVT::i64, Z,
DAG.getConstant(NegConstant, DL, MVT::i64));
SDValue AddOrZ = NegConstant != 0 ? Add : Z;
SDValue Subc = DAG.getNode(ISD::SUBC, DL, DAG.getVTList(MVT::i64, MVT::Glue),
DAG.getConstant(0, DL, MVT::i64), AddOrZ);
return DAG.getNode(ISD::ADDE, DL, VTs, LHS, DAG.getConstant(0, DL, MVT::i64),
SDValue(Subc.getNode(), 1));
}
SDValue Subc =
DAG.getNode(ISD::USUBO_CARRY, DL, DAG.getVTList(MVT::i64, CarryType),
DAG.getConstant(0, DL, MVT::i64), AddOrZ,
DAG.getConstant(0, DL, CarryType));
SDValue Invert = DAG.getNode(ISD::XOR, DL, CarryType, Subc.getValue(1),
DAG.getConstant(1UL, DL, CarryType));
return DAG.getNode(ISD::UADDO_CARRY, DL, VTs, LHS,
DAG.getConstant(0, DL, MVT::i64), Invert);
}
}

return SDValue();
Expand Down
9 changes: 8 additions & 1 deletion llvm/lib/Target/PowerPC/PPCISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ namespace llvm {
SRA,
SHL,

/// These nodes represent PPC arithmetic operations with carry.
ADDC,
ADDE,
SUBC,
SUBE,

/// FNMSUB - Negated multiply-subtract instruction.
FNMSUB,

Expand Down Expand Up @@ -1280,7 +1286,6 @@ namespace llvm {
SDValue LowerGlobalTLSAddressLinux(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerUaddo(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSSUBO(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
Expand Down Expand Up @@ -1316,6 +1321,8 @@ namespace llvm {
SDValue LowerBSWAP(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerATOMIC_CMP_SWAP(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerIS_FPCLASS(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerADDSUBO(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerToLibCall(const char *LibCallName, SDValue Op,
SelectionDAG &DAG) const;
SDValue lowerLibCallBasedOnType(const char *LibCallFloatName,
Expand Down
Loading