reimplement the second half of the or/add optimization. We should now

only end up emitting LEA instead of OR.  If we aren't able to promote
something into an LEA, we should never be emitting it as an ADD.

Add some testcases that we emit "or" in cases where we used to produce
an "add".


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116026 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-10-08 01:05:10 +00:00
parent 0f448b5bf6
commit cd3167b281
4 changed files with 87 additions and 20 deletions

View File

@ -1036,21 +1036,34 @@ def ADD32rr_DB : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
def ADD64rr_DB : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
"", // orq/addq REG, REG
[(set GR64:$dst, (or_is_add GR64:$src1, GR64:$src2))]>;
def ADD16ri_DB : I<0, Pseudo, (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2),
"", // orw/addw REG, imm
[(set GR16:$dst, (or_is_add GR16:$src1, imm:$src2))]>;
def ADD32ri_DB : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
"", // orl/addl REG, imm
[(set GR32:$dst, (or_is_add GR32:$src1, imm:$src2))]>;
def ADD64ri32_DB : I<0, Pseudo,
(outs GR64:$dst), (ins GR64:$src1, i64i32imm:$src2),
"", // orq/addq REG, imm
[(set GR64:$dst, (or_is_add GR64:$src1,
i64immSExt32:$src2))]>;
def ADD16ri8_DB : I<0, Pseudo,
(outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
"", // orw/addw REG, imm8
[(set GR16:$dst,(or_is_add GR16:$src1,i16immSExt8:$src2))]>;
def ADD32ri8_DB : I<0, Pseudo,
(outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
"", // orl/addl REG, imm8
[(set GR32:$dst,(or_is_add GR32:$src1,i32immSExt8:$src2))]>;
def ADD64ri8_DB : I<0, Pseudo,
(outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2),
"", // orq/addq REG, imm8
[(set GR64:$dst, (or_is_add GR64:$src1,
i64immSExt8:$src2))]>;
}
def : Pat<(or_is_add GR16:$src1, imm:$src2),
(ADD16ri GR16:$src1, imm:$src2)>;
def : Pat<(or_is_add GR32:$src1, imm:$src2),
(ADD32ri GR32:$src1, imm:$src2)>;
def : Pat<(or_is_add GR64:$src1, i64immSExt32:$src2),
(ADD64ri32 GR64:$src1, i64immSExt32:$src2)>;
def : Pat<(or_is_add GR16:$src1, i16immSExt8:$src2),
(ADD16ri8 GR16:$src1, i16immSExt8:$src2)>;
def : Pat<(or_is_add GR32:$src1, i32immSExt8:$src2),
(ADD32ri8 GR32:$src1, i32immSExt8:$src2)>;
def : Pat<(or_is_add GR64:$src1, i64immSExt8:$src2),
(ADD64ri8 GR64:$src1, i64immSExt8:$src2)>;
} // AddedComplexity

View File

