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;
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:
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);
}
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);
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);
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;
# 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: <unknown>:0:0: unable to legalize instruction: %11:_(s64), %12:_(s1) = G_USUBE %6:_, %8:_, %10:_ (in function: test_sub_i128)
+# ERR64: remark: <unknown>:0:0: unable to legalize instruction: %9:_(s64), %10:_(s1) = G_USUBO %5:_, %7:_ (in function: test_sub_i128)
-# ERR32: remark: <unknown>:0:0: unable to legalize instruction: %13:_(s32), %14:_(s1) = G_USUBE %8:_, %10:_, %12:_ (in function: test_sub_i42)
-# ERR32: remark: <unknown>:0:0: unable to legalize instruction: %9:_(s32), %10:_(s1) = G_USUBE %4:_, %6:_, %8:_ (in function: test_sub_i64)
-# ERR32: remark: <unknown>:0:0: unable to legalize instruction: %19:_(s32), %20:_(s1) = G_USUBE %8:_, %12:_, %18:_ (in function: test_sub_i128)
+# ERR32: remark: <unknown>:0:0: unable to legalize instruction: %11:_(s32), %12:_(s1) = G_USUBO %7:_, %9:_ (in function: test_sub_i42)
+# ERR32: remark: <unknown>:0:0: unable to legalize instruction: %7:_(s32), %8:_(s1) = G_USUBO %3:_, %5:_ (in function: test_sub_i64)
+# ERR32: remark: <unknown>:0:0: unable to legalize instruction: %13:_(s32), %14:_(s1) = G_USUBO %5:_, %9:_ (in function: test_sub_i128)
--- |