[llvm-commits] [llvm] r73622 - in /llvm/trunk: lib/Target/ARM/ARMISelDAGToDAG.cpp lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/ARMInstrThumb2.td lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp test/CodeGen/ARM/thumb2-add.ll test/CodeGen/ARM/thumb2-mov.ll test/CodeGen/ARM/thumb2-mov2.ll test/CodeGen/ARM/thumb2-shifter.ll

Anton Korobeynikov asl at math.spbu.ru
Wed Jun 17 11:13:59 PDT 2009


Author: asl
Date: Wed Jun 17 13:13:58 2009
New Revision: 73622

URL: http://llvm.org/viewvc/llvm-project?rev=73622&view=rev
Log:
Initial support for some Thumb2 instructions.
Patch by Viktor Kutuzov and Anton Korzh from Access Softek, Inc.

Added:
    llvm/trunk/test/CodeGen/ARM/thumb2-add.ll
    llvm/trunk/test/CodeGen/ARM/thumb2-mov.ll
    llvm/trunk/test/CodeGen/ARM/thumb2-mov2.ll
    llvm/trunk/test/CodeGen/ARM/thumb2-shifter.ll
Modified:
    llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp

Modified: llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp?rev=73622&r1=73621&r2=73622&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp Wed Jun 17 13:13:58 2009
@@ -52,8 +52,13 @@
 
   virtual const char *getPassName() const {
     return "ARM Instruction Selection";
-  } 
-  
+  }
+
+ /// getI32Imm - Return a target constant with the specified value, of type i32.
+  inline SDValue getI32Imm(unsigned Imm) {
+    return CurDAG->getTargetConstant(Imm, MVT::i32);
+  }
+
   SDNode *Select(SDValue Op);
   virtual void InstructionSelect();
   bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base,
@@ -84,6 +89,9 @@
   bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base,
                              SDValue &OffImm);
 
+  bool SelectShifterOperand(SDValue Op, SDValue N,
+                            SDValue &BaseReg, SDValue &Opc);
+
   bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A,
                                SDValue &B, SDValue &C);
   
@@ -509,8 +517,30 @@
   return false;
 }
 
+bool ARMDAGToDAGISel::SelectShifterOperand(SDValue Op,
+                                           SDValue N,
+                                           SDValue &BaseReg,
+                                           SDValue &Opc) {
+  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
+
+  // Don't match base register only case. That is matched to a separate
+  // lower complexity pattern with explicit register operand.
+  if (ShOpcVal == ARM_AM::no_shift) return false;
+
+  BaseReg = N.getOperand(0);
+  unsigned ShImmVal = 0;
+  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)))
+    ShImmVal = RHS->getZExtValue() & 31;
+  else
+    return false;
+
+  Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
+
+  return true;
+}
+
 bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op,