@ -68,14 +68,20 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
{ X86::ADC64rr, X86::ADC64mr },
{ X86::ADD16ri, X86::ADD16mi },
{ X86::ADD16ri8, X86::ADD16mi8 },
{ X86::ADD16ri_DB, X86::ADD16mi | TB_NOT_REVERSABLE },
{ X86::ADD16ri8_DB, X86::ADD16mi8 | TB_NOT_REVERSABLE },
{ X86::ADD16rr, X86::ADD16mr },
{ X86::ADD16rr_DB, X86::ADD16mr | TB_NOT_REVERSABLE },
{ X86::ADD32ri, X86::ADD32mi },
{ X86::ADD32ri8, X86::ADD32mi8 },
{ X86::ADD32ri_DB, X86::ADD32mi | TB_NOT_REVERSABLE },
{ X86::ADD32ri8_DB, X86::ADD32mi8 | TB_NOT_REVERSABLE },
{ X86::ADD32rr, X86::ADD32mr },
{ X86::ADD32rr_DB, X86::ADD32mr | TB_NOT_REVERSABLE },
{ X86::ADD64ri32, X86::ADD64mi32 },
{ X86::ADD64ri8, X86::ADD64mi8 },
{ X86::ADD64ri32_DB,X86::ADD64mi32 | TB_NOT_REVERSABLE },
{ X86::ADD64ri8_DB, X86::ADD64mi8 | TB_NOT_REVERSABLE },
{ X86::ADD64rr, X86::ADD64mr },
{ X86::ADD64rr_DB, X86::ADD64mr | TB_NOT_REVERSABLE },
{ X86::ADD8ri, X86::ADD8mi },
@ -1160,6 +1166,8 @@ X86InstrInfo::convertToThreeAddressWithLEA(unsigned MIOpc,
break;
case X86::ADD16ri:
case X86::ADD16ri8:
case X86::ADD16ri_DB:
case X86::ADD16ri8_DB:
addRegOffset(MIB, leaInReg, true, MI->getOperand(2).getImm());
break;
case X86::ADD16rr:
@ -1424,6 +1432,8 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
}
case X86::ADD64ri32:
case X86::ADD64ri8:
case X86::ADD64ri32_DB:
case X86::ADD64ri8_DB:
assert(MI->getNumOperands() >= 3 && "Unknown add instruction!");
NewMI = addRegOffset(BuildMI(MF, MI->getDebugLoc(), get(X86::LEA64r))
.addReg(Dest, RegState::Define |
@ -1431,7 +1441,9 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
Src, isKill, MI->getOperand(2).getImm());
break;
case X86::ADD32ri:
case X86::ADD32ri8: {
case X86::ADD32ri8:
case X86::ADD32ri_DB:
case X86::ADD32ri8_DB: {
assert(MI->getNumOperands() >= 3 && "Unknown add instruction!");
unsigned Opc = is64Bit ? X86::LEA64_32r : X86::LEA32r;
NewMI = addRegOffset(BuildMI(MF, MI->getDebugLoc(), get(Opc))
@ -1442,6 +1454,8 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
}
case X86::ADD16ri:
case X86::ADD16ri8:
case X86::ADD16ri_DB:
case X86::ADD16ri8_DB:
if (DisableLEA16)
return is64Bit ? convertToThreeAddressWithLEA(MIOpc, MFI, MBBI, LV) : 0;
assert(MI->getNumOperands() >= 3 && "Unknown add instruction!");

View File

@ -437,9 +437,15 @@ ReSimplify:
// These are pseudo-ops for OR to help with the OR->ADD transformation. We do
// this with an ugly goto in case the resultant OR uses EAX and needs the
// short form.
case X86::ADD16rr_DB: OutMI.setOpcode(X86::OR16rr); goto ReSimplify;
case X86::ADD32rr_DB: OutMI.setOpcode(X86::OR32rr); goto ReSimplify;
case X86::ADD64rr_DB: OutMI.setOpcode(X86::OR64rr); goto ReSimplify;
case X86::ADD16rr_DB: OutMI.setOpcode(X86::OR16rr); goto ReSimplify;
case X86::ADD32rr_DB: OutMI.setOpcode(X86::OR32rr); goto ReSimplify;
case X86::ADD64rr_DB: OutMI.setOpcode(X86::OR64rr); goto ReSimplify;
case X86::ADD16ri_DB: OutMI.setOpcode(X86::OR16ri); goto ReSimplify;
case X86::ADD32ri_DB: OutMI.setOpcode(X86::OR32ri); goto ReSimplify;
case X86::ADD64ri32_DB: OutMI.setOpcode(X86::OR64ri32); goto ReSimplify;
case X86::ADD16ri8_DB: OutMI.setOpcode(X86::OR16ri8); goto ReSimplify;
case X86::ADD32ri8_DB: OutMI.setOpcode(X86::OR32ri8); goto ReSimplify;
case X86::ADD64ri8_DB: OutMI.setOpcode(X86::OR64ri8); goto ReSimplify;
// The assembler backend wants to see branches in their small form and relax
// them to their large form. The JIT can only handle the large form because

View File

@ -1,9 +1,9 @@
; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
; rdar://7527734
define i32 @test(i32 %x) nounwind readnone ssp {
define i32 @test1(i32 %x) nounwind readnone ssp {
entry:
; CHECK: test:
; CHECK: test1:
; CHECK: leal 3(%rdi), %eax
%0 = shl i32 %x, 5 ; <i32> [#uses=1]
%1 = or i32 %0, 3 ; <i32> [#uses=1]
@ -25,3 +25,37 @@ define i64 @test2(i8 %A, i8 %B) nounwind {
%H = or i64 %G, %E ; <i64> [#uses=1]
ret i64 %H
}
;; Test that OR is only emitted as LEA, not as ADD.
define void @test3(i32 %x, i32* %P) nounwind readnone ssp {
entry:
; No reason to emit an add here, should be an or.
; CHECK: test3:
; CHECK: orl $3, %edi
%0 = shl i32 %x, 5
%1 = or i32 %0, 3
store i32 %1, i32* %P
ret void
}
define i32 @test4(i32 %a, i32 %b) nounwind readnone ssp {
entry:
%and = and i32 %a, 6
%and2 = and i32 %b, 16
%or = or i32 %and2, %and
ret i32 %or
; CHECK: test4:
; CHECK: leal (%rsi,%rdi), %eax
}
define void @test5(i32 %a, i32 %b, i32* nocapture %P) nounwind ssp {
entry:
%and = and i32 %a, 6
%and2 = and i32 %b, 16
%or = or i32 %and2, %and
store i32 %or, i32* %P, align 4
ret void
; CHECK: test5:
; CHECK: orl
}