forked from OSchip/llvm-project
[FastISel][AArch64] Fix and extend the tbz/tbnz pattern matching.
The pattern matching failed to recognize all instances of "-1", because when comparing against "-1" we didn't use an APInt of the same bitwidth. This commit fixes this and also adds inverse versions of the conditon to catch more cases. llvm-svn: 222722
This commit is contained in:
parent
32d1a96d69
commit
eb67bd8d74
|
@ -2112,15 +2112,15 @@ bool AArch64FastISel::emitCompareAndBranch(const BranchInst *BI) {
|
|||
|
||||
int TestBit = -1;
|
||||
bool IsCmpNE;
|
||||
if ((Predicate == CmpInst::ICMP_EQ) || (Predicate == CmpInst::ICMP_NE)) {
|
||||
if (const auto *C = dyn_cast<Constant>(LHS))
|
||||
if (C->isNullValue())
|
||||
switch (Predicate) {
|
||||
default:
|
||||
return false;
|
||||
case CmpInst::ICMP_EQ:
|
||||
case CmpInst::ICMP_NE:
|
||||
if (isa<Constant>(LHS) && cast<Constant>(LHS)->isNullValue())
|
||||
std::swap(LHS, RHS);
|
||||
|
||||
if (!isa<Constant>(RHS))
|
||||
return false;
|
||||
|
||||
if (!cast<Constant>(RHS)->isNullValue())
|
||||
if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
|
||||
return false;
|
||||
|
||||
if (const auto *AI = dyn_cast<BinaryOperator>(LHS))
|
||||
|
@ -2143,26 +2143,27 @@ bool AArch64FastISel::emitCompareAndBranch(const BranchInst *BI) {
|
|||
TestBit = 0;
|
||||
|
||||
IsCmpNE = Predicate == CmpInst::ICMP_NE;
|
||||
} else if (Predicate == CmpInst::ICMP_SLT) {
|
||||
if (!isa<Constant>(RHS))
|
||||
return false;
|
||||
|
||||
if (!cast<Constant>(RHS)->isNullValue())
|
||||
break;
|
||||
case CmpInst::ICMP_SLT:
|
||||
case CmpInst::ICMP_SGE:
|
||||
if (!isa<Constant>(RHS) || !cast<Constant>(RHS)->isNullValue())
|
||||
return false;
|
||||
|
||||
TestBit = BW - 1;
|
||||
IsCmpNE = true;
|
||||
} else if (Predicate == CmpInst::ICMP_SGT) {
|
||||
IsCmpNE = Predicate == CmpInst::ICMP_SLT;
|
||||
break;
|
||||
case CmpInst::ICMP_SGT:
|
||||
case CmpInst::ICMP_SLE:
|
||||
if (!isa<ConstantInt>(RHS))
|
||||
return false;
|
||||
|
||||
if (cast<ConstantInt>(RHS)->getValue() != -1)
|
||||
if (cast<ConstantInt>(RHS)->getValue() != APInt(BW, -1, true))
|
||||
return false;
|
||||
|
||||
TestBit = BW - 1;
|
||||
IsCmpNE = false;
|
||||
} else
|
||||
return false;
|
||||
IsCmpNE = Predicate == CmpInst::ICMP_SLE;
|
||||
break;
|
||||
} // end switch
|
||||
|
||||
static const unsigned OpcTable[2][2][2] = {
|
||||
{ {AArch64::CBZW, AArch64::CBZX },
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; RUN: llc -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -mtriple=aarch64-apple-darwin < %s | FileCheck %s
|
||||
; RUN: llc -fast-isel -fast-isel-abort -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -mtriple=aarch64-apple-darwin < %s | FileCheck %s
|
||||
; RUN: llc -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -mtriple=aarch64-apple-darwin < %s | FileCheck --check-prefix=CHECK %s
|
||||
; RUN: llc -fast-isel -fast-isel-abort -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -mtriple=aarch64-apple-darwin < %s | FileCheck --check-prefix=CHECK --check-prefix=FAST %s
|
||||
|
||||
define i32 @icmp_eq_i8(i8 zeroext %a) {
|
||||
; CHECK-LABEL: icmp_eq_i8
|
||||
|
@ -121,6 +121,160 @@ bb2:
|
|||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_slt_i8(i8 zeroext %a) {
|
||||
; FAST-LABEL: icmp_slt_i8
|
||||
; FAST: tbnz w0, #7, {{LBB.+_2}}
|
||||
%1 = icmp slt i8 %a, 0
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_slt_i16(i16 zeroext %a) {
|
||||
; FAST-LABEL: icmp_slt_i16
|
||||
; FAST: tbnz w0, #15, {{LBB.+_2}}
|
||||
%1 = icmp slt i16 %a, 0
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_slt_i32(i32 %a) {
|
||||
; CHECK-LABEL: icmp_slt_i32
|
||||
; CHECK: tbnz w0, #31, {{LBB.+_2}}
|
||||
%1 = icmp slt i32 %a, 0
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_slt_i64(i64 %a) {
|
||||
; CHECK-LABEL: icmp_slt_i64
|
||||
; CHECK: tbnz x0, #63, {{LBB.+_2}}
|
||||
%1 = icmp slt i64 %a, 0
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sge_i8(i8 zeroext %a) {
|
||||
; FAST-LABEL: icmp_sge_i8
|
||||
; FAST: tbz w0, #7, {{LBB.+_2}}
|
||||
%1 = icmp sge i8 %a, 0
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sge_i16(i16 zeroext %a) {
|
||||
; FAST-LABEL: icmp_sge_i16
|
||||
; FAST: tbz w0, #15, {{LBB.+_2}}
|
||||
%1 = icmp sge i16 %a, 0
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sle_i8(i8 zeroext %a) {
|
||||
; FAST-LABEL: icmp_sle_i8
|
||||
; FAST: tbnz w0, #7, {{LBB.+_2}}
|
||||
%1 = icmp sle i8 %a, -1
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sle_i16(i16 zeroext %a) {
|
||||
; FAST-LABEL: icmp_sle_i16
|
||||
; FAST: tbnz w0, #15, {{LBB.+_2}}
|
||||
%1 = icmp sle i16 %a, -1
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sle_i32(i32 %a) {
|
||||
; CHECK-LABEL: icmp_sle_i32
|
||||
; CHECK: tbnz w0, #31, {{LBB.+_2}}
|
||||
%1 = icmp sle i32 %a, -1
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sle_i64(i64 %a) {
|
||||
; CHECK-LABEL: icmp_sle_i64
|
||||
; CHECK: tbnz x0, #63, {{LBB.+_2}}
|
||||
%1 = icmp sle i64 %a, -1
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sgt_i8(i8 zeroext %a) {
|
||||
; FAST-LABEL: icmp_sgt_i8
|
||||
; FAST: tbz w0, #7, {{LBB.+_2}}
|
||||
%1 = icmp sgt i8 %a, -1
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sgt_i16(i16 zeroext %a) {
|
||||
; FAST-LABEL: icmp_sgt_i16
|
||||
; FAST: tbz w0, #15, {{LBB.+_2}}
|
||||
%1 = icmp sgt i16 %a, -1
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sgt_i32(i32 %a) {
|
||||
; CHECK-LABEL: icmp_sgt_i32
|
||||
; CHECK: tbz w0, #31, {{LBB.+_2}}
|
||||
%1 = icmp sgt i32 %a, -1
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sgt_i64(i64 %a) {
|
||||
; FAST-LABEL: icmp_sgt_i64
|
||||
; FAST: tbz x0, #63, {{LBB.+_2}}
|
||||
%1 = icmp sgt i64 %a, -1
|
||||
br i1 %1, label %bb1, label %bb2, !prof !0
|
||||
bb1:
|
||||
ret i32 1
|
||||
bb2:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Test that we don't fold the 'and' instruction into the compare.
|
||||
define i32 @icmp_eq_and_i32(i32 %a, i1 %c) {
|
||||
; CHECK-LABEL: icmp_eq_and_i32
|
||||
|
|
Loading…
Reference in New Issue