llvm.org GIT mirror llvm / 18efe26
Implement ctlz and cttz with bsr and bsf. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45024 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 12 years ago
5 changed file(s) with 119 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
209209 setOperationAction(ISD::FLT_ROUNDS , MVT::i32 , Custom);
210210
211211 setOperationAction(ISD::CTPOP , MVT::i8 , Expand);
212 setOperationAction(ISD::CTTZ , MVT::i8 , Expand);
213 setOperationAction(ISD::CTLZ , MVT::i8 , Expand);
212 setOperationAction(ISD::CTTZ , MVT::i8 , Custom);
213 setOperationAction(ISD::CTLZ , MVT::i8 , Custom);
214214 setOperationAction(ISD::CTPOP , MVT::i16 , Expand);
215 setOperationAction(ISD::CTTZ , MVT::i16 , Expand);
216 setOperationAction(ISD::CTLZ , MVT::i16 , Expand);
215 setOperationAction(ISD::CTTZ , MVT::i16 , Custom);
216 setOperationAction(ISD::CTLZ , MVT::i16 , Custom);
217217 setOperationAction(ISD::CTPOP , MVT::i32 , Expand);
218 setOperationAction(ISD::CTTZ , MVT::i32 , Expand);
219 setOperationAction(ISD::CTLZ , MVT::i32 , Expand);
218 setOperationAction(ISD::CTTZ , MVT::i32 , Custom);
219 setOperationAction(ISD::CTLZ , MVT::i32 , Custom);
220220 if (Subtarget->is64Bit()) {
221221 setOperationAction(ISD::CTPOP , MVT::i64 , Expand);
222 setOperationAction(ISD::CTTZ , MVT::i64 , Expand);
223 setOperationAction(ISD::CTLZ , MVT::i64 , Expand);
222 setOperationAction(ISD::CTTZ , MVT::i64 , Custom);
223 setOperationAction(ISD::CTLZ , MVT::i64 , Custom);
224224 }
225225
226226 setOperationAction(ISD::READCYCLECOUNTER , MVT::i64 , Custom);
53445344 ISD::TRUNCATE : ISD::ZERO_EXTEND), VT, RetVal);
53455345 }
53465346
5347 SDOperand X86TargetLowering::LowerCTLZ(SDOperand Op, SelectionDAG &DAG) {
5348 MVT::ValueType VT = Op.getValueType();
5349 MVT::ValueType OpVT = VT;
5350 unsigned NumBits = MVT::getSizeInBits(VT);
5351
5352 Op = Op.getOperand(0);
5353 if (VT == MVT::i8) {
5354 OpVT = MVT::i32;
5355 Op = DAG.getNode(ISD::ZERO_EXTEND, OpVT, Op);
5356 }
5357 if (VT == MVT::i32 || VT == MVT::i64)
5358 return DAG.getNode(ISD::XOR, OpVT, DAG.getNode(X86ISD::BSR, OpVT, Op),
5359 DAG.getConstant(NumBits-1, OpVT));
5360
5361 Op = DAG.getNode(ISD::SUB, OpVT, DAG.getConstant(NumBits-1, OpVT),
5362 DAG.getNode(X86ISD::BSR, OpVT, Op));
5363 if (VT == MVT::i8)
5364 Op = DAG.getNode(ISD::TRUNCATE, MVT::i8, Op);
5365 return Op;
5366 }
5367
5368 SDOperand X86TargetLowering::LowerCTTZ(SDOperand Op, SelectionDAG &DAG) {
5369 MVT::ValueType VT = Op.getValueType();
5370 MVT::ValueType OpVT = VT;
5371
5372 Op = Op.getOperand(0);
5373 if (VT == MVT::i8) {
5374 OpVT = MVT::i32;
5375 Op = DAG.getNode(ISD::ZERO_EXTEND, OpVT, Op);
5376 }
5377 Op = DAG.getNode(X86ISD::BSF, OpVT, Op);
5378 if (VT == MVT::i8)
5379 Op = DAG.getNode(ISD::TRUNCATE, MVT::i8, Op);
5380 return Op;
5381 }
5382
53475383 /// LowerOperation - Provide custom lowering hooks for some operations.
53485384 ///
53495385 SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
53865422 case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
53875423 case ISD::TRAMPOLINE: return LowerTRAMPOLINE(Op, DAG);
53885424 case ISD::FLT_ROUNDS: return LowerFLT_ROUNDS(Op, DAG);
5389
5425 case ISD::CTLZ: return LowerCTLZ(Op, DAG);
5426 case ISD::CTTZ: return LowerCTTZ(Op, DAG);
53905427
53915428 // FIXME: REMOVE THIS WHEN LegalizeDAGTypes lands.
53925429 case ISD::READCYCLECOUNTER:
54065443 const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
54075444 switch (Opcode) {
54085445 default: return NULL;
5446 case X86ISD::BSF: return "X86ISD::BSF";
5447 case X86ISD::BSR: return "X86ISD::BSR";
54095448 case X86ISD::SHLD: return "X86ISD::SHLD";
54105449 case X86ISD::SHRD: return "X86ISD::SHRD";
54115450 case X86ISD::FAND: return "X86ISD::FAND";
2626 enum NodeType {
2727 // Start the numbering where the builtin ops leave off.
2828 FIRST_NUMBER = ISD::BUILTIN_OP_END+X86::INSTRUCTION_LIST_END,
29
30 /// BSF - Bit scan forward.
31 /// BSR - Bit scan reverse.
32 BSF,
33 BSR,
2934
3035 /// SHLD, SHRD - Double shift instructions. These correspond to
3136 /// X86::SHLDxx and X86::SHRDxx instructions.
488493 SDOperand LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG);
489494 SDOperand LowerTRAMPOLINE(SDOperand Op, SelectionDAG &DAG);
490495 SDOperand LowerFLT_ROUNDS(SDOperand Op, SelectionDAG &DAG);
496 SDOperand LowerCTLZ(SDOperand Op, SelectionDAG &DAG);
497 SDOperand LowerCTTZ(SDOperand Op, SelectionDAG &DAG);
491498 SDNode *ExpandFP_TO_SINT(SDNode *N, SelectionDAG &DAG);
492499 SDNode *ExpandREADCYCLECOUNTER(SDNode *N, SelectionDAG &DAG);
493500 };
5656
5757 def SDT_X86TCRET : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>;
5858
59 def X86bsf : SDNode<"X86ISD::BSF", SDTIntUnaryOp>;
60 def X86bsr : SDNode<"X86ISD::BSR", SDTIntUnaryOp>;
5961 def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>;
6062 def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>;
6163
443445 def XCHG32rm : I<0x87, MRMSrcMem,
444446 (outs), (ins GR32:$src1, i32mem:$src2),
445447 "xchg{l}\t{$src2|$src1}, {$src1|$src2}", []>;
448
449 // Bit scan instructions.
450 let Defs = [EFLAGS] in {
451 def BSF16rr : I<0xBC, AddRegFrm, (outs GR16:$dst), (ins GR16:$src),
452 "bsf{w}\t{$src, $dst||$dst, $src}",
453 [(set GR16:$dst, (X86bsf GR16:$src))]>, TB;
454 def BSF16rm : I<0xBC, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src),
455 "bsf{w}\t{$src, $dst||$dst, $src}",
456 [(set GR16:$dst, (X86bsf (loadi16 addr:$src)))]>, TB;
457 def BSF32rr : I<0xBC, AddRegFrm, (outs GR32:$dst), (ins GR32:$src),
458 "bsf{l}\t{$src, $dst||$dst, $src}",
459 [(set GR32:$dst, (X86bsf GR32:$src))]>, TB;
460 def BSF32rm : I<0xBC, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
461 "bsf{l}\t{$src, $dst||$dst, $src}",
462 [(set GR32:$dst, (X86bsf (loadi32 addr:$src)))]>, TB;
463
464 def BSR16rr : I<0xBD, AddRegFrm, (outs GR16:$dst), (ins GR16:$src),
465 "bsr{w}\t{$src, $dst||$dst, $src}",
466 [(set GR16:$dst, (X86bsr GR16:$src))]>, TB;
467 def BSR16rm : I<0xBD, MRMSrcMem, (outs GR16:$dst), (ins i16mem:$src),
468 "bsr{w}\t{$src, $dst||$dst, $src}",
469 [(set GR16:$dst, (X86bsr (loadi16 addr:$src)))]>, TB;
470 def BSR32rr : I<0xBD, AddRegFrm, (outs GR32:$dst), (ins GR32:$src),
471 "bsr{l}\t{$src, $dst||$dst, $src}",
472 [(set GR32:$dst, (X86bsr GR32:$src))]>, TB;
473 def BSR32rm : I<0xBD, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
474 "bsr{l}\t{$src, $dst||$dst, $src}",
475 [(set GR32:$dst, (X86bsr (loadi32 addr:$src)))]>, TB;
476 } // Defs = [EFLAGS]
446477
447478 def LEA16r : I<0x8D, MRMSrcMem,
448479 (outs GR16:$dst), (ins i32mem:$src),
165165 "xchg{q}\t{$src2|$src1}, {$src1|$src2}", []>;
166166 def XCHG64rm : RI<0x87, MRMSrcMem, (outs), (ins GR64:$src1, i64mem:$src2),
167167 "xchg{q}\t{$src2|$src1}, {$src1|$src2}", []>;
168
169 // Bit scan instructions.
170 let Defs = [EFLAGS] in {
171 def BSF64rr : RI<0xBC, AddRegFrm, (outs GR64:$dst), (ins GR64:$src),
172 "bsf{q}\t{$src, $dst||$dst, $src}",
173 [(set GR64:$dst, (X86bsf GR64:$src))]>, TB;
174 def BSF64rm : RI<0xBC, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
175 "bsf{q}\t{$src, $dst||$dst, $src}",
176 [(set GR64:$dst, (X86bsf (loadi64 addr:$src)))]>, TB;
177
178 def BSR64rr : RI<0xBD, AddRegFrm, (outs GR64:$dst), (ins GR64:$src),
179 "bsr{q}\t{$src, $dst||$dst, $src}",
180 [(set GR64:$dst, (X86bsr GR64:$src))]>, TB;
181 def BSR64rm : RI<0xBD, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
182 "bsr{q}\t{$src, $dst||$dst, $src}",
183 [(set GR64:$dst, (X86bsr (loadi64 addr:$src)))]>, TB;
184 } // Defs = [EFLAGS]
168185
169186 // Repeat string ops
170187 let Defs = [RCX,RDI,RSI], Uses = [RCX,RDI,RSI] in
0 ; RUN: llvm-as < %s | llc -march=x86 | grep bsr
1 ; RUN: llvm-as < %s | llc -march=x86 | grep bsf
2
3 define i32 @t1(i32 %x) nounwind {
4 %tmp = tail call i32 @llvm.ctlz.i32( i32 %x )
5 ret i32 %tmp
6 }
7
8 declare i32 @llvm.ctlz.i32(i32) nounwind readnone
9
10 define i32 @t2(i32 %x) nounwind {
11 %tmp = tail call i32 @llvm.cttz.i32( i32 %x )
12 ret i32 %tmp
13 }
14
15 declare i32 @llvm.cttz.i32(i32) nounwind readnone