[llvm] r353307 - [InlineAsm][X86] Add backend support for X86 flag output parameters.

Nirav Dave via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 6 07:26:29 PST 2019


Author: niravd
Date: Wed Feb  6 07:26:29 2019
New Revision: 353307

URL: http://llvm.org/viewvc/llvm-project?rev=353307&view=rev
Log:
[InlineAsm][X86] Add backend support for X86 flag output parameters.

Allow custom handling of inline assembly output parameters and add X86
flag parameter support.

Added:
    llvm/trunk/test/CodeGen/X86/inline-asm-flag-output.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/TargetLowering.h
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.h

Modified: llvm/trunk/include/llvm/CodeGen/TargetLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLowering.h?rev=353307&r1=353306&r2=353307&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/TargetLowering.h (original)
+++ llvm/trunk/include/llvm/CodeGen/TargetLowering.h Wed Feb  6 07:26:29 2019
@@ -3658,6 +3658,12 @@ public:
                                             std::vector<SDValue> &Ops,
                                             SelectionDAG &DAG) const;
 
+  // Lower custom output constraints. If invalid, return SDValue().
+  virtual SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue *Flag,
+                                              SDLoc DL,
+                                              const AsmOperandInfo &OpInfo,
+                                              SelectionDAG &DAG) const;
+
   //===--------------------------------------------------------------------===//
   // Div utility functions
   //

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=353307&r1=353306&r2=353307&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Feb  6 07:26:29 2019
@@ -7688,11 +7688,9 @@ void SelectionDAGBuilder::visitInlineAsm
 
     switch (OpInfo.Type) {
     case InlineAsm::isOutput:
-      if (OpInfo.ConstraintType != TargetLowering::C_RegisterClass &&
-          OpInfo.ConstraintType != TargetLowering::C_Register) {
-        // Memory output, or 'other' output (e.g. 'X' constraint).
-        assert(OpInfo.isIndirect && "Memory output must be indirect operand");
-
+      if (OpInfo.ConstraintType == TargetLowering::C_Memory ||
+          (OpInfo.ConstraintType == TargetLowering::C_Other &&
+           OpInfo.isIndirect)) {
         unsigned ConstraintID =
             TLI.getInlineAsmMemConstraint(OpInfo.ConstraintCode);
         assert(ConstraintID != InlineAsm::Constraint_Unknown &&
@@ -7705,12 +7703,13 @@ void SelectionDAGBuilder::visitInlineAsm
                                                         MVT::i32));
         AsmNodeOperands.push_back(OpInfo.CallOperand);
         break;
-      } else if (OpInfo.ConstraintType == TargetLowering::C_Register ||
+      } else if ((OpInfo.ConstraintType == TargetLowering::C_Other &&
+                  !OpInfo.isIndirect) ||
+                 OpInfo.ConstraintType == TargetLowering::C_Register ||
                  OpInfo.ConstraintType == TargetLowering::C_RegisterClass) {
-        // Otherwise, this is a register or register class output.
-
-        // Copy the output from the appropriate register.  Find a register that
-        // we can use.
+        // Otherwise, this outputs to a register (directly for C_Register /
+        // C_RegisterClass, and a target-defined fashion for C_Other). Find a
+        // register that we can use.
         if (OpInfo.AssignedRegs.Regs.empty()) {
           emitInlineAsmError(
               CS, "couldn't allocate output register for constraint '" +
@@ -7941,13 +7940,16 @@ void SelectionDAGBuilder::visitInlineAsm
             DAG, FuncInfo, getCurSDLoc(), Chain, &Flag, CS.getInstruction());
         break;
       case TargetLowering::C_Other:
+        Val = TLI.LowerAsmOutputForConstraint(Chain, &Flag, getCurSDLoc(),
+                                              OpInfo, DAG);
+        break;
       case TargetLowering::C_Memory:
         break; // Already handled.
       case TargetLowering::C_Unknown:
         assert(false && "Unexpected unknown constraint");
       }
 
-      // Indirect output are manifest as stores. Record output chains.
+      // Indirect output manifest as stores. Record output chains.
       if (OpInfo.isIndirect) {
 
         const Value *Ptr = OpInfo.CallOperandVal;

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=353307&r1=353306&r2=353307&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Wed Feb  6 07:26:29 2019
@@ -3231,6 +3231,12 @@ const char *TargetLowering::LowerXConstr
   return nullptr;
 }
 
+SDValue TargetLowering::LowerAsmOutputForConstraint(
+    SDValue &Chain, SDValue *Flag, SDLoc DL, const AsmOperandInfo &OpInfo,
+    SelectionDAG &DAG) const {
+  return SDValue();
+}
+
 /// Lower the specified operand into the Ops vector.
 /// If it is invalid, don't add anything to Ops.
 void TargetLowering::LowerAsmOperandForConstraint(SDValue Op,

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=353307&r1=353306&r2=353307&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed Feb  6 07:26:29 2019
@@ -42494,6 +42494,40 @@ bool X86TargetLowering::ExpandInlineAsm(
   return false;
 }
 
+static X86::CondCode parseConstraintCode(llvm::StringRef Constraint) {
+  X86::CondCode Cond = StringSwitch<X86::CondCode>(Constraint)
+                           .Case("{@cca}", X86::COND_A)
+                           .Case("{@ccae}", X86::COND_AE)
+                           .Case("{@ccb}", X86::COND_B)
+                           .Case("{@ccbe}", X86::COND_BE)
+                           .Case("{@ccc}", X86::COND_B)
+                           .Case("{@cce}", X86::COND_E)
+                           .Case("{@ccz}", X86::COND_NE)
+                           .Case("{@ccg}", X86::COND_G)
+                           .Case("{@ccge}", X86::COND_GE)
+                           .Case("{@ccl}", X86::COND_L)
+                           .Case("{@ccle}", X86::COND_LE)
+                           .Case("{@ccna}", X86::COND_BE)
+                           .Case("{@ccnae}", X86::COND_B)
+                           .Case("{@ccnb}", X86::COND_AE)
+                           .Case("{@ccnbe}", X86::COND_A)
+                           .Case("{@ccnc}", X86::COND_AE)
+                           .Case("{@ccne}", X86::COND_NE)
+                           .Case("{@ccnz}", X86::COND_NE)
+                           .Case("{@ccng}", X86::COND_LE)
+                           .Case("{@ccnge}", X86::COND_L)
+                           .Case("{@ccnl}", X86::COND_GE)
+                           .Case("{@ccnle}", X86::COND_G)
+                           .Case("{@ccno}", X86::COND_NO)
+                           .Case("{@ccnp}", X86::COND_P)
+                           .Case("{@ccns}", X86::COND_NS)
+                           .Case("{@cco}", X86::COND_O)
+                           .Case("{@ccp}", X86::COND_P)
+                           .Case("{@ccs}", X86::COND_S)
+                           .Default(X86::COND_INVALID);
+  return Cond;
+}
+
 /// Given a constraint letter, return the type of constraint for this target.
 X86TargetLowering::ConstraintType
 X86TargetLowering::getConstraintType(StringRef Constraint) const {
@@ -42554,7 +42588,8 @@ X86TargetLowering::getConstraintType(Str
         return C_RegisterClass;
       }
     }
-  }
+  } else if (parseConstraintCode(Constraint) != X86::COND_INVALID)
+    return C_Other;
   return TargetLowering::getConstraintType(Constraint);
 }
 
