From: Evan Cheng Date: Tue, 21 Jul 2009 00:31:12 +0000 (+0000) Subject: Fix ARM isle code that optimize multiply by constants which are power-of-2 +/- 1. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=af9e7a7c20d541cfaaaed9dfa21046ac6652cc03;p=oota-llvm.git Fix ARM isle code that optimize multiply by constants which are power-of-2 +/- 1. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76520 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index 95ed887ef6d..c943baf75d9 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -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; diff --git a/test/CodeGen/ARM/mul_const.ll b/test/CodeGen/ARM/mul_const.ll new file mode 100644 index 00000000000..f5ace1852a4 --- /dev/null +++ b/test/CodeGen/ARM/mul_const.ll @@ -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 +} diff --git a/test/CodeGen/Thumb2/mul_const.ll b/test/CodeGen/Thumb2/mul_const.ll new file mode 100644 index 00000000000..ca0ede45eb2 --- /dev/null +++ b/test/CodeGen/Thumb2/mul_const.ll @@ -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 +}