[llvm] r217007 - [FastISel][AArch64] Add target-dependent instruction selection for Add/Sub.
Juergen Ributzka
juergen at apple.com
Tue Sep 2 18:38:36 PDT 2014
Author: ributzka
Date: Tue Sep 2 20:38:36 2014
New Revision: 217007
URL: http://llvm.org/viewvc/llvm-project?rev=217007&view=rev
Log:
[FastISel][AArch64] Add target-dependent instruction selection for Add/Sub.
There is already target-dependent instruction selection support for Adds/Subs to
support compares and the intrinsics with overflow check. This takes advantage of
the existing infrastructure to also support Add/Sub, which allows the folding of
immediates, sign-/zero-extends, and shifts.
This fixes rdar://problem/18207316.
Modified:
llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll
Modified: llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp?rev=217007&r1=217006&r2=217007&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp Tue Sep 2 20:38:36 2014
@@ -113,6 +113,7 @@ class AArch64FastISel : public FastISel
private:
// Selection routines.
+ bool selectAddSub(const Instruction *I);
bool SelectLoad(const Instruction *I);
bool SelectStore(const Instruction *I);
bool SelectBranch(const Instruction *I);
@@ -149,32 +150,25 @@ private:
const Value *Cond);
// Emit helper routines.
- unsigned emitAddsSubs(bool UseAdds, MVT RetVT, const Value *LHS,
- const Value *RHS, bool IsZExt = false,
- bool WantResult = true);
- unsigned emitAddsSubs_rr(bool UseAdds, MVT RetVT, unsigned LHSReg,
- bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
- bool WantResult = true);
- unsigned emitAddsSubs_ri(bool UseAdds, MVT RetVT, unsigned LHSReg,
- bool LHSIsKill, uint64_t Imm,
- bool WantResult = true);
+ unsigned emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
+ const Value *RHS, bool SetFlags = false,
+ bool WantResult = true, bool IsZExt = false);
+ unsigned emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
+ bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
+ bool SetFlags = false, bool WantResult = true);
+ unsigned emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
+ bool LHSIsKill, uint64_t Imm, bool SetFlags = false,
+ bool WantResult = true);
unsigned emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
AArch64_AM::ShiftExtendType ShiftType,
- uint64_t ShiftImm, bool WantResult = true);
- unsigned emitAddsSubs_rs(bool UseAdds, MVT RetVT, unsigned LHSReg,
- bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
- AArch64_AM::ShiftExtendType ShiftType,
- uint64_t ShiftImm, bool WantResult = true);
+ uint64_t ShiftImm, bool SetFlags = false,
+ bool WantResult = true);
unsigned emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
AArch64_AM::ShiftExtendType ExtType,
- uint64_t ShiftImm, bool WantResult = true);
-
- unsigned emitAddsSubs_rx(bool UseAdds, MVT RetVT, unsigned LHSReg,
- bool LHSIsKill, unsigned RHSReg, bool RHSIsKill,
- AArch64_AM::ShiftExtendType ExtType,
- uint64_t ShiftImm, bool WantResult = true);
+ uint64_t ShiftImm, bool SetFlags = false,
+ bool WantResult = true);
// Emit functions.
bool emitCmp(const Value *LHS, const Value *RHS, bool IsZExt);
@@ -187,10 +181,12 @@ private:
MachineMemOperand *MMO = nullptr);
unsigned EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
unsigned Emiti1Ext(unsigned SrcReg, MVT DestVT, bool isZExt);
- unsigned emitAdds(MVT RetVT, const Value *LHS, const Value *RHS,
- bool IsZExt = false, bool WantResult = true);
- unsigned emitSubs(MVT RetVT, const Value *LHS, const Value *RHS,
- bool IsZExt = false, bool WantResult = true);
+ unsigned emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
+ bool SetFlags = false, bool WantResult = true,
+ bool IsZExt = false);
+ unsigned emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
+ bool SetFlags = false, bool WantResult = true,
+ bool IsZExt = false);
unsigned emitSubs_rr(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
unsigned RHSReg, bool RHSIsKill, bool WantResult = true);
unsigned emitSubs_rs(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
@@ -855,9 +851,9 @@ void AArch64FastISel::AddLoadStoreOperan
MIB.addMemOperand(MMO);
}
-unsigned AArch64FastISel::emitAddsSubs(bool UseAdds, MVT RetVT,
- const Value *LHS, const Value *RHS,
- bool IsZExt, bool WantResult) {
+unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
+ const Value *RHS, bool SetFlags,
+ bool WantResult, bool IsZExt) {
AArch64_AM::ShiftExtendType ExtendType = AArch64_AM::InvalidShiftExtend;
bool NeedExtend = false;
switch (RetVT.SimpleTy) {
@@ -882,11 +878,11 @@ unsigned AArch64FastISel::emitAddsSubs(b
RetVT.SimpleTy = std::max(RetVT.SimpleTy, MVT::i32);
// Canonicalize immediates to the RHS first.
- if (UseAdds && isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
+ if (UseAdd && isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS))
std::swap(LHS, RHS);
// Canonicalize shift immediate to the RHS.
- if (UseAdds && isValueAvailable(LHS))
+ if (UseAdd && isValueAvailable(LHS))
if (const auto *SI = dyn_cast<BinaryOperator>(LHS))
if (isa<ConstantInt>(SI->getOperand(1)))
if (SI->getOpcode() == Instruction::Shl ||
@@ -906,11 +902,11 @@ unsigned AArch64FastISel::emitAddsSubs(b
if (const auto *C = dyn_cast<ConstantInt>(RHS)) {
uint64_t Imm = IsZExt ? C->getZExtValue() : C->getSExtValue();
if (C->isNegative())
- ResultReg =
- emitAddsSubs_ri(!UseAdds, RetVT, LHSReg, LHSIsKill, -Imm, WantResult);
+ ResultReg = emitAddSub_ri(!UseAdd, RetVT, LHSReg, LHSIsKill, -Imm,
+ SetFlags, WantResult);
else
- ResultReg =
- emitAddsSubs_ri(UseAdds, RetVT, LHSReg, LHSIsKill, Imm, WantResult);
+ ResultReg = emitAddSub_ri(UseAdd, RetVT, LHSReg, LHSIsKill, Imm, SetFlags,
+ WantResult);
}
if (ResultReg)
return ResultReg;
@@ -924,16 +920,16 @@ unsigned AArch64FastISel::emitAddsSubs(b
if (!RHSReg)
return 0;
bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
- return emitAddsSubs_rx(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg,
- RHSIsKill, ExtendType, C->getZExtValue(),
- WantResult);
+ return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
+ RHSIsKill, ExtendType, C->getZExtValue(),
+ SetFlags, WantResult);
}
unsigned RHSReg = getRegForValue(RHS);
if (!RHSReg)
return 0;
bool RHSIsKill = hasTrivialKill(RHS);
- return emitAddsSubs_rx(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
- ExtendType, 0, WantResult);
+ return emitAddSub_rx(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
+ ExtendType, 0, SetFlags, WantResult);
}
// Check if the shift can be folded into the instruction.
@@ -953,8 +949,9 @@ unsigned AArch64FastISel::emitAddsSubs(b
if (!RHSReg)
return 0;
bool RHSIsKill = hasTrivialKill(SI->getOperand(0));
- return emitAddsSubs_rs(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg,
- RHSIsKill, ShiftType, ShiftVal, WantResult);
+ return emitAddSub_rs(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg,
+ RHSIsKill, ShiftType, ShiftVal, SetFlags,
+ WantResult);
}
}
}
@@ -967,31 +964,34 @@ unsigned AArch64FastISel::emitAddsSubs(b
if (NeedExtend)
RHSReg = EmitIntExt(SrcVT, RHSReg, RetVT, IsZExt);
- return emitAddsSubs_rr(UseAdds, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
- WantResult);
+ return emitAddSub_rr(UseAdd, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
+ SetFlags, WantResult);
}
-unsigned AArch64FastISel::emitAddsSubs_rr(bool UseAdds, MVT RetVT,
- unsigned LHSReg, bool LHSIsKill,
- unsigned RHSReg, bool RHSIsKill,
- bool WantResult) {
+unsigned AArch64FastISel::emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
+ bool LHSIsKill, unsigned RHSReg,
+ bool RHSIsKill, bool SetFlags,
+ bool WantResult) {
assert(LHSReg && RHSReg && "Invalid register number.");
if (RetVT != MVT::i32 && RetVT != MVT::i64)
return 0;
- static const unsigned OpcTable[2][2] = {
- { AArch64::ADDSWrr, AArch64::ADDSXrr },
- { AArch64::SUBSWrr, AArch64::SUBSXrr }
+ static const unsigned OpcTable[2][2][2] = {
+ { { AArch64::SUBWrr, AArch64::SUBXrr },
+ { AArch64::ADDWrr, AArch64::ADDXrr } },
+ { { AArch64::SUBSWrr, AArch64::SUBSXrr },
+ { AArch64::ADDSWrr, AArch64::ADDSXrr } }
};
- unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
+ bool Is64Bit = RetVT == MVT::i64;
+ unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
+ const TargetRegisterClass *RC =
+ Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
unsigned ResultReg;
- if (WantResult) {
- const TargetRegisterClass *RC =
- (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+ if (WantResult)
ResultReg = createResultReg(RC);
- } else
- ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
+ else
+ ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
const MCInstrDesc &II = TII.get(Opc);
LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
@@ -999,13 +999,12 @@ unsigned AArch64FastISel::emitAddsSubs_r
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
.addReg(LHSReg, getKillRegState(LHSIsKill))
.addReg(RHSReg, getKillRegState(RHSIsKill));
-
return ResultReg;
}
-unsigned AArch64FastISel::emitAddsSubs_ri(bool UseAdds, MVT RetVT,
- unsigned LHSReg, bool LHSIsKill,
- uint64_t Imm, bool WantResult) {
+unsigned AArch64FastISel::emitAddSub_ri(bool UseAdd, MVT RetVT, unsigned LHSReg,
+ bool LHSIsKill, uint64_t Imm,
+ bool SetFlags, bool WantResult) {
assert(LHSReg && "Invalid register number.");
if (RetVT != MVT::i32 && RetVT != MVT::i64)
@@ -1020,18 +1019,24 @@ unsigned AArch64FastISel::emitAddsSubs_r
} else
return 0;
- static const unsigned OpcTable[2][2] = {
- { AArch64::ADDSWri, AArch64::ADDSXri },
- { AArch64::SUBSWri, AArch64::SUBSXri }
+ static const unsigned OpcTable[2][2][2] = {
+ { { AArch64::SUBWri, AArch64::SUBXri },
+ { AArch64::ADDWri, AArch64::ADDXri } },
+ { { AArch64::SUBSWri, AArch64::SUBSXri },
+ { AArch64::ADDSWri, AArch64::ADDSXri } }
};
- unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
+ bool Is64Bit = RetVT == MVT::i64;
+ unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
+ const TargetRegisterClass *RC;
+ if (SetFlags)
+ RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+ else
+ RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
unsigned ResultReg;
- if (WantResult) {
- const TargetRegisterClass *RC =
- (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+ if (WantResult)
ResultReg = createResultReg(RC);
- } else
- ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
+ else
+ ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
const MCInstrDesc &II = TII.get(Opc);
LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
@@ -1039,66 +1044,35 @@ unsigned AArch64FastISel::emitAddsSubs_r
.addReg(LHSReg, getKillRegState(LHSIsKill))
.addImm(Imm)
.addImm(getShifterImm(AArch64_AM::LSL, ShiftImm));
-
return ResultReg;
}
-unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT,
- unsigned LHSReg, bool LHSIsKill,
- unsigned RHSReg, bool RHSIsKill,
+unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
+ bool LHSIsKill, unsigned RHSReg,
+ bool RHSIsKill,
AArch64_AM::ShiftExtendType ShiftType,
- uint64_t ShiftImm, bool WantResult) {
- assert(LHSReg && RHSReg && "Invalid register number.");
-
- if (RetVT != MVT::i32 && RetVT != MVT::i64)
- return 0;
-
- static const unsigned OpcTable[2][2] = {
- { AArch64::ADDWrs, AArch64::ADDXrs },
- { AArch64::SUBWrs, AArch64::SUBXrs }
- };
- unsigned Opc = OpcTable[!UseAdd][(RetVT == MVT::i64)];
- unsigned ResultReg;
- if (WantResult) {
- const TargetRegisterClass *RC =
- (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
- ResultReg = createResultReg(RC);
- } else
- ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
-
- const MCInstrDesc &II = TII.get(Opc);
- LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
- RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(LHSReg, getKillRegState(LHSIsKill))
- .addReg(RHSReg, getKillRegState(RHSIsKill))
- .addImm(getShifterImm(ShiftType, ShiftImm));
-
- return ResultReg;
-}
-
-unsigned AArch64FastISel::emitAddsSubs_rs(bool UseAdds, MVT RetVT,
- unsigned LHSReg, bool LHSIsKill,
- unsigned RHSReg, bool RHSIsKill,
- AArch64_AM::ShiftExtendType ShiftType,
- uint64_t ShiftImm, bool WantResult) {
+ uint64_t ShiftImm, bool SetFlags,
+ bool WantResult) {
assert(LHSReg && RHSReg && "Invalid register number.");
if (RetVT != MVT::i32 && RetVT != MVT::i64)
return 0;
- static const unsigned OpcTable[2][2] = {
- { AArch64::ADDSWrs, AArch64::ADDSXrs },
- { AArch64::SUBSWrs, AArch64::SUBSXrs }
+ static const unsigned OpcTable[2][2][2] = {
+ { { AArch64::SUBWrs, AArch64::SUBXrs },
+ { AArch64::ADDWrs, AArch64::ADDXrs } },
+ { { AArch64::SUBSWrs, AArch64::SUBSXrs },
+ { AArch64::ADDSWrs, AArch64::ADDSXrs } }
};
- unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
+ bool Is64Bit = RetVT == MVT::i64;
+ unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
+ const TargetRegisterClass *RC =
+ Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
unsigned ResultReg;
- if (WantResult) {
- const TargetRegisterClass *RC =
- (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+ if (WantResult)
ResultReg = createResultReg(RC);
- } else
- ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
+ else
+ ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
const MCInstrDesc &II = TII.get(Opc);
LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
@@ -1107,66 +1081,38 @@ unsigned AArch64FastISel::emitAddsSubs_r
.addReg(LHSReg, getKillRegState(LHSIsKill))
.addReg(RHSReg, getKillRegState(RHSIsKill))
.addImm(getShifterImm(ShiftType, ShiftImm));
-
return ResultReg;
}
-unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT,
- unsigned LHSReg, bool LHSIsKill,
- unsigned RHSReg, bool RHSIsKill,
+unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
+ bool LHSIsKill, unsigned RHSReg,
+ bool RHSIsKill,
AArch64_AM::ShiftExtendType ExtType,
- uint64_t ShiftImm, bool WantResult) {
+ uint64_t ShiftImm, bool SetFlags,
+ bool WantResult) {
assert(LHSReg && RHSReg && "Invalid register number.");
if (RetVT != MVT::i32 && RetVT != MVT::i64)
return 0;
- static const unsigned OpcTable[2][2] = {
- { AArch64::ADDWrx, AArch64::ADDXrx },
- { AArch64::SUBWrx, AArch64::SUBXrx }
+ static const unsigned OpcTable[2][2][2] = {
+ { { AArch64::SUBWrx, AArch64::SUBXrx },
+ { AArch64::ADDWrx, AArch64::ADDXrx } },
+ { { AArch64::SUBSWrx, AArch64::SUBSXrx },
+ { AArch64::ADDSWrx, AArch64::ADDSXrx } }
};
- unsigned Opc = OpcTable[!UseAdd][(RetVT == MVT::i64)];
- unsigned ResultReg;
- if (WantResult) {
- const TargetRegisterClass *RC =
- (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
- ResultReg = createResultReg(RC);
- } else
- ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
-
- const MCInstrDesc &II = TII.get(Opc);
- LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
- RHSReg = constrainOperandRegClass(II, RHSReg, II.getNumDefs() + 1);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg)
- .addReg(LHSReg, getKillRegState(LHSIsKill))
- .addReg(RHSReg, getKillRegState(RHSIsKill))
- .addImm(getArithExtendImm(ExtType, ShiftImm));
-
- return ResultReg;
-}
-
-unsigned AArch64FastISel::emitAddsSubs_rx(bool UseAdds, MVT RetVT,
- unsigned LHSReg, bool LHSIsKill,
- unsigned RHSReg, bool RHSIsKill,
- AArch64_AM::ShiftExtendType ExtType,
- uint64_t ShiftImm, bool WantResult) {
- assert(LHSReg && RHSReg && "Invalid register number.");
-
- if (RetVT != MVT::i32 && RetVT != MVT::i64)
- return 0;
-
- static const unsigned OpcTable[2][2] = {
- { AArch64::ADDSWrx, AArch64::ADDSXrx },
- { AArch64::SUBSWrx, AArch64::SUBSXrx }
- };
- unsigned Opc = OpcTable[!UseAdds][(RetVT == MVT::i64)];
+ bool Is64Bit = RetVT == MVT::i64;
+ unsigned Opc = OpcTable[SetFlags][UseAdd][Is64Bit];
+ const TargetRegisterClass *RC = nullptr;
+ if (SetFlags)
+ RC = Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+ else
+ RC = Is64Bit ? &AArch64::GPR64spRegClass : &AArch64::GPR32spRegClass;
unsigned ResultReg;
- if (WantResult) {
- const TargetRegisterClass *RC =
- (RetVT == MVT::i64) ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
+ if (WantResult)
ResultReg = createResultReg(RC);
- } else
- ResultReg = (RetVT == MVT::i64) ? AArch64::XZR : AArch64::WZR;
+ else
+ ResultReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
const MCInstrDesc &II = TII.get(Opc);
LHSReg = constrainOperandRegClass(II, LHSReg, II.getNumDefs());
@@ -1175,7 +1121,6 @@ unsigned AArch64FastISel::emitAddsSubs_r
.addReg(LHSReg, getKillRegState(LHSIsKill))
.addReg(RHSReg, getKillRegState(RHSIsKill))
.addImm(getArithExtendImm(ExtType, ShiftImm));
-
return ResultReg;
}
@@ -1203,13 +1148,14 @@ bool AArch64FastISel::emitCmp(const Valu
bool AArch64FastISel::emitICmp(MVT RetVT, const Value *LHS, const Value *RHS,
bool IsZExt) {
- return emitSubs(RetVT, LHS, RHS, IsZExt, /*WantResult=*/false) != 0;
+ return emitSub(RetVT, LHS, RHS, /*SetFlags=*/true, /*WantResult=*/false,
+ IsZExt) != 0;
}
bool AArch64FastISel::emitICmp_ri(MVT RetVT, unsigned LHSReg, bool LHSIsKill,
uint64_t Imm) {
- return emitAddsSubs_ri(false, RetVT, LHSReg, LHSIsKill, Imm,
- /*WantResult=*/false) != 0;
+ return emitAddSub_ri(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, Imm,
+ /*SetFlags=*/true, /*WantResult=*/false) != 0;
}
bool AArch64FastISel::emitFCmp(MVT RetVT, const Value *LHS, const Value *RHS) {
@@ -1247,23 +1193,23 @@ bool AArch64FastISel::emitFCmp(MVT RetVT
return true;
}
-unsigned AArch64FastISel::emitAdds(MVT RetVT, const Value *LHS,
- const Value *RHS, bool IsZExt,
- bool WantResult) {
- return emitAddsSubs(true, RetVT, LHS, RHS, IsZExt, WantResult);
+unsigned AArch64FastISel::emitAdd(MVT RetVT, const Value *LHS, const Value *RHS,
+ bool SetFlags, bool WantResult, bool IsZExt) {
+ return emitAddSub(/*UseAdd=*/true, RetVT, LHS, RHS, SetFlags, WantResult,
+ IsZExt);
}
-unsigned AArch64FastISel::emitSubs(MVT RetVT, const Value *LHS,
- const Value *RHS, bool IsZExt,
- bool WantResult) {
- return emitAddsSubs(false, RetVT, LHS, RHS, IsZExt, WantResult);
+unsigned AArch64FastISel::emitSub(MVT RetVT, const Value *LHS, const Value *RHS,
+ bool SetFlags, bool WantResult, bool IsZExt) {
+ return emitAddSub(/*UseAdd=*/false, RetVT, LHS, RHS, SetFlags, WantResult,
+ IsZExt);
}
unsigned AArch64FastISel::emitSubs_rr(MVT RetVT, unsigned LHSReg,
bool LHSIsKill, unsigned RHSReg,
bool RHSIsKill, bool WantResult) {
- return emitAddsSubs_rr(false, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
- WantResult);
+ return emitAddSub_rr(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, RHSReg,
+ RHSIsKill, /*SetFlags=*/true, WantResult);
}
unsigned AArch64FastISel::emitSubs_rs(MVT RetVT, unsigned LHSReg,
@@ -1271,8 +1217,9 @@ unsigned AArch64FastISel::emitSubs_rs(MV
bool RHSIsKill,
AArch64_AM::ShiftExtendType ShiftType,
uint64_t ShiftImm, bool WantResult) {
- return emitAddsSubs_rs(false, RetVT, LHSReg, LHSIsKill, RHSReg, RHSIsKill,
- ShiftType, ShiftImm, WantResult);
+ return emitAddSub_rs(/*UseAdd=*/false, RetVT, LHSReg, LHSIsKill, RHSReg,
+ RHSIsKill, ShiftType, ShiftImm, /*SetFlags=*/true,
+ WantResult);
}
// FIXME: This should be eventually generated automatically by tblgen.
@@ -1376,6 +1323,24 @@ bool AArch64FastISel::EmitLoad(MVT VT, u
return true;
}
+bool AArch64FastISel::selectAddSub(const Instruction *I) {
+ MVT VT;
+ if (!isTypeSupported(I->getType(), VT))
+ return false;
+
+ unsigned ResultReg;
+ if (I->getOpcode() == Instruction::Add)
+ ResultReg = emitAdd(VT, I->getOperand(0), I->getOperand(1));
+ else if (I->getOpcode() == Instruction::Sub)
+ ResultReg = emitSub(VT, I->getOperand(0), I->getOperand(1));
+ else
+ llvm_unreachable("Unexpected instruction.");
+
+ assert(ResultReg && "Couldn't select Add/Sub instruction.");
+ UpdateValueMap(I, ResultReg);
+ return true;
+}
+
bool AArch64FastISel::SelectLoad(const Instruction *I) {
MVT VT;
// Verify we have a legal type before going any further. Currently, we handle
@@ -2512,13 +2477,21 @@ bool AArch64FastISel::FastLowerIntrinsic
switch (II->getIntrinsicID()) {
default: llvm_unreachable("Unexpected intrinsic!");
case Intrinsic::sadd_with_overflow:
- ResultReg1 = emitAdds(VT, LHS, RHS); CC = AArch64CC::VS; break;
+ ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
+ CC = AArch64CC::VS;
+ break;
case Intrinsic::uadd_with_overflow:
- ResultReg1 = emitAdds(VT, LHS, RHS); CC = AArch64CC::HS; break;
+ ResultReg1 = emitAdd(VT, LHS, RHS, /*SetFlags=*/true);
+ CC = AArch64CC::HS;
+ break;
case Intrinsic::ssub_with_overflow:
- ResultReg1 = emitSubs(VT, LHS, RHS); CC = AArch64CC::VS; break;
+ ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
+ CC = AArch64CC::VS;
+ break;
case Intrinsic::usub_with_overflow:
- ResultReg1 = emitSubs(VT, LHS, RHS); CC = AArch64CC::LO; break;
+ ResultReg1 = emitSub(VT, LHS, RHS, /*SetFlags=*/true);
+ CC = AArch64CC::LO;
+ break;
case Intrinsic::smul_with_overflow: {
CC = AArch64CC::NE;
unsigned LHSReg = getRegForValue(LHS);
@@ -3442,11 +3415,15 @@ bool AArch64FastISel::TargetSelectInstru
default:
return false;
case Instruction::Add:
- return SelectBinaryOp(I, ISD::ADD);
+ if (!selectAddSub(I))
+ return SelectBinaryOp(I, ISD::ADD);
+ return true;
+ case Instruction::Sub:
+ if (!selectAddSub(I))
+ return SelectBinaryOp(I, ISD::SUB);
+ return true;
case Instruction::FAdd:
return SelectBinaryOp(I, ISD::FADD);
- case Instruction::Sub:
- return SelectBinaryOp(I, ISD::SUB);
case Instruction::FSub:
// FNeg is currently represented in LLVM IR as a special case of FSub.
if (BinaryOperator::isFNeg(I))
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll?rev=217007&r1=217006&r2=217007&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-gv.ll Tue Sep 2 20:38:36 2014
@@ -6,9 +6,9 @@
define void @Initrand() nounwind {
entry:
; CHECK: @Initrand
-; CHECK: adrp x[[REG:[0-9]+]], _seed at GOTPAGE
-; CHECK: ldr x[[REG2:[0-9]+]], [x[[REG]], _seed at GOTPAGEOFF]
-; CHECK: str x{{[0-9]+}}, [x[[REG2]]]
+; CHECK: adrp [[REG:x[0-9]+]], _seed at GOTPAGE
+; CHECK: ldr [[REG2:x[0-9]+]], {{\[}}[[REG]], _seed at GOTPAGEOFF{{\]}}
+; CHECK: str {{x[0-9]+}}, {{\[}}[[REG2]]{{\]}}
store i64 74755, i64* @seed, align 8
ret void
}
@@ -16,17 +16,17 @@ entry:
define i32 @Rand() nounwind {
entry:
; CHECK: @Rand
-; CHECK: adrp x[[REG:[0-9]+]], _seed at GOTPAGE
-; CHECK: ldr x[[REG2:[0-9]+]], [x[[REG]], _seed at GOTPAGEOFF]
-; CHECK: movz x[[REG3:[0-9]+]], #0x51d
-; CHECK: ldr x[[REG4:[0-9]+]], [x[[REG2]]]
-; CHECK: mul x[[REG5:[0-9]+]], x[[REG4]], x[[REG3]]
-; CHECK: movz x[[REG6:[0-9]+]], #0x3619
-; CHECK: add x[[REG7:[0-9]+]], x[[REG5]], x[[REG6]]
-; CHECK: orr x[[REG8:[0-9]+]], xzr, #0xffff
-; CHECK: and x[[REG9:[0-9]+]], x[[REG7]], x[[REG8]]
-; CHECK: str x[[REG9]], [x[[REG]]]
-; CHECK: ldr x{{[0-9]+}}, [x[[REG]]]
+; CHECK: adrp [[REG1:x[0-9]+]], _seed at GOTPAGE
+; CHECK: ldr [[REG2:x[0-9]+]], {{\[}}[[REG1]], _seed at GOTPAGEOFF{{\]}}
+; CHECK: movz [[REG3:x[0-9]+]], #0x3619
+; CHECK: movz [[REG4:x[0-9]+]], #0x51d
+; CHECK: ldr [[REG5:x[0-9]+]], {{\[}}[[REG2]]{{\]}}
+; CHECK: mul [[REG6:x[0-9]+]], [[REG5]], [[REG4]]
+; CHECK: add [[REG7:x[0-9]+]], [[REG6]], [[REG3]]
+; CHECK: orr [[REG8:x[0-9]+]], xzr, #0xffff
+; CHECK: and [[REG9:x[0-9]+]], [[REG7]], [[REG8]]
+; CHECK: str [[REG9]], {{\[}}[[REG1]]{{\]}}
+; CHECK: ldr {{x[0-9]+}}, {{\[}}[[REG1]]{{\]}}
%0 = load i64* @seed, align 8
%mul = mul nsw i64 %0, 1309
%add = add nsw i64 %mul, 13849
More information about the llvm-commits
mailing list