llvm.org GIT mirror llvm / 602fc06
1. merge fast-isel-shift-imm.ll into fast-isel-x86-64.ll 2. implement rdar://9289501 - fast isel should fold trivial multiplies to shifts 3. teach tblgen to handle shift immediates that are different sizes than the shifted operands, eliminating some code from the X86 fast isel backend. 4. Have FastISel::SelectBinaryOp use (the poorly named) FastEmit_ri_ function instead of FastEmit_ri to simplify code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129666 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 9 years ago
6 changed file(s) with 95 addition(s) and 61 deletion(s). Raw diff Collapse all Expand all
338338
339339 bool Op1IsKill = hasTrivialKill(I->getOperand(1));
340340
341 unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(),
342 ISDOpcode, Op1, Op1IsKill,
343 CI->getZExtValue());
344 if (ResultReg != 0) {
345 // We successfully emitted code for the given LLVM Instruction.
346 UpdateValueMap(I, ResultReg);
347 return true;
348 }
341 unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op1,
342 Op1IsKill, CI->getZExtValue(),
343 VT.getSimpleVT());
344 if (ResultReg == 0) return false;
345
346 // We successfully emitted code for the given LLVM Instruction.
347 UpdateValueMap(I, ResultReg);
348 return true;
349349 }
350350
351351
352352 unsigned Op0 = getRegForValue(I->getOperand(0));
353 if (Op0 == 0)
354 // Unhandled operand. Halt "fast" selection and bail.
353 if (Op0 == 0) // Unhandled operand. Halt "fast" selection and bail.
355354 return false;
356355
357356 bool Op0IsKill = hasTrivialKill(I->getOperand(0));
358357
359358 // Check if the second operand is a constant and handle it appropriately.
360359 if (ConstantInt *CI = dyn_cast(I->getOperand(1))) {
361 unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(),
362 ISDOpcode, Op0, Op0IsKill,
363 CI->getZExtValue());
364 if (ResultReg != 0) {
365 // We successfully emitted code for the given LLVM Instruction.
366 UpdateValueMap(I, ResultReg);
367 return true;
368 }
360 uint64_t Imm = CI->getZExtValue();
361
362 unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op0,
363 Op0IsKill, Imm, VT.getSimpleVT());
364 if (ResultReg == 0) return false;
365
366 // We successfully emitted code for the given LLVM Instruction.
367 UpdateValueMap(I, ResultReg);
368 return true;
369369 }
370370
371371 // Check if the second operand is a constant float.
985985 unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode,
986986 unsigned Op0, bool Op0IsKill,
987987 uint64_t Imm, MVT ImmType) {
988 // If this is a multiply by a power of two, emit this as a shift left.
989 if (Opcode == ISD::MUL && isPowerOf2_64(Imm)) {
990 Opcode = ISD::SHL;
991 Imm = Log2_64(Imm);
992 }
993
994 // Horrible hack (to be removed), check to make sure shift amounts are
995 // in-range.
996 if ((Opcode == ISD::SHL || Opcode == ISD::SRA || Opcode == ISD::SRL) &&
997 Imm >= VT.getSizeInBits())
998 return 0;
999
9881000 // First check if immediate type is legal. If not, we can't use the ri form.
9891001 unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Op0IsKill, Imm);
9901002 if (ResultReg != 0)
10831083 }
10841084
10851085 bool X86FastISel::X86SelectShift(const Instruction *I) {
1086 unsigned CReg = 0, OpReg = 0, OpImm = 0;
1086 unsigned CReg = 0, OpReg = 0;
10871087 const TargetRegisterClass *RC = NULL;
10881088 if (I->getType()->isIntegerTy(8)) {
10891089 CReg = X86::CL;
10901090 RC = &X86::GR8RegClass;
10911091 switch (I->getOpcode()) {
1092 case Instruction::LShr: OpReg = X86::SHR8rCL; OpImm = X86::SHR8ri; break;
1093 case Instruction::AShr: OpReg = X86::SAR8rCL; OpImm = X86::SAR8ri; break;
1094 case Instruction::Shl: OpReg = X86::SHL8rCL; OpImm = X86::SHL8ri; break;
1092 case Instruction::LShr: OpReg = X86::SHR8rCL; break;
1093 case Instruction::AShr: OpReg = X86::SAR8rCL; break;
1094 case Instruction::Shl: OpReg = X86::SHL8rCL; break;
10951095 default: return false;
10961096 }
10971097 } else if (I->getType()->isIntegerTy(16)) {
10981098 CReg = X86::CX;
10991099 RC = &X86::GR16RegClass;
11001100 switch (I->getOpcode()) {
1101 case Instruction::LShr: OpReg = X86::SHR16rCL; OpImm = X86::SHR16ri; break;
1102 case Instruction::AShr: OpReg = X86::SAR16rCL; OpImm = X86::SAR16ri; break;
1103 case Instruction::Shl: OpReg = X86::SHL16rCL; OpImm = X86::SHL16ri; break;
1101 case Instruction::LShr: OpReg = X86::SHR16rCL; break;
1102 case Instruction::AShr: OpReg = X86::SAR16rCL; break;
1103 case Instruction::Shl: OpReg = X86::SHL16rCL; break;
11041104 default: return false;
11051105 }
11061106 } else if (I->getType()->isIntegerTy(32)) {
11071107 CReg = X86::ECX;
11081108 RC = &X86::GR32RegClass;
11091109 switch (I->getOpcode()) {
1110 case Instruction::LShr: OpReg = X86::SHR32rCL; OpImm = X86::SHR32ri; break;
1111 case Instruction::AShr: OpReg = X86::SAR32rCL; OpImm = X86::SAR32ri; break;
1112 case Instruction::Shl: OpReg = X86::SHL32rCL; OpImm = X86::SHL32ri; break;
1110 case Instruction::LShr: OpReg = X86::SHR32rCL; break;
1111 case Instruction::AShr: OpReg = X86::SAR32rCL; break;
1112 case Instruction::Shl: OpReg = X86::SHL32rCL; break;
11131113 default: return false;
11141114 }
11151115 } else if (I->getType()->isIntegerTy(64)) {
11161116 CReg = X86::RCX;
11171117 RC = &X86::GR64RegClass;
11181118 switch (I->getOpcode()) {
1119 case Instruction::LShr: OpReg = X86::SHR64rCL; OpImm = X86::SHR64ri; break;
1120 case Instruction::AShr: OpReg = X86::SAR64rCL; OpImm = X86::SAR64ri; break;
1121 case Instruction::Shl: OpReg = X86::SHL64rCL; OpImm = X86::SHL64ri; break;
1119 case Instruction::LShr: OpReg = X86::SHR64rCL; break;
1120 case Instruction::AShr: OpReg = X86::SAR64rCL; break;
1121 case Instruction::Shl: OpReg = X86::SHL64rCL; break;
11221122 default: return false;
11231123 }
11241124 } else {
11311131
11321132 unsigned Op0Reg = getRegForValue(I->getOperand(0));
11331133 if (Op0Reg == 0) return false;
1134
1135 // Fold immediate in shl(x,3).
1136 if (const ConstantInt *CI = dyn_cast(I->getOperand(1))) {
1137 unsigned ResultReg = createResultReg(RC);
1138 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(OpImm),
1139 ResultReg).addReg(Op0Reg).addImm(CI->getZExtValue() & 0xff);
1140 UpdateValueMap(I, ResultReg);
1141 return true;
1142 }
11431134
11441135 unsigned Op1Reg = getRegForValue(I->getOperand(1));
11451136 if (Op1Reg == 0) return false;
+0
-8
test/CodeGen/X86/fast-isel-shift-imm.ll less more
None ; RUN: llc < %s -march=x86 -O0 | grep {sarl \$80, %e}
1 ; PR3242
2
3 define void @foo(i32 %x, i32* %p) nounwind {
4 %y = ashr i32 %x, 50000
5 store i32 %y, i32* %p
6 ret void
7 }
None ; RUN: llc < %s -fast-isel -O0 -regalloc=fast | FileCheck %s
0 ; RUN: llc < %s -fast-isel -O0 -regalloc=fast -asm-verbose=0 | FileCheck %s
11
22 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
33 target triple = "x86_64-apple-darwin10.0.0"
6060 ; CHECK-NEXT: movzbl (%rax,%rdi), %eax
6161 ; CHECK-NEXT: ret
6262 }
63
64
65 ; PR3242 - Out of range shifts should not be folded by fastisel.
66 define void @test5(i32 %x, i32* %p) nounwind {
67 %y = ashr i32 %x, 50000
68 store i32 %y, i32* %p
69 ret void
70
71 ; CHECK: test5:
72 ; CHECK: movl $50000, %ecx
73 ; CHECK: sarl %cl, %edi
74 ; CHECK: ret
75 }
76
77 ; rdar://9289501 - fast isel should fold trivial multiplies to shifts.
78 define i64 @test6(i64 %x) nounwind ssp {
79 entry:
80 %mul = mul nsw i64 %x, 8
81 ret i64 %mul
82
83 ; CHECK: test6:
84 ; CHECK: leaq (,%rdi,8), %rax
85 }
86
87 define i32 @test7(i32 %x) nounwind ssp {
88 entry:
89 %mul = mul nsw i32 %x, 8
90 ret i32 %mul
91 ; CHECK: test7:
92 ; CHECK: leal (,%rdi,8), %eax
93 }
94
33 target triple = "x86_64-apple-darwin10.0.0"
44
55 ; CHECK: f0:
6 ; CHECK: addq %rax, (%rdi)
7 ; CHECK: # encoding: [0xf0,0x48,0x01,0x07]
6 ; CHECK: addq %rcx, (%rdi)
7 ; CHECK: # encoding: [0xf0,0x48,0x01,0x0f]
88 ; CHECK: ret
9 define void @f0(i64* %a0) {
9 define void @f0(i64* %a0) nounwind {
1010 %t0 = and i64 1, 1
1111 call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) nounwind
1212 %1 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %a0, i64 %t0) nounwind
5151 /// of the Operands array accordingly. Return true if all the operands
5252 /// are supported, false otherwise.
5353 ///
54 bool initialize(TreePatternNode *InstPatNode,
55 const CodeGenTarget &Target,
54 bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target,
5655 MVT::SimpleValueType VT) {
5756
5857 if (!InstPatNode->isLeaf()) {
7372
7473 // For now, filter out any operand with a predicate.
7574 // For now, filter out any operand with multiple values.
76 if (!Op->getPredicateFns().empty() ||
77 Op->getNumTypes() != 1)
78 return false;
79
80 assert(Op->hasTypeSet(0) && "Type infererence not done?");
81 // For now, all the operands must have the same type.
82 if (Op->getType(0) != VT)
75 if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1)
8376 return false;
8477
8578 if (!Op->isLeaf()) {
9487 // For now, ignore other non-leaf nodes.
9588 return false;
9689 }
90
91 assert(Op->hasTypeSet(0) && "Type infererence not done?");
92
93 // For now, all the operands must have the same type (if they aren't
94 // immediates). Note that this causes us to reject variable sized shifts
95 // on X86.
96 if (Op->getType(0) != VT)
97 return false;
98
9799 DefInit *OpDI = dynamic_cast(Op->getLeafValue());
98100 if (!OpDI)
99101 return false;
320322 assert(InstPatNode->getChild(0)->getNumTypes() == 1);
321323 VT = InstPatNode->getChild(0)->getType(0);
322324 }
325
326 if (InstPatOp->getName() =="shl") {
327 InstPatNode->dump();
328 }
329
323330
324331 // For now, filter out instructions which just set a register to
325332 // an Operand or an immediate, like MOV32ri.