Skip to content

Conversation

@jayfoad
Copy link
Contributor

@jayfoad jayfoad commented Jun 2, 2025

In practice this register is indistinguishable from xer, so remove it
and use xer throughout.

In practice this register is indistinguishable from xer, so remove it and use xer throughout.
@llvmbot
Copy link
Member

llvmbot commented Jun 2, 2025

@llvm/pr-subscribers-backend-powerpc

Author: Jay Foad (jayfoad)

Changes

In practice this register is indistinguishable from xer, so remove it
and use xer throughout.


Patch is 39.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/142420.diff

16 Files Affected:

  • (modified) llvm/lib/Target/PowerPC/PPCISelLowering.cpp (+3-3)
  • (modified) llvm/lib/Target/PowerPC/PPCInstr64Bit.td (+10-10)
  • (modified) llvm/lib/Target/PowerPC/PPCInstrInfo.cpp (+4-4)
  • (modified) llvm/lib/Target/PowerPC/PPCInstrInfo.td (+24-24)
  • (modified) llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/PowerPC/PPCRegisterInfo.td (+1-8)
  • (modified) llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll (+29-29)
  • (modified) llvm/test/CodeGen/PowerPC/aix-cc-byval-split.ll (+2-2)
  • (modified) llvm/test/CodeGen/PowerPC/carry-liveness-after-expand-isel.ll (+8-8)
  • (modified) llvm/test/CodeGen/PowerPC/convert-ri-addi-to-ri.mir (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/convert-rr-to-ri-instrs-out-of-range.mir (+8-8)
  • (modified) llvm/test/CodeGen/PowerPC/convert-rr-to-ri-instrs.mir (+20-20)
  • (modified) llvm/test/CodeGen/PowerPC/ctrloop-do-not-duplicate-mi.mir (+1-1)
  • (modified) llvm/test/CodeGen/PowerPC/early-ret-verify.mir (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/ifcvt.mir (+2-2)
  • (modified) llvm/test/CodeGen/PowerPC/opt-sub-inst-cr0-live.mir (+3-3)
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 0c2a506005604..02e0df26b9c13 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -13633,9 +13633,9 @@ 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); + if (isPhysRegUsedAfter(PPC::XER, MI.getIterator())) { + copy0MBB->addLiveIn(PPC::XER); + sinkMBB->addLiveIn(PPC::XER); } // Set the call frame size on entry to the new basic blocks. diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 659c1a9079c33..32c86ad0b5ea1 100644 --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -763,7 +763,7 @@ defm ADDC8 : XOForm_1rc<31, 10, 0, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB), [(set i64:$RT, (PPCaddc i64:$RA, i64:$RB))]>, PPC970_DGroup_Cracked; -let Defs = [CARRY] in +let Defs = [XER] in def ADDIC8 : DForm_2<12, (outs g8rc:$RST), (ins g8rc:$RA, s16imm64:$D), "addic $RST, $RA, $D", IIC_IntGeneral, [(set i64:$RST, (PPCaddc i64:$RA, imm64SExt16:$D))]>; @@ -779,7 +779,7 @@ def LA8 : DForm_2<14, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s16imm64:$D), [(set i64:$RST, (add i64:$RA, (PPClo tglobaladdr:$D, 0)))]>, MemriOp; -let Defs = [CARRY] in { +let Defs = [XER] in { def SUBFIC8: DForm_2< 8, (outs g8rc:$RST), (ins g8rc:$RA, s16imm64:$D), "subfic $RST, $RA, $D", IIC_IntGeneral, [(set i64:$RST, (PPCsubc imm64SExt16:$D, i64:$RA))]>; @@ -794,26 +794,26 @@ defm SUBF8 : XOForm_1rx<31, 40, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB), defm NEG8 : XOForm_3r<31, 104, 0, (outs g8rc:$RT), (ins g8rc:$RA), "neg", "$RT, $RA", IIC_IntSimple, [(set i64:$RT, (ineg i64:$RA))]>; -let Uses = [CARRY] in { +let Uses = [XER] in { let isCommutable = 1 in defm ADDE8 : XOForm_1rc<31, 138, 0, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB), "adde", "$RT, $RA, $RB", IIC_IntGeneral, - [(set i64:$RT, (PPCadde i64:$RA, i64:$RB, CARRY))]>; + [(set i64:$RT, (PPCadde i64:$RA, i64:$RB, XER))]>; defm ADDME8 : XOForm_3rc<31, 234, 0, (outs g8rc:$RT), (ins g8rc:$RA), "addme", "$RT, $RA", IIC_IntGeneral, - [(set i64:$RT, (PPCadde i64:$RA, -1, CARRY))]>; + [(set i64:$RT, (PPCadde i64:$RA, -1, XER))]>; defm ADDZE8 : XOForm_3rc<31, 202, 0, (outs g8rc:$RT), (ins g8rc:$RA), "addze", "$RT, $RA", IIC_IntGeneral, - [(set i64:$RT, (PPCadde i64:$RA, 0, CARRY))]>; + [(set i64:$RT, (PPCadde i64:$RA, 0, XER))]>; defm SUBFE8 : XOForm_1rc<31, 136, 0, (outs g8rc:$RT), (ins g8rc:$RA, g8rc:$RB), "subfe", "$RT, $RA, $RB", IIC_IntGeneral, - [(set i64:$RT, (PPCsube i64:$RB, i64:$RA, CARRY))]>; + [(set i64:$RT, (PPCsube i64:$RB, i64:$RA, XER))]>; defm SUBFME8 : XOForm_3rc<31, 232, 0, (outs g8rc:$RT), (ins g8rc:$RA), "subfme", "$RT, $RA", IIC_IntGeneral, - [(set i64:$RT, (PPCsube -1, i64:$RA, CARRY))]>; + [(set i64:$RT, (PPCsube -1, i64:$RA, XER))]>; defm SUBFZE8 : XOForm_3rc<31, 200, 0, (outs g8rc:$RT), (ins g8rc:$RA), "subfze", "$RT, $RA", IIC_IntGeneral, - [(set i64:$RT, (PPCsube 0, i64:$RA, CARRY))]>; + [(set i64:$RT, (PPCsube 0, i64:$RA, XER))]>; } } // isCodeGenOnly @@ -983,7 +983,7 @@ defm EXTSWSLI : XSForm_1rc<31, 445, (outs g8rc:$RA), (ins g8rc:$RS, u6imm:$SH), []>, isPPC64, Requires<[IsISA3_0]>; // For fast-isel: -let isCodeGenOnly = 1, Defs = [CARRY] in +let isCodeGenOnly = 1, Defs = [XER] in def SRADI_32 : XSForm_1<31, 413, (outs gprc:$RA), (ins gprc:$RS, u6imm:$SH), "sradi $RA, $RS, $SH", IIC_IntRotateDI, []>, isPPC64; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 9d4d2d864fc32..99b6dd03f25c5 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1760,20 +1760,20 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } else if ((PPC::G8RCRegClass.contains(DestReg) || PPC::GPRCRegClass.contains(DestReg)) && - SrcReg == PPC::CARRY) { + SrcReg == PPC::XER) { bool Is64Bit = PPC::G8RCRegClass.contains(DestReg); BuildMI(MBB, I, DL, get(Is64Bit ? PPC::MFSPR8 : PPC::MFSPR), DestReg) .addImm(1) - .addReg(PPC::CARRY, RegState::Implicit); + .addReg(PPC::XER, RegState::Implicit); return; } else if ((PPC::G8RCRegClass.contains(SrcReg) || PPC::GPRCRegClass.contains(SrcReg)) && - DestReg == PPC::CARRY) { + DestReg == PPC::XER) { bool Is64Bit = PPC::G8RCRegClass.contains(SrcReg); BuildMI(MBB, I, DL, get(Is64Bit ? PPC::MTSPR8 : PPC::MTSPR)) .addImm(1) .addReg(SrcReg) - .addReg(PPC::CARRY, RegState::ImplicitDefine); + .addReg(PPC::XER, RegState::ImplicitDefine); return; } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index b70290df07b1c..3a8a9a7c413b8 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -789,11 +789,11 @@ multiclass XForm_6rc<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmbase, string asmstr, InstrItinClass itin, list<dag> pattern> { let BaseName = asmbase in { - let Defs = [CARRY] in + let Defs = [XER] in def NAME : XForm_6<opcode, xo, OOL, IOL, !strconcat(asmbase, !strconcat(" ", asmstr)), itin, pattern>, RecFormRel; - let Defs = [CARRY, CR0] in + let Defs = [XER, CR0] in def _rec : XForm_6<opcode, xo, OOL, IOL, !strconcat(asmbase, !strconcat(". ", asmstr)), itin, []>, isRecordForm, RecFormRel; @@ -804,11 +804,11 @@ multiclass XForm_10rc<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmbase, string asmstr, InstrItinClass itin, list<dag> pattern> { let BaseName = asmbase in { - let Defs = [CARRY] in + let Defs = [XER] in def NAME : XForm_10<opcode, xo, OOL, IOL, !strconcat(asmbase, !strconcat(" ", asmstr)), itin, pattern>, RecFormRel; - let Defs = [CARRY, CR0] in + let Defs = [XER, CR0] in def _rec : XForm_10<opcode, xo, OOL, IOL, !strconcat(asmbase, !strconcat(". ", asmstr)), itin, []>, isRecordForm, RecFormRel; @@ -900,21 +900,21 @@ multiclass XOForm_1rc<bits<6> opcode, bits<9> xo, bit oe, dag OOL, dag IOL, string asmbase, string asmstr, InstrItinClass itin, list<dag> pattern> { let BaseName = asmbase in { - let Defs = [CARRY] in + let Defs = [XER] in def NAME : XOForm_1<opcode, xo, oe, OOL, IOL, !strconcat(asmbase, !strconcat(" ", asmstr)), itin, pattern>, RecFormRel; - let Defs = [CARRY, CR0] in + let Defs = [XER, CR0] in def _rec : XOForm_1<opcode, xo, oe, OOL, IOL, !strconcat(asmbase, !strconcat(". ", asmstr)), itin, []>, isRecordForm, RecFormRel; } let BaseName = !strconcat(asmbase, "O") in { - let Defs = [CARRY, XER] in + let Defs = [XER] in def O : XOForm_1<opcode, xo, 1, OOL, IOL, !strconcat(asmbase, !strconcat("o ", asmstr)), itin, []>, RecFormRel; - let Defs = [CARRY, XER, CR0] in + let Defs = [XER, CR0] in def O_rec : XOForm_1<opcode, xo, 1, OOL, IOL, !strconcat(asmbase, !strconcat("o. ", asmstr)), itin, []>, isRecordForm, RecFormRel; @@ -949,21 +949,21 @@ multiclass XOForm_3rc<bits<6> opcode, bits<9> xo, bit oe, dag OOL, dag IOL, string asmbase, string asmstr, InstrItinClass itin, list<dag> pattern> { let BaseName = asmbase in { - let Defs = [CARRY] in + let Defs = [XER] in def NAME : XOForm_3<opcode, xo, oe, OOL, IOL, !strconcat(asmbase, !strconcat(" ", asmstr)), itin, pattern>, RecFormRel; - let Defs = [CARRY, CR0] in + let Defs = [XER, CR0] in def _rec : XOForm_3<opcode, xo, oe, OOL, IOL, !strconcat(asmbase, !strconcat(". ", asmstr)), itin, []>, isRecordForm, RecFormRel; } let BaseName = !strconcat(asmbase, "O") in { - let Defs = [CARRY, XER] in + let Defs = [XER] in def O : XOForm_3<opcode, xo, 1, OOL, IOL, !strconcat(asmbase, !strconcat("o ", asmstr)), itin, []>, RecFormRel; - let Defs = [CARRY, XER, CR0] in + let Defs = [XER, CR0] in def O_rec : XOForm_3<opcode, xo, 1, OOL, IOL, !strconcat(asmbase, !strconcat("o. ", asmstr)), itin, []>, isRecordForm, RecFormRel; @@ -1030,11 +1030,11 @@ multiclass XSForm_1rc<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, string asmbase, string asmstr, InstrItinClass itin, list<dag> pattern> { let BaseName = asmbase in { - let Defs = [CARRY] in + let Defs = [XER] in def NAME : XSForm_1<opcode, xo, OOL, IOL, !strconcat(asmbase, !strconcat(" ", asmstr)), itin, pattern>, RecFormRel; - let Defs = [CARRY, CR0] in + let Defs = [XER, CR0] in def _rec : XSForm_1<opcode, xo, OOL, IOL, !strconcat(asmbase, !strconcat(". ", asmstr)), itin, []>, isRecordForm, RecFormRel; @@ -2312,12 +2312,12 @@ def ADDI : DForm_2<14, (outs gprc:$RST), (ins gprc_nor0:$RA, s16imm:$D), "addi $RST, $RA, $D", IIC_IntSimple, [(set i32:$RST, (add i32:$RA, imm32SExt16:$D))]>; let BaseName = "addic" in { -let Defs = [CARRY] in +let Defs = [XER] in def ADDIC : DForm_2<12, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D), "addic $RST, $RA, $D", IIC_IntGeneral, [(set i32:$RST, (PPCaddc i32:$RA, imm32SExt16:$D))]>, RecFormRel, PPC970_DGroup_Cracked; -let Defs = [CARRY, CR0] in +let Defs = [XER, CR0] in def ADDIC_rec : DForm_2<13, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D), "addic. $RST, $RA, $D", IIC_IntGeneral, []>, isRecordForm, RecFormRel; @@ -2333,7 +2333,7 @@ def LA : DForm_2<14, (outs gprc:$RST), (ins gprc_nor0:$RA, s16imm:$D), def MULLI : DForm_2< 7, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D), "mulli $RST, $RA, $D", IIC_IntMulLI, [(set i32:$RST, (mul i32:$RA, imm32SExt16:$D))]>; -let Defs = [CARRY] in +let Defs = [XER] in def SUBFIC : DForm_2< 8, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D), "subfic $RST, $RA, $D", IIC_IntGeneral, [(set i32:$RST, (PPCsubc imm32SExt16:$D, i32:$RA))]>; @@ -2971,26 +2971,26 @@ defm SUBFC : XOForm_1rc<31, 8, 0, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), defm NEG : XOForm_3r<31, 104, 0, (outs gprc:$RT), (ins gprc:$RA), "neg", "$RT, $RA", IIC_IntSimple, [(set i32:$RT, (ineg i32:$RA))]>; -let Uses = [CARRY] in { +let Uses = [XER] in { let isCommutable = 1 in defm ADDE : XOForm_1rc<31, 138, 0, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), "adde", "$RT, $RA, $RB", IIC_IntGeneral, - [(set i32:$RT, (PPCadde i32:$RA, i32:$RB, CARRY))]>; + [(set i32:$RT, (PPCadde i32:$RA, i32:$RB, XER))]>; defm ADDME : XOForm_3rc<31, 234, 0, (outs gprc:$RT), (ins gprc:$RA), "addme", "$RT, $RA", IIC_IntGeneral, - [(set i32:$RT, (PPCadde i32:$RA, -1, CARRY))]>; + [(set i32:$RT, (PPCadde i32:$RA, -1, XER))]>; defm ADDZE : XOForm_3rc<31, 202, 0, (outs gprc:$RT), (ins gprc:$RA), "addze", "$RT, $RA", IIC_IntGeneral, - [(set i32:$RT, (PPCadde i32:$RA, 0, CARRY))]>; + [(set i32:$RT, (PPCadde i32:$RA, 0, XER))]>; defm SUBFE : XOForm_1rc<31, 136, 0, (outs gprc:$RT), (ins gprc:$RA, gprc:$RB), "subfe", "$RT, $RA, $RB", IIC_IntGeneral, - [(set i32:$RT, (PPCsube i32:$RB, i32:$RA, CARRY))]>; + [(set i32:$RT, (PPCsube i32:$RB, i32:$RA, XER))]>; defm SUBFME : XOForm_3rc<31, 232, 0, (outs gprc:$RT), (ins gprc:$RA), "subfme", "$RT, $RA", IIC_IntGeneral, - [(set i32:$RT, (PPCsube -1, i32:$RA, CARRY))]>; + [(set i32:$RT, (PPCsube -1, i32:$RA, XER))]>; defm SUBFZE : XOForm_3rc<31, 200, 0, (outs gprc:$RT), (ins gprc:$RA), "subfze", "$RT, $RA", IIC_IntGeneral, - [(set i32:$RT, (PPCsube 0, i32:$RA, CARRY))]>; + [(set i32:$RT, (PPCsube 0, i32:$RA, XER))]>; } } diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp index 51902ad218d1c..1fa62b5e8d534 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -627,7 +627,7 @@ bool PPCRegisterInfo::getRegAllocationHints(Register VirtReg, const TargetRegisterClass * PPCRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { - if (RC == &PPC::CARRYRCRegClass) + if (RC == &PPC::XERRCRegClass) return TM.isPPC64() ? &PPC::G8RCRegClass : &PPC::GPRCRegClass; return RC; } diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td index 359adc31eb10b..1a39336dc7a20 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td @@ -307,13 +307,6 @@ def SPEFSCR: SPR<512, "spefscr">, DwarfRegNum<[612, 112]>; def XER: SPR<1, "xer">, DwarfRegNum<[76]>; -// Carry bit. In the architecture this is really bit 0 of the XER register -// (which really is SPR register 1); this is the only bit interesting to a -// compiler. -def CARRY: SPR<1, "xer">, DwarfRegNum<[76]> { - let Aliases = [XER]; -} - // FP rounding mode: bits 30 and 31 of the FP status and control register // This is not allocated as a normal register; it appears only in // Uses and Defs. The ABI says it needs to be preserved by a function, @@ -492,7 +485,7 @@ def LR8RC : RegisterClass<"PPC", [i64], 64, (add LR8)> { } def VRSAVERC : RegisterClass<"PPC", [i32], 32, (add VRSAVE)>; -def CARRYRC : RegisterClass<"PPC", [i32], 32, (add CARRY, XER)> { +def XERRC : RegisterClass<"PPC", [i32], 32, (add XER)> { let CopyCost = -1; let isAllocatable = 0; } diff --git a/llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll b/llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll index aead5762d0921..a66224ec96b1e 100644 --- a/llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll +++ b/llvm/test/CodeGen/PowerPC/aix-cc-abi-mir.ll @@ -301,12 +301,12 @@ define i64 @test_i64(i64 %a, i64 %b, i64 %c, i64 %d) { ; 32BIT: bb.0.entry: ; 32BIT-NEXT: liveins: $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10 ; 32BIT-NEXT: {{ $}} - ; 32BIT-NEXT: renamable $r4 = ADDC killed renamable $r4, killed renamable $r6, implicit-def $carry - ; 32BIT-NEXT: renamable $r3 = ADDE killed renamable $r3, killed renamable $r5, implicit-def dead $carry, implicit killed $carry - ; 32BIT-NEXT: renamable $r4 = ADDC killed renamable $r4, killed renamable $r8, implicit-def $carry - ; 32BIT-NEXT: renamable $r3 = ADDE killed renamable $r3, killed renamable $r7, implicit-def dead $carry, implicit killed $carry - ; 32BIT-NEXT: renamable $r4 = ADDC killed renamable $r4, killed renamable $r10, implicit-def $carry - ; 32BIT-NEXT: renamable $r3 = ADDE killed renamable $r3, killed renamable $r9, implicit-def dead $carry, implicit killed $carry + ; 32BIT-NEXT: renamable $r4 = ADDC killed renamable $r4, killed renamable $r6, implicit-def $xer + ; 32BIT-NEXT: renamable $r3 = ADDE killed renamable $r3, killed renamable $r5, implicit-def dead $xer, implicit killed $xer + ; 32BIT-NEXT: renamable $r4 = ADDC killed renamable $r4, killed renamable $r8, implicit-def $xer + ; 32BIT-NEXT: renamable $r3 = ADDE killed renamable $r3, killed renamable $r7, implicit-def dead $xer, implicit killed $xer + ; 32BIT-NEXT: renamable $r4 = ADDC killed renamable $r4, killed renamable $r10, implicit-def $xer + ; 32BIT-NEXT: renamable $r3 = ADDE killed renamable $r3, killed renamable $r9, implicit-def dead $xer, implicit killed $xer ; 32BIT-NEXT: BLR implicit $lr, implicit $rm, implicit $r3, implicit $r4 ; ; 64BIT-LABEL: name: test_i64 @@ -678,9 +678,9 @@ define i64 @callee_mixed_ints(i32 %a, i8 signext %b, i32 %c, i16 signext %d, i64 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r4 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r5 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r6 - ; 32BIT-NEXT: renamable $r5 = SRAWI renamable $r3, 31, implicit-def dead $carry - ; 32BIT-NEXT: renamable $r4 = ADDC killed renamable $r3, killed renamable $r8, implicit-def $carry - ; 32BIT-NEXT: renamable $r3 = ADDE killed renamable $r5, killed renamable $r7, implicit-def dead $carry, implicit killed $carry + ; 32BIT-NEXT: renamable $r5 = SRAWI renamable $r3, 31, implicit-def dead $xer + ; 32BIT-NEXT: renamable $r4 = ADDC killed renamable $r3, killed renamable $r8, implicit-def $xer + ; 32BIT-NEXT: renamable $r3 = ADDE killed renamable $r5, killed renamable $r7, implicit-def dead $xer, implicit killed $xer ; 32BIT-NEXT: BLR implicit $lr, implicit $rm, implicit $r3, implicit $r4 ; ; 64BIT-LABEL: name: callee_mixed_ints @@ -1113,30 +1113,30 @@ define i64 @test_ints_stack(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r4 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r5 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r6 - ; 32BIT-NEXT: renamable $r5 = SRAWI renamable $r11, 31, implicit-def dead $carry - ; 32BIT-NEXT: renamable $r4 = SRAWI renamable $r12, 31, implicit-def dead $carry + ; 32BIT-NEXT: renamable $r5 = SRAWI renamable $r11, 31, implicit-def dead $xer + ; 32BIT-NEXT: renamable $r4 = SRAWI renamable $r12, 31, implicit-def dead $xer ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r7 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r8 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r9 ; 32BIT-NEXT: renamable $r3 = nsw ADD4 killed renamable $r3, killed renamable $r10 - ; 32BIT-NEXT: renamable $r6 = SRAWI renamable $r3, 31, implicit-def dead $carry - ; 32BIT-NEXT: renamable $r3 = ADDC killed renamable $r3, killed renamable $r25, implicit-def $carry - ; 32BIT-NEXT: renamable $r6 = ADDE killed renamable $r6, killed renamable $r26, implicit-def dead $carry, implicit $carry - ; 32BIT-NEXT: renamable $r7 = SRAWI renamable $r27, 31, implicit-def dead $carry - ; 32BIT-NEXT: renamable $r3 = ADDC killed renamable $r3, killed renamable $r27, implicit-def $carry - ; 32BIT-NEXT: renamable $r6 ... [truncated] 
@jayfoad
Copy link
Contributor Author

jayfoad commented Jun 2, 2025

This is really an RFC the PPC maintainers, since I don't know much about the PPC architecture myself.

The motivation is to remove a use of Aliases since it would be nice if we could get rid of that in the long term. Also Aliases kind of implies that the two registers carry and xer overlap but are not identical, so several regunits would be generated to represent that. Whereas from the way the backend uses these registers, they seem to be completely identical, so only one regunit would be required.

Copy link
Contributor

@artagnon artagnon left a comment

Choose a reason for hiding this comment

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

If I understand correctly, CARRY is identical to XER, and I'm unclear on the purpose of the Alias: perhaps for readability?

@RolandF77
Copy link
Collaborator

The PPC XER is not equivalent to carry. The XER also contains overflow (OV) and summary overflow (SO) bits. amongst other things. OV is used by addex and some add, subtract, and multiply instructions with the "O" suffix.

@jayfoad
Copy link
Contributor Author

jayfoad commented Jun 2, 2025

The PPC XER is not equivalent to carry. The XER also contains overflow (OV) and summary overflow (SO) bits. amongst other things. OV is used by addex and some add, subtract, and multiply instructions with the "O" suffix.

Yes, I understand that in the architecture, "carry" is just one bit in the "xer" register. But looking at the definition of CARRY in PPCRegisterInfo.td, it is identical to the definition of XER. Nothing about the definition or how it is used in the compiler says that it only represents one bit in the full register. So I think it is OK to replace all uses of CARRY with XER.

@RolandF77
Copy link
Collaborator

Hmm. OK, I see what you mean - the compiler can't currently tell the difference internally because XER and Carry are set to the same value in PPCRegisterInfo.td.

However, in PPCInstrInfo.td care is taken to differentiate between them. Seems like it would be more accurate to make Carry a subregister, but OV references are just represented as XER currently so there might be no practical benefit. Looks like your change is fine, though it feels to me like a step backward.

@jayfoad jayfoad requested a review from chenzheng1030 June 4, 2025 08:41
@jayfoad
Copy link
Contributor Author

jayfoad commented Jun 5, 2025

Looks like your change is fine, though it feels to me like a step backward.

I guess it's a shame to lose the information about which instructions only use/define the carry bit, as opposed to the whole xer register. But given that the compiler wasn't using it for anything, do you trust that that information was correct? And it did have a real (not necessarily measurable!) compile time cost, since it used extra registers and extra regunits.

@chenzheng1030 do you have an opinion here?

@jayfoad
Copy link
Contributor Author

jayfoad commented Jul 21, 2025

Ping - I could commit based on @artagnon's approval but I'd really like to hear from @chenzheng1030 or any other PowerPC maintainer.

@amy-kwan
Copy link
Contributor

I see that @weiguozhi added the alias to XER to carry in e6fb4e1, presumably for inline asm.

However, the patch does not have a test case associated with it, so it would be good to check if we can come up with a test case and see if this change breaks it.

@lei137
Copy link
Contributor

lei137 commented Jul 22, 2025

I think it's worth pointing out that XER was added in e6fb4e1 and CARRY set as an alias to it. Initially we only defined the CARRY as that is the only bit within XER that is interesting to the ppc compiler.

@lei137
Copy link
Contributor

lei137 commented Jul 22, 2025

@jayfoad Do you have a use case that shows this? AFAIK alias means they are exactly the same and it would be interesting to see how aliasing affects the regunits.

The motivation is to remove a use of Aliases since it would be nice if we could get rid of that in the long term. Also Aliases kind of implies that the two registers carry and xer overlap but are not identical, so several regunits would be generated to represent that.

@jayfoad
Copy link
Contributor Author

jayfoad commented Jul 24, 2025

@lei137 without my patch:

$ llvm-tblgen -gen-register-info -register-info-debug -I include -I lib/Target/PowerPC/ -o /dev/null lib/Target/PowerPC/PPC.td 2>&1 | sed -En '/Register (CARRY|XER):/,/^Register/p' Register CARRY:	CostPerUse: 0	CoveredBySubregs: 0	HasDisjunctSubRegs: 0	RegUnit 1	RegUnit 2 Register CTR: Register XER:	CostPerUse: 0	CoveredBySubregs: 0	HasDisjunctSubRegs: 0	RegUnit 2	RegUnit 11 Register ZERO: 

I.e. CARRY has regunits 1 and 2, XER has regunits 2 and 11, as if they partially overlap.

@lei137
Copy link
Contributor

lei137 commented Aug 1, 2025

@lei137 without my patch:

$ llvm-tblgen -gen-register-info -register-info-debug -I include -I lib/Target/PowerPC/ -o /dev/null lib/Target/PowerPC/PPC.td 2>&1 | sed -En '/Register (CARRY|XER):/,/^Register/p' Register CARRY:	CostPerUse: 0	CoveredBySubregs: 0	HasDisjunctSubRegs: 0	RegUnit 1	RegUnit 2 Register CTR: Register XER:	CostPerUse: 0	CoveredBySubregs: 0	HasDisjunctSubRegs: 0	RegUnit 2	RegUnit 11 Register ZERO: 

I.e. CARRY has regunits 1 and 2, XER has regunits 2 and 11, as if they partially overlap.

I am not familiar with the register allocation, so does this mean having this CARRY alias will cause the compiler to generate 1 more regunit then needed? What kind of side effects does that cause?

@bzEq
Copy link
Collaborator

bzEq commented Aug 2, 2025

The motivation is to remove a use of Aliases since it would be nice if we could get rid of that in the long term.

@jayfoad May I know why removing Aliases in the long term? After that we use only SubReg to describe register relationships?

@bzEq
Copy link
Collaborator

bzEq commented Aug 2, 2025

I think it's worth pointing out that XER was added in e6fb4e1 and CARRY set as an alias to it. Initially we only defined the CARRY as that is the only bit within XER that is interesting to the ppc compiler.

If we don't want to remove CARRY, making CARRY a subreg of XER looks viable to me.

@lei137
Copy link
Contributor

lei137 commented Aug 28, 2025

I think it's worth pointing out that XER was added in e6fb4e1 and CARRY set as an alias to it. Initially we only defined the CARRY as that is the only bit within XER that is interesting to the ppc compiler.

If we don't want to remove CARRY, making CARRY a subreg of XER looks viable to me.

That sounds reasonable to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment