mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 19:12:56 +02:00
Revert "[X86] Replace slow LEA instructions in X86"
This reverts commit r303183, it broke various buildbots and introduced sanitizer errors. llvm-svn: 303199
This commit is contained in:
parent
3633380341
commit
6ef635c682
@ -235,8 +235,6 @@ def FeatureLEAUsesAG : SubtargetFeature<"lea-uses-ag", "LEAUsesAG", "true",
|
||||
"LEA instruction needs inputs at AG stage">;
|
||||
def FeatureSlowLEA : SubtargetFeature<"slow-lea", "SlowLEA", "true",
|
||||
"LEA instruction with certain arguments is slow">;
|
||||
def FeatureSlow3OpsLEA : SubtargetFeature<"slow-3ops-lea", "Slow3OpsLEA", "true",
|
||||
"LEA instruction with 3 ops or certain registers is slow">;
|
||||
def FeatureSlowIncDec : SubtargetFeature<"slow-incdec", "SlowIncDec", "true",
|
||||
"INC and DEC instructions are slower than ADD and SUB">;
|
||||
def FeatureSoftFloat
|
||||
@ -482,7 +480,6 @@ def SNBFeatures : ProcessorFeatures<[], [
|
||||
FeatureXSAVE,
|
||||
FeatureXSAVEOPT,
|
||||
FeatureLAHFSAHF,
|
||||
FeatureSlow3OpsLEA,
|
||||
FeatureFastScalarFSQRT,
|
||||
FeatureFastSHLDRotate
|
||||
]>;
|
||||
|
@ -27,26 +27,20 @@
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
void initializeFixupLEAPassPass(PassRegistry &);
|
||||
}
|
||||
|
||||
#define FIXUPLEA_DESC "X86 LEA Fixup"
|
||||
#define FIXUPLEA_NAME "x86-fixup-LEAs"
|
||||
|
||||
#define DEBUG_TYPE FIXUPLEA_NAME
|
||||
#define DEBUG_TYPE "x86-fixup-LEAs"
|
||||
|
||||
STATISTIC(NumLEAs, "Number of LEA instructions created");
|
||||
|
||||
namespace {
|
||||
class FixupLEAPass : public MachineFunctionPass {
|
||||
enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };
|
||||
|
||||
static char ID;
|
||||
/// \brief Loop over all of the instructions in the basic block
|
||||
/// replacing applicable instructions with LEA instructions,
|
||||
/// where appropriate.
|
||||
bool processBasicBlock(MachineFunction &MF, MachineFunction::iterator MFI);
|
||||
|
||||
StringRef getPassName() const override { return "X86 LEA Fixup"; }
|
||||
|
||||
/// \brief Given a machine register, look for the instruction
|
||||
/// which writes it in the current basic block. If found,
|
||||
@ -68,22 +62,6 @@ class FixupLEAPass : public MachineFunctionPass {
|
||||
void processInstructionForSLM(MachineBasicBlock::iterator &I,
|
||||
MachineFunction::iterator MFI);
|
||||
|
||||
|
||||
/// \brief Given a LEA instruction which is unprofitable
|
||||
/// on SNB+ try to replace it with other instructions.
|
||||
/// According to Intel's Optimization Reference Manual:
|
||||
/// " For LEA instructions with three source operands and some specific
|
||||
/// situations, instruction latency has increased to 3 cycles, and must
|
||||
/// dispatch via port 1:
|
||||
/// - LEA that has all three source operands: base, index, and offset
|
||||
/// - LEA that uses base and index registers where the base is EBP, RBP,
|
||||
/// or R13
|
||||
/// - LEA that uses RIP relative addressing mode
|
||||
/// - LEA that uses 16-bit addressing mode "
|
||||
/// This function currently handles the first 2 cases only.
|
||||
MachineInstr *processInstrForSlow3OpLEA(MachineInstr &MI,
|
||||
MachineFunction::iterator MFI);
|
||||
|
||||
/// \brief Look for LEAs that add 1 to reg or subtract 1 from reg
|
||||
/// and convert them to INC or DEC respectively.
|
||||
bool fixupIncDec(MachineBasicBlock::iterator &I,
|
||||
@ -107,13 +85,7 @@ class FixupLEAPass : public MachineFunctionPass {
|
||||
MachineBasicBlock::iterator &MBBI) const;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
StringRef getPassName() const override { return FIXUPLEA_DESC; }
|
||||
|
||||
FixupLEAPass() : MachineFunctionPass(ID) {
|
||||
initializeFixupLEAPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
FixupLEAPass() : MachineFunctionPass(ID) {}
|
||||
|
||||
/// \brief Loop over all of the basic blocks,
|
||||
/// replacing instructions by equivalent LEA instructions
|
||||
@ -132,11 +104,8 @@ private:
|
||||
bool OptIncDec;
|
||||
bool OptLEA;
|
||||
};
|
||||
}
|
||||
|
||||
char FixupLEAPass::ID = 0;
|
||||
|
||||
INITIALIZE_PASS(FixupLEAPass, FIXUPLEA_NAME, FIXUPLEA_DESC, false, false)
|
||||
}
|
||||
|
||||
MachineInstr *
|
||||
FixupLEAPass::postRAConvertToLEA(MachineFunction::iterator &MFI,
|
||||
@ -199,7 +168,7 @@ bool FixupLEAPass::runOnMachineFunction(MachineFunction &Func) {
|
||||
MF = &Func;
|
||||
const X86Subtarget &ST = Func.getSubtarget<X86Subtarget>();
|
||||
OptIncDec = !ST.slowIncDec() || Func.getFunction()->optForMinSize();
|
||||
OptLEA = ST.LEAusesAG() || ST.slowLEA() || ST.slow3OpsLEA();
|
||||
OptLEA = ST.LEAusesAG() || ST.slowLEA();
|
||||
|
||||
if (!OptLEA && !OptIncDec)
|
||||
return false;
|
||||
@ -273,64 +242,9 @@ FixupLEAPass::searchBackwards(MachineOperand &p, MachineBasicBlock::iterator &I,
|
||||
return MachineBasicBlock::iterator();
|
||||
}
|
||||
|
||||
static inline bool isLEA(const int Opcode) {
|
||||
return Opcode == X86::LEA16r || Opcode == X86::LEA32r ||
|
||||
Opcode == X86::LEA64r || Opcode == X86::LEA64_32r;
|
||||
}
|
||||
|
||||
static inline bool isInefficientLEAReg(unsigned int Reg) {
|
||||
return Reg == X86::EBP || Reg == X86::RBP || Reg == X86::R13;
|
||||
}
|
||||
|
||||
static inline bool isRegOperand(const MachineOperand &Op) {
|
||||
return Op.isReg() && Op.getReg() != X86::NoRegister;
|
||||
}
|
||||
/// hasIneffecientLEARegs - LEA that uses base and index registers
|
||||
/// where the base is EBP, RBP, or R13
|
||||
static inline bool hasInefficientLEABaseReg(const MachineOperand &Base,
|
||||
const MachineOperand &Index) {
|
||||
return Base.isReg() && isInefficientLEAReg(Base.getReg()) &&
|
||||
isRegOperand(Index);
|
||||
}
|
||||
|
||||
static inline bool hasLEAOffset(const MachineOperand &Offset) {
|
||||
return (Offset.isImm() && Offset.getImm() != 0) || Offset.isGlobal();
|
||||
}
|
||||
|
||||
// LEA instruction that has all three operands: offset, base and index
|
||||
static inline bool isThreeOperandsLEA(const MachineOperand &Base,
|
||||
const MachineOperand &Index,
|
||||
const MachineOperand &Offset) {
|
||||
return isRegOperand(Base) && isRegOperand(Index) && hasLEAOffset(Offset);
|
||||
}
|
||||
|
||||
static inline int getADDrrFromLEA(int LEAOpcode) {
|
||||
switch (LEAOpcode) {
|
||||
default:
|
||||
llvm_unreachable("Unexpected LEA instruction");
|
||||
case X86::LEA16r:
|
||||
return X86::ADD16rr;
|
||||
case X86::LEA32r:
|
||||
return X86::ADD32rr;
|
||||
case X86::LEA64_32r:
|
||||
case X86::LEA64r:
|
||||
return X86::ADD64rr;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int getADDriFromLEA(int LEAOpcode, const MachineOperand &Offset) {
|
||||
bool IsInt8 = Offset.isImm() && isInt<8>(Offset.getImm());
|
||||
switch (LEAOpcode) {
|
||||
default:
|
||||
llvm_unreachable("Unexpected LEA instruction");
|
||||
case X86::LEA16r:
|
||||
return IsInt8 ? X86::ADD16ri8 : X86::ADD16ri;
|
||||
case X86::LEA32r:
|
||||
case X86::LEA64_32r:
|
||||
return IsInt8 ? X86::ADD32ri8 : X86::ADD32ri;
|
||||
case X86::LEA64r:
|
||||
return IsInt8 ? X86::ADD64ri8 : X86::ADD64ri32;
|
||||
}
|
||||
static inline bool isLEA(const int opcode) {
|
||||
return opcode == X86::LEA16r || opcode == X86::LEA32r ||
|
||||
opcode == X86::LEA64r || opcode == X86::LEA64_32r;
|
||||
}
|
||||
|
||||
/// isLEASimpleIncOrDec - Does this LEA have one these forms:
|
||||
@ -423,8 +337,8 @@ void FixupLEAPass::seekLEAFixup(MachineOperand &p,
|
||||
void FixupLEAPass::processInstructionForSLM(MachineBasicBlock::iterator &I,
|
||||
MachineFunction::iterator MFI) {
|
||||
MachineInstr &MI = *I;
|
||||
const int Opcode = MI.getOpcode();
|
||||
if (!isLEA(Opcode))
|
||||
const int opcode = MI.getOpcode();
|
||||
if (!isLEA(opcode))
|
||||
return;
|
||||
if (MI.getOperand(5).getReg() != 0 || !MI.getOperand(4).isImm() ||
|
||||
!TII->isSafeToClobberEFLAGS(*MFI, I))
|
||||
@ -436,144 +350,55 @@ void FixupLEAPass::processInstructionForSLM(MachineBasicBlock::iterator &I,
|
||||
return;
|
||||
if (MI.getOperand(2).getImm() > 1)
|
||||
return;
|
||||
int addrr_opcode, addri_opcode;
|
||||
switch (opcode) {
|
||||
default:
|
||||
llvm_unreachable("Unexpected LEA instruction");
|
||||
case X86::LEA16r:
|
||||
addrr_opcode = X86::ADD16rr;
|
||||
addri_opcode = X86::ADD16ri;
|
||||
break;
|
||||
case X86::LEA32r:
|
||||
addrr_opcode = X86::ADD32rr;
|
||||
addri_opcode = X86::ADD32ri;
|
||||
break;
|
||||
case X86::LEA64_32r:
|
||||
case X86::LEA64r:
|
||||
addrr_opcode = X86::ADD64rr;
|
||||
addri_opcode = X86::ADD64ri32;
|
||||
break;
|
||||
}
|
||||
DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););
|
||||
DEBUG(dbgs() << "FixLEA: Replaced by: ";);
|
||||
MachineInstr *NewMI = nullptr;
|
||||
const MachineOperand &Dst = MI.getOperand(0);
|
||||
// Make ADD instruction for two registers writing to LEA's destination
|
||||
if (SrcR1 != 0 && SrcR2 != 0) {
|
||||
const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(Opcode));
|
||||
const MachineOperand &Src = MI.getOperand(SrcR1 == DstR ? 3 : 1);
|
||||
NewMI =
|
||||
BuildMI(*MFI, I, MI.getDebugLoc(), ADDrr, DstR).addReg(DstR).add(Src);
|
||||
const MachineOperand &Src1 = MI.getOperand(SrcR1 == DstR ? 1 : 3);
|
||||
const MachineOperand &Src2 = MI.getOperand(SrcR1 == DstR ? 3 : 1);
|
||||
NewMI = BuildMI(*MF, MI.getDebugLoc(), TII->get(addrr_opcode))
|
||||
.add(Dst)
|
||||
.add(Src1)
|
||||
.add(Src2);
|
||||
MFI->insert(I, NewMI);
|
||||
DEBUG(NewMI->dump(););
|
||||
}
|
||||
// Make ADD instruction for immediate
|
||||
if (MI.getOperand(4).getImm() != 0) {
|
||||
const MCInstrDesc &ADDri =
|
||||
TII->get(getADDriFromLEA(Opcode, MI.getOperand(4)));
|
||||
const MachineOperand &SrcR = MI.getOperand(SrcR1 == DstR ? 1 : 3);
|
||||
NewMI = BuildMI(*MFI, I, MI.getDebugLoc(), ADDri, DstR)
|
||||
NewMI = BuildMI(*MF, MI.getDebugLoc(), TII->get(addri_opcode))
|
||||
.add(Dst)
|
||||
.add(SrcR)
|
||||
.addImm(MI.getOperand(4).getImm());
|
||||
MFI->insert(I, NewMI);
|
||||
DEBUG(NewMI->dump(););
|
||||
}
|
||||
if (NewMI) {
|
||||
MFI->erase(I);
|
||||
I = NewMI;
|
||||
I = static_cast<MachineBasicBlock::iterator>(NewMI);
|
||||
}
|
||||
}
|
||||
|
||||
MachineInstr *
|
||||
FixupLEAPass::processInstrForSlow3OpLEA(MachineInstr &MI,
|
||||
MachineFunction::iterator MFI) {
|
||||
|
||||
const int LEAOpcode = MI.getOpcode();
|
||||
if (!isLEA(LEAOpcode))
|
||||
return nullptr;
|
||||
|
||||
const MachineOperand &Dst = MI.getOperand(0);
|
||||
const MachineOperand &Base = MI.getOperand(1);
|
||||
const MachineOperand &Scale = MI.getOperand(2);
|
||||
const MachineOperand &Index = MI.getOperand(3);
|
||||
const MachineOperand &Offset = MI.getOperand(4);
|
||||
const MachineOperand &Segment = MI.getOperand(5);
|
||||
|
||||
if (!(isThreeOperandsLEA(Base, Index, Offset) ||
|
||||
hasInefficientLEABaseReg(Base, Index)) ||
|
||||
!TII->isSafeToClobberEFLAGS(*MFI, MI) ||
|
||||
Segment.getReg() != X86::NoRegister)
|
||||
return nullptr;
|
||||
|
||||
unsigned int DstR = Dst.getReg();
|
||||
unsigned int BaseR = Base.getReg();
|
||||
unsigned int IndexR = Index.getReg();
|
||||
unsigned SSDstR =
|
||||
(LEAOpcode == X86::LEA64_32r) ? getX86SubSuperRegister(DstR, 64) : DstR;
|
||||
bool IsScale1 = Scale.getImm() == 1;
|
||||
bool IsInefficientBase = isInefficientLEAReg(BaseR);
|
||||
bool IsInefficientIndex = isInefficientLEAReg(IndexR);
|
||||
|
||||
// Skip these cases since it takes more than 2 instructions
|
||||
// to replace the LEA instruction.
|
||||
if (IsInefficientBase && SSDstR == BaseR && !IsScale1)
|
||||
return nullptr;
|
||||
if (LEAOpcode == X86::LEA64_32r && IsInefficientBase &&
|
||||
(IsInefficientIndex || !IsScale1))
|
||||
return nullptr;
|
||||
|
||||
const DebugLoc DL = MI.getDebugLoc();
|
||||
const MCInstrDesc &ADDrr = TII->get(getADDrrFromLEA(LEAOpcode));
|
||||
const MCInstrDesc &ADDri = TII->get(getADDriFromLEA(LEAOpcode, Offset));
|
||||
|
||||
DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MI.dump(););
|
||||
DEBUG(dbgs() << "FixLEA: Replaced by: ";);
|
||||
|
||||
// First try to replace LEA with one or two (for the 3-op LEA case)
|
||||
// add instructions:
|
||||
// 1.lea (%base,%index,1), %base => add %index,%base
|
||||
// 2.lea (%base,%index,1), %index => add %base,%index
|
||||
if (IsScale1 && (DstR == BaseR || DstR == IndexR)) {
|
||||
const MachineOperand &Src = DstR == BaseR ? Index : Base;
|
||||
MachineInstr *NewMI =
|
||||
BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Src);
|
||||
DEBUG(NewMI->dump(););
|
||||
// Create ADD instruction for the Offset in case of 3-Ops LEA.
|
||||
if (hasLEAOffset(Offset)) {
|
||||
NewMI = BuildMI(*MFI, MI, DL, ADDri, DstR).addReg(DstR).add(Offset);
|
||||
DEBUG(NewMI->dump(););
|
||||
}
|
||||
return NewMI;
|
||||
}
|
||||
// If the base is inefficient try switching the index and base operands,
|
||||
// otherwise just break the 3-Ops LEA inst into 2-Ops LEA + ADD instruction:
|
||||
// lea offset(%base,%index,scale),%dst =>
|
||||
// lea (%base,%index,scale); add offset,%dst
|
||||
if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {
|
||||
MachineInstr *NewMI = BuildMI(*MFI, MI, DL, TII->get(LEAOpcode))
|
||||
.add(Dst)
|
||||
.add(IsInefficientBase ? Index : Base)
|
||||
.add(Scale)
|
||||
.add(IsInefficientBase ? Base : Index)
|
||||
.addImm(0)
|
||||
.add(Segment);
|
||||
DEBUG(NewMI->dump(););
|
||||
// Create ADD instruction for the Offset in case of 3-Ops LEA.
|
||||
if (hasLEAOffset(Offset)) {
|
||||
NewMI = BuildMI(*MFI, MI, DL, ADDri, DstR).addReg(DstR).add(Offset);
|
||||
DEBUG(NewMI->dump(););
|
||||
}
|
||||
return NewMI;
|
||||
}
|
||||
// Handle the rest of the cases with inefficient base register:
|
||||
assert(SSDstR != BaseR && "SSDstR == BaseR should be handled already!");
|
||||
assert(IsInefficientBase && "efficient base should be handled already!");
|
||||
|
||||
// lea (%base,%index,1), %dst => mov %base,%dst; add %index,%dst
|
||||
if (IsScale1 && !hasLEAOffset(Offset)) {
|
||||
TII->copyPhysReg(*MFI, MI, DL, DstR, BaseR, Base.isKill());
|
||||
DEBUG(MI.getPrevNode()->dump(););
|
||||
|
||||
MachineInstr *NewMI =
|
||||
BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Index);
|
||||
DEBUG(NewMI->dump(););
|
||||
return NewMI;
|
||||
}
|
||||
// lea offset(%base,%index,scale), %dst =>
|
||||
// lea offset( ,%index,scale), %dst; add %base,%dst
|
||||
MachineInstr *NewMI = BuildMI(*MFI, MI, DL, TII->get(LEAOpcode))
|
||||
.add(Dst)
|
||||
.addReg(0)
|
||||
.add(Scale)
|
||||
.add(Index)
|
||||
.add(Offset)
|
||||
.add(Segment);
|
||||
DEBUG(NewMI->dump(););
|
||||
|
||||
NewMI = BuildMI(*MFI, MI, DL, ADDrr, DstR).addReg(DstR).add(Base);
|
||||
DEBUG(NewMI->dump(););
|
||||
return NewMI;
|
||||
}
|
||||
|
||||
bool FixupLEAPass::processBasicBlock(MachineFunction &MF,
|
||||
MachineFunction::iterator MFI) {
|
||||
|
||||
@ -585,16 +410,8 @@ bool FixupLEAPass::processBasicBlock(MachineFunction &MF,
|
||||
if (OptLEA) {
|
||||
if (MF.getSubtarget<X86Subtarget>().isSLM())
|
||||
processInstructionForSLM(I, MFI);
|
||||
|
||||
else {
|
||||
if (MF.getSubtarget<X86Subtarget>().slow3OpsLEA()) {
|
||||
if (auto *NewMI = processInstrForSlow3OpLEA(*I, MFI)) {
|
||||
MFI->erase(I);
|
||||
I = NewMI;
|
||||
}
|
||||
} else
|
||||
processInstruction(I, MFI);
|
||||
}
|
||||
else
|
||||
processInstruction(I, MFI);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -253,11 +253,6 @@ protected:
|
||||
/// True if the LEA instruction with certain arguments is slow
|
||||
bool SlowLEA;
|
||||
|
||||
/// True if the LEA instruction has all three source operands: base, index,
|
||||
/// and offset or if the LEA instruction uses base and index registers where
|
||||
/// the base is EBP, RBP,or R13
|
||||
bool Slow3OpsLEA;
|
||||
|
||||
/// True if INC and DEC instructions are slow when writing to flags
|
||||
bool SlowIncDec;
|
||||
|
||||
@ -495,7 +490,6 @@ public:
|
||||
bool callRegIndirect() const { return CallRegIndirect; }
|
||||
bool LEAusesAG() const { return LEAUsesAG; }
|
||||
bool slowLEA() const { return SlowLEA; }
|
||||
bool slow3OpsLEA() const { return Slow3OpsLEA; }
|
||||
bool slowIncDec() const { return SlowIncDec; }
|
||||
bool hasCDI() const { return HasCDI; }
|
||||
bool hasPFI() const { return HasPFI; }
|
||||
|
@ -61,7 +61,6 @@ static cl::opt<bool> EnableMachineCombinerPass("x86-machine-combiner",
|
||||
namespace llvm {
|
||||
|
||||
void initializeWinEHStatePassPass(PassRegistry &);
|
||||
void initializeFixupLEAPassPass(PassRegistry &);
|
||||
void initializeX86ExecutionDepsFixPass(PassRegistry &);
|
||||
|
||||
} // end namespace llvm
|
||||
@ -76,7 +75,6 @@ extern "C" void LLVMInitializeX86Target() {
|
||||
initializeWinEHStatePassPass(PR);
|
||||
initializeFixupBWInstPassPass(PR);
|
||||
initializeEvexToVexInstPassPass(PR);
|
||||
initializeFixupLEAPassPass(PR);
|
||||
initializeX86ExecutionDepsFixPass(PR);
|
||||
}
|
||||
|
||||
|
@ -1,508 +0,0 @@
|
||||
# RUN: llc -run-pass x86-fixup-LEAs -mcpu=corei7-avx -o - %s | FileCheck %s
|
||||
--- |
|
||||
; ModuleID = 'test/CodeGen/X86/fixup-lea.ll'
|
||||
source_filename = "test/CodeGen/X86/fixup-lea.ll"
|
||||
target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
|
||||
target triple = "i386"
|
||||
;generated using: llc -stop-after x86-pad-short-functions fixup-lea.ll > leaFinxup32.mir
|
||||
|
||||
;test2add_32: 3 operands LEA32r that can be replaced with 2 add instructions
|
||||
; where ADD32ri8 is chosen
|
||||
define i32 @test2add_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;test2add_ebp_32: 3 operands LEA32r that can be replaced with 2 add instructions
|
||||
; where the base is rbp/r13/ebp register
|
||||
define i32 @test2add_ebp_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;test1add_ebp_32: 2 operands LEA32r where base register is ebp and can be replaced
|
||||
; with an add instruction
|
||||
define i32 @test1add_ebp_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;testleaadd_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions
|
||||
define i32 @testleaadd_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;testleaadd_ebp_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions
|
||||
; where the base is ebp register
|
||||
define i32 @testleaadd_ebp_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;test1lea_ebp_32: 2 operands LEA32r wher base register is rbp/r13/ebp and can be replaced
|
||||
; with a lea instruction
|
||||
define i32 @test1lea_ebp_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;test2addi32_32: 3 operands LEA32r that can be replaced with 2 add instructions where ADD32ri32
|
||||
; is chosen
|
||||
define i32 @test2addi32_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;test1mov1add_ebp_32: 2 operands LEA32r that can be replaced with 1 add 1 mov instructions
|
||||
; where the base is rbp/r13/ebp register
|
||||
define i32 @test1mov1add_ebp_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;testleaadd_ebp_index_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions
|
||||
; where the base and the index are ebp register and there is offset
|
||||
define i32 @testleaadd_ebp_index_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;testleaadd_ebp_index2_32: 3 operands LEA32r that can be replaced with 1 lea 1 add instructions
|
||||
; where the base and the index are ebp register and there is scale
|
||||
define i32 @testleaadd_ebp_index2_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;test_skip_opt_32: 3 operands LEA32r that can not be replaced with 2 instructions
|
||||
define i32 @test_skip_opt_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
;test_skip_eflags_32: LEA32r that cannot be replaced since its not safe to clobber eflags
|
||||
define i32 @test_skip_eflags_32() {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test2add_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%eax' }
|
||||
- { reg: '%ebp' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp
|
||||
; CHECK: %eax = ADD32rr %eax, killed %ebp
|
||||
; CHECK: %eax = ADD32ri8 %eax, -5
|
||||
|
||||
%eax = LEA32r killed %eax, 1, killed %ebp, -5, _
|
||||
RETQ %eax
|
||||
|
||||
...
|
||||
---
|
||||
name: test2add_ebp_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%eax' }
|
||||
- { reg: '%ebp' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp
|
||||
; CHECK: %ebp = ADD32rr %ebp, killed %eax
|
||||
; CHECK: %ebp = ADD32ri8 %ebp, -5
|
||||
|
||||
%ebp = LEA32r killed %ebp, 1, killed %eax, -5, _
|
||||
RETQ %ebp
|
||||
|
||||
...
|
||||
---
|
||||
name: test1add_ebp_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%eax' }
|
||||
- { reg: '%ebp' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp
|
||||
; CHECK: %ebp = ADD32rr %ebp, killed %eax
|
||||
|
||||
%ebp = LEA32r killed %ebp, 1, killed %eax, 0, _
|
||||
RETQ %ebp
|
||||
|
||||
...
|
||||
---
|
||||
name: testleaadd_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%eax' }
|
||||
- { reg: '%ebp' }
|
||||
- { reg: '%ebx' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp, %esi
|
||||
; CHECK: %ebx = LEA32r killed %eax, 1, killed %ebp, 0
|
||||
; CHECK: %ebx = ADD32ri8 %ebx, -5
|
||||
|
||||
%ebx = LEA32r killed %eax, 1, killed %ebp, -5, _
|
||||
RETQ %ebx
|
||||
|
||||
...
|
||||
---
|
||||
name: testleaadd_ebp_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%eax' }
|
||||
- { reg: '%ebp' }
|
||||
- { reg: '%ebx' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp
|
||||
; CHECK: %ebx = LEA32r killed %eax, 1, killed %ebp, 0, _
|
||||
; CHECK: %ebx = ADD32ri8 %ebx, -5
|
||||
|
||||
%ebx = LEA32r killed %ebp, 1, killed %eax, -5, _
|
||||
RETQ %ebx
|
||||
|
||||
...
|
||||
---
|
||||
name: test1lea_ebp_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%eax' }
|
||||
- { reg: '%ebp' }
|
||||
- { reg: '%ebx' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp
|
||||
; CHECK: %ebx = LEA32r killed %eax, 1, killed %ebp, 0, _
|
||||
|
||||
%ebx = LEA32r killed %ebp, 1, killed %eax, 0, _
|
||||
RETQ %ebx
|
||||
|
||||
...
|
||||
---
|
||||
name: test2addi32_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%eax' }
|
||||
- { reg: '%ebp' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp
|
||||
; CHECK: %eax = ADD32rr %eax, killed %ebp
|
||||
; CHECK: %eax = ADD32ri %eax, 129
|
||||
|
||||
%eax = LEA32r killed %eax, 1, killed %ebp, 129, _
|
||||
RETQ %eax
|
||||
|
||||
...
|
||||
---
|
||||
name: test1mov1add_ebp_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%eax' }
|
||||
- { reg: '%ebp' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp, %ebx
|
||||
; CHECK: %ebx = MOV32rr killed %ebp
|
||||
; CHECK: %ebx = ADD32rr %ebx, killed %ebp
|
||||
|
||||
%ebx = LEA32r killed %ebp, 1, killed %ebp, 0, _
|
||||
RETQ %ebx
|
||||
|
||||
...
|
||||
---
|
||||
name: testleaadd_ebp_index_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%ebx' }
|
||||
- { reg: '%ebp' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp, %ebx
|
||||
; CHECK: %ebx = LEA32r _, 1, killed %ebp, 5, _
|
||||
; CHECK: %ebx = ADD32rr %ebx, killed %ebp
|
||||
|
||||
%ebx = LEA32r killed %ebp, 1, killed %ebp, 5, _
|
||||
RETQ %ebx
|
||||
|
||||
...
|
||||
---
|
||||
name: testleaadd_ebp_index2_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%ebx' }
|
||||
- { reg: '%ebp' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp, %ebx
|
||||
; CHECK: %ebx = LEA32r _, 4, killed %ebp, 5, _
|
||||
; CHECK: %ebx = ADD32rr %ebx, killed %ebp
|
||||
|
||||
%ebx = LEA32r killed %ebp, 4, killed %ebp, 5, _
|
||||
RETQ %ebx
|
||||
|
||||
...
|
||||
---
|
||||
name: test_skip_opt_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%ebx' }
|
||||
- { reg: '%ebp' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp, %ebx
|
||||
; CHECK: %ebp = LEA32r killed %ebp, 4, killed %ebp, 0, _
|
||||
|
||||
%ebp = LEA32r killed %ebp, 4, killed %ebp, 0, _
|
||||
RETQ %ebp
|
||||
|
||||
...
|
||||
---
|
||||
name: test_skip_eflags_32
|
||||
alignment: 4
|
||||
exposesReturnsTwice: false
|
||||
legalized: false
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '%ebp' }
|
||||
- { reg: '%eax' }
|
||||
frameInfo:
|
||||
isFrameAddressTaken: false
|
||||
isReturnAddressTaken: false
|
||||
hasStackMap: false
|
||||
hasPatchPoint: false
|
||||
stackSize: 0
|
||||
offsetAdjustment: 0
|
||||
maxAlignment: 0
|
||||
adjustsStack: false
|
||||
hasCalls: false
|
||||
maxCallFrameSize: 0
|
||||
hasOpaqueSPAdjustment: false
|
||||
hasVAStart: false
|
||||
hasMustTailInVarArgFunc: false
|
||||
body: |
|
||||
bb.0 (%ir-block.0):
|
||||
liveins: %eax, %ebp, %ebx
|
||||
; CHECK: %ebx = LEA32r killed %eax, 4, killed %eax, 5, _
|
||||
; CHECK: %ebp = LEA32r killed %ebx, 4, killed %ebx, 0, _
|
||||
; CHECK: %ebp = ADD32ri8 %ebp, 5
|
||||
|
||||
CMP32rr %eax, killed %ebx, implicit-def %eflags
|
||||
%ebx = LEA32r killed %eax, 4, killed %eax, 5, _
|
||||
JE_1 %bb.1, implicit %eflags
|
||||
RETQ %ebx
|
||||
bb.1:
|
||||
liveins: %eax, %ebp, %ebx
|
||||
%ebp = LEA32r killed %ebx, 4, killed %ebx, 5, _
|
||||
RETQ %ebp
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user