[GISel][AArch64] Allow PatLeafs to be imported in GISel which were previously causing warnings (#140935)
Previously PatLeafs could not be imported, causing the following warnings to be emitted when running tblgen with `-warn-on-skipped-patterns:` ``` /work/clean/llvm/lib/Target/AArch64/AArch64InstrInfo.td:2631:1: warning: Skipped pattern: Src pattern child has unsupported predicate def : Pat<(i64 (mul top32Zero:$Rn, top32Zero:$Rm)), ^ ``` These changes allow the patterns to now be imported successfully.
This commit is contained in:
parent
2f15637e04
commit
f3ffee601c
@ -161,6 +161,12 @@ enum {
|
||||
/// - Pred(2) - The predicate to test
|
||||
GIM_CheckImmOperandPredicate,
|
||||
|
||||
/// Check a leaf predicate on the specified instruction.
|
||||
/// - InsnID(ULEB128) - Instruction ID
|
||||
/// - OpIdx(ULEB128) - Operand index
|
||||
/// - Pred(2) - The predicate to test
|
||||
GIM_CheckLeafOperandPredicate,
|
||||
|
||||
/// Check a memory operation has the specified atomic ordering.
|
||||
/// - InsnID(ULEB128) - Instruction ID
|
||||
/// - Ordering(ULEB128) - The AtomicOrdering value
|
||||
@ -707,6 +713,12 @@ protected:
|
||||
"Subclasses must override this with a tablegen-erated function");
|
||||
}
|
||||
|
||||
virtual bool testMOPredicate_MO(unsigned, const MachineOperand &,
|
||||
const MatcherState &State) const {
|
||||
llvm_unreachable(
|
||||
"Subclasses must override this with a tablegen-erated function");
|
||||
}
|
||||
|
||||
virtual bool testSimplePredicate(unsigned) const {
|
||||
llvm_unreachable("Subclass does not implement testSimplePredicate!");
|
||||
}
|
||||
|
@ -410,6 +410,26 @@ bool GIMatchTableExecutor::executeMatchTable(
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case GIM_CheckLeafOperandPredicate: {
|
||||
uint64_t InsnID = readULEB();
|
||||
uint64_t OpIdx = readULEB();
|
||||
uint16_t Predicate = readU16();
|
||||
DEBUG_WITH_TYPE(TgtExecutor::getName(),
|
||||
dbgs() << CurrentIdx
|
||||
<< ": GIM_CheckLeafOperandPredicate(MIs[" << InsnID
|
||||
<< "]->getOperand(" << OpIdx
|
||||
<< "), Predicate=" << Predicate << ")\n");
|
||||
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
|
||||
assert(State.MIs[InsnID]->getOperand(OpIdx).isReg() &&
|
||||
"Expected register operand");
|
||||
assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
|
||||
MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
|
||||
|
||||
if (!testMOPredicate_MO(Predicate, MO, State))
|
||||
if (handleReject() == RejectAndGiveUp)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case GIM_CheckIsBuildVectorAllOnes:
|
||||
case GIM_CheckIsBuildVectorAllZeros: {
|
||||
uint64_t InsnID = readULEB();
|
||||
|
@ -1061,7 +1061,9 @@ class OutPatFrag<dag ops, dag frag>
|
||||
// PatLeaf's are pattern fragments that have no operands. This is just a helper
|
||||
// to define immediates and other common things concisely.
|
||||
class PatLeaf<dag frag, code pred = [{}], SDNodeXForm xform = NOOP_SDNodeXForm>
|
||||
: PatFrag<(ops), frag, pred, xform>;
|
||||
: PatFrag<(ops), frag, pred, xform> {
|
||||
code GISelLeafPredicateCode = ?;
|
||||
}
|
||||
|
||||
|
||||
// ImmLeaf is a pattern fragment with a constraint on the immediate. The
|
||||
|
@ -685,23 +685,35 @@ defm trunc_masked_scatter_i32 : masked_gather_scatter<trunc_masked_scatter_i32>;
|
||||
def top16Zero: PatLeaf<(i32 GPR32:$src), [{
|
||||
return Op.getValueType() == MVT::i32 &&
|
||||
CurDAG->MaskedValueIsZero(Op, APInt::getHighBitsSet(32, 16));
|
||||
}]>;
|
||||
}]> {
|
||||
let GISelLeafPredicateCode = [{
|
||||
return VT && VT->maskedValueIsZero(Reg, APInt::getHighBitsSet(32, 16)); }];
|
||||
}
|
||||
|
||||
// top32Zero - answer true if the upper 32 bits of $src are 0, false otherwise
|
||||
def top32Zero: PatLeaf<(i64 GPR64:$src), [{
|
||||
return Op.getValueType() == MVT::i64 &&
|
||||
CurDAG->MaskedValueIsZero(Op, APInt::getHighBitsSet(64, 32));
|
||||
}]>;
|
||||
}]> {
|
||||
let GISelLeafPredicateCode = [{
|
||||
return VT && VT->maskedValueIsZero(Reg, APInt::getHighBitsSet(64, 32)); }];
|
||||
}
|
||||
|
||||
// topbitsallzero - Return true if all bits except the lowest bit are known zero
|
||||
def topbitsallzero32: PatLeaf<(i32 GPR32:$src), [{
|
||||
return Op.getValueType() == MVT::i32 &&
|
||||
CurDAG->MaskedValueIsZero(Op, APInt::getHighBitsSet(32, 31));
|
||||
}]>;
|
||||
}]> {
|
||||
let GISelLeafPredicateCode = [{
|
||||
return VT && VT->maskedValueIsZero(Reg, APInt::getHighBitsSet(32, 31)); }];
|
||||
}
|
||||
def topbitsallzero64: PatLeaf<(i64 GPR64:$src), [{
|
||||
return Op.getValueType() == MVT::i64 &&
|
||||
CurDAG->MaskedValueIsZero(Op, APInt::getHighBitsSet(64, 63));
|
||||
}]>;
|
||||
}]> {
|
||||
let GISelLeafPredicateCode = [{
|
||||
return VT && VT->maskedValueIsZero(Reg, APInt::getHighBitsSet(64, 63)); }];
|
||||
}
|
||||
|
||||
// Node definitions.
|
||||
// Compare-and-branch
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "MCTargetDesc/AArch64MCTargetDesc.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
|
||||
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
|
||||
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
|
||||
|
@ -1291,21 +1291,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_ldrb_h(ptr %x0, i16 %x1) {
|
||||
; CHECK-SD-LABEL: umull_ldrb_h:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrb w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-SD-NEXT: umull x0, w8, w9
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_ldrb_h:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrb w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-GI-NEXT: mul x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_ldrb_h:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrb w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-NEXT: umull x0, w8, w9
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i8, ptr %x0
|
||||
%zext = zext i8 %ext64 to i64
|
||||
@ -1315,21 +1307,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_ldrb_h_commuted(ptr %x0, i16 %x1) {
|
||||
; CHECK-SD-LABEL: umull_ldrb_h_commuted:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrb w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-SD-NEXT: umull x0, w9, w8
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_ldrb_h_commuted:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrb w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-GI-NEXT: mul x0, x9, x8
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_ldrb_h_commuted:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrb w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-NEXT: umull x0, w9, w8
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i8, ptr %x0
|
||||
%zext = zext i8 %ext64 to i64
|
||||
@ -1339,18 +1323,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_ldrh_w(ptr %x0, i32 %x1) {
|
||||
; CHECK-SD-LABEL: umull_ldrh_w:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrh w8, [x0]
|
||||
; CHECK-SD-NEXT: umull x0, w8, w1
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_ldrh_w:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrh w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: mul x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_ldrh_w:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrh w8, [x0]
|
||||
; CHECK-NEXT: umull x0, w8, w1
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i16, ptr %x0
|
||||
%zext = zext i16 %ext64 to i64
|
||||
@ -1360,21 +1337,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_ldr_b(ptr %x0, i8 %x1) {
|
||||
; CHECK-SD-LABEL: umull_ldr_b:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xff
|
||||
; CHECK-SD-NEXT: umull x0, w8, w9
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_ldr_b:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xff
|
||||
; CHECK-GI-NEXT: mul x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_ldr_b:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xff
|
||||
; CHECK-NEXT: umull x0, w8, w9
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i32, ptr %x0
|
||||
%zext = zext i32 %ext64 to i64
|
||||
@ -1384,18 +1353,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_ldr2_w(ptr %x0, i32 %x1) {
|
||||
; CHECK-SD-LABEL: umull_ldr2_w:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: umull x0, w8, w1
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_ldr2_w:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: mul x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_ldr2_w:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: umull x0, w8, w1
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1405,19 +1367,12 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_ldr2_ldr2(ptr %x0, ptr %x1) {
|
||||
; CHECK-SD-LABEL: umull_ldr2_ldr2:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: ldr w9, [x1]
|
||||
; CHECK-SD-NEXT: umull x0, w8, w9
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_ldr2_ldr2:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: ldr w9, [x1]
|
||||
; CHECK-GI-NEXT: mul x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_ldr2_ldr2:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: ldr w9, [x1]
|
||||
; CHECK-NEXT: umull x0, w8, w9
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1428,18 +1383,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_ldr2_d(ptr %x0, i64 %x1) {
|
||||
; CHECK-SD-LABEL: umull_ldr2_d:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: umull x0, w8, w1
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_ldr2_d:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: mul x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_ldr2_d:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: umull x0, w8, w1
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1449,21 +1397,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umaddl_ldrb_h(ptr %x0, i16 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umaddl_ldrb_h:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrb w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-SD-NEXT: umaddl x0, w8, w9, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_ldrb_h:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrb w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-GI-NEXT: madd x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_ldrb_h:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrb w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-NEXT: umaddl x0, w8, w9, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i8, ptr %x0
|
||||
%zext = zext i8 %ext64 to i64
|
||||
@ -1474,21 +1414,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umaddl_ldrb_h_commuted(ptr %x0, i16 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umaddl_ldrb_h_commuted:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrb w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-SD-NEXT: umaddl x0, w9, w8, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_ldrb_h_commuted:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrb w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-GI-NEXT: madd x0, x9, x8, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_ldrb_h_commuted:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrb w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-NEXT: umaddl x0, w9, w8, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i8, ptr %x0
|
||||
%zext = zext i8 %ext64 to i64
|
||||
@ -1499,18 +1431,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umaddl_ldrh_w(ptr %x0, i32 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umaddl_ldrh_w:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrh w8, [x0]
|
||||
; CHECK-SD-NEXT: umaddl x0, w8, w1, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_ldrh_w:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrh w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: madd x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_ldrh_w:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrh w8, [x0]
|
||||
; CHECK-NEXT: umaddl x0, w8, w1, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i16, ptr %x0
|
||||
%zext = zext i16 %ext64 to i64
|
||||
@ -1521,21 +1446,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umaddl_ldr_b(ptr %x0, i8 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umaddl_ldr_b:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xff
|
||||
; CHECK-SD-NEXT: umaddl x0, w8, w9, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_ldr_b:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xff
|
||||
; CHECK-GI-NEXT: madd x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_ldr_b:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xff
|
||||
; CHECK-NEXT: umaddl x0, w8, w9, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i32, ptr %x0
|
||||
%zext = zext i32 %ext64 to i64
|
||||
@ -1546,18 +1463,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umaddl_ldr2_w(ptr %x0, i32 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umaddl_ldr2_w:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: umaddl x0, w8, w1, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_ldr2_w:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: madd x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_ldr2_w:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: umaddl x0, w8, w1, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1568,19 +1478,12 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umaddl_ldr2_ldr2(ptr %x0, ptr %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umaddl_ldr2_ldr2:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: ldr w9, [x1]
|
||||
; CHECK-SD-NEXT: umaddl x0, w8, w9, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_ldr2_ldr2:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: ldr w9, [x1]
|
||||
; CHECK-GI-NEXT: madd x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_ldr2_ldr2:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: ldr w9, [x1]
|
||||
; CHECK-NEXT: umaddl x0, w8, w9, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1592,18 +1495,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umaddl_ldr2_d(ptr %x0, i64 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umaddl_ldr2_d:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: umaddl x0, w8, w1, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_ldr2_d:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: madd x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_ldr2_d:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: umaddl x0, w8, w1, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1614,21 +1510,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umnegl_ldrb_h(ptr %x0, i16 %x1) {
|
||||
; CHECK-SD-LABEL: umnegl_ldrb_h:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrb w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-SD-NEXT: umnegl x0, w8, w9
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umnegl_ldrb_h:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrb w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-GI-NEXT: mneg x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umnegl_ldrb_h:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrb w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-NEXT: umnegl x0, w8, w9
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i8, ptr %x0
|
||||
%zext = zext i8 %ext64 to i64
|
||||
@ -1639,21 +1527,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umnegl_ldrb_h_commuted(ptr %x0, i16 %x1) {
|
||||
; CHECK-SD-LABEL: umnegl_ldrb_h_commuted:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrb w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-SD-NEXT: umnegl x0, w9, w8
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umnegl_ldrb_h_commuted:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrb w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-GI-NEXT: mneg x0, x9, x8
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umnegl_ldrb_h_commuted:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrb w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-NEXT: umnegl x0, w9, w8
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i8, ptr %x0
|
||||
%zext = zext i8 %ext64 to i64
|
||||
@ -1664,18 +1544,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umnegl_ldrh_w(ptr %x0, i32 %x1) {
|
||||
; CHECK-SD-LABEL: umnegl_ldrh_w:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrh w8, [x0]
|
||||
; CHECK-SD-NEXT: umnegl x0, w8, w1
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umnegl_ldrh_w:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrh w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: mneg x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umnegl_ldrh_w:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrh w8, [x0]
|
||||
; CHECK-NEXT: umnegl x0, w8, w1
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i16, ptr %x0
|
||||
%zext = zext i16 %ext64 to i64
|
||||
@ -1686,21 +1559,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umnegl_ldr_b(ptr %x0, i8 %x1) {
|
||||
; CHECK-SD-LABEL: umnegl_ldr_b:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xff
|
||||
; CHECK-SD-NEXT: umnegl x0, w8, w9
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umnegl_ldr_b:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xff
|
||||
; CHECK-GI-NEXT: mneg x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umnegl_ldr_b:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xff
|
||||
; CHECK-NEXT: umnegl x0, w8, w9
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i32, ptr %x0
|
||||
%zext = zext i32 %ext64 to i64
|
||||
@ -1711,18 +1576,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umnegl_ldr2_w(ptr %x0, i32 %x1) {
|
||||
; CHECK-SD-LABEL: umnegl_ldr2_w:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: umnegl x0, w8, w1
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umnegl_ldr2_w:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: mneg x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umnegl_ldr2_w:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: umnegl x0, w8, w1
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1733,19 +1591,12 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umnegl_ldr2_ldr2(ptr %x0, ptr %x1) {
|
||||
; CHECK-SD-LABEL: umnegl_ldr2_ldr2:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: ldr w9, [x1]
|
||||
; CHECK-SD-NEXT: umnegl x0, w8, w9
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umnegl_ldr2_ldr2:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: ldr w9, [x1]
|
||||
; CHECK-GI-NEXT: mneg x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umnegl_ldr2_ldr2:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: ldr w9, [x1]
|
||||
; CHECK-NEXT: umnegl x0, w8, w9
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1757,18 +1608,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umnegl_ldr2_d(ptr %x0, i64 %x1) {
|
||||
; CHECK-SD-LABEL: umnegl_ldr2_d:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: umnegl x0, w8, w1
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umnegl_ldr2_d:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: mneg x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umnegl_ldr2_d:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: umnegl x0, w8, w1
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1779,21 +1623,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umsubl_ldrb_h(ptr %x0, i16 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umsubl_ldrb_h:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrb w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-SD-NEXT: umsubl x0, w8, w9, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umsubl_ldrb_h:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrb w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-GI-NEXT: msub x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umsubl_ldrb_h:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrb w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-NEXT: umsubl x0, w8, w9, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i8, ptr %x0
|
||||
%zext = zext i8 %ext64 to i64
|
||||
@ -1804,21 +1640,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umsubl_ldrb_h_commuted(ptr %x0, i16 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umsubl_ldrb_h_commuted:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrb w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-SD-NEXT: umsubl x0, w9, w8, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umsubl_ldrb_h_commuted:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrb w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-GI-NEXT: msub x0, x9, x8, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umsubl_ldrb_h_commuted:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrb w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xffff
|
||||
; CHECK-NEXT: umsubl x0, w9, w8, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i8, ptr %x0
|
||||
%zext = zext i8 %ext64 to i64
|
||||
@ -1829,18 +1657,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umsubl_ldrh_w(ptr %x0, i32 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umsubl_ldrh_w:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrh w8, [x0]
|
||||
; CHECK-SD-NEXT: umsubl x0, w8, w1, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umsubl_ldrh_w:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrh w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: msub x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umsubl_ldrh_w:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrh w8, [x0]
|
||||
; CHECK-NEXT: umsubl x0, w8, w1, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i16, ptr %x0
|
||||
%zext = zext i16 %ext64 to i64
|
||||
@ -1851,21 +1672,13 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umsubl_ldr_b(ptr %x0, i8 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umsubl_ldr_b:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-SD-NEXT: and x9, x1, #0xff
|
||||
; CHECK-SD-NEXT: umsubl x0, w8, w9, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umsubl_ldr_b:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-GI-NEXT: and x9, x1, #0xff
|
||||
; CHECK-GI-NEXT: msub x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umsubl_ldr_b:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
|
||||
; CHECK-NEXT: and x9, x1, #0xff
|
||||
; CHECK-NEXT: umsubl x0, w8, w9, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i32, ptr %x0
|
||||
%zext = zext i32 %ext64 to i64
|
||||
@ -1876,18 +1689,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umsubl_ldr2_w(ptr %x0, i32 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umsubl_ldr2_w:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: umsubl x0, w8, w1, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umsubl_ldr2_w:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: msub x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umsubl_ldr2_w:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: umsubl x0, w8, w1, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1898,19 +1704,12 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umsubl_ldr2_ldr2(ptr %x0, ptr %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umsubl_ldr2_ldr2:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: ldr w9, [x1]
|
||||
; CHECK-SD-NEXT: umsubl x0, w8, w9, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umsubl_ldr2_ldr2:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: ldr w9, [x1]
|
||||
; CHECK-GI-NEXT: msub x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umsubl_ldr2_ldr2:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: ldr w9, [x1]
|
||||
; CHECK-NEXT: umsubl x0, w8, w9, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1922,18 +1721,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umsubl_ldr2_d(ptr %x0, i64 %x1, i64 %x2) {
|
||||
; CHECK-SD-LABEL: umsubl_ldr2_d:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: umsubl x0, w8, w1, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umsubl_ldr2_d:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: msub x0, x8, x9, x2
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umsubl_ldr2_d:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: umsubl x0, w8, w1, x2
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 4294967295
|
||||
@ -1944,20 +1736,12 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_ldr2_w_cc1(ptr %x0, i32 %x1) {
|
||||
; CHECK-SD-LABEL: umull_ldr2_w_cc1:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr x8, [x0]
|
||||
; CHECK-SD-NEXT: and x8, x8, #0x7fffffff
|
||||
; CHECK-SD-NEXT: umull x0, w8, w1
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_ldr2_w_cc1:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr x8, [x0]
|
||||
; CHECK-GI-NEXT: mov w9, w1
|
||||
; CHECK-GI-NEXT: and x8, x8, #0x7fffffff
|
||||
; CHECK-GI-NEXT: mul x0, x8, x9
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_ldr2_w_cc1:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr x8, [x0]
|
||||
; CHECK-NEXT: and x8, x8, #0x7fffffff
|
||||
; CHECK-NEXT: umull x0, w8, w1
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%ext64 = load i64, ptr %x0
|
||||
%and = and i64 %ext64, 2147483647
|
||||
@ -1998,18 +1782,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @umull_and_lshr(i64 %x) {
|
||||
; CHECK-SD-LABEL: umull_and_lshr:
|
||||
; CHECK-SD: // %bb.0:
|
||||
; CHECK-SD-NEXT: lsr x8, x0, #32
|
||||
; CHECK-SD-NEXT: umull x0, w0, w8
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umull_and_lshr:
|
||||
; CHECK-GI: // %bb.0:
|
||||
; CHECK-GI-NEXT: lsr x8, x0, #32
|
||||
; CHECK-GI-NEXT: mov w9, w0
|
||||
; CHECK-GI-NEXT: mul x0, x9, x8
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umull_and_lshr:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: lsr x8, x0, #32
|
||||
; CHECK-NEXT: umull x0, w0, w8
|
||||
; CHECK-NEXT: ret
|
||||
%lo = and i64 %x, u0xffffffff
|
||||
%hi = lshr i64 %x, 32
|
||||
%mul = mul i64 %lo, %hi
|
||||
@ -2028,18 +1805,11 @@ define i64 @umull_and_and(i64 %x, i64 %y) {
|
||||
}
|
||||
|
||||
define i64 @umaddl_and_lshr(i64 %x, i64 %a) {
|
||||
; CHECK-SD-LABEL: umaddl_and_lshr:
|
||||
; CHECK-SD: // %bb.0:
|
||||
; CHECK-SD-NEXT: lsr x8, x0, #32
|
||||
; CHECK-SD-NEXT: umaddl x0, w0, w8, x1
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_and_lshr:
|
||||
; CHECK-GI: // %bb.0:
|
||||
; CHECK-GI-NEXT: lsr x8, x0, #32
|
||||
; CHECK-GI-NEXT: mov w9, w0
|
||||
; CHECK-GI-NEXT: madd x0, x9, x8, x1
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_and_lshr:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: lsr x8, x0, #32
|
||||
; CHECK-NEXT: umaddl x0, w0, w8, x1
|
||||
; CHECK-NEXT: ret
|
||||
%lo = and i64 %x, u0xffffffff
|
||||
%hi = lshr i64 %x, 32
|
||||
%mul = mul i64 %lo, %hi
|
||||
@ -2048,16 +1818,10 @@ define i64 @umaddl_and_lshr(i64 %x, i64 %a) {
|
||||
}
|
||||
|
||||
define i64 @umaddl_and_and(i64 %x, i64 %y, i64 %a) {
|
||||
; CHECK-SD-LABEL: umaddl_and_and:
|
||||
; CHECK-SD: // %bb.0:
|
||||
; CHECK-SD-NEXT: umaddl x0, w0, w1, x2
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: umaddl_and_and:
|
||||
; CHECK-GI: // %bb.0:
|
||||
; CHECK-GI-NEXT: umull x8, w0, w1
|
||||
; CHECK-GI-NEXT: add x0, x2, x8
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: umaddl_and_and:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: umaddl x0, w0, w1, x2
|
||||
; CHECK-NEXT: ret
|
||||
%lo = and i64 %x, u0xffffffff
|
||||
%hi = and i64 %y, u0xffffffff
|
||||
%mul = mul i64 %lo, %hi
|
||||
|
@ -174,7 +174,7 @@ define <2 x i16> @test_varidx_extract_v4s16(<4 x i16> %x, i32 %idx) {
|
||||
; CHECK-GISEL-NEXT: and x9, x9, #0x3
|
||||
; CHECK-GISEL-NEXT: // kill: def $d0 killed $d0 def $q0
|
||||
; CHECK-GISEL-NEXT: str d0, [sp, #8]
|
||||
; CHECK-GISEL-NEXT: madd x8, x9, x8, x10
|
||||
; CHECK-GISEL-NEXT: umaddl x8, w9, w8, x10
|
||||
; CHECK-GISEL-NEXT: umov w9, v0.h[1]
|
||||
; CHECK-GISEL-NEXT: ld1 { v0.h }[0], [x8]
|
||||
; CHECK-GISEL-NEXT: mov v0.s[1], w9
|
||||
|
@ -34,8 +34,7 @@ define i32 @test_rev_w_srl16(i16 %a) {
|
||||
; CHECK-GI-LABEL: test_rev_w_srl16:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: and w8, w0, #0xffff
|
||||
; CHECK-GI-NEXT: rev w8, w8
|
||||
; CHECK-GI-NEXT: lsr w0, w8, #16
|
||||
; CHECK-GI-NEXT: rev16 w0, w8
|
||||
; CHECK-GI-NEXT: ret
|
||||
entry:
|
||||
%0 = zext i16 %a to i32
|
||||
@ -45,12 +44,18 @@ entry:
|
||||
}
|
||||
|
||||
define i32 @test_rev_w_srl16_load(ptr %a) {
|
||||
; CHECK-LABEL: test_rev_w_srl16_load:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrh w8, [x0]
|
||||
; CHECK-NEXT: rev w8, w8
|
||||
; CHECK-NEXT: lsr w0, w8, #16
|
||||
; CHECK-NEXT: ret
|
||||
; CHECK-SD-LABEL: test_rev_w_srl16_load:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldrh w8, [x0]
|
||||
; CHECK-SD-NEXT: rev w8, w8
|
||||
; CHECK-SD-NEXT: lsr w0, w8, #16
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: test_rev_w_srl16_load:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldrh w8, [x0]
|
||||
; CHECK-GI-NEXT: rev16 w0, w8
|
||||
; CHECK-GI-NEXT: ret
|
||||
entry:
|
||||
%0 = load i16, ptr %a
|
||||
%1 = zext i16 %0 to i32
|
||||
@ -71,8 +76,7 @@ define i32 @test_rev_w_srl16_add(i8 %a, i8 %b) {
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: and w8, w1, #0xff
|
||||
; CHECK-GI-NEXT: add w8, w8, w0, uxtb
|
||||
; CHECK-GI-NEXT: rev w8, w8
|
||||
; CHECK-GI-NEXT: lsr w0, w8, #16
|
||||
; CHECK-GI-NEXT: rev16 w0, w8
|
||||
; CHECK-GI-NEXT: ret
|
||||
entry:
|
||||
%0 = zext i8 %a to i32
|
||||
@ -96,8 +100,7 @@ define i64 @test_rev_x_srl32(i32 %a) {
|
||||
; CHECK-GI-LABEL: test_rev_x_srl32:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: mov w8, w0
|
||||
; CHECK-GI-NEXT: rev x8, x8
|
||||
; CHECK-GI-NEXT: lsr x0, x8, #32
|
||||
; CHECK-GI-NEXT: rev32 x0, x8
|
||||
; CHECK-GI-NEXT: ret
|
||||
entry:
|
||||
%0 = zext i32 %a to i64
|
||||
@ -107,12 +110,18 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @test_rev_x_srl32_load(ptr %a) {
|
||||
; CHECK-LABEL: test_rev_x_srl32_load:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w8, [x0]
|
||||
; CHECK-NEXT: rev x8, x8
|
||||
; CHECK-NEXT: lsr x0, x8, #32
|
||||
; CHECK-NEXT: ret
|
||||
; CHECK-SD-LABEL: test_rev_x_srl32_load:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ldr w8, [x0]
|
||||
; CHECK-SD-NEXT: rev x8, x8
|
||||
; CHECK-SD-NEXT: lsr x0, x8, #32
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: test_rev_x_srl32_load:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ldr w8, [x0]
|
||||
; CHECK-GI-NEXT: rev32 x0, x8
|
||||
; CHECK-GI-NEXT: ret
|
||||
entry:
|
||||
%0 = load i32, ptr %a
|
||||
%1 = zext i32 %0 to i64
|
||||
@ -122,18 +131,11 @@ entry:
|
||||
}
|
||||
|
||||
define i64 @test_rev_x_srl32_shift(i64 %a) {
|
||||
; CHECK-SD-LABEL: test_rev_x_srl32_shift:
|
||||
; CHECK-SD: // %bb.0: // %entry
|
||||
; CHECK-SD-NEXT: ubfx x8, x0, #2, #29
|
||||
; CHECK-SD-NEXT: rev32 x0, x8
|
||||
; CHECK-SD-NEXT: ret
|
||||
;
|
||||
; CHECK-GI-LABEL: test_rev_x_srl32_shift:
|
||||
; CHECK-GI: // %bb.0: // %entry
|
||||
; CHECK-GI-NEXT: ubfx x8, x0, #2, #29
|
||||
; CHECK-GI-NEXT: rev x8, x8
|
||||
; CHECK-GI-NEXT: lsr x0, x8, #32
|
||||
; CHECK-GI-NEXT: ret
|
||||
; CHECK-LABEL: test_rev_x_srl32_shift:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ubfx x8, x0, #2, #29
|
||||
; CHECK-NEXT: rev32 x0, x8
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = shl i64 %a, 33
|
||||
%1 = lshr i64 %0, 35
|
||||
|
@ -630,7 +630,7 @@ define <8 x i8> @insert_v8i8_c(<8 x i8> %a, i8 %b, i32 %c) {
|
||||
; CHECK-GI-NEXT: mov w8, #1 // =0x1
|
||||
; CHECK-GI-NEXT: str d0, [sp, #8]
|
||||
; CHECK-GI-NEXT: and x9, x9, #0x7
|
||||
; CHECK-GI-NEXT: mul x8, x9, x8
|
||||
; CHECK-GI-NEXT: umull x8, w9, w8
|
||||
; CHECK-GI-NEXT: add x9, sp, #8
|
||||
; CHECK-GI-NEXT: strb w0, [x9, x8]
|
||||
; CHECK-GI-NEXT: ldr d0, [sp, #8]
|
||||
@ -682,7 +682,7 @@ define <16 x i8> @insert_v16i8_c(<16 x i8> %a, i8 %b, i32 %c) {
|
||||
; CHECK-GI-NEXT: mov w8, #1 // =0x1
|
||||
; CHECK-GI-NEXT: str q0, [sp]
|
||||
; CHECK-GI-NEXT: and x9, x9, #0xf
|
||||
; CHECK-GI-NEXT: mul x8, x9, x8
|
||||
; CHECK-GI-NEXT: umull x8, w9, w8
|
||||
; CHECK-GI-NEXT: mov x9, sp
|
||||
; CHECK-GI-NEXT: strb w0, [x9, x8]
|
||||
; CHECK-GI-NEXT: ldr q0, [sp], #16
|
||||
|
@ -82,6 +82,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||
// CHECK-NEXT: bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat &Imm) const override;
|
||||
// CHECK-NEXT: const uint8_t *getMatchTable() const override;
|
||||
// CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override;
|
||||
// CHECK-NEXT: bool testMOPredicate_MO(unsigned PredicateID, const MachineOperand &MO, const MatcherState &State) const override;
|
||||
// CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override;
|
||||
// CHECK-NEXT: bool runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override;
|
||||
// CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL
|
||||
@ -157,6 +158,25 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||
// CHECK-NEXT: GICXXPred_MI_Predicate_frag = GICXXPred_Invalid + 1,
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK-LABEL: // PatFrag predicates.
|
||||
// CHECK-NEXT: enum {
|
||||
// CHECK-NEXT: GICXXPred_MO_Predicate_leaf = GICXXPred_Invalid + 1,
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// CHECK-LABEL: bool MyTargetInstructionSelector::testMOPredicate_MO(unsigned PredicateID, const MachineOperand & MO, const MatcherState &State) const {
|
||||
// CHECK-NEXT: const auto &Operands = State.RecordedOperands;
|
||||
// CHECK-NEXT: Register Reg = MO.getReg();
|
||||
// CHECK-NEXT: (void)Operands;
|
||||
// CHECK-NEXT: switch (PredicateID) {
|
||||
// CHECK-NEXT: case GICXXPred_MO_Predicate_leaf: {
|
||||
// CHECK-NEXT: return true;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: llvm_unreachable("Unknown predicate");
|
||||
// CHECK-NEXT: return false;
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK-LABEL: // PatFrag predicates.
|
||||
// CHECK-NEXT: enum {
|
||||
// CHECK-NEXT: GICXXPred_I64_Predicate_cimm8 = GICXXPred_Invalid + 1,
|
||||
@ -508,12 +528,12 @@ def : Pat<(frag GPR32:$src1, complex:$src2, complex:$src3),
|
||||
// R00C-NEXT: GIR_EraseRootFromParent_Done,
|
||||
// R00C-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
|
||||
//
|
||||
// R00O-NEXT: GIM_Reject,
|
||||
// R00O: GIM_Reject,
|
||||
// R00O-NEXT: // Label [[GROUP_NUM]]: @[[GROUP]]
|
||||
// R00O-NEXT: GIM_Reject,
|
||||
// R00O: // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
|
||||
// R00O-NEXT: GIM_Reject,
|
||||
// R00O-NEXT: }; // Size: 1856 bytes
|
||||
// R00O-NEXT: }; // Size: 1878 bytes
|
||||
|
||||
def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
|
||||
[(set GPR32:$dst,
|
||||
@ -828,7 +848,7 @@ def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>;
|
||||
// NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
|
||||
// NOOPT-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // src3
|
||||
// NOOPT-NEXT: GIR_RootConstrainSelectedInstOperands,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 28,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 29,
|
||||
// NOOPT-NEXT: GIR_EraseRootFromParent_Done,
|
||||
// NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
|
||||
|
||||
@ -837,6 +857,35 @@ def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
|
||||
(mul (add GPR32:$src1, GPR32:$src2), GPR32:$src3))]>,
|
||||
Requires<[HasA]>;
|
||||
|
||||
//===- Test a simple pattern with a PatLeaf and a predicate. ---------===//
|
||||
//
|
||||
// NOOPT-NEXT: /* 882 */ GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4(924), // Rule ID 24 //
|
||||
// NOOPT-NEXT: /* 887 */ GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
|
||||
// NOOPT-NEXT: /* 890 */ GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_SUB),
|
||||
// NOOPT-NEXT: /* 894 */ // MIs[0] DstI[dst]
|
||||
// NOOPT-NEXT: /* 894 */ GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_s32,
|
||||
// NOOPT-NEXT: /* 897 */ GIM_RootCheckRegBankForClass, /*Op*/0, /*RC*/GIMT_Encode2(MyTarget::GPR32RegClassID),
|
||||
// NOOPT-NEXT: /* 901 */ // MIs[0] src1
|
||||
// NOOPT-NEXT: /* 901 */ GIM_RootCheckType, /*Op*/1, /*Type*/GILLT_s32,
|
||||
// NOOPT-NEXT: /* 904 */ GIM_CheckLeafOperandPredicate, /*MI*/0, /*MO*/1, /*Predicate*/GIMT_Encode2(GICXXPred_MO_Predicate_leaf),
|
||||
// NOOPT-NEXT: /* 909 */ // MIs[0] src2
|
||||
// NOOPT-NEXT: /* 909 */ GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32,
|
||||
// NOOPT-NEXT: /* 912 */ GIM_CheckLeafOperandPredicate, /*MI*/0, /*MO*/2, /*Predicate*/GIMT_Encode2(GICXXPred_MO_Predicate_leaf),
|
||||
// NOOPT-NEXT: /* 917 */ // (sub:{ *:[i32] } GPR32:{ *:[i32] }<<P:Predicate_leaf>>:$src1, GPR32:{ *:[i32] }<<P:Predicate_leaf>>:$src2) => (INSN5:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2)
|
||||
// NOOPT-NEXT: /* 917 */ GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::INSN5),
|
||||
// NOOPT-NEXT: /* 922 */ GIR_RootConstrainSelectedInstOperands,
|
||||
// NOOPT-NEXT: /* 923 */ // GIR_Coverage, 24,
|
||||
// NOOPT-NEXT: /* 923 */ GIR_Done,
|
||||
// NOOPT-NEXT: /* 924 */ // Label 13: @924
|
||||
|
||||
def leaf: PatLeaf<(i32 GPR32:$src), [{ return true; // C++ code }]> {
|
||||
let GISelLeafPredicateCode = [{ return true; }];
|
||||
}
|
||||
def INSN5 : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2), []>;
|
||||
def : Pat<(sub leaf:$src1, leaf:$src2), (INSN5 GPR32:$src1, GPR32:$src2)>;
|
||||
|
||||
|
||||
|
||||
//===- Test a simple pattern with just a specific leaf immediate. ---------===//
|
||||
//
|
||||
// NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ GIMT_Encode4([[LABEL:[0-9]+]]),
|
||||
@ -984,7 +1033,7 @@ def LOAD : I<(outs GPR32:$dst), (ins GPR32:$src1),
|
||||
// NOOPT-NEXT: // (ld:{ *:[i32] } GPR32:{ *:[i32] }:$src)<<P:Predicate_unindexedload>><<P:Predicate_load>> => (LOAD:{ *:[i32] } GPR32:{ *:[i32] }:$src)
|
||||
// NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::LOAD),
|
||||
// NOOPT-NEXT: GIR_RootConstrainSelectedInstOperands,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 24,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 25,
|
||||
// NOOPT-NEXT: GIR_Done,
|
||||
// NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
|
||||
|
||||
@ -1083,7 +1132,7 @@ def DOUBLE : I<(outs GPR32:$dst), (ins GPR32:$src), [(set GPR32:$dst, (add GPR32
|
||||
// NOOPT-NEXT: // (add:{ *:[i32] } i32:{ *:[i32] }:$samename, i32:{ *:[i32] }:$othername) => (InsnWithSpeciallyNamedDef:{ *:[i32] } i32:{ *:[i32] }:$samename, i32:{ *:[i32] }:$othername)
|
||||
// NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::InsnWithSpeciallyNamedDef),
|
||||
// NOOPT-NEXT: GIR_RootConstrainSelectedInstOperands,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 25,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 26,
|
||||
// NOOPT-NEXT: GIR_Done,
|
||||
// NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
|
||||
|
||||
@ -1106,7 +1155,7 @@ def : Pat<(add i32:$samename, i32:$othername),
|
||||
// NOOPT-NEXT: // (add:{ *:[i32] } i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2) => (ADD:{ *:[i32] } i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2)
|
||||
// NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(MyTarget::ADD),
|
||||
// NOOPT-NEXT: GIR_RootConstrainSelectedInstOperands,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 26,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 27,
|
||||
// NOOPT-NEXT: GIR_Done,
|
||||
// NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
|
||||
|
||||
@ -1157,7 +1206,7 @@ def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
|
||||
// NOOPT-NEXT: // (bitconvert:{ *:[i32] } FPR32:{ *:[f32] }:$src1) => (COPY_TO_REGCLASS:{ *:[i32] } FPR32:{ *:[f32] }:$src1, GPR32:{ *:[i32] })
|
||||
// NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),
|
||||
// NOOPT-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, GIMT_Encode2(MyTarget::GPR32RegClassID),
|
||||
// NOOPT-NEXT: // GIR_Coverage, 27,
|
||||
// NOOPT-NEXT: // GIR_Coverage, 28,
|
||||
// NOOPT-NEXT: GIR_Done,
|
||||
// NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
|
||||
|
||||
@ -1206,5 +1255,5 @@ def BR : I<(outs), (ins unknown:$target),
|
||||
[(br bb:$target)]>;
|
||||
|
||||
// NOOPT-NEXT: GIM_Reject,
|
||||
// NOOPT-NEXT: }; // Size: 1459 bytes
|
||||
// NOOPT-NEXT: }; // Size: 1501 bytes
|
||||
// NOOPT-NEXT: return MatchTable0;
|
||||
|
@ -54,6 +54,7 @@ class I<dag OOps, dag IOps, list<dag> Pat>
|
||||
// CHECK-NEXT: bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat &Imm) const override;
|
||||
// CHECK-NEXT: const uint8_t *getMatchTable() const override;
|
||||
// CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override;
|
||||
// CHECK-NEXT: bool testMOPredicate_MO(unsigned PredicateID, const MachineOperand &MO, const MatcherState &State) const override;
|
||||
// CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override;
|
||||
// CHECK-NEXT: bool runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override;
|
||||
// CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL
|
||||
|
@ -899,6 +899,11 @@ TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) {
|
||||
assert(
|
||||
(!hasPredCode() || !hasImmCode()) &&
|
||||
".td file corrupt: can't have a node predicate *and* an imm predicate");
|
||||
|
||||
if (hasGISelPredicateCode() && hasGISelLeafPredicateCode())
|
||||
PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
|
||||
".td file corrupt: can't have GISelPredicateCode *and* "
|
||||
"GISelLeafPredicateCode");
|
||||
}
|
||||
|
||||
bool TreePredicateFn::hasPredCode() const {
|
||||
@ -1293,8 +1298,20 @@ bool TreePredicateFn::hasGISelPredicateCode() const {
|
||||
}
|
||||
|
||||
std::string TreePredicateFn::getGISelPredicateCode() const {
|
||||
return std::string(
|
||||
PatFragRec->getRecord()->getValueAsString("GISelPredicateCode"));
|
||||
return PatFragRec->getRecord()->getValueAsString("GISelPredicateCode").str();
|
||||
}
|
||||
|
||||
bool TreePredicateFn::hasGISelLeafPredicateCode() const {
|
||||
return PatFragRec->getRecord()
|
||||
->getValueAsOptionalString("GISelLeafPredicateCode")
|
||||
.has_value();
|
||||
}
|
||||
|
||||
std::string TreePredicateFn::getGISelLeafPredicateCode() const {
|
||||
return PatFragRec->getRecord()
|
||||
->getValueAsOptionalString("GISelLeafPredicateCode")
|
||||
.value_or(StringRef())
|
||||
.str();
|
||||
}
|
||||
|
||||
StringRef TreePredicateFn::getImmType() const {
|
||||
|
@ -590,6 +590,11 @@ public:
|
||||
bool hasGISelPredicateCode() const;
|
||||
std::string getGISelPredicateCode() const;
|
||||
|
||||
// If true, indicates that GlobalISel-based C++ code was supplied for checking
|
||||
// register operands.
|
||||
bool hasGISelLeafPredicateCode() const;
|
||||
std::string getGISelLeafPredicateCode() const;
|
||||
|
||||
private:
|
||||
bool hasPredCode() const;
|
||||
bool hasImmCode() const;
|
||||
|
@ -33,6 +33,8 @@ Error failUnsupported(const Twine &Reason) {
|
||||
std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) {
|
||||
if (Predicate.hasGISelPredicateCode())
|
||||
return "GICXXPred_MI_" + Predicate.getFnName();
|
||||
if (Predicate.hasGISelLeafPredicateCode())
|
||||
return "GICXXPred_MO_" + Predicate.getFnName();
|
||||
return "GICXXPred_" + Predicate.getImmTypeIdentifier().str() + "_" +
|
||||
Predicate.getFnName();
|
||||
}
|
||||
@ -1326,6 +1328,19 @@ void OperandImmPredicateMatcher::emitPredicateOpcodes(MatchTable &Table,
|
||||
<< MatchTable::LineBreak;
|
||||
}
|
||||
|
||||
//===- OperandLeafPredicateMatcher
|
||||
//-----------------------------------------===//
|
||||
|
||||
void OperandLeafPredicateMatcher::emitPredicateOpcodes(
|
||||
MatchTable &Table, RuleMatcher &Rule) const {
|
||||
Table << MatchTable::Opcode("GIM_CheckLeafOperandPredicate")
|
||||
<< MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
|
||||
<< MatchTable::Comment("MO") << MatchTable::ULEB128Value(OpIdx)
|
||||
<< MatchTable::Comment("Predicate")
|
||||
<< MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate))
|
||||
<< MatchTable::LineBreak;
|
||||
}
|
||||
|
||||
//===- OperandMatcher -----------------------------------------------------===//
|
||||
|
||||
std::string OperandMatcher::getOperandExpr(unsigned InsnVarID) const {
|
||||
|
@ -824,6 +824,7 @@ public:
|
||||
IPM_OneUse,
|
||||
IPM_GenericPredicate,
|
||||
IPM_MIFlags,
|
||||
OPM_LeafPredicate,
|
||||
OPM_SameOperand,
|
||||
OPM_ComplexPattern,
|
||||
OPM_IntrinsicID,
|
||||
@ -1255,6 +1256,26 @@ public:
|
||||
RuleMatcher &Rule) const override;
|
||||
};
|
||||
|
||||
/// Generates code to check that this operand is a register whose value meets
|
||||
/// the predicate.
|
||||
class OperandLeafPredicateMatcher : public OperandPredicateMatcher {
|
||||
protected:
|
||||
TreePredicateFn Predicate;
|
||||
|
||||
public:
|
||||
OperandLeafPredicateMatcher(unsigned InsnVarID, unsigned OpIdx,
|
||||
const TreePredicateFn &Predicate)
|
||||
: OperandPredicateMatcher(OPM_LeafPredicate, InsnVarID, OpIdx),
|
||||
Predicate(Predicate) {}
|
||||
|
||||
static bool classof(const PredicateMatcher *P) {
|
||||
return P->getKind() == OPM_LeafPredicate;
|
||||
}
|
||||
|
||||
void emitPredicateOpcodes(MatchTable &Table,
|
||||
RuleMatcher &Rule) const override;
|
||||
};
|
||||
|
||||
/// Generates code to check that a set of predicates match for a particular
|
||||
/// operand.
|
||||
class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> {
|
||||
|
@ -182,6 +182,7 @@ void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl(
|
||||
emitSubtargetFeatureBitsetImpl(OS, Rules);
|
||||
emitComplexPredicates(OS, ComplexOperandMatchers);
|
||||
emitMIPredicateFns(OS);
|
||||
emitLeafPredicateFns(OS);
|
||||
emitI64ImmPredicateFns(OS);
|
||||
emitAPFloatImmPredicateFns(OS);
|
||||
emitAPIntImmPredicateFns(OS);
|
||||
@ -234,6 +235,9 @@ void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl(
|
||||
<< " bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI"
|
||||
", const MatcherState &State) "
|
||||
"const override;\n"
|
||||
<< " bool testMOPredicate_MO(unsigned PredicateID, const MachineOperand "
|
||||
"&MO, const MatcherState &State) "
|
||||
"const override;\n"
|
||||
<< " bool testSimplePredicate(unsigned PredicateID) const override;\n"
|
||||
<< " bool runCustomAction(unsigned FnID, const MatcherState &State, "
|
||||
"NewMIVector &OutMIs) "
|
||||
|
@ -79,8 +79,8 @@ class GlobalISelMatchTableExecutorEmitter {
|
||||
raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
|
||||
StringRef ArgName, StringRef AdditionalArgs,
|
||||
StringRef AdditionalDeclarations, ArrayRef<PredicateObject> Predicates,
|
||||
std::function<StringRef(PredicateObject)> GetPredEnumName,
|
||||
std::function<StringRef(PredicateObject)> GetPredCode,
|
||||
llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName,
|
||||
llvm::function_ref<StringRef(PredicateObject)> GetPredCode,
|
||||
StringRef Comment) {
|
||||
if (!Comment.empty())
|
||||
OS << "// " << Comment << "\n";
|
||||
@ -135,14 +135,34 @@ protected:
|
||||
void emitMIPredicateFnsImpl(
|
||||
raw_ostream &OS, StringRef AdditionalDecls,
|
||||
ArrayRef<PredicateObject> Predicates,
|
||||
std::function<StringRef(PredicateObject)> GetPredEnumName,
|
||||
std::function<StringRef(PredicateObject)> GetPredCode,
|
||||
llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName,
|
||||
llvm::function_ref<StringRef(PredicateObject)> GetPredCode,
|
||||
StringRef Comment = "") {
|
||||
return emitCxxPredicateFns(
|
||||
OS, "MI", "const MachineInstr &", "MI", ", const MatcherState &State",
|
||||
AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment);
|
||||
}
|
||||
|
||||
/// Emits `testMOPredicate_MO`.
|
||||
/// \tparam PredicateObject An object representing a predicate to emit.
|
||||
/// \param OS Output stream.
|
||||
/// \param AdditionalDecls Additional C++ variable declarations.
|
||||
/// \param Predicates Predicates to emit.
|
||||
/// \param GetPredEnumName Returns an enum name for a given predicate.
|
||||
/// \param GetPredCode Returns the C++ code of a given predicate.
|
||||
/// \param Comment Optional comment for the enum declaration.
|
||||
template <typename PredicateObject>
|
||||
void emitLeafPredicateFnsImpl(
|
||||
raw_ostream &OS, StringRef AdditionalDecls,
|
||||
ArrayRef<PredicateObject> Predicates,
|
||||
llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName,
|
||||
llvm::function_ref<StringRef(PredicateObject)> GetPredCode,
|
||||
StringRef Comment = "") {
|
||||
return emitCxxPredicateFns(
|
||||
OS, "MO", "const MachineOperand &", "MO", ", const MatcherState &State",
|
||||
AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment);
|
||||
}
|
||||
|
||||
/// Helper function to emit the following executor functions:
|
||||
/// * testImmPredicate_I64 (TypeIdentifier=I64)
|
||||
/// * testImmPredicate_APInt (TypeIdentifier=APInt)
|
||||
@ -160,8 +180,8 @@ protected:
|
||||
void emitImmPredicateFnsImpl(
|
||||
raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
|
||||
ArrayRef<PredicateObject> Predicates,
|
||||
std::function<StringRef(PredicateObject)> GetPredEnumName,
|
||||
std::function<StringRef(PredicateObject)> GetPredCode,
|
||||
llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName,
|
||||
llvm::function_ref<StringRef(PredicateObject)> GetPredCode,
|
||||
StringRef Comment = "") {
|
||||
return emitCxxPredicateFns(OS, TypeIdentifier, ArgType, "Imm", "", "",
|
||||
Predicates, GetPredEnumName, GetPredCode,
|
||||
@ -189,6 +209,10 @@ public:
|
||||
/// Note: `emitMIPredicateFnsImpl` can be used to do most of the work.
|
||||
virtual void emitMIPredicateFns(raw_ostream &OS) = 0;
|
||||
|
||||
/// Emit the `testLeafPredicate` function
|
||||
/// Note `emitLeafPredicateFnsImpl` can be used to do most of the work.
|
||||
virtual void emitLeafPredicateFns(raw_ostream &OS) = 0;
|
||||
|
||||
/// Emit the `testImmPredicate_I64` function.
|
||||
/// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
|
||||
virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0;
|
||||
|
@ -2414,6 +2414,7 @@ class GICombinerEmitter final : public GlobalISelMatchTableExecutorEmitter {
|
||||
void emitAdditionalImpl(raw_ostream &OS) override;
|
||||
|
||||
void emitMIPredicateFns(raw_ostream &OS) override;
|
||||
void emitLeafPredicateFns(raw_ostream &OS) override;
|
||||
void emitI64ImmPredicateFns(raw_ostream &OS) override;
|
||||
void emitAPFloatImmPredicateFns(raw_ostream &OS) override;
|
||||
void emitAPIntImmPredicateFns(raw_ostream &OS) override;
|
||||
@ -2581,6 +2582,12 @@ void GICombinerEmitter::emitMIPredicateFns(raw_ostream &OS) {
|
||||
[](const CXXPredicateCode *C) -> StringRef { return C->Code; });
|
||||
}
|
||||
|
||||
void GICombinerEmitter::emitLeafPredicateFns(raw_ostream &OS) {
|
||||
// Unused, but still needs to be called.
|
||||
emitLeafPredicateFnsImpl<unsigned>(
|
||||
OS, "", {}, [](unsigned) { return ""; }, [](unsigned) { return ""; });
|
||||
}
|
||||
|
||||
void GICombinerEmitter::emitI64ImmPredicateFns(raw_ostream &OS) {
|
||||
// Unused, but still needs to be called.
|
||||
emitImmPredicateFnsImpl<unsigned>(
|
||||
|
@ -321,6 +321,7 @@ public:
|
||||
void emitAdditionalImpl(raw_ostream &OS) override;
|
||||
|
||||
void emitMIPredicateFns(raw_ostream &OS) override;
|
||||
void emitLeafPredicateFns(raw_ostream &OS) override;
|
||||
void emitI64ImmPredicateFns(raw_ostream &OS) override;
|
||||
void emitAPFloatImmPredicateFns(raw_ostream &OS) override;
|
||||
void emitAPIntImmPredicateFns(raw_ostream &OS) override;
|
||||
@ -1110,8 +1111,16 @@ Error GlobalISelEmitter::importChildMatcher(
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
if (SrcChild.hasAnyPredicate())
|
||||
return failedImport("Src pattern child has unsupported predicate");
|
||||
if (SrcChild.hasAnyPredicate()) {
|
||||
for (const TreePredicateCall &Call : SrcChild.getPredicateCalls()) {
|
||||
const TreePredicateFn &Predicate = Call.Fn;
|
||||
|
||||
if (!Predicate.hasGISelLeafPredicateCode())
|
||||
return failedImport("Src pattern child has unsupported predicate");
|
||||
OM.addPredicate<OperandLeafPredicateMatcher>(Predicate);
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Check for constant immediates.
|
||||
if (auto *ChildInt = dyn_cast<IntInit>(SrcChild.getLeafValue())) {
|
||||
@ -2293,6 +2302,26 @@ void GlobalISelEmitter::emitMIPredicateFns(raw_ostream &OS) {
|
||||
"PatFrag predicates.");
|
||||
}
|
||||
|
||||
void GlobalISelEmitter::emitLeafPredicateFns(raw_ostream &OS) {
|
||||
std::vector<const Record *> MatchedRecords;
|
||||
llvm::copy_if(AllPatFrags, std::back_inserter(MatchedRecords),
|
||||
[](const Record *R) {
|
||||
return (!R->getValueAsOptionalString("GISelLeafPredicateCode")
|
||||
.value_or(std::string())
|
||||
.empty());
|
||||
});
|
||||
emitLeafPredicateFnsImpl<const Record *>(
|
||||
OS,
|
||||
" const auto &Operands = State.RecordedOperands;\n"
|
||||
" Register Reg = MO.getReg();\n"
|
||||
" (void)Operands;",
|
||||
ArrayRef<const Record *>(MatchedRecords), &getPatFragPredicateEnumName,
|
||||
[](const Record *R) {
|
||||
return R->getValueAsString("GISelLeafPredicateCode");
|
||||
},
|
||||
"PatFrag predicates.");
|
||||
}
|
||||
|
||||
void GlobalISelEmitter::emitI64ImmPredicateFns(raw_ostream &OS) {
|
||||
std::vector<const Record *> MatchedRecords;
|
||||
llvm::copy_if(AllPatFrags, std::back_inserter(MatchedRecords),
|
||||
|
Loading…
x
Reference in New Issue
Block a user