- Divides the comparisons in two types: comparisons that only use N and Z
authorLauro Ramos Venancio <lauro.venancio@gmail.com>
Mon, 2 Apr 2007 01:30:03 +0000 (01:30 +0000)
committerLauro Ramos Venancio <lauro.venancio@gmail.com>
Mon, 2 Apr 2007 01:30:03 +0000 (01:30 +0000)
flags (ARMISD::CMPNZ) and comparisons that use all flags (ARMISD::CMP).
- Defines the instructions: TST, TEQ (ARM) and TST (Thumb).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35573 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMISelLowering.h
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb.td
test/CodeGen/ARM/tst_teq.ll [new file with mode: 0644]

index bb715cb3ca48d34351ce433cf84def828094e412..8f3457a0452344896bfff5ffa78a7e7eb3c22e05 100644 (file)
@@ -266,6 +266,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case ARMISD::RET_FLAG:      return "ARMISD::RET_FLAG";
   case ARMISD::PIC_ADD:       return "ARMISD::PIC_ADD";
   case ARMISD::CMP:           return "ARMISD::CMP";
+  case ARMISD::CMPNZ:         return "ARMISD::CMPNZ";
   case ARMISD::CMPFP:         return "ARMISD::CMPFP";
   case ARMISD::CMPFPw0:       return "ARMISD::CMPFPw0";
   case ARMISD::FMSTAT:        return "ARMISD::FMSTAT";
@@ -946,8 +947,21 @@ static SDOperand getARMCmp(SDOperand LHS, SDOperand RHS, ISD::CondCode CC,
   }
 
   ARMCC::CondCodes CondCode = IntCCToARMCC(CC);
+  ARMISD::NodeType CompareType;
+  switch (CondCode) {
+  default:
+    CompareType = ARMISD::CMP;
+    break;
+  case ARMCC::EQ:
+  case ARMCC::NE:
+  case ARMCC::MI:
+  case ARMCC::PL:
+    // Uses only N and Z Flags
+    CompareType = ARMISD::CMPNZ;
+    break;
+  }
   ARMCC = DAG.getConstant(CondCode, MVT::i32);
-  return DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
+  return DAG.getNode(CompareType, MVT::Flag, LHS, RHS);
 }
 
 /// Returns a appropriate VFP CMP (fcmp{s|d}+fmstat) for the given operands.
index 8846decd9bf7fef83d0be63274b30e5319c955e5..9842b9248bda88e97654f59575f63f6732ce6a27 100644 (file)
@@ -43,6 +43,7 @@ namespace llvm {
       PIC_ADD,      // Add with a PC operand and a PIC label.
 
       CMP,          // ARM compare instructions.
+      CMPNZ,        // ARM compare that uses only N or Z flags.
       CMPFP,        // ARM VFP compare instruction, sets FPSCR.
       CMPFPw0,      // ARM VFP compare against zero instruction, sets FPSCR.
       FMSTAT,       // ARM fmstat instruction.
index 36d2e4a0460fa8f37f3a6b5bf1a8d68585f9cbb5..1c3e34bd3044ff300bdeb0806129818805914f71 100644 (file)
@@ -70,6 +70,9 @@ def ARMbrjt          : SDNode<"ARMISD::BR_JT", SDT_ARMBrJT,
 def ARMcmp           : SDNode<"ARMISD::CMP", SDT_ARMCmp,
                               [SDNPOutFlag]>;
 
+def ARMcmpNZ         : SDNode<"ARMISD::CMPNZ", SDT_ARMCmp,
+                              [SDNPOutFlag]>;
+
 def ARMpic_add       : SDNode<"ARMISD::PIC_ADD", SDT_ARMPICAdd>;
 
 def ARMsrl_flag      : SDNode<"ARMISD::SRL_FLAG", SDTIntUnaryOp, [SDNPOutFlag]>;
@@ -1023,10 +1026,15 @@ def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm),
              (CMNri  GPR:$src, so_imm_neg:$imm)>;
 
 // Note that TST/TEQ don't set all the same flags that CMP does!
