aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2009-06-25 23:34:10 +0000
committerEvan Cheng <evan.cheng@apple.com>2009-06-25 23:34:10 +0000
commit626742231863db0e9aeef1be1fd48e9f4b7e22f8 (patch)
tree493aacbcc694b2ab84e68d197f6323f3bc8bec8c
parent0b49c32c56443a41f76c415bddc226488217da2f (diff)
downloadexternal_llvm-626742231863db0e9aeef1be1fd48e9f4b7e22f8.zip
external_llvm-626742231863db0e9aeef1be1fd48e9f4b7e22f8.tar.gz
external_llvm-626742231863db0e9aeef1be1fd48e9f4b7e22f8.tar.bz2
Select ADC, SBC, and RSC instead of the ADCS, SBCS, and RSCS when the carry bit def is not used.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74228 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td71
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td90
-rw-r--r--test/CodeGen/ARM/carry.ll4
-rw-r--r--test/CodeGen/Thumb2/carry.ll4
4 files changed, 120 insertions, 49 deletions
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index a2a8607..4958f70 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -103,6 +103,8 @@ def HasThumb2 : Predicate<"Subtarget->hasThumb2()">;
def IsARM : Predicate<"!Subtarget->isThumb()">;
def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">;
def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">;
+def CarryDefIsUnused : Predicate<"N.getNode()->hasNUsesOfValue(0, 1)">;
+def CarryDefIsUsed : Predicate<"N.getNode()->hasAnyUseOfValue(1)">;
//===----------------------------------------------------------------------===//
// ARM Flag Definitions.
@@ -430,19 +432,40 @@ multiclass AI_bin_rrot<bits<8> opcod, string opc, PatFrag opnode> {
Requires<[IsARM, HasV6]>;
}
-/// AI1_bin_cs_irs - A binary operation that both uses and defines CPSR. It's
-/// currently not predicable.
-let Defs = [CPSR], Uses = [CPSR] in {
-multiclass AI1_bin_cs_irs<bits<4> opcod, string opc, PatFrag opnode> {
- def ri : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
+/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube.
+let Uses = [CPSR] in {
+multiclass AI1_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode> {
+ def ri : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
+ DPFrm, opc, " $dst, $a, $b",
+ [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+ def rr : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
+ DPFrm, opc, " $dst, $a, $b",
+ [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+ def rs : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
+ DPSoRegFrm, opc, " $dst, $a, $b",
+ [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+ // Carry setting variants
+ def Sri : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
DPFrm, !strconcat(opc, "s $dst, $a, $b"),
- [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
- def rr : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
+ [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>,
+ Requires<[IsARM, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+ def Srr : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
DPFrm, !strconcat(opc, "s $dst, $a, $b"),
- [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
- def rs : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
+ [(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>,
+ Requires<[IsARM, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+ def Srs : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
DPSoRegFrm, !strconcat(opc, "s $dst, $a, $b"),
- [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
+ [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>,
+ Requires<[IsARM, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
}
}
@@ -910,11 +933,10 @@ defm ADDS : AI1_bin_s_irs<0b0100, "add",
defm SUBS : AI1_bin_s_irs<0b0010, "sub",
BinOpFrag<(subc node:$LHS, node:$RHS)>>;
-// FIXME: Do not allow ADCS / SBCS to be predicated for now.
-defm ADCS : AI1_bin_cs_irs<0b0101, "adc",
- BinOpFrag<(adde node:$LHS, node:$RHS)>>;
-defm SBCS : AI1_bin_cs_irs<0b0110, "sbc",
- BinOpFrag<(sube node:$LHS, node:$RHS)>>;
+defm ADC : AI1_adde_sube_irs<0b0101, "adc",
+ BinOpFrag<(adde node:$LHS, node:$RHS)>>;
+defm SBC : AI1_adde_sube_irs<0b0110, "sbc",
+ BinOpFrag<(sube node:$LHS, node:$RHS)>>;
// These don't define reg/reg forms, because they are handled above.
def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
@@ -935,14 +957,27 @@ def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
[(set GPR:$dst, (subc so_reg:$b, GPR:$a))]>;
}
-// FIXME: Do not allow RSC to be predicated for now.
+let Uses = [CPSR] in {
+def RSCri : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
+ DPFrm, "rsc", " $dst, $a, $b",
+ [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+def RSCrs : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
+ DPSoRegFrm, "rsc", " $dst, $a, $b",
+ [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
+}
+
+// FIXME: Allow these to be predicated.
let Defs = [CPSR], Uses = [CPSR] in {
def RSCSri : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
DPFrm, "rscs $dst, $a, $b",
- [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>;
+ [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
def RSCSrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
DPSoRegFrm, "rscs $dst, $a, $b",
- [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>;
+ [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>,
+ Requires<[IsARM, CarryDefIsUnused]>;
}
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 3a44bbd..8276356 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -223,43 +223,80 @@ multiclass T2I_bin_ii12rs<string opc, PatFrag opnode> {
[(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>;
}
-/// T2I_bin_cs_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
+/// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
/// binary operation that produces a value and use and define the carry bit.
/// It's not predicable.
-let Defs = [CPSR], Uses = [CPSR] in {
-multiclass T2I_bin_cs_irs<string opc, PatFrag opnode> {
+let Uses = [CPSR] in {
+multiclass T2I_adde_sube_irs<string opc, PatFrag opnode> {
// shifted imm
- def ri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
- !strconcat(opc, "s $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>;
+ def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
// register
- def rr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
- !strconcat(opc, "s $dst, $lhs, $rhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>;
+ def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ opc, " $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
// shifted register
- def rs : T2XI<(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))]>;
+ def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+ opc, "s $dst, $lhs, $rhs",
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
+ // Carry setting variants
+ // shifted imm
+ def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs),
+ !strconcat(opc, "s $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+ // register
+ def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ !strconcat(opc, "s $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
+ // shifted register
+ def Srs : T2XI<(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<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
}
}
-/// T2I_rbin_cs_is - Same as T2I_bin_cs_irs except the order of operands are
+/// T2I_rsc_is - Same as T2I_adde_sube_irs except the order of operands are
/// reversed. It doesn't define the 'rr' form since it's handled by its
-/// T2I_bin_cs_irs counterpart.
+/// T2I_adde_sube_irs counterpart.
let Defs = [CPSR], Uses = [CPSR] in {
-multiclass T2I_rbin_cs_is<string opc, PatFrag opnode> {
+multiclass T2I_rsc_is<string opc, PatFrag opnode> {
// shifted imm
- def ri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs),
- !strconcat(opc, "s $dst, $rhs, $lhs"),
- [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>;
- // register
- def rr : T2XI<(outs GPR:$dst), (ins GPR:$rhs, GPR:$lhs),
+ def ri : T2sI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs),
+ opc, " $dst, $rhs, $lhs",
+ [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
+ // shifted register
+ def rs : T2sI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs),
+ opc, " $dst, $rhs, $lhs",
+ [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUnused]>;
+ // shifted imm
+ def Sri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs),
!strconcat(opc, "s $dst, $rhs, $lhs"),
- [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>;
+ [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
// shifted register
- def rs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs),
+ def Srs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs),
!strconcat(opc, "s $dst, $rhs, $lhs"),
- [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>;
+ [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>,
+ Requires<[IsThumb, HasThumb2, CarryDefIsUsed]> {
+ let Defs = [CPSR];
+ }
}
}
@@ -385,14 +422,13 @@ defm t2SUB : T2I_bin_ii12rs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
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)>>;
-// FIXME: predication support
-defm t2ADC : T2I_bin_cs_irs<"adc", BinOpFrag<(adde node:$LHS, node:$RHS)>>;
-defm t2SBC : T2I_bin_cs_irs<"sbc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
+defm t2ADC : T2I_adde_sube_irs<"adc", BinOpFrag<(adde node:$LHS, node:$RHS)>>;
+defm t2SBC : T2I_adde_sube_irs<"sbc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
// RSB, RSC
defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
defm t2RSBS : T2I_rbin_s_is <"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
-defm t2RSC : T2I_rbin_cs_is<"rsc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
+defm t2RSC : T2I_rsc_is <"rsc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
def : Thumb2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
diff --git a/test/CodeGen/ARM/carry.ll b/test/CodeGen/ARM/carry.ll
index 82a5693..3bf2dc0 100644
--- a/test/CodeGen/ARM/carry.ll
+++ b/test/CodeGen/ARM/carry.ll
@@ -1,6 +1,6 @@
; RUN: llvm-as < %s | llc -march=arm | grep "subs r" | count 2
-; RUN: llvm-as < %s | llc -march=arm | grep adc
-; RUN: llvm-as < %s | llc -march=arm | grep sbc
+; RUN: llvm-as < %s | llc -march=arm | grep "adc r"
+; RUN: llvm-as < %s | llc -march=arm | grep "sbc r" | count 2
define i64 @f1(i64 %a, i64 %b) {
entry:
diff --git a/test/CodeGen/Thumb2/carry.ll b/test/CodeGen/Thumb2/carry.ll
index aa551c7..3450c5a 100644
--- a/test/CodeGen/Thumb2/carry.ll
+++ b/test/CodeGen/Thumb2/carry.ll
@@ -1,6 +1,6 @@
; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep "subs r" | count 2
-; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep adc
-; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep sbc
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep "adc r"
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep "sbc r" | count 2
define i64 @f1(i64 %a, i64 %b) {
entry: