Skip to content

[PowerPC] Deprecate uses of ISD::ADDC/ISD::ADDE/ISD::SUBC/ISD::SUBE #133155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all 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 used after \p MBI.
bool isPhysRegUsedAfter(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
24 changes: 24 additions & 0 deletions llvm/lib/CodeGen/LivePhysRegs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,27 @@ void llvm::computeAndAddLiveIns(LivePhysRegs &LiveRegs,
computeLiveIns(LiveRegs, MBB);
addLiveIns(MBB, LiveRegs);
}

// Returns true if `Reg` is used after this iterator in the rest of the
// basic block or any successors of the basic block.
bool llvm::isPhysRegUsedAfter(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 (isPhysRegUsedAfter(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
Loading