Skip to content

Commit

Permalink
[globalisel] Update GlobalISel emitter to match new representation of…
Browse files Browse the repository at this point in the history
… extending loads

Summary:
Previously, a extending load was represented at (G_*EXT (G_LOAD x)).
This had a few drawbacks:
* G_LOAD had to be legal for all sizes you could extend from, even if
  registers didn't naturally hold those sizes.
* All sizes you could extend from had to be allocatable just in case the
  extend went missing (e.g. by optimization).
* At minimum, G_*EXT and G_TRUNC had to be legal for these sizes. As we
  improve optimization of extends and truncates, this legality requirement
  would spread without considerable care w.r.t when certain combines were
  permitted.
* The SelectionDAG importer required some ugly and fragile pattern
  rewriting to translate patterns into this style.

This patch changes the representation to:
* (G_[SZ]EXTLOAD x)
* (G_LOAD x) any-extends when MMO.getSize() * 8 < ResultTy.getSizeInBits()
which resolves these issues by allowing targets to work entirely in their
native register sizes, and by having a more direct translation from
SelectionDAG patterns.

Each extending load can be lowered by the legalizer into separate extends
and loads, however a target that supports s1 will need the any-extending
load to extend to at least s8 since LLVM does not represent memory accesses
smaller than 8 bit. The legalizer can widenScalar G_LOAD into an
any-extending load but sign/zero-extending loads need help from something
else like a combiner pass. A follow-up patch that adds combiner helpers for
for this will follow.

The new representation requires that the MMO correctly reflect the memory
access so this has been corrected in a couple tests. I've also moved the
extending loads to their own tests since they are (mostly) separate opcodes
now. Additionally, the re-write appears to have invalidated two tests from
select-with-no-legality-check.mir since the matcher table no longer contains
loads that result in s1's and they aren't legal in AArch64 anymore.

Depends on D45540

Reviewers: ab, aditya_nandakumar, bogner, rtereshin, volkan, rovka, javed.absar

Reviewed By: rtereshin

Subscribers: javed.absar, llvm-commits, kristof.beyls

Differential Revision: https://reviews.llvm.org/D45541

llvm-svn: 331601
  • Loading branch information
