Skip to content

Commit

Permalink
GlobalISel: legalize integer comparisons on AArch64.
Browse files Browse the repository at this point in the history
Next step is doing both legalizations at the same time! Marvel at GlobalISel's
cunning.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@279566 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
TNorthover committed Aug 23, 2016
1 parent 2956257 commit 4f24b7d
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 3 deletions.
22 changes: 22 additions & 0 deletions include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,28 @@ class MachineIRBuilder {
/// \return The newly created instruction.
MachineInstrBuilder buildAnyExtend(LLT Ty, unsigned Res, unsigned Op);

/// Build and insert \p Res<def> = G_SEXT \p { DstTy, SrcTy }\p Op
///
/// G_SEXT produces a register of the specified width, with bits 0 to
/// sizeof(\p Ty) * 8 set to \p Op. The remaining bits are duplicated from the
/// high bit of \p Op (i.e. 2s-complement sign extended).
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return The newly created instruction.
MachineInstrBuilder buildSExt(ArrayRef<LLT> Tys, unsigned Res, unsigned Op);

/// Build and insert \p Res<def> = G_ZEXT \p { DstTy, SrcTy } \p Op
///
/// G_ZEXT produces a register of the specified width, with bits 0 to
/// sizeof(\p Ty) * 8 set to \p Op. The remaining bits are 0. For a vector
/// register, each element is extended individually.
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return The newly created instruction.
MachineInstrBuilder buildZExt(ArrayRef<LLT> Tys, unsigned Res, unsigned Op);

/// Build and insert G_BR unsized \p Dest
///
/// G_BR is an unconditional branch to \p Dest.
Expand Down
10 changes: 10 additions & 0 deletions lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,16 @@ MachineInstrBuilder MachineIRBuilder::buildAnyExtend(LLT Ty, unsigned Res,
return buildInstr(TargetOpcode::G_ANYEXTEND, Ty).addDef(Res).addUse(Op);
}

MachineInstrBuilder MachineIRBuilder::buildSExt(ArrayRef<LLT> Tys, unsigned Res,
unsigned Op) {
return buildInstr(TargetOpcode::G_SEXT, Tys).addDef(Res).addUse(Op);
}

MachineInstrBuilder MachineIRBuilder::buildZExt(ArrayRef<LLT> Tys, unsigned Res,
unsigned Op) {
return buildInstr(TargetOpcode::G_ZEXT, Tys).addDef(Res).addUse(Op);
}

MachineInstrBuilder MachineIRBuilder::buildExtract(ArrayRef<LLT> ResTys,
ArrayRef<unsigned> Results,
ArrayRef<uint64_t> Indices,
Expand Down
36 changes: 34 additions & 2 deletions lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ MachineLegalizeHelper::narrowScalar(MachineInstr &MI, unsigned TypeIdx,
MachineLegalizeHelper::LegalizeResult
MachineLegalizeHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx,
LLT WideTy) {
assert(TypeIdx == 0 && "don't know how to handle secondary types yet");

unsigned WideSize = WideTy.getSizeInBits();
MIRBuilder.setInstr(MI);

Expand Down Expand Up @@ -180,6 +178,40 @@ MachineLegalizeHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx,
MI.eraseFromParent();
return Legalized;
}
case TargetOpcode::G_ICMP: {
if (TypeIdx == 0) {
unsigned TstExt = MRI.createGenericVirtualRegister(WideSize);
MIRBuilder.buildICmp(
{WideTy, MI.getType(1)},
static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
TstExt, MI.getOperand(2).getReg(), MI.getOperand(3).getReg());
MIRBuilder.buildTrunc(MI.getType(), MI.getOperand(0).getReg(), TstExt);
MI.eraseFromParent();
return Legalized;
} else {
bool IsSigned = CmpInst::isSigned(
static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
unsigned Op0Ext = MRI.createGenericVirtualRegister(WideSize);
unsigned Op1Ext = MRI.createGenericVirtualRegister(WideSize);
if (IsSigned) {
MIRBuilder.buildSExt({WideTy, MI.getType(1)}, Op0Ext,
MI.getOperand(2).getReg());
MIRBuilder.buildSExt({WideTy, MI.getType(1)}, Op1Ext,
MI.getOperand(3).getReg());
} else {
MIRBuilder.buildZExt({WideTy, MI.getType(1)}, Op0Ext,
MI.getOperand(2).getReg());
MIRBuilder.buildZExt({WideTy, MI.getType(1)}, Op1Ext,
MI.getOperand(3).getReg());
}
MIRBuilder.buildICmp(
{MI.getType(0), WideTy},
static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
MI.eraseFromParent();
return Legalized;
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/MIRParser/MIParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1522,7 +1522,7 @@ bool MIParser::parsePredicateOperand(MachineOperand &Dest) {

lex();
Dest = MachineOperand::CreatePredicate(Pred);
if (!expectAndConsume(MIToken::rparen))
if (expectAndConsume(MIToken::rparen))
return error("predicate should be terminated by ')'.");

return false;
Expand Down
13 changes: 13 additions & 0 deletions lib/Target/AArch64/AArch64MachineLegalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ AArch64MachineLegalizer::AArch64MachineLegalizer() {

setAction({TargetOpcode::G_FCONSTANT, s16}, WidenScalar);

// Comparisons: we produce a result in s32 with undefined high-bits for
// now. Values being compared can be 32 or 64-bits.
for (auto CmpOp : { G_ICMP }) {
setAction({CmpOp, 0, s32}, Legal);
setAction({CmpOp, 1, s32}, Legal);
setAction({CmpOp, 1, s64}, Legal);

for (auto Ty : {s1, s8, s16}) {
setAction({CmpOp, 0, Ty}, WidenScalar);
setAction({CmpOp, 1, Ty}, WidenScalar);
}
}

// Control-flow
setAction({G_BR, LLT::unsized()}, Legal);
setAction({G_BRCOND, s32}, Legal);
Expand Down

0 comments on commit 4f24b7d

Please sign in to comment.