From: Robert Khasanov Date: Thu, 21 Aug 2014 09:27:00 +0000 (+0000) Subject: [x86] Broadwell: ADOX/ADCX. Added _addcarryx_u{32|64} intrinsics to LLVM. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=10dacc4b528fbf5c8d0c9973f89691d409d4a608 [x86] Broadwell: ADOX/ADCX. Added _addcarryx_u{32|64} intrinsics to LLVM. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216162 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 3ea947126e6..5fe90400e3f 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -2758,6 +2758,18 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_rdseed_64 : Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; } +//===----------------------------------------------------------------------===// +// ADX + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_addcarryx_u32: GCCBuiltin<"__builtin_ia32_addcarryx_u32">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_addcarryx_u64: GCCBuiltin<"__builtin_ia32_addcarryx_u64">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; +} + //===----------------------------------------------------------------------===// // RTM intrinsics. Transactional Memory support. diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index abc80351ec4..81949942ddc 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -15355,7 +15355,7 @@ static SDValue LowerREADCYCLECOUNTER(SDValue Op, const X86Subtarget *Subtarget, } enum IntrinsicType { - GATHER, SCATTER, PREFETCH, RDSEED, RDRAND, RDPMC, RDTSC, XTEST + GATHER, SCATTER, PREFETCH, RDSEED, RDRAND, RDPMC, RDTSC, XTEST, ADX }; struct IntrinsicData { @@ -15451,6 +15451,10 @@ static void InitIntinsicsMap() { IntrinsicData(RDTSC, X86ISD::RDTSCP_DAG, 0))); IntrMap.insert(std::make_pair(Intrinsic::x86_rdpmc, IntrinsicData(RDPMC, X86ISD::RDPMC_DAG, 0))); + IntrMap.insert(std::make_pair(Intrinsic::x86_addcarryx_u32, + IntrinsicData(ADX, X86ISD::ADC, 0))); + IntrMap.insert(std::make_pair(Intrinsic::x86_addcarryx_u64, + IntrinsicData(ADX, X86ISD::ADC, 0))); Initialized = true; } @@ -15543,6 +15547,25 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget *Subtarget, return DAG.getNode(ISD::MERGE_VALUES, dl, Op->getVTList(), Ret, SDValue(InTrans.getNode(), 1)); } + // ADC/ADCX + case ADX: { + SmallVector Results; + SDVTList CFVTs = DAG.getVTList(Op->getValueType(0), MVT::Other); + SDVTList VTs = DAG.getVTList(Op.getOperand(3)->getValueType(0), MVT::Other); + SDValue GenCF = DAG.getNode(X86ISD::ADD, dl, CFVTs, Op.getOperand(2), + DAG.getConstant(-1, MVT::i8)); + SDValue Res = DAG.getNode(Intr.Opc0, dl, VTs, Op.getOperand(3), + Op.getOperand(4), GenCF.getValue(1)); + SDValue Store = DAG.getStore(Op.getOperand(0), dl, Res.getValue(0), + Op.getOperand(5), MachinePointerInfo(), + false, false, 0); + SDValue SetCC = DAG.getNode(X86ISD::SETCC, dl, MVT::i8, + DAG.getConstant(X86::COND_B, MVT::i8), + Res.getValue(1)); + Results.push_back(SetCC); + Results.push_back(Store); + return DAG.getMergeValues(Results, dl); + } } llvm_unreachable("Unknown Intrinsic Type"); } diff --git a/lib/Target/X86/X86InstrArithmetic.td b/lib/Target/X86/X86InstrArithmetic.td index f2574cc3700..25e1e8094f3 100644 --- a/lib/Target/X86/X86InstrArithmetic.td +++ b/lib/Target/X86/X86InstrArithmetic.td @@ -1355,49 +1355,57 @@ let Predicates = [HasBMI2] in { //===----------------------------------------------------------------------===// // ADCX Instruction // -let hasSideEffects = 0, Predicates = [HasADX], Defs = [EFLAGS] in { +let hasSideEffects = 0, Defs = [EFLAGS], Uses = [EFLAGS], + Constraints = "$src0 = $dst", AddedComplexity = 10 in { let SchedRW = [WriteALU] in { - def ADCX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), - "adcx{l}\t{$src, $dst|$dst, $src}", - [], IIC_BIN_NONMEM>, T8PD; - - def ADCX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), - "adcx{q}\t{$src, $dst|$dst, $src}", - [], IIC_BIN_NONMEM>, T8PD, Requires<[In64BitMode]>; + def ADCX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), + (ins GR32:$src0, GR32:$src), "adcx{l}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, EFLAGS, + (X86adc_flag GR32:$src0, GR32:$src, EFLAGS))], + IIC_BIN_CARRY_NONMEM>, T8PD, Requires<[HasADX]>; + def ADCX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst), + (ins GR64:$src0, GR64:$src), "adcx{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, EFLAGS, + (X86adc_flag GR64:$src0, GR64:$src, EFLAGS))], + IIC_BIN_CARRY_NONMEM>, T8PD, Requires<[HasADX, In64BitMode]>; } // SchedRW let mayLoad = 1, SchedRW = [WriteALULd] in { - def ADCX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), - "adcx{l}\t{$src, $dst|$dst, $src}", - [], IIC_BIN_MEM>, T8PD; - - def ADCX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), - "adcx{q}\t{$src, $dst|$dst, $src}", - [], IIC_BIN_MEM>, T8PD, Requires<[In64BitMode]>; + def ADCX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src0, i32mem:$src), "adcx{l}\t{$src, $dst|$dst, $src}", + [(set GR32:$dst, EFLAGS, + (X86adc_flag GR32:$src0, (loadi32 addr:$src), EFLAGS))], + IIC_BIN_CARRY_MEM>, T8PD, Requires<[HasADX]>; + + def ADCX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst), + (ins GR64:$src0, i64mem:$src), "adcx{q}\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, EFLAGS, + (X86adc_flag GR64:$src0, (loadi64 addr:$src), EFLAGS))], + IIC_BIN_CARRY_MEM>, T8PD, Requires<[HasADX, In64BitMode]>; } } //===----------------------------------------------------------------------===// // ADOX Instruction // -let hasSideEffects = 0, Predicates = [HasADX], Defs = [EFLAGS] in { +let hasSideEffects = 0, Defs = [EFLAGS], Uses = [EFLAGS] in { let SchedRW = [WriteALU] in { def ADOX32rr : I<0xF6, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), "adox{l}\t{$src, $dst|$dst, $src}", - [], IIC_BIN_NONMEM>, T8XS; + [], IIC_BIN_NONMEM>, T8XS, Requires<[HasADX]>; def ADOX64rr : RI<0xF6, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), "adox{q}\t{$src, $dst|$dst, $src}", - [], IIC_BIN_NONMEM>, T8XS, Requires<[In64BitMode]>; + [], IIC_BIN_NONMEM>, T8XS, Requires<[HasADX, In64BitMode]>; } // SchedRW let mayLoad = 1, SchedRW = [WriteALULd] in { def ADOX32rm : I<0xF6, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), "adox{l}\t{$src, $dst|$dst, $src}", - [], IIC_BIN_MEM>, T8XS; + [], IIC_BIN_MEM>, T8XS, Requires<[HasADX]>; def ADOX64rm : RI<0xF6, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), "adox{q}\t{$src, $dst|$dst, $src}", - [], IIC_BIN_MEM>, T8XS, Requires<[In64BitMode]>; + [], IIC_BIN_MEM>, T8XS, Requires<[HasADX, In64BitMode]>; } } diff --git a/test/CodeGen/X86/adx-intrinsics.ll b/test/CodeGen/X86/adx-intrinsics.ll new file mode 100644 index 00000000000..2711055a046 --- /dev/null +++ b/test/CodeGen/X86/adx-intrinsics.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=broadwell --show-mc-encoding| FileCheck %s --check-prefix=ADX --check-prefix=CHECK + +declare i8 @llvm.x86.addcarryx.u32(i8, i32, i32, i8*) + +define i8 @test_addcarryx_u32(i8 %c, i32 %a, i32 %b, i8* %ptr) { +; CHECK-LABEL: test_addcarryx_u32 +; CHECK: addb +; ADX: adcxl +; CHECK: setb +; CHECK: retq + %ret = tail call i8 @llvm.x86.addcarryx.u32(i8 %c, i32 %a, i32 %b, i8* %ptr) + ret i8 %ret; +} + +declare i8 @llvm.x86.addcarryx.u64(i8, i64, i64, i8*) + +define i8 @test_addcarryx_u64(i8 %c, i64 %a, i64 %b, i8* %ptr) { +; CHECK-LABEL: test_addcarryx_u64 +; CHECK: addb +; ADX: adcxq +; CHECK: setb +; CHECK: retq + %ret = tail call i8 @llvm.x86.addcarryx.u64(i8 %c, i64 %a, i64 %b, i8* %ptr) + ret i8 %ret; +} +