From: Aditya Nandakumar Date: Tue, 28 Aug 2018 18:54:10 +0000 (+0000) Subject: [GISel]: Add missing opcodes for overflow intrinsics X-Git-Tag: llvmorg-8.0.0-rc1~9982 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6b4d343e1365ac1e8f04659216d5b190f90b4694;p=platform%2Fupstream%2Fllvm.git [GISel]: Add missing opcodes for overflow intrinsics https://reviews.llvm.org/D51197 Currently, IRTranslator (and GISel) seems to be arbitrarily picking which overflow intrinsics get mapped into opcodes which either have a carry as an input or not. For intrinsics such as Intrinsic::uadd_with_overflow, translate it to an opcode (G_UADDO) which doesn't have any carry inputs (similar to LLVM IR). This patch adds 4 missing opcodes for completeness - G_UADDO, G_USUBO, G_SSUBE and G_SADDE. llvm-svn: 340865 --- diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index dfd15ac..a683f05 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -362,10 +362,18 @@ HANDLE_TARGET_OPCODE(G_FCMP) /// 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) @@ -374,10 +382,18 @@ 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) diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index 2a2bef2..399cea9 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -311,6 +311,14 @@ def G_PTR_MASK : GenericInstruction { // 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); @@ -326,6 +334,19 @@ def G_SADDO : GenericInstruction { 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); @@ -333,13 +354,20 @@ def G_USUBE : GenericInstruction { 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); diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 25145c2..974629b 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -717,17 +717,11 @@ void IRTranslator::getStackGuard(unsigned DstReg, bool IRTranslator::translateOverflowIntrinsic(const CallInst &CI, unsigned Op, MachineIRBuilder &MIRBuilder) { ArrayRef 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; } @@ -819,11 +813,11 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, 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: diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index cf30558..a2bbc27 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -844,8 +844,7 @@ define void @test_sadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) { ; 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) @@ -877,8 +876,7 @@ define void @test_ssub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) { ; 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) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index d5206cc..f776ca6 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -189,18 +189,30 @@ # 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 #