@@ -42725,6 +42760,33 @@ LowerXConstraint(EVT ConstraintVT) const
   return TargetLowering::LowerXConstraint(ConstraintVT);
 }
 
+// Lower @cc targets via setcc.
+SDValue X86TargetLowering::LowerAsmOutputForConstraint(
+    SDValue &Chain, SDValue *Flag, SDLoc DL, const AsmOperandInfo &OpInfo,
+    SelectionDAG &DAG) const {
+  X86::CondCode Cond = parseConstraintCode(OpInfo.ConstraintCode);
+  if (Cond == X86::COND_INVALID)
+    return SDValue();
+  // Check that return type is valid.
+  if (OpInfo.ConstraintVT.isVector() || !OpInfo.ConstraintVT.isInteger() ||
+      OpInfo.ConstraintVT.getSizeInBits() < 8)
+    report_fatal_error("Flag output operand is of invalid type");
+
+  // Get EFLAGS register. Only update chain when copyfrom is glued.
+  SDValue EFlags;
+  if (Flag) {
+    EFlags = DAG.getCopyFromReg(Chain, DL, X86::EFLAGS, MVT::i32, *Flag);
+    Chain = EFlags.getValue(1);
+  } else
+    EFlags = DAG.getCopyFromReg(Chain, DL, X86::EFLAGS, MVT::i32);
+  // Extract CC code.
+  SDValue CC = getSETCC(Cond, EFlags, DL, DAG);
+  // Extend to 32-bits
+  SDValue Result = DAG.getNode(ISD::ZERO_EXTEND, DL, OpInfo.ConstraintVT, CC);
+
+  return Result;
+}
+
 /// Lower the specified operand into the Ops vector.
 /// If it is invalid, don't add anything to Ops.
 void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
@@ -43081,6 +43143,9 @@ X86TargetLowering::getRegForInlineAsmCon
     }
   }
 
