forked from OSchip/llvm-project
[AArch64] Implement target hook function to decide folding (mul (add x, c1), c2)
Prevent the folding if it leads to worse code. Reviewed By: dmgreen Differential Revision: https://reviews.llvm.org/D108871
This commit is contained in:
parent
1ece14b652
commit
095bea23d0
|
@ -12189,6 +12189,33 @@ bool AArch64TargetLowering::isLegalAddImmediate(int64_t Immed) const {
|
|||
return IsLegal;
|
||||
}
|
||||
|
||||
// Return false to prevent folding
|
||||
// (mul (add x, c1), c2) -> (add (mul x, c2), c2*c1) in DAGCombine,
|
||||
// if the folding leads to worse code.
|
||||
bool AArch64TargetLowering::isMulAddWithConstProfitable(
|
||||
const SDValue &AddNode, const SDValue &ConstNode) const {
|
||||
// Let the DAGCombiner decide for vector types and large types.
|
||||
const EVT VT = AddNode.getValueType();
|
||||
if (VT.isVector() || VT.getScalarSizeInBits() > 64)
|
||||
return true;
|
||||
|
||||
// It is worse if c1 is legal add immediate, while c1*c2 is not
|
||||
// and has to be composed by at least two instructions.
|
||||
const ConstantSDNode *C1Node = cast<ConstantSDNode>(AddNode.getOperand(1));
|
||||
const ConstantSDNode *C2Node = cast<ConstantSDNode>(ConstNode);
|
||||
const int64_t C1 = C1Node->getSExtValue();
|
||||
const int64_t C2 = C2Node->getSExtValue();
|
||||
if (!isLegalAddImmediate(C1) || isLegalAddImmediate(C1 * C2))
|
||||
return true;
|
||||
SmallVector<AArch64_IMM::ImmInsnModel, 4> Insn;
|
||||
AArch64_IMM::expandMOVImm(C1 * C2, VT.getSizeInBits(),Insn);
|
||||
if (Insn.size() > 1)
|
||||
return false;
|
||||
|
||||
// Default to true and let the DAGCombiner decide.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Integer comparisons are implemented with ADDS/SUBS, so the range of valid
|
||||
// immediates is the same as for an add or a sub.
|
||||
bool AArch64TargetLowering::isLegalICmpImmediate(int64_t Immed) const {
|
||||
|
|
|
@ -595,6 +595,9 @@ public:
|
|||
bool isLegalAddImmediate(int64_t) const override;
|
||||
bool isLegalICmpImmediate(int64_t) const override;
|
||||
|
||||
bool isMulAddWithConstProfitable(const SDValue &AddNode,
|
||||
const SDValue &ConstNode) const override;
|
||||
|
||||
bool shouldConsiderGEPOffsetSplit() const override;
|
||||
|
||||
EVT getOptimalMemOpType(const MemOp &Op,
|
||||
|
|
|
@ -104,10 +104,9 @@ define signext i32 @addimm_mulimm_accept_13(i32 signext %a) {
|
|||
define i64 @addimm_mulimm_reject_00(i64 %a) {
|
||||
; CHECK-LABEL: addimm_mulimm_reject_00:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: mov w9, #1200
|
||||
; CHECK-NEXT: mov w8, #3700
|
||||
; CHECK-NEXT: movk w9, #175, lsl #16
|
||||
; CHECK-NEXT: madd x0, x0, x8, x9
|
||||
; CHECK-NEXT: add x8, x0, #3100
|
||||
; CHECK-NEXT: mov w9, #3700
|
||||
; CHECK-NEXT: mul x0, x8, x9
|
||||
; CHECK-NEXT: ret
|
||||
%tmp0 = add i64 %a, 3100
|
||||
%tmp1 = mul i64 %tmp0, 3700
|
||||
|
@ -117,10 +116,9 @@ define i64 @addimm_mulimm_reject_00(i64 %a) {
|
|||
define i64 @addimm_mulimm_reject_01(i64 %a) {
|
||||
; CHECK-LABEL: addimm_mulimm_reject_01:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: mov x9, #-1200
|
||||
; CHECK-NEXT: mov w8, #3700
|
||||
; CHECK-NEXT: movk x9, #65360, lsl #16
|
||||
; CHECK-NEXT: madd x0, x0, x8, x9
|
||||
; CHECK-NEXT: sub x8, x0, #3100
|
||||
; CHECK-NEXT: mov w9, #3700
|
||||
; CHECK-NEXT: mul x0, x8, x9
|
||||
; CHECK-NEXT: ret
|
||||
%tmp0 = add i64 %a, -3100
|
||||
%tmp1 = mul i64 %tmp0, 3700
|
||||
|
@ -130,10 +128,9 @@ define i64 @addimm_mulimm_reject_01(i64 %a) {
|
|||
define signext i32 @addimm_mulimm_reject_02(i32 signext %a) {
|
||||
; CHECK-LABEL: addimm_mulimm_reject_02:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: mov w9, #1200
|
||||
; CHECK-NEXT: mov w8, #3700
|
||||
; CHECK-NEXT: movk w9, #175, lsl #16
|
||||
; CHECK-NEXT: madd w0, w0, w8, w9
|
||||
; CHECK-NEXT: add w8, w0, #3100
|
||||
; CHECK-NEXT: mov w9, #3700
|
||||
; CHECK-NEXT: mul w0, w8, w9
|
||||
; CHECK-NEXT: ret
|
||||
%tmp0 = add i32 %a, 3100
|
||||
%tmp1 = mul i32 %tmp0, 3700
|
||||
|
@ -143,10 +140,9 @@ define signext i32 @addimm_mulimm_reject_02(i32 signext %a) {
|
|||
define signext i32 @addimm_mulimm_reject_03(i32 signext %a) {
|
||||
; CHECK-LABEL: addimm_mulimm_reject_03:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: mov w9, #64336
|
||||
; CHECK-NEXT: mov w8, #3700
|
||||
; CHECK-NEXT: movk w9, #65360, lsl #16
|
||||
; CHECK-NEXT: madd w0, w0, w8, w9
|
||||
; CHECK-NEXT: sub w8, w0, #3100
|
||||
; CHECK-NEXT: mov w9, #3700
|
||||
; CHECK-NEXT: mul w0, w8, w9
|
||||
; CHECK-NEXT: ret
|
||||
%tmp0 = add i32 %a, -3100
|
||||
%tmp1 = mul i32 %tmp0, 3700
|
||||
|
|
|
@ -154,11 +154,10 @@ define i1 @t32_6_3(i32 %X) nounwind {
|
|||
define i1 @t32_6_4(i32 %X) nounwind {
|
||||
; CHECK-LABEL: t32_6_4:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: mov w8, #43691
|
||||
; CHECK-NEXT: mov w9, #21844
|
||||
; CHECK-NEXT: movk w8, #43690, lsl #16
|
||||
; CHECK-NEXT: movk w9, #21845, lsl #16
|
||||
; CHECK-NEXT: madd w8, w0, w8, w9
|
||||
; CHECK-NEXT: mov w9, #43691
|
||||
; CHECK-NEXT: sub w8, w0, #4
|
||||
; CHECK-NEXT: movk w9, #43690, lsl #16
|
||||
; CHECK-NEXT: mul w8, w8, w9
|
||||
; CHECK-NEXT: mov w9, #43690
|
||||
; CHECK-NEXT: ror w8, w8, #1
|
||||
; CHECK-NEXT: movk w9, #10922, lsl #16
|
||||
|
@ -173,11 +172,10 @@ define i1 @t32_6_4(i32 %X) nounwind {
|
|||
define i1 @t32_6_5(i32 %X) nounwind {
|
||||
; CHECK-LABEL: t32_6_5:
|
||||
; CHECK: // %bb.0:
|
||||
; CHECK-NEXT: mov w8, #43691
|
||||
; CHECK-NEXT: mov w9, #43689
|
||||
; CHECK-NEXT: movk w8, #43690, lsl #16
|
||||
; CHECK-NEXT: mov w9, #43691
|
||||
; CHECK-NEXT: sub w8, w0, #5
|
||||
; CHECK-NEXT: movk w9, #43690, lsl #16
|
||||
; CHECK-NEXT: madd w8, w0, w8, w9
|
||||
; CHECK-NEXT: mul w8, w8, w9
|
||||
; CHECK-NEXT: mov w9, #43690
|
||||
; CHECK-NEXT: ror w8, w8, #1
|
||||
; CHECK-NEXT: movk w9, #10922, lsl #16
|
||||
|
|
Loading…
Reference in New Issue