llvm.org GIT mirror llvm / abc00cb
[ARM] Support and tests for transform of LDR rt, = to MOV This change implements the transformation in processInstruction() for the LDR rt, =expression to MOV rt, expression when the expression can be evaluated and can fit into the immediate field of the MOV or a MVN. Across the ARM and Thumb instruction sets there are several cases to consider, each with a different range of representatble constants. In ARM we have: * Modified immediate (All ARM architectures) * MOVW (v6t2 and above) In Thumb we have: * Modified immediate (v6t2, v7m and v8m.mainline) * MOVW (v6t2, v7m, v8.mainline and v8m.baseline) * Narrow Thumb MOV that can be used in an IT block (non flag-setting) If the immediate fits any of the available alternatives then we make the transformation. Fixes 25722. Patch by Peter Smith. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269354 91177308-0d34-0410-b5e6-96231b3b80d8 Renato Golin 4 years ago
6 changed file(s) with 391 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
256256 bool hasThumb() const {
257257 return getSTI().getFeatureBits()[ARM::HasV4TOps];
258258 }
259 bool hasThumb2() const {
260 return getSTI().getFeatureBits()[ARM::FeatureThumb2];
261 }
259262 bool hasV6Ops() const {
260263 return getSTI().getFeatureBits()[ARM::HasV6Ops];
264 }
265 bool hasV6T2Ops() const {
266 return getSTI().getFeatureBits()[ARM::HasV6T2Ops];
261267 }
262268 bool hasV6MOps() const {
263269 return getSTI().getFeatureBits()[ARM::HasV6MOps];
52465252 S = Parser.getTok().getLoc();
52475253 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
52485254 return Error(S, "unexpected token in operand");
5249
52505255 Parser.Lex(); // Eat '='
52515256 const MCExpr *SubExprVal;
52525257 if (getParser().parseExpression(SubExprVal))
68696874 return true;
68706875 case ARM::LDRConstPool:
68716876 case ARM::tLDRConstPool:
6872 case ARM::t2LDRConstPool: {
6873 // Handle the pseudo instruction for ldr rn,=
6874 // For now we always create the constant pool entry and load from it
6875 // FIXME: Use a MOV or MVN when the immediate will fit
6877 case ARM::t2LDRConstPool: {
6878 // Pseudo instruction ldr rt, =immediate is converted to a
6879 // MOV rt, immediate if immediate is known and representable
6880 // otherwise we create a constant pool entry that we load from.
68766881 MCInst TmpInst;
68776882 if (Inst.getOpcode() == ARM::LDRConstPool)
68786883 TmpInst.setOpcode(ARM::LDRi12);
68836888 const ARMOperand &PoolOperand =
68846889 static_cast(*Operands[3]);
68856890 const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm();
6891 // If SubExprVal is a constant we may be able to use a MOV
6892 if (isa(SubExprVal) &&
6893 Inst.getOperand(0).getReg() != ARM::PC &&
6894 Inst.getOperand(0).getReg() != ARM::SP) {
6895 int64_t Value =
6896 (int64_t) (cast(SubExprVal))->getValue();
6897 bool UseMov = true;
6898 bool MovHasS = true;
6899 if (Inst.getOpcode() == ARM::LDRConstPool) {
6900 // ARM Constant
6901 if (ARM_AM::getSOImmVal(Value) != -1) {
6902 Value = ARM_AM::getSOImmVal(Value);
6903 TmpInst.setOpcode(ARM::MOVi);
6904 }
6905 else if (ARM_AM::getSOImmVal(~Value) != -1) {
6906 Value = ARM_AM::getSOImmVal(~Value);
6907 TmpInst.setOpcode(ARM::MVNi);
6908 }
6909 else if (hasV6T2Ops() &&
6910 Value >=0 && Value < 65536) {
6911 TmpInst.setOpcode(ARM::MOVi16);
6912 MovHasS = false;
6913 }
6914 else
6915 UseMov = false;
6916 }
6917 else {
6918 // Thumb/Thumb2 Constant
6919 if (hasThumb2() &&
6920 ARM_AM::getT2SOImmVal(Value) != -1)
6921 TmpInst.setOpcode(ARM::t2MOVi);
6922 else if (hasThumb2() &&
6923 ARM_AM::getT2SOImmVal(~Value) != -1) {
6924 TmpInst.setOpcode(ARM::t2MVNi);
6925 Value = ~Value;
6926 }
6927 else if (hasV8MBaseline() &&
6928 Value >=0 && Value < 65536) {
6929 TmpInst.setOpcode(ARM::t2MOVi16);
6930 MovHasS = false;
6931 }
6932 else
6933 UseMov = false;
6934 }
6935 if (UseMov) {
6936 TmpInst.addOperand(Inst.getOperand(0)); // Rt
6937 TmpInst.addOperand(MCOperand::createImm(Value)); // Immediate
6938 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6939 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6940 if (MovHasS)
6941 TmpInst.addOperand(MCOperand::createReg(0)); // S
6942 Inst = TmpInst;
6943 return true;
6944 }
6945 }
6946 // No opportunity to use MOV/MVN create constant pool
68866947 const MCExpr *CPLoc =
68876948 getTargetStreamer().addConstantPoolEntry(SubExprVal,
68886949 PoolOperand.getStartLoc());
0 @RUN: llvm-mc -triple armv7-base-apple-darwin %s | FileCheck --check-prefix=CHECK-ARM --check-prefix=CHECK %s
1 @RUN: llvm-mc -triple thumbv7-base-apple-darwin %s | FileCheck --check-prefix=CHECK-THUMB2 --check-prefix=CHECK %s
2
3 @
4 @ Check that ldr to constant pool correctly transfers the condition codes
5 @
6 @ simple test
7 .section __TEXT,a,regular,pure_instructions
8 @ CHECK-LABEL: f0:
9 f0:
10 it eq
11 ldreq r0, =0x10002
12 @ CHECK: ldreq r0, Ltmp0
13
14 @ loading multiple constants
15 .section __TEXT,b,regular,pure_instructions
16 @ CHECK-LABEL: f1:
17 f1:
18 ite eq
19 ldreq r0, =0x10003
20 @ CHECK: ldreq r0, Ltmp1
21 ldrne r0, =0x10004
22 @ CHECK: ldrne r0, Ltmp2
23
24 @ transformation to mov
25 .section __TEXT,d,regular,pure_instructions
26 @ CHECK-LABEL: f2:
27 f2:
28 @ Can use the narrow Thumb mov as it does not set flags in an IT block
29 it eq
30 ldreq r1, =0x1
31 @ CHECK: moveq r1, #1
32
33 @ Must use the wide Thumb mov if the constant can't be represented
34 ite eq
35 ldreq r2, = 0x1f000000
36 @ CHECK-ARM moveq r2, #520093696
37 @ CHECK-THUMB2 moveq.w r2, #520093696
38 ldrne r3, = 0x00001234
39 @ CHECK movwne r2, #4660
40
41 @
42 @ Constant Pools
43 @
44 @ CHECK: .section __TEXT,a,regular,pure_instructions
45 @ CHECK: .p2align 2
46 @ CHECK: Ltmp0:
47 @ CHECK: .long 65538
48
49 @ CHECK: .section __TEXT,b,regular,pure_instructions
50 @ CHECK: .p2align 2
51 @ CHECK: Ltmp1:
52 @ CHECK: .long 65539
53 @ CHECK: Ltmp2:
54 @ CHECK: .long 65540
0 @RUN: llvm-mc -triple armv7-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-ARM --check-prefix=CHECK %s
1 @RUN: llvm-mc -triple thumbv7-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-THUMB2 --check-prefix=CHECK %s
2
3 @
4 @ Check that ldr to constant pool correctly transfers the condition codes
5 @
6 @ simple test
7 .section a,"ax",%progbits
8 @ CHECK-LABEL: f0:
9 f0:
10 it eq
11 ldreq r0, =0x10002
12 @ CHECK: ldreq r0, .Ltmp[[TMP0:[0-9]+]]
13
14 @ loading multiple constants
15 .section b,"ax",%progbits
16 @ CHECK-LABEL: f1:
17 f1:
18 ite eq
19 ldreq r0, =0x10003
20 @ CHECK: ldreq r0, .Ltmp[[TMP1:[0-9]+]]
21 ldrne r0, =0x10004
22 @ CHECK: ldrne r0, .Ltmp[[TMP2:[0-9]+]]
23
24 @ transformation to mov
25 .section c, "ax", %progbits
26 @ CHECK-LABEL: f2:
27 f2:
28 @ Can use the narrow Thumb mov as it does not set flags in an IT block
29 it eq
30 ldreq r1, =0x1
31 @ CHECK: moveq r1, #1
32
33 @ Must use the wide Thumb mov if the constant can't be represented
34 ite eq
35 ldreq r2, = 0x1f000000
36 @ CHECK-ARM moveq r2, #520093696
37 @ CHECK-THUMB2 moveq.w r2, #520093696
38 ldrne r3, = 0x00001234
39 @ CHECK movwne r2, #4660
40
41 @
42 @ Constant Pools
43 @
44 @ CHECK: .section a,"ax",%progbits
45 @ CHECK: .p2align 2
46 @ CHECK: .Ltmp[[TMP0]]
47 @ CHECK: .long 65538
48
49 @ CHECK: .section b,"ax",%progbits
50 @ CHECK: .p2align 2
51 @ CHECK: .Ltmp[[TMP1]]
52 @ CHECK: .long 65539
53 @ CHECK: .Ltmp[[TMP2]]
54 @ CHECK: .long 65540
33 @ between darwin and linux. Any tests added here should have a matching
44 @ test added there.
55
6 @RUN: llvm-mc -triple armv7-apple-darwin %s | FileCheck %s
7 @RUN: llvm-mc -triple thumbv5-apple-darwin %s | FileCheck %s
8 @RUN: llvm-mc -triple thumbv7-apple-darwin %s | FileCheck %s
9
6 @RUN: llvm-mc -triple armv7-base-apple-darwin %s | FileCheck --check-prefix=CHECK-ARM --check-prefix=CHECK %s
7 @RUN: llvm-mc -triple armv5-base-apple-darwin %s | FileCheck --check-prefix=CHECK-ARMV5 --check-prefix=CHECK %s
8 @RUN: llvm-mc -triple thumbv5-base-apple-darwin %s | FileCheck --check-prefix=CHECK-THUMB --check-prefix=CHECK %s
9 @RUN: llvm-mc -triple thumbv7-base-apple-darwin %s | FileCheck --check-prefix=CHECK-THUMB2 --check-prefix=CHECK %s
10 @RUN: llvm-mc -triple thumbv8m.base-base-apple-darwin %s | FileCheck --check-prefix=CHECK-BASELINE --check-prefix=CHECK %s
1011 @
1112 @ Check that large constants are converted to ldr from constant pool
1213 @
151152 @ CHECK: ldr r0, Ltmp15
152153 adds r0, r0, #1
153154
155 @ transformation to mov
156 .section __TEXT,m,regular,pure_instructions
157 @ CHECK-LABEL: f16:
158 f16:
159
160 @ Representable in ARM, and Thumb with support mov.w or movw
161 ldr r1, =0x1
162 @ CHECK-ARM: mov r1, #1
163 @ CHECK-ARMV5: mov r1, #1
164 @ CHECK-THUMB: ldr r1, Ltmp16
165 @ CHECK-THUMB2: mov.w r1, #1
166 @ CHECK-BASELINE: movw r1, #1
167
168 @ Immediate is representable in A1 and T2 modified immediate only not movw
169 ldr r2, =0x120000
170 @ CHECK-ARM: mov r2, #1179648
171 @ CHECK-ARMV5: mov r2, #1179648
172 @ CHECK-THUMB: ldr r2, Ltmp17
173 @ CHECK-THUMB2: mov.w r2, #1179648
174 @ CHECK-BASELINE: ldr r2, Ltmp16
175
176 @ Immediate can be represented only with movw instruction
177 ldr r3, =0x1234
178 @ CHECK-ARM: movw r3, #4660
179 @ CHECK-ARMV5: ldr r3, Ltmp16
180 @ CHECK-THUMB: ldr r3, Ltmp18
181 @ CHECK-THUMB2: movw r3, #4660
182 @ CHECK-BASELINE: movw r3, #4660
183
184 @ Immediate can be represented only with T2 modified immediate
185 ldr r4, =0xabababab
186 @ CHECK-ARM: ldr r4, Ltmp16
187 @ CHECK-ARMV5: ldr r4, Ltmp17
188 @ CHECK-THUMB: ldr r4, Ltmp19
189 @ CHECK-THUMB2: mov.w r4, #2880154539
190 @ CHECK-BASELINE: ldr r4, Ltmp17
191
192 @ Immediate can be represented only with A1 modified immediate
193 ldr r5, =0x1000000b
194 @ CHECK-ARM: mov r5, #268435467
195 @ CHECK-ARMV5: mov r5, #268435467
196 @ CHECK-THUMB: ldr r5, Ltmp20
197 @ CHECK-THUMB2: ldr r5, Ltmp16
198 @ CHECK-BASELINE: ldr r5, Ltmp18
199
200 @ Negative numbers can be used with MVN or in Thumb2 with modified immediate
201 ldr r6, =-1
202 @ CHECK-ARM: mvn r6, #0
203 @ CHECK-ARMV5: mvn r6, #0
204 @ CHECK-THUMB: ldr r6, Ltmp21
205 @ CHECK-THUMB2: mov.w r6, #-1
206 @ CHECK-BASELINE: ldr r6, Ltmp19
207 ldr r7, =-0x100
208 @ CHECK-ARM: mvn r7, #255
209 @ CHECK-ARMV5: mvn r7, #255
210 @ CHECK-THUMB: ldr r7, Ltmp22
211 @ CHECK-THUMB2: mvn r7, #255
212 @ CHECK-BASELINE: ldr r7, Ltmp20
213
214 @ Constant expressions can be used
215 .equ expr, 0x10 + 0x10
216 ldr r0, = expr
217 @ CHECK-ARM: mov r0, #32
218 @ CHECK-ARMV5: mov r0, #32
219 @ CHECK-THUMB: ldr r0, Ltmp23
220 @ CHECK-THUMB2: mov.w r0, #32
221 @ CHECK-BASELINE: movw r0, #32
222 ldr r1, = expr - 0x10
223 @ CHECK-ARM: mov r1, #16
224 @ CHECK-ARMV5: mov r1, #16
225 @ CHECK-THUMB: ldr r1, Ltmp24
226 @ CHECK-THUMB2: mov.w r1, #16
227 @ CHECK-BASELINE: movw r1, #16
228
229 @ usage of translation in macro
230 .macro usemov_in_a_macro
231 ldr r2, =0x3
232 ldr r3, =expr
233 .endm
234 @ CHECK-LABEL: f17:
235 f17:
236 usemov_in_a_macro
237 @ CHECK-ARM: mov r2, #3
238 @ CHECK-ARM: mov r3, #32
239 @ CHECK-ARMV5: mov r2, #3
240 @ CHECK-ARMV5: mov r3, #32
241 @ CHECK-THUMB: ldr r2, Ltmp25
242 @ CHECK-THUMB: ldr r3, Ltmp26
243 @ CHECK-THUMB2: mov.w r2, #3
244 @ CHECK-THUMB2: mov.w r3, #32
245 @ CHECK-BASELINE: movw r2, #3
246 @ CHECK-BASELINE: movw r3, #32
154247 @
155248 @ Constant Pools
156249 @
0 @RUN: llvm-mc -triple armv5-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-ARM %s
1 @RUN: not llvm-mc -triple thumbv7-unknown-linux-gnueabi %s 2>&1 | FileCheck --check-prefix=CHECK-SP %s
2 @RUN: not llvm-mc -triple thumbv5-unknown-linux-gnueabi %s 2>&1 | FileCheck --check-prefix=CHECK-NONE %s
3 @RUN: llvm-mc -triple armv5-base-apple-darwin %s | FileCheck --check-prefix=CHECK-DARWIN-ARM %s
4 @RUN: not llvm-mc -triple thumbv7-base-apple-darwin %s 2>&1 | FileCheck --check-prefix=CHECK-DARWIN-SP %s
5 @RUN: not llvm-mc -triple thumbv5-base.apple.darwin %s 2>&1 | FileCheck --check-prefix=CHECK-NONE %s
6
7 @ We dont't do the transformation for rt = sp or pc
8 @ as it is unpredictable for many of the MOV encondings
9 ldr pc, = 0x4
10 @ CHECK-ARM: ldr pc, .Ltmp[[TMP0:[0-9]+]]
11 @ CHECK-DARWIN-ARM: ldr pc, Ltmp0
12 @ CHECK-SP: error: instruction requires: arm-mode
13 @ CHECK-DARWIN-SP: error: instruction requires: arm-mode
14 @ CHECK-NONE: error: instruction requires: arm-mode
15 ldr sp, = 0x8
16 @ CHECK-ARM: ldr sp, .Ltmp[[TMP1:[0-9]+]]
17 @ CHECK-DARWIN-ARM: ldr sp, Ltmp1
18 @ CHECK-SP: ldr.w sp, .Ltmp[[TMP0:[0-9]+]]
19 @ CHECK-DARWIN-SP: ldr.w sp, Ltmp0
20 @ CHECK-NONE: error: instruction requires: arm-mode
33 @ between darwin and linux. Any tests added here should have a matching
44 @ test added there.
55
6 @RUN: llvm-mc -triple armv7-unknown-linux-gnueabi %s | FileCheck %s
7 @RUN: llvm-mc -triple thumbv5-unknown-linux-gnueabi %s | FileCheck %s
8 @RUN: llvm-mc -triple thumbv7-unknown-linux-gnueabi %s | FileCheck %s
9
6 @RUN: llvm-mc -triple armv7-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-ARM --check-prefix=CHECK %s
7 @RUN: llvm-mc -triple armv5-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-ARMV5 --check-prefix=CHECK %s
8 @RUN: llvm-mc -triple thumbv5-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-THUMB --check-prefix=CHECK %s
9 @RUN: llvm-mc -triple thumbv7-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-THUMB2 --check-prefix=CHECK %s
10 @RUN: llvm-mc -triple thumbv8m.base-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-BASELINE --check-prefix=CHECK %s
1011 @
1112 @ Check that large constants are converted to ldr from constant pool
1213 @
151152 @ CHECK: ldr r0, .Ltmp[[TMP15:[0-9]+]]
152153 adds r0, r0, #1
153154
155 @ transformation to mov
156 .section m, "ax", %progbits
157 @ CHECK-LABEL: f16:
158 f16:
159
160 @ Representable in ARM, and Thumb with support mov.w or movw
161 ldr r1, =0x1
162 @ CHECK-ARM: mov r1, #1
163 @ CHECK-ARMV5: mov r1, #1
164 @ CHECK-THUMB: ldr r1, .Ltmp[[TMP16:[0-9]+]]
165 @ CHECK-THUMB2: mov.w r1, #1
166 @ CHECK-BASELINE: movw r1, #1
167
168 @ Immediate is representable in A1 and T2 modified immediate only not movw
169 ldr r2, =0x120000
170 @ CHECK-ARM: mov r2, #1179648
171 @ CHECK-ARMV5: mov r2, #1179648
172 @ CHECK-THUMB: ldr r2, .Ltmp[[TMP17:[0-9]+]]
173 @ CHECK-THUMB2: mov.w r2, #1179648
174 @ CHECK-BASELINE: ldr r2, .Ltmp[[TMP16:[0-9]+]]
175
176 @ Immediate can be represented only with movw instruction
177 ldr r3, =0x1234
178 @ CHECK-ARM: movw r3, #4660
179 @ CHECK-ARMV5: ldr r3, .Ltmp[[TMP16:[0-9]+]]
180 @ CHECK-THUMB: ldr r3, .Ltmp[[TMP18:[0-9]+]]
181 @ CHECK-THUMB2: movw r3, #4660
182 @ CHECK-BASELINE: movw r3, #4660
183
184 @ Immediate can be represented only with T2 modified immediate
185 ldr r4, =0xabababab
186 @ CHECK-ARM: ldr r4, .Ltmp[[TMP16:[0-9]+]]
187 @ CHECK-ARMV5: ldr r4, .Ltmp[[TMP17:[0-9]+]]
188 @ CHECK-THUMB: ldr r4, .Ltmp[[TMP19:[0-9]+]]
189 @ CHECK-THUMB2: mov.w r4, #2880154539
190 @ CHECK-BASELINE: ldr r4, .Ltmp[[TMP17:[0-9]+]]
191
192 @ Immediate can be represented only with A1 modified immediate
193 ldr r5, =0x1000000b
194 @ CHECK-ARM: mov r5, #268435467
195 @ CHECK-ARMV5: mov r5, #268435467
196 @ CHECK-THUMB: ldr r5, .Ltmp[[TMP20:[0-9]+]]
197 @ CHECK-THUMB2: ldr r5, .Ltmp[[TMP16:[0-9]+]]
198 @ CHECK-BASELINE: ldr r5, .Ltmp[[TMP18:[0-9]+]]
199
200 @ Negative numbers can be used with MVN or in Thumb2 with modified immediate
201 ldr r6, =-1
202 @ CHECK-ARM: mvn r6, #0
203 @ CHECK-ARMV5: mvn r6, #0
204 @ CHECK-THUMB: ldr r6, .Ltmp[[TMP21:[0-9]+]]
205 @ CHECK-THUMB2: mov.w r6, #-1
206 @ CHECK-BASELINE: ldr r6, .Ltmp[[TMP19:[0-9]+]]
207 ldr r7, =-0x100
208 @ CHECK-ARM: mvn r7, #255
209 @ CHECK-ARMV5: mvn r7, #255
210 @ CHECK-THUMB: ldr r7, .Ltmp[[TMP22:[0-9]+]]
211 @ CHECK-THUMB2: mvn r7, #255
212 @ CHECK-BASELINE: ldr r7, .Ltmp[[TMP20:[0-9]+]]
213
214 @ Constant expressions can be used
215 .equ expr, 0x10 + 0x10
216 ldr r0, = expr
217 @ CHECK-ARM: mov r0, #32
218 @ CHECK-ARMV5: mov r0, #32
219 @ CHECK-THUMB: ldr r0, .Ltmp[[TMP23:[0-9]+]]
220 @ CHECK-THUMB2: mov.w r0, #32
221 @ CHECK-BASELINE: movw r0, #32
222 ldr r1, = expr - 0x10
223 @ CHECK-ARM: mov r1, #16
224 @ CHECK-ARMV5: mov r1, #16
225 @ CHECK-THUMB: ldr r1, .Ltmp[[TMP24:[0-9]+]]
226 @ CHECK-THUMB2: mov.w r1, #16
227 @ CHECK-BASELINE: movw r1, #16
228
229 @ usage of translation in macro
230 .macro usemov_in_a_macro
231 ldr r2, =0x3
232 ldr r3, =expr
233 .endm
234 @ CHECK-LABEL: f17:
235 f17:
236 usemov_in_a_macro
237 @ CHECK-ARM: mov r2, #3
238 @ CHECK-ARM: mov r3, #32
239 @ CHECK-ARMV5: mov r2, #3
240 @ CHECK-ARMV5: mov r3, #32
241 @ CHECK-THUMB: ldr r2, .Ltmp[[TMP25:[0-9]+]]
242 @ CHECK-THUMB: ldr r3, .Ltmp[[TMP26:[0-9]+]]
243 @ CHECK-THUMB2: mov.w r2, #3
244 @ CHECK-THUMB2: mov.w r3, #32
245 @ CHECK-BASELINE: movw r2, #3
246 @ CHECK-BASELINE: movw r3, #32
154247 @
155248 @ Constant Pools
156249 @