Index: lib/Target/ARM/ARMRegisterInfo.td =================================================================== --- lib/Target/ARM/ARMRegisterInfo.td +++ lib/Target/ARM/ARMRegisterInfo.td @@ -205,13 +205,20 @@ def GPR : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12), SP, LR, PC)> { // Allocate LR as the first CSR since it is always saved anyway. + // For Thumb2, using LR would force 32bit Thumb2 instructions, not the smaller + // Thumb1 ones. It is a little better for codesize on average to use the + // default order. // For Thumb1 mode, we don't want to allocate hi regs at all, as we don't // know how to spill them. If we make our prologue/epilogue code smarter at // some point, we can go back to using the above allocation orders for the // Thumb1 instructions that know how to use hi regs. let AltOrders = [(add LR, GPR), (trunc GPR, 8)]; let AltOrderSelect = [{ - return 1 + MF.getSubtarget().isThumb1Only(); + if (MF.getSubtarget().isThumb1Only()) + return 2; + if (MF.getSubtarget().isThumb2() && MF.getFunction().optForMinSize()) + return 0; + return 1; }]; let DiagnosticString = "operand must be a register in range [r0, r15]"; } @@ -222,7 +229,11 @@ def GPRnopc : RegisterClass<"ARM", [i32], 32, (sub GPR, PC)> { let AltOrders = [(add LR, GPRnopc), (trunc GPRnopc, 8)]; let AltOrderSelect = [{ - return 1 + MF.getSubtarget().isThumb1Only(); + if (MF.getSubtarget().isThumb1Only()) + return 2; + if (MF.getSubtarget().isThumb2() && MF.getFunction().optForMinSize()) + return 0; + return 1; }]; let DiagnosticString = "operand must be a register in range [r0, r14]"; } @@ -233,7 +244,11 @@ def GPRwithAPSR : RegisterClass<"ARM", [i32], 32, (add (sub GPR, PC), APSR_NZCV)> { let AltOrders = [(add LR, GPRnopc), (trunc GPRnopc, 8)]; let AltOrderSelect = [{ - return 1 + MF.getSubtarget().isThumb1Only(); + if (MF.getSubtarget().isThumb1Only()) + return 2; + if (MF.getSubtarget().isThumb2() && MF.getFunction().optForMinSize()) + return 0; + return 1; }]; let DiagnosticString = "operand must be a register in range [r0, r14] or apsr_nzcv"; } @@ -254,7 +269,11 @@ def rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> { let AltOrders = [(add LR, rGPR), (trunc rGPR, 8)]; let AltOrderSelect = [{ - return 1 + MF.getSubtarget().isThumb1Only(); + if (MF.getSubtarget().isThumb1Only()) + return 2; + if (MF.getSubtarget().isThumb2() && MF.getFunction().optForMinSize()) + return 0; + return 1; }]; let DiagnosticType = "rGPR"; } Index: test/CodeGen/Thumb2/reg-order.ll =================================================================== --- test/CodeGen/Thumb2/reg-order.ll +++ test/CodeGen/Thumb2/reg-order.ll @@ -5,15 +5,15 @@ define i32 @test(i32 %a, i32 %b, i32 %c, i32 %d) #0 { ; CHECK-LABEL: test: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: .save {r7, lr} -; CHECK-NEXT: push {r7, lr} -; CHECK-NEXT: add.w lr, r3, r0 +; CHECK-NEXT: .save {r4, lr} +; CHECK-NEXT: push {r4, lr} +; CHECK-NEXT: adds r4, r3, r0 ; CHECK-NEXT: add.w r12, r2, r1 ; CHECK-NEXT: add r0, r1 ; CHECK-NEXT: adds r1, r3, r2 -; CHECK-NEXT: mul r12, lr, r12 -; CHECK-NEXT: mla r0, r1, r0, r12 -; CHECK-NEXT: pop {r7, pc} +; CHECK-NEXT: mul r4, r4, r12 +; CHECK-NEXT: mla r0, r1, r0, r4 +; CHECK-NEXT: pop {r4, pc} entry: %add = add nsw i32 %b, %a %add1 = add nsw i32 %d, %c @@ -28,40 +28,40 @@ define void @loop(i32 %I, i8* %A, i8* %B) #0 { ; CHECK-LABEL: loop: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: .save {r4, r5, r6, lr} -; CHECK-NEXT: push {r4, r5, r6, lr} +; CHECK-NEXT: .save {r4, r5, r6, r7, lr} +; CHECK-NEXT: push {r4, r5, r6, r7, lr} ; CHECK-NEXT: mov.w r12, #0 ; CHECK-NEXT: b .LBB1_2 ; CHECK-NEXT: .LBB1_1: @ %for.body ; CHECK-NEXT: @ in Loop: Header=BB1_2 Depth=1 -; CHECK-NEXT: add.w r3, r12, r12, lsl #1 -; CHECK-NEXT: add.w lr, r2, r12, lsl #2 -; CHECK-NEXT: add r3, r1 +; CHECK-NEXT: add.w r4, r12, r12, lsl #1 +; CHECK-NEXT: add.w r3, r2, r12, lsl #2 +; CHECK-NEXT: add r4, r1 ; CHECK-NEXT: add.w r12, r12, #1 -; CHECK-NEXT: ldrsb.w r5, [r3, #2] -; CHECK-NEXT: ldrsb.w r4, [r3] -; CHECK-NEXT: mov r6, r5 -; CHECK-NEXT: cmp r4, r5 +; CHECK-NEXT: ldrsb.w r6, [r4, #2] +; CHECK-NEXT: ldrsb.w r5, [r4] +; CHECK-NEXT: mov r7, r6 +; CHECK-NEXT: cmp r5, r6 ; CHECK-NEXT: it gt -; CHECK-NEXT: movgt r6, r4 -; CHECK-NEXT: ldrsb.w r3, [r3, #1] -; CHECK-NEXT: cmp r6, r3 +; CHECK-NEXT: movgt r7, r5 +; CHECK-NEXT: ldrsb.w r4, [r4, #1] +; CHECK-NEXT: cmp r7, r4 ; CHECK-NEXT: it le -; CHECK-NEXT: movle r6, r3 -; CHECK-NEXT: subs r3, r6, r3 -; CHECK-NEXT: subs r5, r6, r5 -; CHECK-NEXT: strb.w r5, [lr, #3] -; CHECK-NEXT: strb.w r3, [lr, #2] -; CHECK-NEXT: subs r3, r6, r4 -; CHECK-NEXT: strb.w r3, [lr, #1] -; CHECK-NEXT: mvns r3, r6 -; CHECK-NEXT: strb.w r3, [lr] +; CHECK-NEXT: movle r7, r4 +; CHECK-NEXT: subs r4, r7, r4 +; CHECK-NEXT: subs r6, r7, r6 +; CHECK-NEXT: strb r6, [r3, #3] +; CHECK-NEXT: strb r4, [r3, #2] +; CHECK-NEXT: subs r4, r7, r5 +; CHECK-NEXT: strb r4, [r3, #1] +; CHECK-NEXT: mvns r4, r7 +; CHECK-NEXT: strb r4, [r3] ; CHECK-NEXT: .LBB1_2: @ %for.cond ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: cmp r12, r0 ; CHECK-NEXT: blt .LBB1_1 ; CHECK-NEXT: @ %bb.3: @ %for.cond.cleanup -; CHECK-NEXT: pop {r4, r5, r6, pc} +; CHECK-NEXT: pop {r4, r5, r6, r7, pc} entry: br label %for.cond