+  if (parseConstraintCode(Constraint) != X86::COND_INVALID)
+    return std::make_pair(0U, &X86::GR32RegClass);
+
   // Use the default implementation in TargetLowering to convert the register
   // constraint into a member of a register class.
   std::pair<unsigned, const TargetRegisterClass*> Res;

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=353307&r1=353306&r2=353307&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Wed Feb  6 07:26:29 2019
@@ -923,6 +923,11 @@ namespace llvm {
       return TargetLowering::getInlineAsmMemConstraint(ConstraintCode);
     }
 
+    /// Handle Lowering flag assembly outputs.
+    SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue *Flag, SDLoc DL,
+                                        const AsmOperandInfo &Constraint,
+                                        SelectionDAG &DAG) const override;
+
     /// Given a physical register constraint
     /// (e.g. {edx}), return the register number and the register class for the
     /// register.  This should only be used for C_Register constraints.  On

Added: llvm/trunk/test/CodeGen/X86/inline-asm-flag-output.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inline-asm-flag-output.ll?rev=353307&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/inline-asm-flag-output.ll (added)
+++ llvm/trunk/test/CodeGen/X86/inline-asm-flag-output.ll Wed Feb  6 07:26:29 2019
@@ -0,0 +1,954 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686--   -no-integrated-as | FileCheck %s -check-prefix=X32
+; RUN: llc < %s -mtriple=x86_64-- -no-integrated-as | FileCheck %s -check-prefix=X64
+
+define i32 @test_cca(i64 %nr, i64* %addr) {
+; X32-LABEL: test_cca:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setbe %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_cca:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setbe %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@cca},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccae(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccae:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setb %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccae:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setb %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccae},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccb(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccb:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setae %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccb:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setae %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccb},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccbe(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccbe:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    seta %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccbe:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    seta %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccbe},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccc(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccc:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setae %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccc:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setae %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccc},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_cce(i64 %nr, i64* %addr) {
+; X32-LABEL: test_cce:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setne %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_cce:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setne %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@cce},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccz(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccz:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    sete %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccz:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    sete %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccz},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccg(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccg:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setle %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccg:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setle %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccg},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccge(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccge:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setl %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccge:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setl %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccge},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccl(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccl:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setge %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccl:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setge %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccl},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccle(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccle:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setg %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccle:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setg %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccle},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccna(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccna:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    seta %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccna:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    seta %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccna},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnae(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnae:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setae %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnae:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setae %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnae},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnb(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnb:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setb %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnb:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setb %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnb},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnbe(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnbe:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setbe %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnbe:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setbe %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnbe},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnc(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnc:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setb %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnc:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setb %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnc},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccne(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccne:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    sete %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccne:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    sete %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccne},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnz(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnz:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    sete %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnz:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    sete %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnz},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccng(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccng:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setg %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccng:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setg %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccng},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnge(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnge:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setge %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnge:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setge %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnge},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnl(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnl:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setl %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnl:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setl %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnl},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnle(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnle:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setle %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnle:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setle %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnle},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccno(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccno:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    seto %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccno:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    seto %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccno},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccnp(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccnp:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setnp %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccnp:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setnp %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccnp},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccns(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccns:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    sets %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccns:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    sets %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccns},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_cco(i64 %nr, i64* %addr) {
+; X32-LABEL: test_cco:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setno %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_cco:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setno %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@cco},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccp(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccp:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setnp %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccp:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setnp %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccp},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}
+
+
+define i32 @test_ccs(i64 %nr, i64* %addr) {
+; X32-LABEL: test_ccs:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    pushl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 8
+; X32-NEXT:    .cfi_offset %esi, -8
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X32-NEXT:    xorl %eax, %eax
+; X32-NEXT:    #APP
+; X32-NEXT:    cmp %ecx,(%esi)
+; X32-NEXT:    #NO_APP
+; X32-NEXT:    setns %al
+; X32-NEXT:    popl %esi
+; X32-NEXT:    .cfi_def_cfa_offset 4
+; X32-NEXT:    retl
+;
+; X64-LABEL: test_ccs:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    xorl %eax, %eax
+; X64-NEXT:    #APP
+; X64-NEXT:    cmp %rdi,(%rsi)
+; X64-NEXT:    #NO_APP
+; X64-NEXT:    setns %al
+; X64-NEXT:    retq
+entry:
+  %cc = tail call i32 asm "cmp $2,$1", "={@ccs},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr) nounwind
+  %tobool = icmp eq i32 %cc, 0
+  %rv = zext i1 %tobool to i32
+  ret i32 %rv
+}




More information about the llvm-commits mailing list