From 91afb4b769e769b1c68425567813d3f6f2a3dfb2 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Fri, 16 Jun 2023 13:31:50 +0100 Subject: [PATCH] [GlobalISel][X86] Add handling of scalar G_USUBE opcodes Extend the G_UADDE handling to also support G_USUBE --- llvm/lib/Target/X86/X86InstructionSelector.cpp | 36 ++++++++++++++-------- llvm/lib/Target/X86/X86LegalizerInfo.cpp | 4 +-- .../X86/GlobalISel/legalize-leading-zeros.mir | 2 +- llvm/test/CodeGen/X86/GlobalISel/legalize-sub.mir | 8 ++--- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Target/X86/X86InstructionSelector.cpp b/llvm/lib/Target/X86/X86InstructionSelector.cpp index 0dbd9ca..7116295 100644 --- a/llvm/lib/Target/X86/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/X86InstructionSelector.cpp @@ -92,7 +92,7 @@ private: MachineFunction &MF) const; bool selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; - bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI, + bool selectUAddSubE(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; bool selectDebugInstr(MachineInstr &I, MachineRegisterInfo &MRI) const; bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const; @@ -403,7 +403,8 @@ bool X86InstructionSelector::select(MachineInstr &I) { case TargetOpcode::G_FCMP: return selectFCmp(I, MRI, MF); case TargetOpcode::G_UADDE: - return selectUadde(I, MRI, MF); + case TargetOpcode::G_USUBE: + return selectUAddSubE(I, MRI, MF); case TargetOpcode::G_UNMERGE_VALUES: return selectUnmergeValues(I, MRI, MF); case TargetOpcode::G_MERGE_VALUES: @@ -1069,41 +1070,52 @@ bool X86InstructionSelector::selectFCmp(MachineInstr &I, return true; } -bool X86InstructionSelector::selectUadde(MachineInstr &I, +bool X86InstructionSelector::selectUAddSubE(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const { - assert((I.getOpcode() == TargetOpcode::G_UADDE) && "unexpected instruction"); + assert((I.getOpcode() == TargetOpcode::G_UADDE || + I.getOpcode() == TargetOpcode::G_USUBE) && + "unexpected instruction"); const Register DstReg = I.getOperand(0).getReg(); const Register CarryOutReg = I.getOperand(1).getReg(); const Register Op0Reg = I.getOperand(2).getReg(); const Register Op1Reg = I.getOperand(3).getReg(); Register CarryInReg = I.getOperand(4).getReg(); + bool IsSub = I.getOpcode() == TargetOpcode::G_USUBE; const LLT DstTy = MRI.getType(DstReg); assert(DstTy.isScalar() && "G_UADDE only supported for scalar types"); // TODO: Handle immediate argument variants? - unsigned OpADC, OpADD; + unsigned OpADC, OpADD, OpSBB, OpSUB; switch (DstTy.getSizeInBits()) { case 8: OpADC = X86::ADC8rr; OpADD = X86::ADD8rr; + OpSBB = X86::SBB8rr; + OpSUB = X86::SUB8rr; break; case 16: OpADC = X86::ADC16rr; OpADD = X86::ADD16rr; + OpSBB = X86::SBB16rr; + OpSUB = X86::SUB16rr; break; case 32: OpADC = X86::ADC32rr; OpADD = X86::ADD32rr; + OpSBB = X86::SBB32rr; + OpSUB = X86::SUB32rr; break; case 64: OpADC = X86::ADC64rr; OpADD = X86::ADD64rr; + OpSBB = X86::SBB64rr; + OpSUB = X86::SUB64rr; break; default: - llvm_unreachable("Can't select G_UADDE, unsupported type."); + llvm_unreachable("Can't select G_UADDE/G_USUBE, unsupported type."); } const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI); @@ -1117,8 +1129,8 @@ bool X86InstructionSelector::selectUadde(MachineInstr &I, } unsigned Opcode = 0; - if (Def->getOpcode() == TargetOpcode::G_UADDE) { - // carry set by prev ADD. + if (Def->getOpcode() == I.getOpcode()) { + // carry set by prev ADD/SUB. BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS) .addReg(CarryInReg); @@ -1126,17 +1138,17 @@ bool X86InstructionSelector::selectUadde(MachineInstr &I, if (!RBI.constrainGenericRegister(CarryInReg, *DstRC, MRI)) return false; - Opcode = OpADC; + Opcode = IsSub ? OpSBB : OpADC; } else if (auto val = getIConstantVRegVal(CarryInReg, MRI)) { // carry is constant, support only 0. if (*val != 0) return false; - Opcode = OpADD; + Opcode = IsSub ? OpSUB : OpADD; } else return false; - MachineInstr &AddInst = + MachineInstr &Inst = *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg) .addReg(Op0Reg) .addReg(Op1Reg); @@ -1144,7 +1156,7 @@ bool X86InstructionSelector::selectUadde(MachineInstr &I, BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg) .addReg(X86::EFLAGS); - if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) || + if (!constrainSelectedInstRegOperands(Inst, TII, TRI, RBI) || !RBI.constrainGenericRegister(CarryOutReg, *DstRC, MRI)) return false; diff --git a/llvm/lib/Target/X86/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/X86LegalizerInfo.cpp index cf49d7c..406c9d4 100644 --- a/llvm/lib/Target/X86/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/X86LegalizerInfo.cpp @@ -148,8 +148,8 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, .clampScalar(0, s8, sMaxScalar) .scalarize(0); - // TODO: Add G_UADDO/G_USUBO/G_USUBE handling - getActionDefinitionsBuilder(G_UADDE) + // TODO: Add G_UADDO/G_USUBO handling + getActionDefinitionsBuilder({G_UADDE, G_USUBE}) .legalIf([=](const LegalityQuery &Query) -> bool { return typePairInSet(0, 1, {{s8, s1}, {s16, s1}, {s32, s1}})(Query) || (Is64Bit && typePairInSet(0, 1, {{s64, s1}})(Query)); diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-leading-zeros.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-leading-zeros.mir index 18052c6..5a0b341 100644 --- a/llvm/test/CodeGen/X86/GlobalISel/legalize-leading-zeros.mir +++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-leading-zeros.mir @@ -3,7 +3,7 @@ # RUN: llc -mtriple=i386-linux-gnu -mattr=+lzcnt -run-pass=legalizer -global-isel-abort=2 -pass-remarks-missed='gisel*' %s 2>%t -o - | FileCheck %s --check-prefixes=CHECK,X86 # RUN: FileCheck -check-prefix=ERR32 %s < %t -# ERR32: remark: :0:0: unable to legalize instruction: %14:_(s32), %15:_(s1) = G_USUBE %9:_, %11:_, %13:_ (in function: test_ctlz35) +# ERR32: remark: :0:0: unable to legalize instruction: %12:_(s32), %13:_(s1) = G_USUBO %8:_, %10:_ (in function: test_ctlz35) # ERR32: remark: :0:0: unable to legalize instruction: %10:_(s64) = G_CTLZ_ZERO_UNDEF %4:_(s32) (in function: test_ctlz64) # test count leading zeros for s16, s32, and s64 diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-sub.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-sub.mir index eeb89eb..1a14ab9 100644 --- a/llvm/test/CodeGen/X86/GlobalISel/legalize-sub.mir +++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-sub.mir @@ -5,11 +5,11 @@ # RUN: llc -O0 -mtriple=i386-linux-gnu -run-pass=legalizer -global-isel-abort=2 -pass-remarks-missed='gisel*' %s 2>%t -o - | FileCheck %s --check-prefixes=CHECK,X32 # RUN: FileCheck -check-prefix=ERR32 %s < %t -# ERR64: remark: :0:0: unable to legalize instruction: %11:_(s64), %12:_(s1) = G_USUBE %6:_, %8:_, %10:_ (in function: test_sub_i128) +# ERR64: remark: :0:0: unable to legalize instruction: %9:_(s64), %10:_(s1) = G_USUBO %5:_, %7:_ (in function: test_sub_i128) -# ERR32: remark: :0:0: unable to legalize instruction: %13:_(s32), %14:_(s1) = G_USUBE %8:_, %10:_, %12:_ (in function: test_sub_i42) -# ERR32: remark: :0:0: unable to legalize instruction: %9:_(s32), %10:_(s1) = G_USUBE %4:_, %6:_, %8:_ (in function: test_sub_i64) -# ERR32: remark: :0:0: unable to legalize instruction: %19:_(s32), %20:_(s1) = G_USUBE %8:_, %12:_, %18:_ (in function: test_sub_i128) +# ERR32: remark: :0:0: unable to legalize instruction: %11:_(s32), %12:_(s1) = G_USUBO %7:_, %9:_ (in function: test_sub_i42) +# ERR32: remark: :0:0: unable to legalize instruction: %7:_(s32), %8:_(s1) = G_USUBO %3:_, %5:_ (in function: test_sub_i64) +# ERR32: remark: :0:0: unable to legalize instruction: %13:_(s32), %14:_(s1) = G_USUBO %5:_, %9:_ (in function: test_sub_i128) --- | -- 2.7.4