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
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
@@ -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) {
24 changes: 24 additions & 0 deletions llvm/lib/CodeGen/LivePhysRegs.cpp
Original file line number Diff line number Diff line change
@@ -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
@@ -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"
@@ -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.
@@ -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);

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

@@ -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);
@@ -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;
@@ -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();
@@ -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;
@@ -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));
@@ -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
@@ -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();
9 changes: 8 additions & 1 deletion llvm/lib/Target/PowerPC/PPCISelLowering.h
Original file line number Diff line number Diff line change
@@ -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,

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