Fix ARM isle code that optimize multiply by constants which are power-of-2 +/- 1.

llvm-svn: 76520
This commit is contained in:
Evan Cheng 2009-07-21 00:31:12 +00:00
parent 9a47392f2e
commit 0d8b0cf3b8
3 changed files with 61 additions and 16 deletions

View File

@ -949,26 +949,36 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
unsigned RHSV = C->getZExtValue();
if (!RHSV) break;
if (isPowerOf2_32(RHSV-1)) { // 2^n+1?
unsigned ShImm = Log2_32(RHSV-1);
if (ShImm >= 32)
break;
SDValue V = Op.getOperand(0);
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1));
SDValue Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
CurDAG->getTargetConstant(ShImm, MVT::i32),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
return CurDAG->SelectNodeTo(N, (Subtarget->isThumb() &&
Subtarget->hasThumb2()) ?
ARM::t2ADDrs : ARM::ADDrs, MVT::i32, Ops, 7);
ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
SDValue ShImmOp = CurDAG->getConstant(ShImm, MVT::i32);
SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6);
} else {
SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7);
}
}
if (isPowerOf2_32(RHSV+1)) { // 2^n-1?
unsigned ShImm = Log2_32(RHSV+1);
if (ShImm >= 32)
break;
SDValue V = Op.getOperand(0);
unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1));
SDValue Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32),
CurDAG->getTargetConstant(ShImm, MVT::i32),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
return CurDAG->SelectNodeTo(N, (Subtarget->isThumb() &&
Subtarget->hasThumb2()) ?
ARM::t2RSBrs : ARM::RSBrs, MVT::i32, Ops, 7);
ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm);
SDValue ShImmOp = CurDAG->getConstant(ShImm, MVT::i32);
SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
if (Subtarget->isThumb() && Subtarget->hasThumb2()) {
SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0 };
return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 5);
} else {
SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 };
return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7);
}
}
}
break;

View File

@ -0,0 +1,17 @@
; RUN: llvm-as < %s | llc -march=arm | FileCheck %s
define i32 @t1(i32 %v) nounwind readnone {
entry:
; CHECK: t1:
; CHECK: add r0, r0, r0, lsl #3
%0 = mul i32 %v, 9
ret i32 %0
}
define i32 @t2(i32 %v) nounwind readnone {
entry:
; CHECK: t2:
; CHECK: rsb r0, r0, r0, lsl #3
%0 = mul i32 %v, 7
ret i32 %0
}

View File

@ -0,0 +1,18 @@
; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | FileCheck %s
; rdar://7069502
define i32 @t1(i32 %v) nounwind readnone {
entry:
; CHECK: t1:
; CHECK: add r0, r0, r0, lsl #3
%0 = mul i32 %v, 9
ret i32 %0
}
define i32 @t2(i32 %v) nounwind readnone {
entry:
; CHECK: t2:
; CHECK: rsb r0, r0, r0, lsl #3
%0 = mul i32 %v, 7
ret i32 %0
}