/// Generic select.
HANDLE_TARGET_OPCODE(G_SELECT)
+/// Generic unsigned add instruction, consuming the normal operands and
+/// producing the result and a carry flag.
+HANDLE_TARGET_OPCODE(G_UADDO)
+
/// Generic unsigned add instruction, consuming the normal operands plus a carry
/// flag, and similarly producing the result and a carry flag.
HANDLE_TARGET_OPCODE(G_UADDE)
+/// Generic unsigned sub instruction, consuming the normal operands and
+/// producing the result and a carry flag.
+HANDLE_TARGET_OPCODE(G_USUBO)
+
/// Generic unsigned subtract instruction, consuming the normal operands plus a
/// carry flag, and similarly producing the result and a carry flag.
HANDLE_TARGET_OPCODE(G_USUBE)
/// flag.
HANDLE_TARGET_OPCODE(G_SADDO)
+/// Generic signed add instruction, consuming the normal operands plus a carry
+/// flag, and similarly producing the result and a carry flag.
+HANDLE_TARGET_OPCODE(G_SADDE)
+
/// Generic signed subtract instruction, producing the result and a signed
/// overflow flag.
HANDLE_TARGET_OPCODE(G_SSUBO)
+/// Generic signed sub instruction, consuming the normal operands plus a carry
+/// flag, and similarly producing the result and a carry flag.
+HANDLE_TARGET_OPCODE(G_SSUBE)
+
/// Generic unsigned multiply instruction, producing the result and a signed
/// overflow flag.
HANDLE_TARGET_OPCODE(G_UMULO)
// Overflow ops
//------------------------------------------------------------------------------
+// Generic unsigned addition producing a carry flag.
+def G_UADDO : GenericInstruction {
+ let OutOperandList = (outs type0:$dst, type1:$carry_out);
+ let InOperandList = (ins type0:$src1, type0:$src2);
+ let hasSideEffects = 0;
+ let isCommutable = 1;
+}
+
// Generic unsigned addition consuming and producing a carry flag.
def G_UADDE : GenericInstruction {
let OutOperandList = (outs type0:$dst, type1:$carry_out);
let isCommutable = 1;
}
+// Generic signed addition consuming and producing a carry flag.
+def G_SADDE : GenericInstruction {
+ let OutOperandList = (outs type0:$dst, type1:$carry_out);
+ let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
+ let hasSideEffects = 0;
+}
+
+// Generic unsigned subtraction producing a carry flag.
+def G_USUBO : GenericInstruction {
+ let OutOperandList = (outs type0:$dst, type1:$carry_out);
+ let InOperandList = (ins type0:$src1, type0:$src2);
+ let hasSideEffects = 0;
+}
// Generic unsigned subtraction consuming and producing a carry flag.
def G_USUBE : GenericInstruction {
let OutOperandList = (outs type0:$dst, type1:$carry_out);
let hasSideEffects = 0;
}
-// Generic unsigned subtraction producing a carry flag.
+// Generic signed subtraction producing a carry flag.
def G_SSUBO : GenericInstruction {
let OutOperandList = (outs type0:$dst, type1:$carry_out);
let InOperandList = (ins type0:$src1, type0:$src2);
let hasSideEffects = 0;
}
+// Generic signed subtraction consuming and producing a carry flag.
+def G_SSUBE : GenericInstruction {
+ let OutOperandList = (outs type0:$dst, type1:$carry_out);
+ let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
+ let hasSideEffects = 0;
+}
+
// Generic unsigned multiplication producing a carry flag.
def G_UMULO : GenericInstruction {
let OutOperandList = (outs type0:$dst, type1:$carry_out);
bool IRTranslator::translateOverflowIntrinsic(const CallInst &CI, unsigned Op,
MachineIRBuilder &MIRBuilder) {
ArrayRef<unsigned> ResRegs = getOrCreateVRegs(CI);
- auto MIB = MIRBuilder.buildInstr(Op)
- .addDef(ResRegs[0])
- .addDef(ResRegs[1])
- .addUse(getOrCreateVReg(*CI.getOperand(0)))
- .addUse(getOrCreateVReg(*CI.getOperand(1)));
-
- if (Op == TargetOpcode::G_UADDE || Op == TargetOpcode::G_USUBE) {
- unsigned Zero = getOrCreateVReg(
- *Constant::getNullValue(Type::getInt1Ty(CI.getContext())));
- MIB.addUse(Zero);
- }
+ MIRBuilder.buildInstr(Op)
+ .addDef(ResRegs[0])
+ .addDef(ResRegs[1])
+ .addUse(getOrCreateVReg(*CI.getOperand(0)))
+ .addUse(getOrCreateVReg(*CI.getOperand(1)));
return true;
}
return true;
}
case Intrinsic::uadd_with_overflow:
- return translateOverflowIntrinsic(CI, TargetOpcode::G_UADDE, MIRBuilder);
+ return translateOverflowIntrinsic(CI, TargetOpcode::G_UADDO, MIRBuilder);
case Intrinsic::sadd_with_overflow:
return translateOverflowIntrinsic(CI, TargetOpcode::G_SADDO, MIRBuilder);
case Intrinsic::usub_with_overflow:
- return translateOverflowIntrinsic(CI, TargetOpcode::G_USUBE, MIRBuilder);
+ return translateOverflowIntrinsic(CI, TargetOpcode::G_USUBO, MIRBuilder);
case Intrinsic::ssub_with_overflow:
return translateOverflowIntrinsic(CI, TargetOpcode::G_SSUBO, MIRBuilder);
case Intrinsic::umul_with_overflow:
; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
-; CHECK: [[ZERO:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
-; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_UADDE [[LHS]], [[RHS]], [[ZERO]]
+; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_UADDO [[LHS]], [[RHS]]
; CHECK: G_STORE [[VAL]](s32), [[ADDR]](p0) :: (store 4 into %ir.addr)
; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[ADDR]], [[CST]](s64)
; CHECK: [[LHS:%[0-9]+]]:_(s32) = COPY $w0
; CHECK: [[RHS:%[0-9]+]]:_(s32) = COPY $w1
; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
-; CHECK: [[ZERO:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
-; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_USUBE [[LHS]], [[RHS]], [[ZERO]]
+; CHECK: [[VAL:%[0-9]+]]:_(s32), [[OVERFLOW:%[0-9]+]]:_(s1) = G_USUBO [[LHS]], [[RHS]]
; CHECK: G_STORE [[VAL]](s32), [[ADDR]](p0) :: (store 4 into %ir.subr)
; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[ADDR]], [[CST]](s64)
# DEBUG-NEXT: G_SELECT (opcode {{[0-9]+}}): 2 type indices
# DEBUG: .. the first uncovered type index: 2, OK
#
+# DEBUG-NEXT: G_UADDO (opcode {{[0-9]+}}): 2 type indices
+# DEBUG: .. type index coverage check SKIPPED: no rules defined
+#
# DEBUG-NEXT: G_UADDE (opcode {{[0-9]+}}): 2 type indices
# DEBUG: .. the first uncovered type index: 2, OK
#
+# DEBUG-NEXT: G_USUBO (opcode {{[0-9]+}}): 2 type indices
+# DEBUG: .. type index coverage check SKIPPED: no rules defined
+#
# DEBUG-NEXT: G_USUBE (opcode {{[0-9]+}}): 2 type indices
# DEBUG: .. the first uncovered type index: 2, OK
#
# DEBUG-NEXT: G_SADDO (opcode {{[0-9]+}}): 2 type indices
# DEBUG: .. the first uncovered type index: 2, OK
#
+# DEBUG-NEXT: G_SADDE (opcode {{[0-9]+}}): 2 type indices
+# DEBUG: .. type index coverage check SKIPPED: no rules defined
+#
# DEBUG-NEXT: G_SSUBO (opcode {{[0-9]+}}): 2 type indices
# DEBUG: .. the first uncovered type index: 2, OK
#
+# DEBUG-NEXT: G_SSUBE (opcode {{[0-9]+}}): 2 type indices
+# DEBUG: .. type index coverage check SKIPPED: no rules defined
+#
# DEBUG-NEXT: G_UMULO (opcode {{[0-9]+}}): 2 type indices
# DEBUG: .. the first uncovered type index: 2, OK
#