[llvm] [X86][CodeGen] Support lowering for CCMP/CTEST (PR #91747)
via llvm-commits
llvm-commits at lists.llvm.org
Fri May 10 06:58:06 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-selectiondag
@llvm/pr-subscribers-backend-x86
Author: Shengchen Kan (KanRobert)
<details>
<summary>Changes</summary>
---
Patch is 57.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/91747.diff
6 Files Affected:
- (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+2-2)
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+161-3)
- (modified) llvm/lib/Target/X86/X86ISelLowering.h (+4)
- (modified) llvm/lib/Target/X86/X86InstrConditionalCompare.td (+21)
- (modified) llvm/lib/Target/X86/X86InstrFragments.td (+6)
- (added) llvm/test/CodeGen/X86/apx/ccmp.ll (+1116)
``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 05ab6e2e48206..d5f8235d3582a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -1765,8 +1765,8 @@ void DAGCombiner::Run(CombineLevel AtLevel) {
if (N->getNumValues() == RV->getNumValues())
DAG.ReplaceAllUsesWith(N, RV.getNode());
else {
- assert(N->getValueType(0) == RV.getValueType() &&
- N->getNumValues() == 1 && "Type mismatch");
+ //assert(N->getValueType(0) == RV.getValueType() &&
+ // N->getNumValues() == 1 && "Type mismatch");
DAG.ReplaceAllUsesWith(N, &RV);
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 4638f7b70358b..c9df98ffbee04 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -33881,6 +33881,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(TESTUI)
NODE_NAME_CASE(FP80_ADD)
NODE_NAME_CASE(STRICT_FP80_ADD)
+ NODE_NAME_CASE(CCMP)
+ NODE_NAME_CASE(CTEST)
}
return nullptr;
#undef NODE_NAME_CASE
@@ -54508,7 +54510,156 @@ static bool onlyZeroFlagUsed(SDValue Flags) {
return true;
}
+
+static int getCondFlagsFromCondCode(X86::CondCode CC) {
+ // CCMP/CTEST has two conditional operands:
+ // - SCC: source conditonal code (same as CMOV)
+ // - DCF: destination conditional flags, which has 4 valid bits
+ //
+ // +----+----+----+----+
+ // | OF | SF | ZF | CF |
+ // +----+----+----+----+
+ //
+ // If SCC(source conditional code) evaluates to false, CCMP/CTEST will updates
+ // the conditional flags by as follows:
+ //
+ // OF = DCF.OF
+ // SF = DCF.SF
+ // ZF = DCF.ZF
+ // CF = DCF.CF
+ // PF = DCF.CF
+ // AF = 0 (Auxiliary Carry Flag)
+ //
+ // Otherwise, the CMP or TEST is executed and it updates the
+ // CSPAZO flags normally.
+ //
+ // NOTE:
+ // If SCC = P, then SCC evaluates to true regardless of the CSPAZO value.
+ // If SCC = NP, then SCC evaluates to false regardless of the CSPAZO value.
+
+ enum { CF = 1, ZF = 2, SF = 4, OF = 8, PF = CF };
+
+
+ switch (CC) {
+ default:
+ llvm_unreachable("Illegal condition code!");
+ case X86::COND_NO:
+ case X86::COND_NE:
+ case X86::COND_GE:
+ case X86::COND_G:
+ case X86::COND_AE:
+ case X86::COND_A:
+ case X86::COND_NS:
+ case X86::COND_NP:
+ return 0;
+ case X86::COND_O:
+ return OF;
+ case X86::COND_B:
+ case X86::COND_BE:
+ return CF;
+ break;
+ case X86::COND_E:
+ case X86::COND_LE:
+ return ZF;
+ case X86::COND_S:
+ case X86::COND_L:
+ return SF;
+ case X86::COND_P:
+ return PF;
+ }
+}
+
+static SDValue
+combineX86SubCmpToCcmpHelper(SDNode *N, SDValue Flag, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget &ST) {
+ SDValue LHS = N->getOperand(0);
+
+ if (!ST.hasCCMP() || LHS.getOpcode() != ISD::AND || !Flag.hasOneUse())
+ return SDValue();
+
+ SDValue SetCC0 = LHS.getOperand(0);
+ SDValue SetCC1 = LHS.getOperand(1);
+ if (SetCC0.getOpcode() != X86ISD::SETCC &&
+ SetCC1.getOpcode() != X86ISD::SETCC)
+ return SDValue();
+
+ SDValue Sub = SetCC1.getOperand(1);
+ // and is commutable. Try to commute the operands and then test again.
+ if (Sub.getOpcode() != X86ISD::SUB)
+ return SDValue();
+
+ SDNode *BrCond = *Flag->uses().begin();
+ if (BrCond->getOpcode() != X86ISD::BRCOND)
+ return SDValue();
+
+ X86::CondCode CC0 =
+ static_cast<X86::CondCode>(SetCC0.getConstantOperandVal(0));
+ if (CC0 == X86::COND_P || CC0 == X86::COND_NP)
+ return SDValue();
+
+ SDValue CFlags = DAG.getTargetConstant(
+ getCondFlagsFromCondCode(X86::GetOppositeBranchCondition(
+ static_cast<X86::CondCode>(SetCC1.getConstantOperandVal(0)))),
+ SDLoc(BrCond), MVT::i8);
+ SDValue CCMP = DAG.getNode(X86ISD::CCMP, SDLoc(N), Flag.getValueType(),
+ {Sub.getOperand(0), Sub.getOperand(1), CFlags,
+ SetCC0.getOperand(0), SetCC0.getOperand(1)});
+ DAG.ReplaceAllUsesOfValueWith(Flag, CCMP);
+
+ SmallVector<SDValue> Ops(BrCond->op_values());
+ unsigned CondNo = 2;
+ X86::CondCode OldCC =
+ static_cast<X86::CondCode>(BrCond->getConstantOperandVal(CondNo));
+ assert(OldCC == X86::COND_NE && "Unexpected CC");
+ if (Ops[CondNo] != SetCC1.getOperand(0)) {
+ Ops[CondNo] = SetCC1.getOperand(0);
+ SDValue NewBrCond =
+ DAG.getNode(X86ISD::BRCOND, SDLoc(BrCond), BrCond->getValueType(0), Ops);
+ DAG.ReplaceAllUsesWith(BrCond, &NewBrCond);
+ DCI.recursivelyDeleteUnusedNodes(BrCond);
+ }
+ return CCMP;
+}
+
+static SDValue combineX86CmpToCcmp(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget &ST) {
+ // cmp(and(setcc(cc0, flag0), setcc(cc1, sub (X, Y))), 0)
+ // brcond ne
+ //
+ // ->
+ //
+ // ccmp(X, Y, cflags, cc0, flag0)
+ // brcond cc1
+ //
+ // where cflags is determined by cc1.
+
+ return combineX86SubCmpToCcmpHelper(N, SDValue(N, 0), DAG, DCI, ST);
+}
+
+static SDValue combineX86SubToCcmp(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget &ST) {
+ // sub(and(setcc(cc0, flag0), setcc(cc1, sub (X, Y))), 1)
+ // brcond ne
+ //
+ // ->
+ //
+ // ccmp(X, Y, cflags, cc0, flag0)
+ // brcond cc1
+ //
+ // if only flag has users, where cflags is determined by cc1.
+
+ if (N->getOpcode() != X86ISD::SUB || !isOneConstant(N->getOperand(1)) ||
+ N->hasAnyUseOfValue(0))
+ return SDValue();
+
+ return combineX86SubCmpToCcmpHelper(N, SDValue(N, 1), DAG, DCI, ST);
+}
+
static SDValue combineCMP(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
const X86Subtarget &Subtarget) {
// Only handle test patterns.
if (!isNullConstant(N->getOperand(1)))
@@ -54523,6 +54674,9 @@ static SDValue combineCMP(SDNode *N, SelectionDAG &DAG,
EVT VT = Op.getValueType();
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ if (SDValue CCMP = combineX86CmpToCcmp(N, DAG, DCI, Subtarget))
+ return CCMP;
+
// If we have a constant logical shift that's only used in a comparison
// against zero turn it into an equivalent AND. This allows turning it into
// a TEST instruction later.
@@ -54651,7 +54805,8 @@ static SDValue combineCMP(SDNode *N, SelectionDAG &DAG,
}
static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
- TargetLowering::DAGCombinerInfo &DCI) {
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget &ST) {
assert((X86ISD::ADD == N->getOpcode() || X86ISD::SUB == N->getOpcode()) &&
"Expected X86ISD::ADD or X86ISD::SUB");
@@ -54662,6 +54817,9 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
bool IsSub = X86ISD::SUB == N->getOpcode();
unsigned GenericOpc = IsSub ? ISD::SUB : ISD::ADD;
+ if (SDValue CCMP = combineX86SubToCcmp(N, DAG, DCI, ST))
+ return CCMP;
+
// If we don't use the flag result, simplify back to a generic ADD/SUB.
if (!N->hasAnyUseOfValue(1)) {
SDValue Res = DAG.getNode(GenericOpc, DL, VT, LHS, RHS);
@@ -56960,11 +57118,11 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
case X86ISD::BLENDV: return combineSelect(N, DAG, DCI, Subtarget);
case ISD::BITCAST: return combineBitcast(N, DAG, DCI, Subtarget);
case X86ISD::CMOV: return combineCMov(N, DAG, DCI, Subtarget);
- case X86ISD::CMP: return combineCMP(N, DAG, Subtarget);
+ case X86ISD::CMP: return combineCMP(N, DAG, DCI, Subtarget);
case ISD::ADD: return combineAdd(N, DAG, DCI, Subtarget);
case ISD::SUB: return combineSub(N, DAG, DCI, Subtarget);
case X86ISD::ADD:
- case X86ISD::SUB: return combineX86AddSub(N, DAG, DCI);
+ case X86ISD::SUB: return combineX86AddSub(N, DAG, DCI, Subtarget);
case X86ISD::SBB: return combineSBB(N, DAG);
case X86ISD::ADC: return combineADC(N, DAG, DCI);
case ISD::MUL: return combineMul(N, DAG, DCI, Subtarget);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index ade54f73bff09..d8596dbdddcb7 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -789,6 +789,10 @@ namespace llvm {
// Perform an FP80 add after changing precision control in FPCW.
STRICT_FP80_ADD,
+ // Conditional compare instructions
+ CCMP,
+ CTEST,
+
// WARNING: Only add nodes here if they are strict FP nodes. Non-memory and
// non-strict FP nodes should be above FIRST_TARGET_STRICTFP_OPCODE.
diff --git a/llvm/lib/Target/X86/X86InstrConditionalCompare.td b/llvm/lib/Target/X86/X86InstrConditionalCompare.td
index e5c1143eba87f..ea558dfcb5ab7 100644
--- a/llvm/lib/Target/X86/X86InstrConditionalCompare.td
+++ b/llvm/lib/Target/X86/X86InstrConditionalCompare.td
@@ -78,6 +78,24 @@ let mayLoad = 1 in {
}
}
+def : Pat<(X86ccmp GR8:$src1, GR8:$src2, timm:$dcf, timm:$cond, EFLAGS),
+ (CCMP8rr GR8:$src1, GR8:$src2, timm:$dcf, timm:$cond)>;
+def : Pat<(X86ccmp GR16:$src1, GR16:$src2, timm:$dcf, timm:$cond, EFLAGS),
+ (CCMP16rr GR16:$src1, GR16:$src2, timm:$dcf, timm:$cond)>;
+def : Pat<(X86ccmp GR32:$src1, GR32:$src2, timm:$dcf, timm:$cond, EFLAGS),
+ (CCMP32rr GR32:$src1, GR32:$src2, timm:$dcf, timm:$cond)>;
+def : Pat<(X86ccmp GR64:$src1, GR64:$src2, timm:$dcf, timm:$cond, EFLAGS),
+ (CCMP64rr GR64:$src1, GR64:$src2, timm:$dcf, timm:$cond)>;
+
+def : Pat<(X86ccmp GR8:$src1, (i8 imm:$src2), timm:$dcf, timm:$cond, EFLAGS),
+ (CCMP8ri GR8:$src1, imm:$src2, timm:$dcf, timm:$cond)>;
+def : Pat<(X86ccmp GR16:$src1, (i16 imm:$src2), timm:$dcf, timm:$cond, EFLAGS),
+ (CCMP16ri GR16:$src1, imm:$src2, timm:$dcf, timm:$cond)>;
+def : Pat<(X86ccmp GR32:$src1, (i32 imm:$src2), timm:$dcf, timm:$cond, EFLAGS),
+ (CCMP32ri GR32:$src1, imm:$src2, timm:$dcf, timm:$cond)>;
+def : Pat<(X86ccmp GR64:$src1, (i64 imm:$src2), timm:$dcf, timm:$cond, EFLAGS),
+ (CCMP64ri32 GR64:$src1, imm:$src2, timm:$dcf, timm:$cond)>;
+
//===----------------------------------------------------------------------===//
// CTEST Instructions
//
@@ -108,3 +126,6 @@ let mayLoad = 1 in {
def CTEST64mr: Ctest<0x85, MRMDestMem, Xi64, i64mem, GR64>;
}
}
+
+def : Pat<(X86ctest GR32:$src1, GR32:$src2, timm:$dcf, timm:$cond, EFLAGS),
+ (CTEST32rr GR32:$src1, GR32:$src2, timm:$dcf, timm:$cond)>;
diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td
index f14c7200af968..664998e76353b 100644
--- a/llvm/lib/Target/X86/X86InstrFragments.td
+++ b/llvm/lib/Target/X86/X86InstrFragments.td
@@ -12,6 +12,9 @@ def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisInt<1>,
def SDTX86FCmp : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisFP<1>,
SDTCisSameAs<1, 2>]>;
+def SDTX86Ccmp : SDTypeProfile<1, 5,
+ [SDTCisVT<3, i8>, SDTCisVT<4, i8>, SDTCisVT<5, i32>]>;
+
def SDTX86Cmov : SDTypeProfile<1, 4,
[SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
SDTCisVT<3, i8>, SDTCisVT<4, i32>]>;
@@ -138,6 +141,9 @@ def X86strict_fcmp : SDNode<"X86ISD::STRICT_FCMP", SDTX86FCmp, [SDNPHasChain]>;
def X86strict_fcmps : SDNode<"X86ISD::STRICT_FCMPS", SDTX86FCmp, [SDNPHasChain]>;
def X86bt : SDNode<"X86ISD::BT", SDTX86CmpTest>;
+def X86ccmp : SDNode<"X86ISD::CCMP", SDTX86Ccmp>;
+def X86ctest : SDNode<"X86ISD::CTEST", SDTX86Ccmp>;
+
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov>;
def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond,
[SDNPHasChain]>;
diff --git a/llvm/test/CodeGen/X86/apx/ccmp.ll b/llvm/test/CodeGen/X86/apx/ccmp.ll
new file mode 100644
index 0000000000000..5d6c281404cb5
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/ccmp.ll
@@ -0,0 +1,1116 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ccmp -verify-machineinstrs -show-mc-encoding | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ccmp,+ndd -verify-machineinstrs -show-mc-encoding | FileCheck %s --check-prefix=NDD
+
+define void @ccmp8rr_zf(i8 noundef %a, i8 noundef %b, i8 noundef %c) {
+; CHECK-LABEL: ccmp8rr_zf:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cmpb %dl, %dil # encoding: [0x40,0x38,0xd7]
+; CHECK-NEXT: ccmpneb {dfv=zf} %dl, %sil # encoding: [0x62,0xf4,0x14,0x05,0x38,0xd6]
+; CHECK-NEXT: jne .LBB0_1 # encoding: [0x75,A]
+; CHECK-NEXT: # fixup A - offset: 1, value: .LBB0_1-1, kind: FK_PCRel_1
+; CHECK-NEXT: # %bb.2: # %if.then
+; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; CHECK-NEXT: jmp foo # TAILCALL
+; CHECK-NEXT: # encoding: [0xeb,A]
+; CHECK-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1
+; CHECK-NEXT: .LBB0_1: # %if.end
+; CHECK-NEXT: retq # encoding: [0xc3]
+;
+; NDD-LABEL: ccmp8rr_zf:
+; NDD: # %bb.0: # %entry
+; NDD-NEXT: cmpb %dl, %dil # encoding: [0x40,0x38,0xd7]
+; NDD-NEXT: ccmpneb {dfv=zf} %dl, %sil # encoding: [0x62,0xf4,0x14,0x05,0x38,0xd6]
+; NDD-NEXT: jne .LBB0_1 # encoding: [0x75,A]
+; NDD-NEXT: # fixup A - offset: 1, value: .LBB0_1-1, kind: FK_PCRel_1
+; NDD-NEXT: # %bb.2: # %if.then
+; NDD-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; NDD-NEXT: jmp foo # TAILCALL
+; NDD-NEXT: # encoding: [0xeb,A]
+; NDD-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1
+; NDD-NEXT: .LBB0_1: # %if.end
+; NDD-NEXT: retq # encoding: [0xc3]
+entry:
+ %cmp = icmp eq i8 %a, %c
+ %cmp1 = icmp eq i8 %b, %c
+ %or.cond = or i1 %cmp, %cmp1
+ br i1 %or.cond, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void (...) @foo()
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+define void @ccmp16rr_sf(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
+; CHECK-LABEL: ccmp16rr_sf:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cmpw %dx, %di # encoding: [0x66,0x39,0xd7]
+; CHECK-NEXT: ccmplew {dfv=sf} %dx, %si # encoding: [0x62,0xf4,0x25,0x0e,0x39,0xd6]
+; CHECK-NEXT: jge .LBB1_1 # encoding: [0x7d,A]
+; CHECK-NEXT: # fixup A - offset: 1, value: .LBB1_1-1, kind: FK_PCRel_1
+; CHECK-NEXT: # %bb.2: # %if.then
+; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; CHECK-NEXT: jmp foo # TAILCALL
+; CHECK-NEXT: # encoding: [0xeb,A]
+; CHECK-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1
+; CHECK-NEXT: .LBB1_1: # %if.end
+; CHECK-NEXT: retq # encoding: [0xc3]
+;
+; NDD-LABEL: ccmp16rr_sf:
+; NDD: # %bb.0: # %entry
+; NDD-NEXT: cmpw %dx, %di # encoding: [0x66,0x39,0xd7]
+; NDD-NEXT: ccmplew {dfv=sf} %dx, %si # encoding: [0x62,0xf4,0x25,0x0e,0x39,0xd6]
+; NDD-NEXT: jge .LBB1_1 # encoding: [0x7d,A]
+; NDD-NEXT: # fixup A - offset: 1, value: .LBB1_1-1, kind: FK_PCRel_1
+; NDD-NEXT: # %bb.2: # %if.then
+; NDD-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; NDD-NEXT: jmp foo # TAILCALL
+; NDD-NEXT: # encoding: [0xeb,A]
+; NDD-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1
+; NDD-NEXT: .LBB1_1: # %if.end
+; NDD-NEXT: retq # encoding: [0xc3]
+entry:
+ %cmp = icmp sgt i16 %a, %c
+ %cmp1 = icmp slt i16 %b, %c
+ %or.cond = or i1 %cmp, %cmp1
+ br i1 %or.cond, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void (...) @foo()
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+define void @ccmp32rr_cf(i32 noundef %a, i32 noundef %b, i32 noundef %c) {
+; CHECK-LABEL: ccmp32rr_cf:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cmpl %edx, %edi # encoding: [0x39,0xd7]
+; CHECK-NEXT: ccmpbl {dfv=cf} %edx, %esi # encoding: [0x62,0xf4,0x0c,0x02,0x39,0xd6]
+; CHECK-NEXT: ja .LBB2_1 # encoding: [0x77,A]
+; CHECK-NEXT: # fixup A - offset: 1, value: .LBB2_1-1, kind: FK_PCRel_1
+; CHECK-NEXT: # %bb.2: # %if.then
+; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; CHECK-NEXT: jmp foo # TAILCALL
+; CHECK-NEXT: # encoding: [0xeb,A]
+; CHECK-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1
+; CHECK-NEXT: .LBB2_1: # %if.end
+; CHECK-NEXT: retq # encoding: [0xc3]
+;
+; NDD-LABEL: ccmp32rr_cf:
+; NDD: # %bb.0: # %entry
+; NDD-NEXT: cmpl %edx, %edi # encoding: [0x39,0xd7]
+; NDD-NEXT: ccmpbl {dfv=cf} %edx, %esi # encoding: [0x62,0xf4,0x0c,0x02,0x39,0xd6]
+; NDD-NEXT: ja .LBB2_1 # encoding: [0x77,A]
+; NDD-NEXT: # fixup A - offset: 1, value: .LBB2_1-1, kind: FK_PCRel_1
+; NDD-NEXT: # %bb.2: # %if.then
+; NDD-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; NDD-NEXT: jmp foo # TAILCALL
+; NDD-NEXT: # encoding: [0xeb,A]
+; NDD-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1
+; NDD-NEXT: .LBB2_1: # %if.end
+; NDD-NEXT: retq # encoding: [0xc3]
+entry:
+ %cmp = icmp uge i32 %a, %c
+ %cmp1 = icmp ule i32 %b, %c
+ %or.cond = or i1 %cmp, %cmp1
+ br i1 %or.cond, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void (...) @foo()
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+define void @ccmp64rr_of(i64 %a, i64 %b) {
+; CHECK-LABEL: ccmp64rr_of:
+; CHECK: # %bb.0: # %bb
+; CHECK-NEXT: testq %rdi, %rdi # encoding: [0x48,0x85,0xff]
+; CHECK-NEXT: ccmpneq {dfv=of} %rsi, %rdi # encoding: [0x62,0xf4,0xc4,0x05,0x39,0xf7]
+; CHECK-NEXT: retq # encoding: [0xc3]
+;
+; NDD-LABEL: ccmp64rr_of:
+; NDD: # %bb.0: # %bb
+; NDD-NEXT: testq %rdi, %rdi # encoding: [0x48,0x85,0xff]
+; NDD-NEXT: ccmpneq {dfv=of} %rsi, %rdi # encoding: [0x62,0xf4,0xc4,0x05,0x39,0xf7]
+; NDD-NEXT: retq # encoding: [0xc3]
+bb:
+ %cond1 = icmp eq i64 %a, 0
+ br i1 %cond1, label %bb3, label %bb1
+
+bb1: ; preds = %bb
+ %smul = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
+ %obit = extractvalue {i64, i1} %smul, 1
+ br i1 %obit, label %bb3, label %bb2
+
+bb2: ; preds = %bb1
+ %tmp = ptrtoint ptr null to i64
+ br label %bb3
+
+bb3: ; preds = %bb2, %bb1, %bb
+ ret void
+}
+
+define void @ccmp8ri_zf(i8 noundef %a, i8 noundef %b, i8 noundef %c) {
+; CHECK-LABEL: ccmp8ri_zf:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cmpb %dl, %dil # encoding: [0x40,0x38,0xd7]
+; CHECK-NEXT: ccmpleb {dfv=zf} $123, %sil # encoding: [0x62,0xf4,0x14,0x0e,0x80,0xfe,0x7b]
+; CHECK-NEXT: jne .LBB4_1 # encoding: [0x75,A]
+; CHECK-NEXT: # fixup A - offset: 1, value: .LBB4_1-1, kind: FK_PCRel_1
+; CHECK-NEXT: # %bb.2: # %if.then
+; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; CHECK-NEXT: jmp foo # TAILCALL
+; CHECK-NEXT: # encoding: [0xeb,A]
+; CHECK-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1
+; CHECK-NEXT: .LBB4_1: # %if.end
+; CHECK-NEXT: retq # encoding: [0xc3]
+;
+; NDD-LABEL: ccmp8ri_zf:
+; NDD: # %bb.0: # %entry
+; NDD-NEXT: cmpb %dl, %dil # encoding: [0x40,0x38,0xd7]
+; NDD-NEXT: ccmpleb {dfv=zf} $123, %sil # encoding: [0x62,0xf4,0x14,0x0e,0x80,0xfe,0x7b]
+; NDD-NEXT: jne .LBB4_1 # encoding: [0x75,A]
+; NDD-NEXT: # fixup A - offset: 1, value: .LBB4_1-1, kind: FK_PCRel_1
+; NDD-NEXT: # %bb.2: # %if.then
+; NDD-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0]
+; NDD-NEXT: jmp foo # TAILCALL
+; NDD-NEXT: # encoding: [0xeb,A]
+; NDD-NEXT: # fixup A - offset: 1, value: foo-1, kind: FK_PCRel_1
+; NDD-NEXT: .LBB4_1: # %if.end
+; NDD-NEXT: retq # encoding: [0xc3]
+entry:
+ %cmp = icmp sgt i8 %a, %c
+ %cmp1 = icmp eq ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/91747
More information about the llvm-commits
mailing list