dsandersllvm committed May 5, 2018
1 parent c86da6b commit f84bc37
Show file tree
Hide file tree
Showing 17 changed files with 557 additions and 240 deletions.
13 changes: 13 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
Expand Up @@ -117,6 +117,19 @@ enum {
GIM_CheckAtomicOrdering,
GIM_CheckAtomicOrderingOrStrongerThan,
GIM_CheckAtomicOrderingWeakerThan,
/// Check the size of the memory access for the given machine memory operand.
/// - InsnID - Instruction ID
/// - MMOIdx - MMO index
/// - Size - The size in bytes of the memory access
GIM_CheckMemorySizeEqualTo,
/// Check the size of the memory access for the given machine memory operand
/// against the size of an operand.
/// - InsnID - Instruction ID
/// - MMOIdx - MMO index
/// - OpIdx - The operand index to compare the MMO against
GIM_CheckMemorySizeEqualToLLT,
GIM_CheckMemorySizeLessThanLLT,
GIM_CheckMemorySizeGreaterThanLLT,

/// Check the type for the specified operand
/// - InsnID - Instruction ID
Expand Down
84 changes: 83 additions & 1 deletion llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
Expand Up @@ -72,7 +72,8 @@ bool InstructionSelector::executeMatchTable(

while (true) {
assert(CurrentIdx != ~0u && "Invalid MatchTable index");
switch (MatchTable[CurrentIdx++]) {
int64_t MatcherOpcode = MatchTable[CurrentIdx++];
switch (MatcherOpcode) {
case GIM_Try: {
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
dbgs() << CurrentIdx << ": Begin try-block\n");
Expand Down Expand Up @@ -284,6 +285,87 @@ bool InstructionSelector::executeMatchTable(
return false;
break;
}
case GIM_CheckMemorySizeEqualTo: {
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t MMOIdx = MatchTable[CurrentIdx++];
uint64_t Size = MatchTable[CurrentIdx++];

DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
dbgs() << CurrentIdx
<< ": GIM_CheckMemorySizeEqual(MIs[" << InsnID
<< "]->memoperands() + " << MMOIdx
<< ", Size=" << Size << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");

if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
if (handleReject() == RejectAndGiveUp)
return false;
break;
}

MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);

DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
dbgs() << MMO->getSize() << " bytes vs " << Size
<< " bytes\n");
if (MMO->getSize() != Size)
if (handleReject() == RejectAndGiveUp)
return false;

break;
}
case GIM_CheckMemorySizeEqualToLLT:
case GIM_CheckMemorySizeLessThanLLT:
case GIM_CheckMemorySizeGreaterThanLLT: {
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t MMOIdx = MatchTable[CurrentIdx++];
int64_t OpIdx = MatchTable[CurrentIdx++];

DEBUG_WITH_TYPE(
TgtInstructionSelector::getName(),
dbgs() << CurrentIdx << ": GIM_CheckMemorySize"
<< (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT
? "EqualTo"
: MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT
? "GreaterThan"
: "LessThan")
<< "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx
<< ", OpIdx=" << OpIdx << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");

MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
if (!MO.isReg()) {
DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
dbgs() << CurrentIdx << ": Not a register\n");
if (handleReject() == RejectAndGiveUp)
return false;
break;
}

if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
if (handleReject() == RejectAndGiveUp)
return false;
break;
}

MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);

unsigned Size = MRI.getType(MO.getReg()).getSizeInBits();
if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT &&
MMO->getSize() * 8 != Size) {
if (handleReject() == RejectAndGiveUp)
return false;
} else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT &&
MMO->getSize() * 8 >= Size) {
if (handleReject() == RejectAndGiveUp)
return false;
} else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT &&
MMO->getSize() * 8 <= Size)
if (handleReject() == RejectAndGiveUp)
return false;