-def TSTrr : AI1<(ops GPR:$a, so_reg:$b), "tst $a, $b", []>;
-def TSTri : AI1<(ops GPR:$a, so_imm:$b), "tst $a, $b", []>;
-def TEQrr : AI1<(ops GPR:$a, so_reg:$b), "teq $a, $b", []>;
-def TEQri : AI1<(ops GPR:$a, so_imm:$b), "teq $a, $b", []>;
+defm TST  : AI1_bin0_irs<"tst", BinOpFrag<(ARMcmpNZ (and node:$LHS, node:$RHS), 0)>>;
+defm TEQ  : AI1_bin0_irs<"teq", BinOpFrag<(ARMcmpNZ (xor node:$LHS, node:$RHS), 0)>>;
+
+defm CMPnz : AI1_bin0_irs<"cmp", BinOpFrag<(ARMcmpNZ node:$LHS, node:$RHS)>>;
+defm CMNnz : AI1_bin0_irs<"cmn", BinOpFrag<(ARMcmpNZ node:$LHS,(ineg node:$RHS))>>;
+
+def : ARMPat<(ARMcmpNZ GPR:$src, so_imm_neg:$imm),
+             (CMNri  GPR:$src, so_imm_neg:$imm)>;
+
 
 // Conditional moves
 def MOVCCr : AI<(ops GPR:$dst, GPR:$false, GPR:$true, CCOp:$cc),
index ad8a88f2077fa61eee9ef7f0b0f3f7fd7479222f..48196369addd7b159bd3b25b33797b08ef35ab58 100644 (file)
@@ -356,7 +356,23 @@ def tCMPi8 : TI<(ops GPR:$lhs, i32imm:$rhs),
 def tCMPr : TI<(ops GPR:$lhs, GPR:$rhs),
                "cmp $lhs, $rhs",
                [(ARMcmp GPR:$lhs, GPR:$rhs)]>;
-               
+
+def tTST  : TI<(ops GPR:$lhs, GPR:$rhs),
+               "tst $lhs, $rhs",
+               [(ARMcmpNZ (and GPR:$lhs, GPR:$rhs), 0)]>;
+
+def tCMNNZ : TI<(ops GPR:$lhs, GPR:$rhs),
+                "cmn $lhs, $rhs",
+                [(ARMcmpNZ GPR:$lhs, (ineg GPR:$rhs))]>;
+
+def tCMPNZi8 : TI<(ops GPR:$lhs, i32imm:$rhs),
+                 "cmp $lhs, $rhs",
+                 [(ARMcmpNZ GPR:$lhs, imm0_255:$rhs)]>;
+
+def tCMPNZr : TI<(ops GPR:$lhs, GPR:$rhs),
+                 "cmp $lhs, $rhs",
+                 [(ARMcmpNZ GPR:$lhs, GPR:$rhs)]>;
+
 // TODO: A7-37: CMP(3) - cmp hi regs
 
 def tEOR : TIt<(ops GPR:$dst, GPR:$lhs, GPR:$rhs),
@@ -472,7 +488,6 @@ def tSXTH  : TI<(ops GPR:$dst, GPR:$src),
                 [(set GPR:$dst, (sext_inreg GPR:$src, i16))]>,
                 Requires<[IsThumb, HasV6]>;
 
-// TODO: A7-122: TST - test.
 
 def tUXTB  : TI<(ops GPR:$dst, GPR:$src),
                 "uxtb $dst, $src",
diff --git a/test/CodeGen/ARM/tst_teq.ll b/test/CodeGen/ARM/tst_teq.ll
new file mode 100644 (file)
index 0000000..fb2f73b
--- /dev/null
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | llc -march=arm &&
+; RUN: llvm-as < %s | llc -march=thumb &&
+; RUN: llvm-as < %s | llc -march=arm | grep "tst" &&
+; RUN: llvm-as < %s | llc -march=arm | grep "teq" &&
+; RUN: llvm-as < %s | llc -march=thumb | grep "tst"
+
+define i32 @f(i32 %a) {
+entry:
+       %tmp2 = and i32 %a, 255         ; <i32> [#uses=1]
+       icmp eq i32 %tmp2, 0            ; <i1>:0 [#uses=1]
+       %retval = select i1 %0, i32 20, i32 10          ; <i32> [#uses=1]
+       ret i32 %retval
+}
+
+define i32 @g(i32 %a) {
+entry:
+        %tmp2 = xor i32 %a, 255
+       icmp eq i32 %tmp2, 0            ; <i1>:0 [#uses=1]
+       %retval = select i1 %0, i32 20, i32 10          ; <i32> [#uses=1]
+       ret i32 %retval
+}