-                                              SDValue N, 
+                                              SDValue N,
                                               SDValue &BaseReg,
                                               SDValue &ShReg,
                                               SDValue &Opc) {
@@ -549,6 +579,10 @@
   switch (N->getOpcode()) {
   default: break;
   case ISD::Constant: {
+    // ARMv6T2 and later should materialize imms via MOV / MOVT pair.
+    if (Subtarget->hasV6T2Ops() || Subtarget->hasThumb2())
+      break;
+
     unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
     bool UseCP = true;
     if (Subtarget->isThumb())

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=73622&r1=73621&r2=73622&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Wed Jun 17 13:13:58 2009
@@ -1385,6 +1385,12 @@
 include "ARMInstrThumb.td"
 
 //===----------------------------------------------------------------------===//
+// Thumb2 Support
+//
+
+include "ARMInstrThumb2.td"
+
+//===----------------------------------------------------------------------===//
 // Floating Point Support
 //
 

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=73622&r1=73621&r2=73622&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Wed Jun 17 13:13:58 2009
@@ -10,3 +10,199 @@
 // This file describes the Thumb2 instruction set.
 //
 //===----------------------------------------------------------------------===//
+
+// Shifted operands. No register controlled shifts for Thumb2.
+// Note: We do not support rrx shifted operands yet.
+def t2_so_reg : Operand<i32>,    // reg imm
+                ComplexPattern<i32, 2, "SelectShifterOperand",
+                               [shl,srl,sra,rotr]> {
+  let PrintMethod = "printSOOperand";
+  let MIOperandInfo = (ops GPR, i32imm);
+}
+
+def LO16 : SDNodeXForm<imm, [{
+  // Transformation function: shift the immediate value down into the low bits.
+  return getI32Imm((unsigned short)N->getZExtValue());
+}]>;
+
+def HI16 : SDNodeXForm<imm, [{
+  // Transformation function: shift the immediate value down into the low bits.
+  return getI32Imm((unsigned)N->getZExtValue() >> 16);
+}]>;
+
+def imm16high : PatLeaf<(i32 imm), [{
+  // Returns true if all bits out of the [31..16] range are 0.
+  return ((N->getZExtValue() & 0xFFFF0000ULL) == N->getZExtValue());
+}], HI16>;
+
+def imm16high0xffff : PatLeaf<(i32 imm), [{
+  // Returns true if lo 16 bits are set and this is a 32-bit value. 
+  return ((N->getZExtValue() & 0x0000FFFFULL) == 0xFFFFULL);
+}], HI16>;
+
+def imm0_4095 : PatLeaf<(i32 imm), [{ 
+  return (uint32_t)N->getZExtValue() < 4096; 
+}]>; 
+
+def imm0_4095_neg : PatLeaf<(i32 imm), [{ 
+ return (uint32_t)-N->getZExtValue() < 4096; 
+}], imm_neg_XFORM>; 
+
+def imm0_65535 : PatLeaf<(i32 imm), [{ 
+  return N->getZExtValue() < 65536; 
+}]>; 
+
+// A6.3.2 Modified immediate constants in Thumb instructions (#<const>)
+// FIXME: Move it the the addrmode matcher code.
+def t2_so_imm : PatLeaf<(i32 imm), [{
+  uint64_t v = N->getZExtValue();
+  if (v == 0 || v > 0xffffffffUL) return false;
+  // variant1 - 0b0000x - 8-bit which could be zero (not supported for now)
+
+  // variant2 - 0b00nnx - 8-bit repeated inside the 32-bit room
+  unsigned hi16 = (unsigned)(v >> 16);
+  unsigned lo16 = (unsigned)(v & 0xffffUL);
+  bool valid = (hi16 == lo16) && (
+    (v & 0x00ff00ffUL) == 0 ||        // type 0001x
+    (v & 0xff00ff00UL) == 0 ||        // type 0010x
+    ((lo16 >> 8) == (lo16 & 0xff)));  // type 0011x
+  if (valid) return true;
+
+  // variant3 - 0b01000..0b11111 - 8-bit shifted inside the 32-bit room
+  unsigned shift = CountLeadingZeros_32(v);
+  uint64_t mask = (0xff000000ULL >> shift);
+  // If valid, it is type 01000 + shift
+  return ((shift < 24) && (v & mask) > 0) && ((v & (~mask)) == 0);
+}]>;
+
+
+//===----------------------------------------------------------------------===//
+//  Thumb-2 to cover the functionality of the ARM instruction set.
+//
+
+/// T2I_bin_irs - Defines a set of (op reg, {so_imm|reg|so_reg}) patterns for a
+//  binary operation that produces a value.
+multiclass T2I_bin_irs<string opc, PatFrag opnode> {
+   // shifted imm
+   def ri : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+                       !strconcat(opc, " $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+                      Requires<[HasThumb2]>;
+   // register
+   def rr : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+                       !strconcat(opc, " $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, 
+                      Requires<[HasThumb2]>;
+   // shifted register
+   def rs : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+                       !strconcat(opc, " $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, 
+                      Requires<[HasThumb2]>;
+}
+
+/// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
+/// instruction modifies the CPSR register.
+let Defs = [CPSR] in {
+multiclass T2I_bin_s_irs<string opc, PatFrag opnode> {
+   // shifted imm
+   def ri : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+                       !strconcat(opc, "s $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+                      Requires<[HasThumb2]>;
+
+   // register
+   def rr : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+                       !strconcat(opc, "s $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, 
+                      Requires<[HasThumb2]>;
+
+   // shifted register
+   def rs : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+                       !strconcat(opc, "s $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, 
+                      Requires<[HasThumb2]>;
+}
+}
+
+/// T2I_bin_c_irs - Similar to T2I_bin_irs except it uses the 's' bit. Also the
+/// instruction can optionally set the CPSR register.
+let Uses = [CPSR] in {
+multiclass T2I_bin_c_irs<string opc, PatFrag opnode> {
+   // shifted imm
+   def ri : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs, cc_out:$s),
+                       !strconcat(opc, "${s} $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+                      Requires<[HasThumb2]>;
+
+   // register
+   def rr : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs, cc_out:$s),
+                       !strconcat(opc, "${s} $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, 
+                      Requires<[HasThumb2]>;
+
+   // shifted register
+   def rs : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs, cc_out:$s),
+                       !strconcat(opc, "${s} $dst, $lhs, $rhs"),
+                       [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, 
+                      Requires<[HasThumb2]>;
+}
+}
+
+//===----------------------------------------------------------------------===//
+//  Arithmetic Instructions.
+//
+
+//===----------------------------------------------------------------------===//
+//  Move Instructions.
+//
+def tMOVi16  : PseudoInst<(outs GPR:$dst), (ins i32imm:$src),
+                          "mov $dst, $src",
+                          [(set GPR:$dst, imm0_65535:$src)]>, 
+                         Requires<[HasThumb2]>;
+
+let isTwoAddress = 1 in
+def tMOVTi16 : PseudoInst<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm),
+                          "movt $dst, $imm",
+                          [(set GPR:$dst, (or (and GPR:$src, 0xffff), 
+                                              imm16high:$imm))]>,
+                         Requires<[HasThumb2]>;
+
+def : Pat<(and (or GPR:$src, imm16high:$imm1), imm16high0xffff:$imm2),
+          (tMOVTi16 GPR:$src, (HI16 imm16high:$imm1))>,
+         Requires<[HasThumb2]>;
+
+def : Pat<(i32 imm:$imm),
+          (tMOVTi16 (tMOVi16 (LO16 imm:$imm)),(HI16 imm:$imm))>,
+         Requires<[HasThumb2]>;
+
+//===----------------------------------------------------------------------===//
+//  Arithmetic Instructions.
+//
+defm t2ADD  : T2I_bin_irs <"add", BinOpFrag<(add node:$LHS, node:$RHS)>>;
+defm t2SUB  : T2I_bin_irs <"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
+
+def tADDri12 : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+                          "add $dst, $lhs, $rhs", 
+                          [(set GPR:$dst, (add GPR:$lhs, imm0_4095:$rhs))]>,
+                         Requires<[HasThumb2]>; 
+def tSUBri12 : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), 
+                          "sub $dst, $lhs, $rhs",
+                          [(set GPR:$dst, (add GPR:$lhs, imm0_4095_neg:$rhs))]>,
+                         Requires<[HasThumb2]>;
+
+defm t2ADDS : T2I_bin_s_irs<"add", BinOpFrag<(addc node:$LHS, node:$RHS)>>;
+defm t2SUBS : T2I_bin_s_irs<"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
+
+defm t2ADC : T2I_bin_c_irs<"adc", BinOpFrag<(adde node:$LHS, node:$RHS)>>;
+defm t2SBC : T2I_bin_c_irs<"sbc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
+
+
+def tMLS : PseudoInst<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), 
+                      "mls $dst, $a, $b, $c", 
+                      [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>,
+                     Requires<[HasThumb2]>;
+
+def tORNrs : PseudoInst<(outs GPR:$dst), (ins GPR:$src1, t2_so_reg:$src2),
+                        "orn $dst, $src1, $src2",
+                        [(set GPR:$dst, (or GPR:$src1, (not t2_so_reg: $src2)))]>,
+                       Requires<[HasThumb2]>;

Modified: llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp?rev=73622&r1=73621&r2=73622&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp Wed Jun 17 13:13:58 2009
@@ -97,6 +97,7 @@
                       const char *Modifier = 0);
     void printSOImmOperand(const MachineInstr *MI, int opNum);
     void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
+    void printSOOperand(const MachineInstr *MI, int OpNum);
     void printSORegOperand(const MachineInstr *MI, int opNum);
     void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
     void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
@@ -396,6 +397,28 @@
   printSOImm(O, ARM_AM::getSOImmVal(V2), VerboseAsm, TAI);
 }
 
+// Constant shifts so_reg is a 3-operand unit corresponding to register forms of
+// the A5.1 "Addressing Mode 1 - Data-processing operands" forms.  This
+// includes:
+// REG 0 - e.g. R5
+// REG IMM, SH_OPC - e.g. R5, LSL #3
+void ARMAsmPrinter::printSOOperand(const MachineInstr *MI, int OpNum) {
+  const MachineOperand &MO1 = MI->getOperand(OpNum);
+  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
+
+  unsigned Reg = MO1.getReg();
+  assert(TargetRegisterInfo::isPhysicalRegister(Reg));
+  O << TM.getRegisterInfo()->getAsmName(Reg);
+
+  // Print the shift opc.
+  O << ", "
+    << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
+    << " ";
+
+  assert(MO2.isImm() && "Not a valid t2_so_reg value!");
+  O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
+}
+
 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
 // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
 //    REG 0   0    - e.g. R5

Added: llvm/trunk/test/CodeGen/ARM/thumb2-add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/thumb2-add.ll?rev=73622&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/ARM/thumb2-add.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/thumb2-add.ll Wed Jun 17 13:13:58 2009
@@ -0,0 +1,50 @@
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep add | grep #255
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep add | grep #256
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep add | grep #257
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep add | grep #4094
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep add | grep #4095
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep add | grep #4096
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep add
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep add | grep lsl | grep #8
+
+define i32 @t2ADDrc_255(i32 %lhs) {
+    %Rd = add i32 %lhs, 255;
+    ret i32 %Rd
+}
+
+define i32 @t2ADDrc_256(i32 %lhs) {
+    %Rd = add i32 %lhs, 256;
+    ret i32 %Rd
+}
+
+define i32 @t2ADDrc_257(i32 %lhs) {
+    %Rd = add i32 %lhs, 257;
+    ret i32 %Rd
+}
+
+define i32 @t2ADDrc_4094(i32 %lhs) {
+    %Rd = add i32 %lhs, 4094;
+    ret i32 %Rd
+}
+
+define i32 @t2ADDrc_4095(i32 %lhs) {
+    %Rd = add i32 %lhs, 4095;
+    ret i32 %Rd
+}
+
+define i32 @t2ADDrc_4096(i32 %lhs) {
+    %Rd = add i32 %lhs, 4096;
+    ret i32 %Rd
+}
+
+define i32 @t2ADDrr(i32 %lhs, i32 %rhs) {
+    %Rd = add i32 %lhs, %rhs;
+    ret i32 %Rd
+}
+
+define i32 @t2ADDrs(i32 %lhs, i32 %rhs) {
+    %tmp = shl i32 %rhs, 8
+    %Rd = add i32 %lhs, %tmp;
+    ret i32 %Rd
+}
+

Added: llvm/trunk/test/CodeGen/ARM/thumb2-mov.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/thumb2-mov.ll?rev=73622&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/ARM/thumb2-mov.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/thumb2-mov.ll Wed Jun 17 13:13:58 2009
@@ -0,0 +1,127 @@
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep #11206827
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep #2868947712
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep #2880154539
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep #251658240
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep #3948544
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep movt
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep #258
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep #4026531840
+
+; Test #<const>
+
+; var 2.1 - 0x00ab00ab
+define i32 @t2_const_var2_1_ok_1(i32 %lhs) {
+    %ret = add i32 %lhs, 11206827 ; 0x00ab00ab
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_1_fail_1(i32 %lhs) {
+    %ret = add i32 %lhs, 11206843 ; 0x00ab00bb
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_1_fail_2(i32 %lhs) {
+    %ret = add i32 %lhs, 27984043 ; 0x01ab00ab
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_1_fail_3(i32 %lhs) {
+    %ret = add i32 %lhs, 27984299 ; 0x01ab01ab
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_1_fail_4(i32 %lhs) {
+    %ret = add i32 %lhs, 28027649 ; 0x01abab01
+    ret i32 %ret
+}
+
+; var 2.2 - 0xab00ab00
+define i32 @t2_const_var2_2_ok_1(i32 %lhs) {
+    %ret = add i32 %lhs, 2868947712 ; 0xab00ab00
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_2_fail_1(i32 %lhs) {
+    %ret = add i32 %lhs, 2868951552 ; 0xab00ba00
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_2_fail_2(i32 %lhs) {
+    %ret = add i32 %lhs, 2868947728 ; 0xab00ab10
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_2_fail_3(i32 %lhs) {
+    %ret = add i32 %lhs, 2869996304 ; 0xab10ab10
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_2_fail_4(i32 %lhs) {
+    %ret = add i32 %lhs, 279685904 ; 0x10abab10
+    ret i32 %ret
+}
+
+; var 2.3 - 0xabababab
+define i32 @t2_const_var2_3_ok_1(i32 %lhs) {
+    %ret = add i32 %lhs, 2880154539 ; 0xabababab
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_3_fail_1(i32 %lhs) {
+    %ret = add i32 %lhs, 2880154554 ; 0xabababba
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_3_fail_2(i32 %lhs) {
+    %ret = add i32 %lhs, 2880158379 ; 0xababbaab
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_3_fail_3(i32 %lhs) {
+    %ret = add i32 %lhs, 2881137579 ; 0xabbaabab
+    ret i32 %ret
+}
+
+define i32 @t2_const_var2_3_fail_4(i32 %lhs) {
+    %ret = add i32 %lhs, 3131812779 ; 0xbaababab
+    ret i32 %ret
+}
+
+; var 3 - 0x0F000000
+define i32 @t2_const_var3_1_ok_1(i32 %lhs) {
+    %ret = add i32 %lhs, 251658240 ; 0x0F000000
+    ret i32 %ret
+}
+
+define i32 @t2_const_var3_2_ok_1(i32 %lhs) {
+    %ret = add i32 %lhs, 3948544 ; 0b00000000001111000100000000000000
+    ret i32 %ret
+}
+
+define i32 @t2_const_var3_2_fail_1(i32 %lhs) {
+    %ret = add i32 %lhs, 3940352 ; 0b00000000001111000010000000000000
+    ret i32 %ret
+}
+
+define i32 @t2_const_var3_3_ok_1(i32 %lhs) {
+    %ret = add i32 %lhs, 258 ; 0b00000000000000000000000100000010
+    ret i32 %ret
+}
+
+define i32 @t2_const_var3_4_ok_1(i32 %lhs) {
+    %ret = add i32 %lhs, 4026531840 ; 0xF0000000
+    ret i32 %ret
+}
+

Added: llvm/trunk/test/CodeGen/ARM/thumb2-mov2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/thumb2-mov2.ll?rev=73622&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/ARM/thumb2-mov2.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/thumb2-mov2.ll Wed Jun 17 13:13:58 2009
@@ -0,0 +1,65 @@
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep movt | grep #1234
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep movt | grep #1234
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep movt | grep #1234
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep movt | grep #1234
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov  | grep movt
+
+define i32 @t2MOVTi16_ok_1(i32 %a) {
+    %1 = and i32 %a, 65535
+    %2 = shl i32 1234, 16
+    %3 = or  i32 %1, %2
+
+    ret i32 %3
+}
+
+define i32 @t2MOVTi16_test_1(i32 %a) {
+    %1 = shl i32  255,   8
+    %2 = shl i32 1234,   8
+    %3 = or  i32   %1, 255  ; This give us 0xFFFF in %3
+    %4 = shl i32   %2,   8  ; This gives us (1234 << 16) in %4
+    %5 = and i32   %a,  %3
+    %6 = or  i32   %4,  %5
+
+    ret i32 %6
+}
+
+define i32 @t2MOVTi16_test_2(i32 %a) {
+    %1 = shl i32  255,   8
+    %2 = shl i32 1234,   8
+    %3 = or  i32   %1, 255  ; This give us 0xFFFF in %3
+    %4 = shl i32   %2,   6
+    %5 = and i32   %a,  %3
+    %6 = shl i32   %4,   2  ; This gives us (1234 << 16) in %6
+    %7 = or  i32   %5,  %6
+
+    ret i32 %7
+}
+
+define i32 @t2MOVTi16_test_3(i32 %a) {
+    %1 = shl i32  255,   8
+    %2 = shl i32 1234,   8
+    %3 = or  i32   %1, 255  ; This give us 0xFFFF in %3
+    %4 = shl i32   %2,   6
+    %5 = and i32   %a,  %3
+    %6 = shl i32   %4,   2  ; This gives us (1234 << 16) in %6
+    %7 = lshr i32  %6,   6
+    %8 = shl i32   %7,   6
+    %9 = or  i32   %5,  %8
+
+    ret i32 %9
+}
+
+define i32 @t2MOVTi16_test_nomatch_1(i32 %a) {
+    %1 = shl i32  255,   8
+    %2 = shl i32 1234,   8
+    %3 = or  i32   %1, 255  ; This give us 0xFFFF in %3
+    %4 = shl i32   %2,   6
+    %5 = and i32   %a,  %3
+    %6 = shl i32   %4,   2  ; This gives us (1234 << 16) in %6
+    %7 = lshr i32  %6,   3
+    %8 = or  i32   %5,  %7
+
+    ret i32 %8
+}
+
+

Added: llvm/trunk/test/CodeGen/ARM/thumb2-shifter.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/thumb2-shifter.ll?rev=73622&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/ARM/thumb2-shifter.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/thumb2-shifter.ll Wed Jun 17 13:13:58 2009
@@ -0,0 +1,40 @@
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep lsl
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep lsr
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep asr
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep ror
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov
+
+define i32 @t2ADDrs_lsl(i32 %X, i32 %Y) {
+        %A = shl i32 %Y, 16
+        %B = add i32 %X, %A
+        ret i32 %B
+}
+
+define i32 @t2ADDrs_lsr(i32 %X, i32 %Y) {
+        %A = lshr i32 %Y, 16
+        %B = add i32 %X, %A
+        ret i32 %B
+}
+
+define i32 @t2ADDrs_asr(i32 %X, i32 %Y) {
+        %A = ashr i32 %Y, 16
+        %B = add i32 %X, %A
+        ret i32 %B
+}
+
+; i32 ror(n) = (x >> n) | (x << (32 - n))
+define i32 @t2ADDrs_ror(i32 %X, i32 %Y) {
+        %A = lshr i32 %Y, 16
+        %B = shl  i32 %Y, 16
+        %C = or   i32 %B, %A
+        %R = add  i32 %X, %C
+        ret i32 %R
+}
+
+define i32 @t2ADDrs_noRegShift(i32 %X, i32 %Y, i8 %sh) {
+        %shift.upgrd.1 = zext i8 %sh to i32
+        %A = shl i32 %Y, %shift.upgrd.1
+        %B = add i32 %X, %A
+        ret i32 %B
+}
+





More information about the llvm-commits mailing list