break;
}
case GIM_CheckType: {
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t OpIdx = MatchTable[CurrentIdx++];
Expand Down
15 changes: 13 additions & 2 deletions llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
Expand Up @@ -28,6 +28,13 @@ class GINodeEquiv<Instruction i, SDNode node> {
// (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel
// stores this information in the MachineMemoryOperand.
bit CheckMMOIsNonAtomic = 0;

// SelectionDAG has one node for all loads and uses predicates to
// differentiate them. GlobalISel on the other hand uses separate opcodes.
// When this is true, the resulting opcode is G_LOAD/G_SEXTLOAD/G_ZEXTLOAD
// depending on the predicates on the node.
Instruction IfSignExtend = ?;
Instruction IfZeroExtend = ?;
}

// These are defined in the same order as the G_* instructions.
Expand Down Expand Up @@ -80,11 +87,15 @@ def : GINodeEquiv<G_BSWAP, bswap>;
// Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some
// complications that tablegen must take care of. For example, Predicates such
// as isSignExtLoad require that this is not a perfect 1:1 mapping since a
// sign-extending load is (G_SEXT (G_LOAD x)) in GlobalISel. Additionally,
// sign-extending load is (G_SEXTLOAD x) in GlobalISel. Additionally,
// G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had
// separate nodes for them. This GINodeEquiv maps the non-atomic loads to
// G_LOAD with a non-atomic MachineMemOperand.
def : GINodeEquiv<G_LOAD, ld> { let CheckMMOIsNonAtomic = 1; }
def : GINodeEquiv<G_LOAD, ld> {
let CheckMMOIsNonAtomic = 1;
let IfSignExtend = G_SEXTLOAD;
let IfZeroExtend = G_ZEXTLOAD;
}
// Broadly speaking G_STORE is equivalent to ISD::STORE but there are some
// complications that tablegen must take care of. For example, predicates such
// as isTruncStore require that this is not a perfect 1:1 mapping since a
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
Expand Up @@ -977,7 +977,6 @@ bool AArch64InstructionSelector::select(MachineInstr &I,

case TargetOpcode::G_LOAD:
case TargetOpcode::G_STORE: {
LLT MemTy = Ty;
LLT PtrTy = MRI.getType(I.getOperand(1).getReg());

if (PtrTy != LLT::pointer(0, 64)) {
Expand All @@ -991,6 +990,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
DEBUG(dbgs() << "Atomic load/store not supported yet\n");
return false;
}
unsigned MemSizeInBits = MemOp.getSize() * 8;

// FIXME: PR36018: Volatile loads in some cases are incorrectly selected by
// folding with an extend. Until we have a G_SEXTLOAD solution bail out if
Expand All @@ -1012,7 +1012,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
const RegisterBank &RB = *RBI.getRegBank(ValReg, MRI, TRI);

const unsigned NewOpc =
selectLoadStoreUIOp(I.getOpcode(), RB.getID(), MemTy.getSizeInBits());
selectLoadStoreUIOp(I.getOpcode(), RB.getID(), MemSizeInBits);
if (NewOpc == I.getOpcode())
return false;

Expand All @@ -1025,7 +1025,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I,
if (PtrMI->getOpcode() == TargetOpcode::G_GEP) {
if (auto COff = getConstantVRegVal(PtrMI->getOperand(2).getReg(), MRI)) {
int64_t Imm = *COff;
const unsigned Size = MemTy.getSizeInBits() / 8;
const unsigned Size = MemSizeInBits / 8;
const unsigned Scale = Log2_32(Size);
if ((Imm & (Size - 1)) == 0 && Imm >= 0 && Imm < (0x1000 << Scale)) {
unsigned Ptr2Reg = PtrMI->getOperand(1).getReg();
Expand Down
35 changes: 34 additions & 1 deletion llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp
Expand Up @@ -136,20 +136,53 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) {
.widenScalarToNextPow2(0);

getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
.legalForTypesWithMemSize({{s32, p0, 8},
{s32, p0, 16},
{s32, p0, 32},
{s64, p0, 64},
{p0, p0, 64},
{v2s32, p0, 64}})
.clampScalar(0, s32, s64)
.widenScalarToNextPow2(0)
// TODO: We could support sum-of-pow2's but the lowering code doesn't know
// how to do that yet.
.unsupportedIfMemSizeNotPow2()
// Lower anything left over into G_*EXT and G_LOAD
.lower();

getActionDefinitionsBuilder({G_LOAD, G_STORE})
getActionDefinitionsBuilder(G_LOAD)
.legalForTypesWithMemSize({{s8, p0, 8},
{s16, p0, 16},
{s32, p0, 32},
{s64, p0, 64},
{p0, p0, 64},
{v2s32, p0, 64}})
// These extends are also legal
.legalForTypesWithMemSize({{s32, p0, 8},
{s32, p0, 16}})
.clampScalar(0, s8, s64)
.widenScalarToNextPow2(0)
// TODO: We could support sum-of-pow2's but the lowering code doesn't know
// how to do that yet.
.unsupportedIfMemSizeNotPow2()
// Lower any any-extending loads left into G_ANYEXT and G_LOAD
.lowerIf([=](const LegalityQuery &Query) {
return Query.Types[0].getSizeInBits() != Query.MMODescrs[0].Size * 8;
})
.clampNumElements(0, v2s32, v2s32);

getActionDefinitionsBuilder(G_STORE)
.legalForTypesWithMemSize({{s8, p0, 8},
{s16, p0, 16},
{s32, p0, 32},
{s64, p0, 64},
{p0, p0, 64},
{v2s32, p0, 64}})
.clampScalar(0, s8, s64)
.widenScalarToNextPow2(0)
// TODO: We could support sum-of-pow2's but the lowering code doesn't know
// how to do that yet.
.unsupportedIfMemSizeNotPow2()
.lowerIf([=](const LegalityQuery &Query) {
return Query.Types[0].isScalar() &&
Query.Types[0].getSizeInBits() != Query.MMODescrs[0].Size * 8;
Expand Down
5 changes: 2 additions & 3 deletions llvm/test/CodeGen/AArch64/GlobalISel/legalize-extload.mir
Expand Up @@ -16,9 +16,8 @@ body: |
liveins: $x0
; CHECK-LABEL: name: test_extload
; CHECK: [[T0:%[0-9]+]]:_(p0) = COPY $x0
; CHECK: [[T1:%[0-9]+]]:_(s8) = G_LOAD [[T0]](p0) :: (load 1 from %ir.addr)
; CHECK: [[T2:%[0-9]+]]:_(s32) = G_ANYEXT [[T1]](s8)
; CHECK: $w0 = COPY [[T2]](s32)
; CHECK: [[T1:%[0-9]+]]:_(s32) = G_LOAD [[T0]](p0) :: (load 1 from %ir.addr)
; CHECK: $w0 = COPY [[T1]](s32)
%0:_(p0) = COPY $x0
%1:_(s32) = G_LOAD %0 :: (load 1 from %ir.addr)
$w0 = COPY %1
Expand Down
5 changes: 2 additions & 3 deletions llvm/test/CodeGen/AArch64/GlobalISel/legalize-sextload.mir
Expand Up @@ -16,9 +16,8 @@ body: |
liveins: $x0
; CHECK-LABEL: name: test_zextload
; CHECK: [[T0:%[0-9]+]]:_(p0) = COPY $x0
; CHECK: [[T1:%[0-9]+]]:_(s8) = G_LOAD [[T0]](p0) :: (load 1 from %ir.addr)
; CHECK: [[T2:%[0-9]+]]:_(s32) = G_SEXT [[T1]](s8)
; CHECK: $w0 = COPY [[T2]](s32)
; CHECK: [[T1:%[0-9]+]]:_(s32) = G_SEXTLOAD [[T0]](p0) :: (load 1 from %ir.addr)
; CHECK: $w0 = COPY [[T1]](s32)
%0:_(p0) = COPY $x0
%1:_(s32) = G_SEXTLOAD %0 :: (load 1 from %ir.addr)
$w0 = COPY %1
Expand Down
5 changes: 2 additions & 3 deletions llvm/test/CodeGen/AArch64/GlobalISel/legalize-zextload.mir
Expand Up @@ -16,9 +16,8 @@ body: |
liveins: $x0
; CHECK-LABEL: name: test_sextload
; CHECK: [[T0:%[0-9]+]]:_(p0) = COPY $x0
; CHECK: [[T1:%[0-9]+]]:_(s8) = G_LOAD [[T0]](p0) :: (load 1 from %ir.addr)
; CHECK: [[T2:%[0-9]+]]:_(s32) = G_ZEXT [[T1]](s8)
; CHECK: $w0 = COPY [[T2]](s32)
; CHECK: [[T1:%[0-9]+]]:_(s32) = G_ZEXTLOAD [[T0]](p0) :: (load 1 from %ir.addr)
; CHECK: $w0 = COPY [[T1]](s32)
%0:_(p0) = COPY $x0
%1:_(s32) = G_ZEXTLOAD %0 :: (load 1 from %ir.addr)
$w0 = COPY %1
Expand Down
36 changes: 18 additions & 18 deletions llvm/test/CodeGen/AArch64/GlobalISel/select-atomicrmw.mir
Expand Up @@ -68,11 +68,11 @@ body: |
; CHECK-LABEL: name: atomicrmw_add_i32
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDADDALW [[CST]], [[COPY]] :: (load store seq_cst 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDADDALW [[CST]], [[COPY]] :: (load store seq_cst 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_ADD %0, %1 :: (load store seq_cst 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_ADD %0, %1 :: (load store seq_cst 4 on %ir.addr)
$w0 = COPY %2(s32)
...

Expand All @@ -88,11 +88,11 @@ body: |
; CHECK-LABEL: name: atomicrmw_sub_i32
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDADDALW [[CST]], [[COPY]] :: (load store seq_cst 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDADDALW [[CST]], [[COPY]] :: (load store seq_cst 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_ADD %0, %1 :: (load store seq_cst 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_ADD %0, %1 :: (load store seq_cst 4 on %ir.addr)
$w0 = COPY %2(s32)
...

Expand All @@ -109,11 +109,11 @@ body: |
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[CST2:%[0-9]+]]:gpr32 = ORNWrr $wzr, [[CST]]
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDCLRAW [[CST2]], [[COPY]] :: (load store acquire 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDCLRAW [[CST2]], [[COPY]] :: (load store acquire 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_AND %0, %1 :: (load store acquire 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_AND %0, %1 :: (load store acquire 4 on %ir.addr)
$w0 = COPY %2(s32)
...

Expand All @@ -129,11 +129,11 @@ body: |
; CHECK-LABEL: name: atomicrmw_or_i32
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDSETLW [[CST]], [[COPY]] :: (load store release 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDSETLW [[CST]], [[COPY]] :: (load store release 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_OR %0, %1 :: (load store release 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_OR %0, %1 :: (load store release 4 on %ir.addr)
$w0 = COPY %2(s32)
...

Expand All @@ -149,11 +149,11 @@ body: |
; CHECK-LABEL: name: atomicrmw_xor_i32
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDEORALW [[CST]], [[COPY]] :: (load store acq_rel 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDEORALW [[CST]], [[COPY]] :: (load store acq_rel 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_XOR %0, %1 :: (load store acq_rel 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_XOR %0, %1 :: (load store acq_rel 4 on %ir.addr)
$w0 = COPY %2(s32)
...

Expand All @@ -169,11 +169,11 @@ body: |
; CHECK-LABEL: name: atomicrmw_min_i32
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDSMINALW [[CST]], [[COPY]] :: (load store acq_rel 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDSMINALW [[CST]], [[COPY]] :: (load store acq_rel 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_MIN %0, %1 :: (load store acq_rel 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_MIN %0, %1 :: (load store acq_rel 4 on %ir.addr)
$w0 = COPY %2(s32)
...

Expand All @@ -189,11 +189,11 @@ body: |
; CHECK-LABEL: name: atomicrmw_max_i32
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDSMAXALW [[CST]], [[COPY]] :: (load store acq_rel 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDSMAXALW [[CST]], [[COPY]] :: (load store acq_rel 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_MAX %0, %1 :: (load store acq_rel 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_MAX %0, %1 :: (load store acq_rel 4 on %ir.addr)
$w0 = COPY %2(s32)
...

Expand All @@ -209,11 +209,11 @@ body: |
; CHECK-LABEL: name: atomicrmw_umin_i32
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDUMINALW [[CST]], [[COPY]] :: (load store acq_rel 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDUMINALW [[CST]], [[COPY]] :: (load store acq_rel 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_UMIN %0, %1 :: (load store acq_rel 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_UMIN %0, %1 :: (load store acq_rel 4 on %ir.addr)
$w0 = COPY %2(s32)
...

Expand All @@ -229,10 +229,10 @@ body: |
; CHECK-LABEL: name: atomicrmw_umax_i32
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
; CHECK: [[CST:%[0-9]+]]:gpr32 = MOVi32imm 1
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDUMAXALW [[CST]], [[COPY]] :: (load store acq_rel 8 on %ir.addr)
; CHECK: [[RES:%[0-9]+]]:gpr32 = LDUMAXALW [[CST]], [[COPY]] :: (load store acq_rel 4 on %ir.addr)
; CHECK: $w0 = COPY [[RES]]
%0:gpr(p0) = COPY $x0
%1:gpr(s32) = G_CONSTANT i32 1
%2:gpr(s32) = G_ATOMICRMW_UMAX %0, %1 :: (load store acq_rel 8 on %ir.addr)
%2:gpr(s32) = G_ATOMICRMW_UMAX %0, %1 :: (load store acq_rel 4 on %ir.addr)
$w0 = COPY %2(s32)
...

0 comments on commit f84bc37

Please sign in to comment.