//
// This file defines the pass that finds instructions that can be
// re-written as LEA instructions in order to reduce pipeline delays.
-// When optimizing for size it replaces suitable LEAs with INC or DEC.
+// It replaces LEAs with ADD/INC/DEC when that is better for size/speed.
//
//===----------------------------------------------------------------------===//
MachineInstr *processInstrForSlow3OpLEA(MachineInstr &MI,
MachineBasicBlock &MBB);
- /// 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,
- MachineBasicBlock &MBB) const;
+ /// Look for LEAs that are really two address LEAs that we might be able to
+ /// turn into regular ADD instructions.
+ bool optTwoAddrLEA(MachineBasicBlock::iterator &I,
+ MachineBasicBlock &MBB, bool OptIncDec,
+ bool UseLEAForSP) const;
/// Determine if an instruction references a machine register
/// and, if so, whether it reads or writes the register.
private:
TargetSchedModel TSM;
- const X86InstrInfo *TII; // Machine instruction info.
+ const X86InstrInfo *TII;
+ const X86RegisterInfo *TRI;
};
}
bool LEAUsesAG = ST.LEAusesAG();
bool OptIncDec = !ST.slowIncDec() || MF.getFunction().hasOptSize();
- bool OptLEA = LEAUsesAG || IsSlowLEA || IsSlow3OpsLEA;
-
- if (!OptLEA && !OptIncDec)
- return false;
+ bool UseLEAForSP = ST.useLeaForSP();
TSM.init(&ST);
TII = ST.getInstrInfo();
+ TRI = ST.getRegisterInfo();
LLVM_DEBUG(dbgs() << "Start X86FixupLEAs\n";);
for (MachineBasicBlock &MBB : MF) {
if (!isLEA(I->getOpcode()))
continue;
- if (OptIncDec && fixupIncDec(I, MBB))
+ if (optTwoAddrLEA(I, MBB, OptIncDec, UseLEAForSP))
continue;
if (IsSlowLEA) {
default:
llvm_unreachable("Unexpected LEA instruction");
case X86::LEA32r:
- return X86::ADD32rr;
case X86::LEA64_32r:
+ return X86::ADD32rr;
case X86::LEA64r:
return X86::ADD64rr;
}
}
}
-/// isLEASimpleIncOrDec - Does this LEA have one these forms:
-/// lea %reg, 1(%reg)
-/// lea %reg, -1(%reg)
-static inline bool isLEASimpleIncOrDec(MachineInstr &LEA) {
- unsigned SrcReg = LEA.getOperand(1 + X86::AddrBaseReg).getReg();
- unsigned DstReg = LEA.getOperand(0).getReg();
- const MachineOperand &AddrDisp = LEA.getOperand(1 + X86::AddrDisp);
- return SrcReg == DstReg &&
- LEA.getOperand(1 + X86::AddrIndexReg).getReg() == 0 &&
- LEA.getOperand(1 + X86::AddrSegmentReg).getReg() == 0 &&
- AddrDisp.isImm() &&
- (AddrDisp.getImm() == 1 || AddrDisp.getImm() == -1);
+static inline unsigned getINCDECFromLEA(unsigned LEAOpcode, bool IsINC) {
+ switch (LEAOpcode) {
+ default:
+ llvm_unreachable("Unexpected LEA instruction");
+ case X86::LEA32r:
+ case X86::LEA64_32r:
+ return IsINC ? X86::INC32r : X86::DEC32r;
+ case X86::LEA64r:
+ return IsINC ? X86::INC64r : X86::DEC64r;
+ }
}
-bool FixupLEAPass::fixupIncDec(MachineBasicBlock::iterator &I,
- MachineBasicBlock &MBB) const {
+bool FixupLEAPass::optTwoAddrLEA(MachineBasicBlock::iterator &I,
+ MachineBasicBlock &MBB, bool OptIncDec,
+ bool UseLEAForSP) const {
MachineInstr &MI = *I;
- if (isLEASimpleIncOrDec(MI) && TII->isSafeToClobberEFLAGS(MBB, I)) {
- unsigned NewOpcode;
- bool isINC = MI.getOperand(1 + X86::AddrDisp).getImm() == 1;
- switch (MI.getOpcode()) {
- default:
- llvm_unreachable("Unexpected LEA instruction");
- case X86::LEA32r:
- case X86::LEA64_32r:
- NewOpcode = isINC ? X86::INC32r : X86::DEC32r;
- break;
- case X86::LEA64r:
- NewOpcode = isINC ? X86::INC64r : X86::DEC64r;
- break;
- }
+ const MachineOperand &Base = MI.getOperand(1 + X86::AddrBaseReg);
+ const MachineOperand &Scale = MI.getOperand(1 + X86::AddrScaleAmt);
+ const MachineOperand &Index = MI.getOperand(1 + X86::AddrIndexReg);
+ const MachineOperand &Disp = MI.getOperand(1 + X86::AddrDisp);
+ const MachineOperand &Segment = MI.getOperand(1 + X86::AddrSegmentReg);
- MachineInstr *NewMI =
- BuildMI(MBB, I, MI.getDebugLoc(), TII->get(NewOpcode))
- .add(MI.getOperand(0))
- .add(MI.getOperand(1 + X86::AddrBaseReg));
- MBB.erase(I);
- I = static_cast<MachineBasicBlock::iterator>(NewMI);
- return true;
+ if (Segment.getReg() != 0 || !Disp.isImm() || Scale.getImm() > 1 ||
+ !TII->isSafeToClobberEFLAGS(MBB, I))
+ return false;
+
+ unsigned DestReg = MI.getOperand(0).getReg();
+ unsigned BaseReg = Base.getReg();
+ unsigned IndexReg = Index.getReg();
+
+ // Don't change stack adjustment LEAs.
+ if (UseLEAForSP && (DestReg == X86::ESP || DestReg == X86::RSP))
+ return false;
+
+ // LEA64_32 has 64-bit operands but 32-bit result.
+ if (MI.getOpcode() == X86::LEA64_32r) {
+ if (BaseReg != 0)
+ BaseReg = TRI->getSubReg(BaseReg, X86::sub_32bit);
+ if (IndexReg != 0)
+ IndexReg = TRI->getSubReg(IndexReg, X86::sub_32bit);
}
- return false;
+
+ MachineInstr *NewMI = nullptr;
+
+ // Look for lea(%reg1, %reg2), %reg1 or lea(%reg2, %reg1), %reg1
+ // which can be turned into add %reg2, %reg1
+ if (BaseReg != 0 && IndexReg != 0 && Disp.getImm() == 0 &&
+ (DestReg == BaseReg || DestReg == IndexReg)) {
+ unsigned NewOpcode = getADDrrFromLEA(MI.getOpcode());
+ if (DestReg != BaseReg)
+ std::swap(BaseReg, IndexReg);
+
+ if (MI.getOpcode() == X86::LEA64_32r) {
+ // TODO: Do we need the super register implicit use?
+ NewMI = BuildMI(MBB, I, MI.getDebugLoc(), TII->get(NewOpcode), DestReg)
+ .addReg(BaseReg).addReg(IndexReg)
+ .addReg(Base.getReg(), RegState::Implicit)
+ .addReg(Index.getReg(), RegState::Implicit);
+ } else {
+ NewMI = BuildMI(MBB, I, MI.getDebugLoc(), TII->get(NewOpcode), DestReg)
+ .addReg(BaseReg).addReg(IndexReg);
+ }
+ } else if (DestReg == BaseReg && IndexReg == 0) {
+ // This is an LEA with only a base register and a displacement,
+ // We can use ADDri or INC/DEC.
+
+ // Does this LEA have one these forms:
+ // lea %reg, 1(%reg)
+ // lea %reg, -1(%reg)
+ if (OptIncDec && (Disp.getImm() == 1 || Disp.getImm() == -1)) {
+ bool IsINC = Disp.getImm() == 1;
+ unsigned NewOpcode = getINCDECFromLEA(MI.getOpcode(), IsINC);
+
+ if (MI.getOpcode() == X86::LEA64_32r) {
+ // TODO: Do we need the super register implicit use?
+ NewMI = BuildMI(MBB, I, MI.getDebugLoc(), TII->get(NewOpcode), DestReg)
+ .addReg(BaseReg).addReg(Base.getReg(), RegState::Implicit);
+ } else {
+ NewMI = BuildMI(MBB, I, MI.getDebugLoc(), TII->get(NewOpcode), DestReg)
+ .addReg(BaseReg);
+ }
+ } else {
+ unsigned NewOpcode = getADDriFromLEA(MI.getOpcode(), Disp);
+ if (MI.getOpcode() == X86::LEA64_32r) {
+ // TODO: Do we need the super register implicit use?
+ NewMI = BuildMI(MBB, I, MI.getDebugLoc(), TII->get(NewOpcode), DestReg)
+ .addReg(BaseReg).addImm(Disp.getImm())
+ .addReg(Base.getReg(), RegState::Implicit);
+ } else {
+ NewMI = BuildMI(MBB, I, MI.getDebugLoc(), TII->get(NewOpcode), DestReg)
+ .addReg(BaseReg).addImm(Disp.getImm());
+ }
+ }
+ } else
+ return false;
+
+ MBB.erase(I);
+ I = NewMI;
+ return true;
}
void FixupLEAPass::processInstruction(MachineBasicBlock::iterator &I,
; CHECK: # %bb.0:
; CHECK-NEXT: addl $5, %edi
; CHECK-NEXT: movslq %edi, %rax
-; CHECK-NEXT: leaq (%rsi,%rax), %rax
+; CHECK-NEXT: addq %rsi, %rax
; CHECK-NEXT: retq
%add = add nsw i32 %i, 5
; CHECK-NEXT: cltq
; CHECK-NEXT: movq $4, %rcx
; CHECK-NEXT: imulq %rcx, %rax
-; CHECK-NEXT: leaq (%rdi,%rax), %rax
+; CHECK-NEXT: addq %rdi, %rax
; CHECK-NEXT: leal 2(%rsi), %edx
; CHECK-NEXT: movslq %edx, %rdx
; CHECK-NEXT: imulq %rcx, %rdx
-; CHECK-NEXT: leaq (%rdi,%rdx), %rdx
+; CHECK-NEXT: addq %rdi, %rdx
; CHECK-NEXT: movl (%rdx), %edx
; CHECK-NEXT: addl (%rax), %edx
; CHECK-NEXT: movslq %esi, %rax
; CHECK-NEXT: imulq %rcx, %rax
-; CHECK-NEXT: leaq (%rdi,%rax), %rax
+; CHECK-NEXT: addq %rdi, %rax
; CHECK-NEXT: movl %edx, (%rax)
; CHECK-NEXT: retq
; CHECK-NEXT: leal 1(%rsi), %eax
; CHECK-NEXT: movq $4, %rcx
; CHECK-NEXT: imulq %rcx, %rax
-; CHECK-NEXT: leaq (%rdi,%rax), %rax
+; CHECK-NEXT: addq %rdi, %rax
; CHECK-NEXT: leal 2(%rsi), %edx
; CHECK-NEXT: imulq %rcx, %rdx
-; CHECK-NEXT: leaq (%rdi,%rdx), %rdx
+; CHECK-NEXT: addq %rdi, %rdx
; CHECK-NEXT: movl (%rdx), %edx
; CHECK-NEXT: addl (%rax), %edx
; CHECK-NEXT: imulq %rcx, %rsi
; X32-NEXT: movl 4(%ecx), %ecx
; X32-NEXT: movl %eax, (%esp)
; X32-NEXT: movl $4, %eax
-; X32-NEXT: leal (%esp,%eax), %eax
+; X32-NEXT: addl %esp, %eax
; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)
; X32-NEXT: movl %ecx, 4(%eax)
; X32-NEXT: calll variadic_callee
; X64_GISEL-NEXT: sarq %cl, %rsi
; X64_GISEL-NEXT: movq $4, %rax
; X64_GISEL-NEXT: imulq %rsi, %rax
-; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
+; X64_GISEL-NEXT: addq %rdi, %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i8:
; X64_GISEL-LABEL: test_gep_i8_const:
; X64_GISEL: # %bb.0:
; X64_GISEL-NEXT: movq $80, %rax
-; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
+; X64_GISEL-NEXT: addq %rdi, %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i8_const:
; X64_GISEL-NEXT: sarq %cl, %rsi
; X64_GISEL-NEXT: movq $4, %rax
; X64_GISEL-NEXT: imulq %rsi, %rax
-; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
+; X64_GISEL-NEXT: addq %rdi, %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i16:
; X64_GISEL-LABEL: test_gep_i16_const:
; X64_GISEL: # %bb.0:
; X64_GISEL-NEXT: movq $80, %rax
-; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
+; X64_GISEL-NEXT: addq %rdi, %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i16_const:
; X64_GISEL-LABEL: test_gep_i32_const:
; X64_GISEL: # %bb.0:
; X64_GISEL-NEXT: movq $20, %rax
-; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
+; X64_GISEL-NEXT: addq %rdi, %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i32_const:
; X64_GISEL: # %bb.0:
; X64_GISEL-NEXT: movq $4, %rax
; X64_GISEL-NEXT: imulq %rsi, %rax
-; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
+; X64_GISEL-NEXT: addq %rdi, %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i64:
; X64_GISEL-LABEL: test_gep_i64_const:
; X64_GISEL: # %bb.0:
; X64_GISEL-NEXT: movq $20, %rax
-; X64_GISEL-NEXT: leaq (%rdi,%rax), %rax
+; X64_GISEL-NEXT: addq %rdi, %rax
; X64_GISEL-NEXT: retq
;
; X64-LABEL: test_gep_i64_const:
; ALL-LABEL: test_gep_folding_largeGepIndex:
; ALL: # %bb.0:
; ALL-NEXT: movabsq $228719476720, %rax # imm = 0x3540BE3FF0
-; ALL-NEXT: leaq (%rdi,%rax), %rax
+; ALL-NEXT: addq %rdi, %rax
; ALL-NEXT: movl %esi, (%rax)
; ALL-NEXT: movl (%rax), %eax
; ALL-NEXT: retq
; BWON-NEXT: .LBB12_1: # =>This Inner Loop Header: Depth=1
; BWON-NEXT: movsbq (%rdi,%rcx), %rax
; BWON-NEXT: movzbl (%rdx,%rax), %r9d
-; BWON-NEXT: leal 1(%rax), %eax
+; BWON-NEXT: incl %eax
; BWON-NEXT: movsbq %al, %rax
; BWON-NEXT: movzbl (%rdx,%rax), %eax
; BWON-NEXT: movb %r9b, (%rsi,%rcx,2)
; BWOFF-NEXT: .LBB12_1: # =>This Inner Loop Header: Depth=1
; BWOFF-NEXT: movsbq (%rdi,%rcx), %rax
; BWOFF-NEXT: movb (%rdx,%rax), %r9b
-; BWOFF-NEXT: leal 1(%rax), %eax
+; BWOFF-NEXT: incl %eax
; BWOFF-NEXT: movsbq %al, %rax
; BWOFF-NEXT: movb (%rdx,%rax), %al
; BWOFF-NEXT: movb %r9b, (%rsi,%rcx,2)
; CHECK-O3-NEXT: movq %rdx, %rax
; CHECK-O3-NEXT: shrq $63, %rax
; CHECK-O3-NEXT: sarq $3, %rdx
-; CHECK-O3-NEXT: leaq (%rdx,%rax), %rax
+; CHECK-O3-NEXT: addq %rdx, %rax
; CHECK-O3-NEXT: retq
%v = load atomic i64, i64* %p unordered, align 8
%ret = sdiv i64 %v, 15
; X64-NEXT: kandw %k1, %k0, %k1 # encoding: [0xc5,0xfc,0x41,0xc9]
; X64-NEXT: kmovw %k1, %eax # encoding: [0xc5,0xf8,0x93,0xc1]
; X64-NEXT: kmovw %k0, %ecx # encoding: [0xc5,0xf8,0x93,0xc8]
-; X64-NEXT: leal (%rcx,%rax), %eax # encoding: [0x8d,0x04,0x01]
+; X64-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8]
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq # encoding: [0xc3]
%res = call i8 @llvm.x86.avx512.ptestm.d.128(<4 x i32> %x0, <4 x i32> %x1, i8 %x2)
; X64-NEXT: kandw %k1, %k0, %k1 # encoding: [0xc5,0xfc,0x41,0xc9]
; X64-NEXT: kmovw %k1, %eax # encoding: [0xc5,0xf8,0x93,0xc1]
; X64-NEXT: kmovw %k0, %ecx # encoding: [0xc5,0xf8,0x93,0xc8]
-; X64-NEXT: leal (%rcx,%rax), %eax # encoding: [0x8d,0x04,0x01]
+; X64-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8]
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq # encoding: [0xc3]
%res = call i8 @llvm.x86.avx512.ptestm.q.128(<2 x i64> %x0, <2 x i64> %x1, i8 %x2)
; X64-NEXT: kandw %k1, %k0, %k1 # encoding: [0xc5,0xfc,0x41,0xc9]
; X64-NEXT: kmovw %k1, %eax # encoding: [0xc5,0xf8,0x93,0xc1]
; X64-NEXT: kmovw %k0, %ecx # encoding: [0xc5,0xf8,0x93,0xc8]
-; X64-NEXT: leal (%rcx,%rax), %eax # encoding: [0x8d,0x04,0x01]
+; X64-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8]
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: vzeroupper # encoding: [0xc5,0xf8,0x77]
; X64-NEXT: retq # encoding: [0xc3]
; X64-NEXT: kandw %k1, %k0, %k1 # encoding: [0xc5,0xfc,0x41,0xc9]
; X64-NEXT: kmovw %k1, %eax # encoding: [0xc5,0xf8,0x93,0xc1]
; X64-NEXT: kmovw %k0, %ecx # encoding: [0xc5,0xf8,0x93,0xc8]
-; X64-NEXT: leal (%rcx,%rax), %eax # encoding: [0x8d,0x04,0x01]
+; X64-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8]
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq # encoding: [0xc3]
%res = call i8 @llvm.x86.avx512.ptestnm.d.128(<4 x i32> %x0, <4 x i32> %x1, i8 %x2)
; X64-NEXT: kandw %k1, %k0, %k1 # encoding: [0xc5,0xfc,0x41,0xc9]
; X64-NEXT: kmovw %k1, %eax # encoding: [0xc5,0xf8,0x93,0xc1]
; X64-NEXT: kmovw %k0, %ecx # encoding: [0xc5,0xf8,0x93,0xc8]
-; X64-NEXT: leal (%rcx,%rax), %eax # encoding: [0x8d,0x04,0x01]
+; X64-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8]
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq # encoding: [0xc3]
%res = call i8 @llvm.x86.avx512.ptestnm.q.128(<2 x i64> %x0, <2 x i64> %x1, i8 %x2)
; X64-NEXT: kandw %k1, %k0, %k1 # encoding: [0xc5,0xfc,0x41,0xc9]
; X64-NEXT: kmovw %k1, %eax # encoding: [0xc5,0xf8,0x93,0xc1]
; X64-NEXT: kmovw %k0, %ecx # encoding: [0xc5,0xf8,0x93,0xc8]
-; X64-NEXT: leal (%rcx,%rax), %eax # encoding: [0x8d,0x04,0x01]
+; X64-NEXT: addl %ecx, %eax # encoding: [0x01,0xc8]
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: vzeroupper # encoding: [0xc5,0xf8,0x77]
; X64-NEXT: retq # encoding: [0xc3]
; X64-NEXT: addb %al, %al
; X64-NEXT: andb $-86, %dil
; X64-NEXT: shrb %dil
-; X64-NEXT: leal (%rdi,%rax), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq
%b = call i8 @llvm.bitreverse.i8(i8 %a)
; X64-NEXT: addb %al, %al
; X64-NEXT: andb $-96, %dil
; X64-NEXT: shrb %dil
-; X64-NEXT: leal (%rdi,%rax), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: shrb $4, %al
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq
; CHECK64-NEXT: andl $-16777216, %edi # imm = 0xFF000000
; CHECK64-NEXT: andl $16711680, %eax # imm = 0xFF0000
; CHECK64-NEXT: orl %edi, %eax
-; CHECK64-NEXT: leal (%rax,%rcx), %eax
+; CHECK64-NEXT: addl %ecx, %eax
; CHECK64-NEXT: retq
%byte1 = lshr i32 %x, 8
%byte0 = shl i32 %x, 8
; CHECK-NEXT: movl %edx, %eax
; CHECK-NEXT: shrl $31, %eax
; CHECK-NEXT: sarl $3, %edx
-; CHECK-NEXT: leal (%edx,%eax), %eax
+; CHECK-NEXT: addl %edx, %eax
; CHECK-NEXT: retl
%resultdiv = sdiv i32 %a, 33
ret i32 %resultdiv
; CHECK-NEXT: shrl %eax
; CHECK-NEXT: addl %edi, %eax
; CHECK-NEXT: andl $-2147483648, %eax # imm = 0x80000000
-; CHECK-NEXT: leal (%rax,%rdi), %eax
+; CHECK-NEXT: addl %edi, %eax
; CHECK-NEXT: retq
%1 = srem i32 %x, -2147483648
ret i32 %1
; CHECK-NEXT: shrl $4, %edi
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: shlq $4, %rax
-; CHECK-NEXT: leaq (%rax,%rdi), %rax
+; CHECK-NEXT: addq %rdi, %rax
; CHECK-NEXT: retq
entry:
%shr = lshr i16 %v, 4
; CHECK-NEXT: shrl $4, %edi
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: shlq $4, %rax
-; CHECK-NEXT: leaq (%rax,%rdi), %rax
+; CHECK-NEXT: addq %rdi, %rax
; CHECK-NEXT: retq
entry:
%shr = lshr i32 %v, 4
; X64-NEXT: # kill: def $edi killed $edi def $rdi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shrl $8, %eax
-; X64-NEXT: leal (%rax,%rdi), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq
;
; FAST-NEXT: .LBB4_1: # %for.body
; FAST-NEXT: # =>This Inner Loop Header: Depth=1
; FAST-NEXT: movzwl %cx, %edx
-; FAST-NEXT: leal -1(%ecx), %ecx
+; FAST-NEXT: addl $-1, %ecx
; FAST-NEXT: cmpl %eax, %edx
; FAST-NEXT: jl .LBB4_1
; FAST-NEXT: # %bb.2: # %for.end
; FAST-NEXT: .LBB5_1: # %for.body
; FAST-NEXT: # =>This Inner Loop Header: Depth=1
; FAST-NEXT: movzwl %cx, %edx
-; FAST-NEXT: leal 1(%ecx), %ecx
+; FAST-NEXT: addl $1, %ecx
; FAST-NEXT: cmpl %eax, %edx
; FAST-NEXT: jl .LBB5_1
; FAST-NEXT: # %bb.2: # %for.end
; X64-NEXT: # kill: def $edi killed $edi def $rdi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $5, %eax
-; X64-NEXT: leal (%rax,%rdi), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: retq
;
; X86-LABEL: mul33_32:
; X64-NEXT: # kill: def $edi killed $edi def $rdi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $5, %eax
-; X64-NEXT: leal (%rax,%rdi), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: retq
;
; X86-LABEL: test2:
; X64-NEXT: # kill: def $edi killed $edi def $rdi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $5, %eax
-; X64-NEXT: leal (%rax,%rdi), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: negl %eax
; X64-NEXT: retq
;
; X64: # %bb.0: # %entry
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: shlq $5, %rax
-; X64-NEXT: leaq (%rax,%rdi), %rax
+; X64-NEXT: addq %rdi, %rax
; X64-NEXT: retq
;
; X86-LABEL: test6:
; X64: # %bb.0: # %entry
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: shlq $5, %rax
-; X64-NEXT: leaq (%rax,%rdi), %rax
+; X64-NEXT: addq %rdi, %rax
; X64-NEXT: negq %rax
; X64-NEXT: retq
;
body: |
bb.0 (%ir-block.0):
liveins: $eax, $ebp
- ; CHECK: $ebp = ADD32rr $ebp, killed $eax
+ ; CHECK: $ebp = ADD32rr $ebp, $eax
$ebp = LEA32r killed $ebp, 1, killed $eax, 0, $noreg
RETQ $ebp
body: |
bb.0 (%ir-block.0):
liveins: $rax, $rbp
- ; CHECK: $ebp = LEA64_32r killed $rax, 1, killed $rbp, 0
+ ; CHECK: $ebp = ADD32rr $ebp, $eax, implicit-def $eflags, implicit $rbp, implicit $rax
$ebp = LEA64_32r killed $rbp, 1, killed $rax, 0, $noreg
RETQ $ebp
body: |
bb.0 (%ir-block.0):
liveins: $rax, $rbp
- ; CHECK: $rbp = ADD64rr $rbp, killed $rax
+ ; CHECK: $rbp = ADD64rr $rbp, $rax
$rbp = LEA64r killed $rbp, 1, killed $rax, 0, $noreg
RETQ $ebp
; X64-NEXT: # kill: def $edi killed $edi def $rdi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $4, %eax
-; X64-NEXT: leal (%rax,%rdi), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: # kill: def $ax killed $ax killed $eax
; X64-NEXT: retq
%mul = mul nsw i16 %x, 17
; X64-NEXT: # kill: def $edi killed $edi def $rdi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $4, %eax
-; X64-NEXT: leal (%rax,%rdi), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: retq
;
; X86-NOOPT-LABEL: test_mul_by_17:
; X64-SLM-NEXT: # kill: def $edi killed $edi def $rdi
; X64-SLM-NEXT: movl %edi, %eax
; X64-SLM-NEXT: shll $6, %eax
-; X64-SLM-NEXT: leal (%rax,%rdi), %eax
+; X64-SLM-NEXT: addl %edi, %eax
; X64-SLM-NEXT: addl %edi, %eax
; X64-SLM-NEXT: retq
%mul = mul nsw i32 %x, 66
; X86-NOOPT-NEXT: addl %ecx, %edx
; X86-NOOPT-NEXT: retl
;
-; X64-HSW-LABEL: test_mul_by_17:
-; X64-HSW: # %bb.0:
-; X64-HSW-NEXT: movq %rdi, %rax
-; X64-HSW-NEXT: shlq $4, %rax
-; X64-HSW-NEXT: leaq (%rax,%rdi), %rax
-; X64-HSW-NEXT: retq
-;
-; X64-JAG-LABEL: test_mul_by_17:
-; X64-JAG: # %bb.0:
-; X64-JAG-NEXT: movq %rdi, %rax
-; X64-JAG-NEXT: shlq $4, %rax
-; X64-JAG-NEXT: leaq (%rax,%rdi), %rax
-; X64-JAG-NEXT: retq
-;
-; X64-SLM-LABEL: test_mul_by_17:
-; X64-SLM: # %bb.0:
-; X64-SLM-NEXT: movq %rdi, %rax
-; X64-SLM-NEXT: shlq $4, %rax
-; X64-SLM-NEXT: addq %rdi, %rax
-; X64-SLM-NEXT: retq
+; X64-OPT-LABEL: test_mul_by_17:
+; X64-OPT: # %bb.0:
+; X64-OPT-NEXT: movq %rdi, %rax
+; X64-OPT-NEXT: shlq $4, %rax
+; X64-OPT-NEXT: addq %rdi, %rax
+; X64-OPT-NEXT: retq
;
; X64-NOOPT-LABEL: test_mul_by_17:
; X64-NOOPT: # %bb.0:
; X64-NEXT: # kill: def $edi killed $edi def $rdi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $4, %eax
-; X64-NEXT: leal (%rax,%rdi), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq
%m = mul i8 %x, 17
; X64-NEXT: addb %al, %dil
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shrb $4, %al
-; X64-NEXT: leal (%rax,%rdi), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: andb $15, %al
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq
; X64-NEXT: addq %rcx, %rdi
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: shrq $4, %rax
-; X64-NEXT: leaq (%rax,%rdi), %rax
+; X64-NEXT: addq %rdi, %rax
; X64-NEXT: movabsq $1085102592571150095, %rcx # imm = 0xF0F0F0F0F0F0F0F
; X64-NEXT: andq %rax, %rcx
; X64-NEXT: movabsq $72340172838076673, %rax # imm = 0x101010101010101
; X64-NEXT: addq %rcx, %rdi
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: shrq $4, %rax
-; X64-NEXT: leaq (%rax,%rdi), %rax
+; X64-NEXT: addq %rdi, %rax
; X64-NEXT: movabsq $1085102592571150095, %rcx # imm = 0xF0F0F0F0F0F0F0F
; X64-NEXT: andq %rax, %rcx
; X64-NEXT: movabsq $72340172838076673, %rax # imm = 0x101010101010101
; CHECK-NEXT: LBB0_34: ## %if.end517
; CHECK-NEXT: ## in Loop: Header=BB0_13 Depth=1
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Reload
-; CHECK-NEXT: leal -324(%rax), %eax
+; CHECK-NEXT: addl $-324, %eax ## imm = 0xFEBC
; CHECK-NEXT: cmpl $59, %eax
; CHECK-NEXT: ja LBB0_35
; CHECK-NEXT: ## %bb.57: ## %if.end517
; CHECK-NEXT: ## in Loop: Header=BB0_3 Depth=2
; CHECK-NEXT: addq $1002, %rbp ## imm = 0x3EA
; CHECK-NEXT: movq %rbx, %rdi
-; CHECK-NEXT: leaq 1001(%rbx), %rbx
+; CHECK-NEXT: addq $1001, %rbx ## imm = 0x3E9
; CHECK-NEXT: movl $1000, %edx ## imm = 0x3E8
; CHECK-NEXT: movl $120, %esi
; CHECK-NEXT: callq _memchr
; X64-NEXT: shlq $5, %rax
; X64-NEXT: shlq $10, %rdi
; X64-NEXT: shrq $57, %rax
-; X64-NEXT: leaq (%rax,%rdi), %rax
+; X64-NEXT: addq %rdi, %rax
; X64-NEXT: retq
%lhs_mul = shl i64 %i, 5
%rhs_mul = shl i64 %i, 10
; X64-NEXT: andl $-8, %eax
; X64-NEXT: shll $25, %eax
; X64-NEXT: shrl $9, %edi
-; X64-NEXT: leal (%rdi,%rax), %eax
+; X64-NEXT: addl %edi, %eax
; X64-NEXT: retq
%lhs_div = lshr i32 %i, 3
%rhs_div = lshr i32 %i, 9
; ANY-NEXT: notl %eax
; ANY-NEXT: cmpw %ax, %di
; ANY-NEXT: cmovbl %edi, %eax
-; ANY-NEXT: leal (%rax,%rsi), %eax
+; ANY-NEXT: addl %esi, %eax
; ANY-NEXT: # kill: def $ax killed $ax killed $eax
; ANY-NEXT: retq
%noty = xor i16 %y, -1
; ANY-NEXT: notl %eax
; ANY-NEXT: cmpl %eax, %edi
; ANY-NEXT: cmovbl %edi, %eax
-; ANY-NEXT: leal (%rax,%rsi), %eax
+; ANY-NEXT: addl %esi, %eax
; ANY-NEXT: retq
%noty = xor i32 %y, -1
%c = icmp ult i32 %x, %noty
; ANY-NEXT: notq %rax
; ANY-NEXT: cmpq %rax, %rdi
; ANY-NEXT: cmovbq %rdi, %rax
-; ANY-NEXT: leaq (%rax,%rsi), %rax
+; ANY-NEXT: addq %rsi, %rax
; ANY-NEXT: retq
%noty = xor i64 %y, -1
%c = icmp ult i64 %x, %noty
bb3:
; CHECK: subl %e[[REG0:[a-z0-9]+]],
-; CHECK: leaq 4({{%[a-z0-9]+}}), %r[[REG0]]
+; CHECK: addq $4, %r[[REG0]]
%tmp14 = phi i64 [ %tmp15, %bb5 ], [ 0, %bb1 ]
%tmp15 = add nuw i64 %tmp14, 4
%tmp16 = trunc i64 %tmp14 to i32
; SSE-NEXT: addb %al, %al
; SSE-NEXT: andb $-86, %dil
; SSE-NEXT: shrb %dil
-; SSE-NEXT: leal (%rdi,%rax), %eax
+; SSE-NEXT: addl %edi, %eax
; SSE-NEXT: # kill: def $al killed $al killed $eax
; SSE-NEXT: retq
;
; AVX-NEXT: addb %al, %al
; AVX-NEXT: andb $-86, %dil
; AVX-NEXT: shrb %dil
-; AVX-NEXT: leal (%rdi,%rax), %eax
+; AVX-NEXT: addl %edi, %eax
; AVX-NEXT: # kill: def $al killed $al killed $eax
; AVX-NEXT: retq
;
; WIN_X64:# %bb.1:
; WIN_X64: andq $-4096, %rdx
; WIN_X64:.LBB0_2:
-; WIN_X64: leaq -4096(%rcx), %rcx
+; WIN_X64: addq $-4096, %rcx
; WIN_X64: movb $0, (%rcx)
; WIN_X64: cmpq %rcx, %rdx
; WIN_X64: jne .LBB0_2
; X32-NEXT: # =>This Inner Loop Header: Depth=1
; X32-NEXT: movl (%ebx,%esi), %ebp
; X32-NEXT: addl (%ebx), %ebp
-; X32-NEXT: leal (%ebx,%esi), %ebx
+; X32-NEXT: addl %esi, %ebx
; X32-NEXT: addl (%esi,%ebx), %ebp
-; X32-NEXT: leal (%ebx,%esi), %ebx
+; X32-NEXT: addl %esi, %ebx
; X32-NEXT: addl (%esi,%ebx), %ebp
-; X32-NEXT: leal (%ebx,%esi), %ebx
+; X32-NEXT: addl %esi, %ebx
; X32-NEXT: addl (%esi,%ebx), %ebp
; X32-NEXT: movl %ebp, (%edx)
-; X32-NEXT: leal (%ebx,%esi), %ebx
+; X32-NEXT: addl %esi, %ebx
; X32-NEXT: addl %edi, %ebx
; X32-NEXT: addl %ecx, %edx
; X32-NEXT: decl %eax