llvm.org GIT mirror llvm / a38bbf7
Build constants using instructions mov/orr or mvn/eor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33141 91177308-0d34-0410-b5e6-96231b3b80d8 Lauro Ramos Venancio 13 years ago
7 changed file(s) with 197 addition(s) and 93 deletion(s). Raw diff Collapse all Expand all
0 //===-- ARMCommon.cpp - Define support functions for ARM --------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file was developed by the "Instituto Nokia de Tecnologia" and
5 // is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //
11 //
12 //===----------------------------------------------------------------------===//
13 #include "ARMCommon.h"
14
15 static inline unsigned rotateL(unsigned x, unsigned n){
16 return ((x << n) | (x >> (32 - n)));
17 }
18
19 static inline unsigned rotateR(unsigned x, unsigned n){
20 return ((x >> n) | (x << (32 - n)));
21 }
22
23 // finds the end position of largest sequence of zeros in binary representation
24 // of 'immediate'.
25 static int findLargestZeroSequence(unsigned immediate){
26 int max_zero_pos = 0;
27 int max_zero_length = 0;
28 int zero_pos;
29 int zero_length;
30 int pos = 0;
31 int end_pos;
32
33 while ((immediate & 0x3) == 0) {
34 immediate = rotateR(immediate, 2);
35 pos+=2;
36 }
37 end_pos = pos+32;
38
39 while (pos
40 while (((immediate & 0x3) != 0)&&(pos
41 immediate = rotateR(immediate, 2);
42 pos+=2;
43 }
44 zero_pos = pos;
45 while (((immediate & 0x3) == 0)&&(pos
46 immediate = rotateR(immediate, 2);
47 pos+=2;
48 }
49 zero_length = pos - zero_pos;
50 if (zero_length > max_zero_length){
51 max_zero_length = zero_length;
52 max_zero_pos = zero_pos % 32;
53 }
54
55 }
56
57 return (max_zero_pos + max_zero_length) % 32;
58 }
59
60 std::vector splitImmediate(unsigned immediate){
61 std::vector immediatePieces;
62
63 if (immediate == 0){
64 immediatePieces.push_back(0);
65 } else {
66 int start_pos = findLargestZeroSequence(immediate);
67 unsigned immediate_tmp = rotateR(immediate, start_pos);
68 int pos = 0;
69 while (pos < 32){
70 while(((immediate_tmp&0x3) == 0)&&(pos<32)){
71 immediate_tmp = rotateR(immediate_tmp,2);
72 pos+=2;
73 }
74 if (pos < 32){
75 immediatePieces.push_back(rotateL(immediate_tmp&0xFF,
76 (start_pos + pos) % 32 ));
77 immediate_tmp = rotateR(immediate_tmp,8);
78 pos+=8;
79 }
80 }
81 }
82 return immediatePieces;
83 }
0 //===-- ARMCommon.h - Define support functions for ARM ----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file was developed by the "Instituto Nokia de Tecnologia" and
5 // is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef ARM_COMMON_H
15 #define ARM_COMMON_H
16
17 #include
18
19 std::vector splitImmediate(unsigned immediate);
20
21 #endif
1212
1313 #include "ARM.h"
1414 #include "ARMTargetMachine.h"
15 #include "ARMCommon.h"
1516 #include "llvm/CallingConv.h"
1617 #include "llvm/DerivedTypes.h"
1718 #include "llvm/Function.h"
2627 #include "llvm/CodeGen/SSARegMap.h"
2728 #include "llvm/Target/TargetLowering.h"
2829 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/MathExtras.h"
2931 #include
3032 using namespace llvm;
3133
102104 setOperationAction(ISD::VAEND, MVT::Other, Expand);
103105 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
104106
105 setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
106 setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
107 setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
108 setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
107109
108110 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
109111 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
542544 return CPI;
543545 }
544546
547 SDOperand LegalizeImmediate(uint32_t immediate, SelectionDAG &DAG,
548 bool canReturnConstant){
549 SDOperand Shift = DAG.getTargetConstant(0, MVT::i32);
550 SDOperand ShiftType = DAG.getTargetConstant(ARMShift::LSL, MVT::i32);
551 std::vectorimmediatePieces = splitImmediate(immediate);
552 if (immediatePieces.size()>1){
553 unsigned movInst = ARM::MOV;
554 unsigned orInst = ARM::ORR;
555 SDNode *node;
556 //try mvn
557 std::vectorimmediateNegPieces = splitImmediate(~immediate);
558 if (immediatePieces.size() > immediateNegPieces.size()) {
559 //use mvn/eor
560 movInst = ARM::MVN;
561 orInst = ARM::EOR;
562 immediatePieces = immediateNegPieces;
563 }
564 SDOperand n = DAG.getTargetConstant(immediatePieces[0], MVT::i32);
565 node = DAG.getTargetNode(movInst, MVT::i32, n, Shift, ShiftType);
566 std::vector::iterator it;
567 for (it=immediatePieces.begin()+1; it != immediatePieces.end(); ++it){
568 n = DAG.getTargetConstant(*it, MVT::i32);
569 SDOperand ops[] = {SDOperand(node, 0), n, Shift, ShiftType};
570 node = DAG.getTargetNode(orInst, MVT::i32, ops, 4);
571 }
572 return SDOperand(node, 0);
573 } else {
574 if (canReturnConstant)
575 return DAG.getTargetConstant(immediate, MVT::i32);
576 else {
577 SDOperand n = DAG.getTargetConstant(immediate, MVT::i32);
578 SDNode *node = DAG.getTargetNode(ARM::MOV, MVT::i32, n, Shift,
579 ShiftType);
580 return SDOperand(node, 0);
581 }
582 }
583 }
584
585 static SDOperand LowerConstantFP(SDOperand Op, SelectionDAG &DAG) {
586 MVT::ValueType VT = Op.getValueType();
587 SDOperand Shift = DAG.getTargetConstant(0, MVT::i32);
588 SDOperand ShiftType = DAG.getTargetConstant(ARMShift::LSL, MVT::i32);
589 SDNode *node;
590 switch (VT) {
591 default: assert(0 && "VT!=f32 && VT!=f64");
592 case MVT::f32: {
593 float val = cast(Op)->getValue();
594 uint32_t i32_val = FloatToBits(val);
595 SDOperand c = LegalizeImmediate(i32_val, DAG, false);
596 node = DAG.getTargetNode(ARM::FMSR, MVT::f32, c);
597 break;
598 }
599 case MVT::f64: {
600 double val = cast(Op)->getValue();
601 uint64_t i64_val = DoubleToBits(val);
602 SDOperand hi = LegalizeImmediate(Hi_32(i64_val), DAG, false);
603 SDOperand lo = LegalizeImmediate(Lo_32(i64_val), DAG, false);
604 node = DAG.getTargetNode(ARM::FMDRR, MVT::f64, lo, hi);
605 break;
606 }
607 }
608 return SDOperand(node, 0);
609 }
610
545611 static SDOperand LowerGlobalAddress(SDOperand Op,
546612 SelectionDAG &DAG) {
547613 GlobalValue *GV = cast(Op)->getGlobal();
848914 abort();
849915 case ISD::ConstantPool:
850916 return LowerConstantPool(Op, DAG);
917 case ISD::ConstantFP:
918 return LowerConstantFP(Op, DAG);
851919 case ISD::GlobalAddress:
852920 return LowerGlobalAddress(Op, DAG);
853921 case ISD::FP_TO_SINT:
9411009 switch(N.getOpcode()) {
9421010 case ISD::Constant: {
9431011 uint32_t val = cast(N)->getValue();
944 if(!isRotInt8Immediate(val)) {
945 SDOperand Z = CurDAG->getTargetConstant(0, MVT::i32);
946 SDNode *n;
947 if (isRotInt8Immediate(~val)) {
948 SDOperand C = CurDAG->getTargetConstant(~val, MVT::i32);
949 n = CurDAG->getTargetNode(ARM::MVN, MVT::i32, C, Z, Z);
950 } else {
951 Constant *C = ConstantInt::get(Type::Int32Ty, val);
952 int alignment = 2;
953 SDOperand Addr = CurDAG->getTargetConstantPool(C, MVT::i32, alignment);
954 n = CurDAG->getTargetNode(ARM::LDR, MVT::i32, Addr, Z);
955 }
956 Arg = SDOperand(n, 0);
957 } else
958 Arg = CurDAG->getTargetConstant(val, MVT::i32);
959
960 Shift = CurDAG->getTargetConstant(0, MVT::i32);
961 ShiftType = CurDAG->getTargetConstant(ARMShift::LSL, MVT::i32);
1012 Shift = CurDAG->getTargetConstant(0, MVT::i32);
1013 ShiftType = CurDAG->getTargetConstant(ARMShift::LSL, MVT::i32);
1014 Arg = LegalizeImmediate(val, *CurDAG, true);
9621015 return true;
9631016 }
1017
9641018 case ISD::SRA:
9651019 Arg = N.getOperand(0);
9661020 Shift = N.getOperand(1);
1313
1414 #include "ARM.h"
1515 #include "ARMRegisterInfo.h"
16 #include "ARMCommon.h"
1617 #include "llvm/CodeGen/MachineInstrBuilder.h"
1718 #include "llvm/CodeGen/MachineFunction.h"
1819 #include "llvm/CodeGen/MachineFrameInfo.h"
3435 return NoFramePointerElim || MFI->hasVarSizedObjects();
3536 }
3637
37 static inline unsigned rotateL(unsigned x, unsigned n){
38 return ((x << n) | (x >> (32 - n)));
39 }
40
41 static inline unsigned rotateR(unsigned x, unsigned n){
42 return ((x >> n) | (x << (32 - n)));
43 }
44
45 // finds the end position of largest sequence of zeros in binary representation
46 // of 'immediate'.
47 static int findLargestZeroSequence(unsigned immediate){
48 int max_zero_pos;
49 int max_zero_length = 0;
50 int zero_pos;
51 int zero_length;
52 int pos = 0;
53 int end_pos;
54
55 while ((immediate & 0x3) == 0) {
56 immediate = rotateR(immediate, 2);
57 pos+=2;
58 }
59 end_pos = pos+32;
60
61 while (pos
62 while ((immediate & 0x3) != 0) {
63 immediate = rotateR(immediate, 2);
64 pos+=2;
65 }
66 zero_pos = pos;
67 while ((immediate & 0x3) == 0) {
68 immediate = rotateR(immediate, 2);
69 pos+=2;
70 }
71 zero_length = pos - zero_pos;
72 if (zero_length > max_zero_length){
73 max_zero_length = zero_length;
74 max_zero_pos = zero_pos % 32;
75 }
76
77 }
78
79 return (max_zero_pos + max_zero_length) % 32;
80 }
81
8238 static void splitInstructionWithImmediate(MachineBasicBlock &BB,
8339 MachineBasicBlock::iterator I,
8440 const TargetInstrDescriptor &TID,
8541 unsigned DestReg,
8642 unsigned OrigReg,
8743 unsigned immediate){
88
89 if (immediate == 0){
90 BuildMI(BB, I, TID, DestReg).addReg(OrigReg).addImm(0)
91 .addImm(0).addImm(ARMShift::LSL);
92 return;
93 }
94
95 int start_pos = findLargestZeroSequence(immediate);
96 unsigned immediate_tmp = rotateR(immediate, start_pos);
97
98 int pos = 0;
99 while (pos < 32){
100 while(((immediate_tmp&0x3) == 0)&&(pos<32)){
101 immediate_tmp = rotateR(immediate_tmp,2);
102 pos+=2;
103 }
104 if (pos < 32){
105 BuildMI(BB, I, TID, DestReg).addReg(OrigReg)
106 .addImm(rotateL(immediate_tmp&0xFF, (start_pos + pos) % 32 ))
107 .addImm(0).addImm(ARMShift::LSL);
108 immediate_tmp = rotateR(immediate_tmp,8);
109 pos+=8;
110 }
111 }
112
44 std::vector immediatePieces = splitImmediate(immediate);
45 std::vector::iterator it;
46 for (it=immediatePieces.begin(); it != immediatePieces.end(); ++it){
47 BuildMI(BB, I, TID, DestReg).addReg(OrigReg)
48 .addImm(*it).addImm(0).addImm(ARMShift::LSL);
49 }
11350 }
11451
11552 ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii)
11 ; RUN: grep "mov r0, #0" %t.s | wc -l | grep 1 &&
22 ; RUN: grep "mov r0, #255" %t.s | wc -l | grep 1 &&
33 ; RUN: grep "mov r0, #256" %t.s | wc -l | grep 1 &&
4 ; RUN: grep ".word.*257" %t.s | wc -l | grep 1 &&
4 ; RUN: grep "mov r0, #1" %t.s | wc -l | grep 2 &&
5 ; RUN: grep "orr r0, r0, #256" %t.s | wc -l | grep 1 &&
56 ; RUN: grep "mov r0, #-1073741761" %t.s | wc -l | grep 1 &&
67 ; RUN: grep "mov r0, #1008" %t.s | wc -l | grep 1 &&
78 ; RUN: grep "cmp r0, #65536" %t.s | wc -l | grep 1 &&
66 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep flds &&
77 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep fstd &&
88 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep fsts &&
9 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep ".word.*1065353216"
9 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep "mov r0, #1065353216"
1010
1111
1212 double %h(double* %v) {
1313 entry:
1414 %tmp = load double* %v ; [#uses=1]
1515 ret double %tmp
16 }
17
18 float %h(float* %v) {
19 entry:
20 %tmp = load float* %v ; [#uses=1]
21 ret float %tmp
1622 }
1723
1824 float %h() {
0 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm &&
1 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep flds | wc -l | grep 2 &&
1 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep "mov r0, #0" | wc -l | grep 1 &&
22 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep "flds.*\[" | wc -l | grep 1 &&
33 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep "fsts.*\[" | wc -l | grep 1
44