Index: lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -956,6 +956,16 @@ cast(OpR->getOperand(1))->getVT() == NewRHS.getValueType()) { NewLHS = OpL; NewRHS = OpR; + // If one operand is sign extension and the other is constant zero, we can + // avoid truncation. + } else if ((OpL->getOpcode() == ISD::AssertSext && + isa(OpR) && + dyn_cast(OpR)->isNullValue()) || + (OpR->getOpcode() == ISD::AssertSext && + isa(OpL) && + dyn_cast(OpL)->isNullValue())) { + NewLHS = OpL; + NewRHS = OpR; } else { NewLHS = ZExtPromotedInteger(NewLHS); NewRHS = ZExtPromotedInteger(NewRHS); Index: test/CodeGen/AArch64/arm64-shrink-wrapping.ll =================================================================== --- test/CodeGen/AArch64/arm64-shrink-wrapping.ll +++ test/CodeGen/AArch64/arm64-shrink-wrapping.ll @@ -508,8 +508,7 @@ ; CHECK-LABEL: noreturn: ; DISABLE: stp ; -; CHECK: and [[TEST:w[0-9]+]], w0, #0xff -; CHECK-NEXT: cbnz [[TEST]], [[ABORT:LBB[0-9_]+]] +; CHECK: cbnz w0, [[ABORT:LBB[0-9_]+]] ; ; CHECK: mov w0, #42 ; Index: test/CodeGen/ARM/arm-shrink-wrapping.ll =================================================================== --- test/CodeGen/ARM/arm-shrink-wrapping.ll +++ test/CodeGen/ARM/arm-shrink-wrapping.ll @@ -501,9 +501,13 @@ ; ; CHECK-LABEL: noreturn: ; DISABLE: push -; -; CHECK: tst{{(\.w)?}} r0, #255 -; CHECK-NEXT: bne [[ABORT:LBB[0-9_]+]] +; ARM-ENABLE: cmp r0, #0 +; ARM-DISABLE: cmp r0, #0 +; ARM-ENABLE: bne [[ABORT:LBB[0-9_]+]] +; ARM-DISABLE: bne [[ABORT:LBB[0-9_]+]] +; THUMB-ENABLE: cbnz r0, [[ABORT:LBB[0-9_]+]] +; THUMB-DISABLE: cbnz r0, [[ABORT:LBB[0-9_]+]] + ; ; CHECK: mov{{s?}} r0, #42 ; Index: test/CodeGen/ARM/interrupt-attr.ll =================================================================== --- test/CodeGen/ARM/interrupt-attr.ll +++ test/CodeGen/ARM/interrupt-attr.ll @@ -49,6 +49,48 @@ ret void } +define arm_aapcscc void @irq_fn_tailcall() alignstack(8) "interrupt"="IRQ" { + ; Must save all registers except banked sp and lr (we save lr anyway because + ; we actually need it at the end to execute the return ourselves). + + ; Also need special function return setting pc and CPSR simultaneously. +; CHECK-A-LABEL: irq_fn_tailcall: +; CHECK-A: push {r0, r1, r2, r3, r10, r11, r12, lr} +; CHECK-A: add r11, sp, #20 +; CHECK-A-NOT: sub sp, sp, #{{[0-9]+}} +; CHECK-A: bfc sp, #0, #3 +; CHECK-A: bl bar +; CHECK-A: sub sp, r11, #20 +; CHECK-A: pop {r0, r1, r2, r3, r10, r11, r12, lr} +; CHECK-A: subs pc, lr, #4 + +; CHECK-A-THUMB-LABEL: irq_fn_tailcall: +; CHECK-A-THUMB: push.w {r0, r1, r2, r3, r4, r7, r12, lr} +; CHECK-A-THUMB: add r7, sp, #20 +; CHECK-A-THUMB: mov r4, sp +; CHECK-A-THUMB: bfc r4, #0, #3 +; CHECK-A-THUMB: bl bar +; CHECK-A-THUMB: sub.w r4, r7, #20 +; CHECK-A-THUMB: mov sp, r4 +; CHECK-A-THUMB: pop.w {r0, r1, r2, r3, r4, r7, r12, lr} +; CHECK-A-THUMB: subs pc, lr, #4 + + ; Normal AAPCS function (r0-r3 pushed onto stack by hardware, lr set to + ; appropriate sentinel so no special return needed). +; CHECK-M-LABEL: irq_fn_tailcall: +; CHECK-M: push {r4, r6, r7, lr} +; CHECK-M: add r7, sp, #8 +; CHECK-M: mov r4, sp +; CHECK-M: bfc r4, #0, #3 +; CHECK-M: mov sp, r4 +; CHECK-M: sub.w r4, r7, #8 +; CHECK-M: mov sp, r4 +; CHECK-M: pop.w {r4, r6, r7, lr} +; CHECK-M: b.w _bar + + tail call arm_aapcscc void @bar() + ret void +} ; We don't push/pop r12, as it is banked for FIQ define arm_aapcscc void @fiq_fn() alignstack(8) "interrupt"="FIQ" { ; CHECK-A-LABEL: fiq_fn: Index: test/CodeGen/Thumb/thumb-shrink-wrapping.ll =================================================================== --- test/CodeGen/Thumb/thumb-shrink-wrapping.ll +++ test/CodeGen/Thumb/thumb-shrink-wrapping.ll @@ -571,8 +571,7 @@ ; CHECK-LABEL: noreturn: ; DISABLE: push ; -; CHECK: movs [[TMP:r[0-9]+]], #255 -; CHECK-NEXT: tst r0, [[TMP]] +; CHECK: cmp r0, #0 ; CHECK-NEXT: bne [[ABORT:LBB[0-9_]+]] ; ; CHECK: movs r0, #42