Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -795,7 +795,7 @@ SDValue And0 = N->getOperand(0), And1 = N->getOperand(1); uint64_t SMPos0, SMSize0, SMPos1, SMSize1; - ConstantSDNode *CN; + ConstantSDNode *CN, *CN1; // See if Op's first operand matches (and $src1 , mask0). if (And0.getOpcode() != ISD::AND) @@ -805,9 +805,10 @@ !isShiftedMask(~CN->getSExtValue(), SMPos0, SMSize0)) return SDValue(); + // See if Op's second operand matches (and (shl $src, pos), mask1). - if (And1.getOpcode() != ISD::AND) - return SDValue(); + if (And1.getOpcode() == ISD::AND && + And1.getOperand(0).getOpcode() == ISD::SHL) { if (!(CN = dyn_cast(And1.getOperand(1))) || !isShiftedMask(CN->getZExtValue(), SMPos1, SMSize1)) @@ -837,6 +838,40 @@ DAG.getConstant(SMPos0, DL, MVT::i32), DAG.getConstant(SMSize0, DL, MVT::i32), And0.getOperand(0)); + } else { + // Pattern match DINS + // $dst = or (and $src, mask0), mask1 + // where mask0 = ((1 << SMSize0) -1) << SMPos0 + // dins $dst, $src, pos, size + if (~CN->getSExtValue() == ((((int64_t) 1 << SMSize0) -1 ) << SMPos0) + && SMSize0 + SMPos0 <= 64) { + // Check if AND instruction has constant as argument + bool isConstCase = And1.getOpcode() != ISD::AND; + if (And1.getOpcode() == ISD::AND) { + if (!(CN1 = dyn_cast(And1->getOperand(1)))) + return SDValue(); + } else { + if (!(CN1 = dyn_cast(N->getOperand(1)))) + return SDValue(); + } + SDLoc DL(N); + EVT ValTy = N->getOperand(0)->getValueType(0); + SDValue Const1; + SDValue SrlX; + if (!isConstCase) { + Const1 = DAG.getConstant(SMPos0, DL, MVT::i32); + SrlX = DAG.getNode(ISD::SRL, DL, And1->getValueType(0), And1, Const1); + } + return DAG.getNode(MipsISD::Ins, DL, N->getValueType(0), + isConstCase ? + DAG.getConstant(CN1->getSExtValue() >> SMPos0, + DL, ValTy) : SrlX, + DAG.getConstant(SMPos0, DL, MVT::i32), + DAG.getConstant(SMSize0, DL, MVT::i32), + And0->getOperand(0)); + } + return SDValue(); + } } static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, Index: test/CodeGen/Mips/dins.ll =================================================================== --- test/CodeGen/Mips/dins.ll +++ test/CodeGen/Mips/dins.ll @@ -0,0 +1,63 @@ +; RUN: llc -O2 -march=mips64 -mcpu=mips64r2 -target-abi=n64 < %s -o - | FileCheck %s + +; #include +; #include +; struct cvmx_buf_ptr { + +; struct { +; unsigned long long addr :37; +; unsigned long long addr1 :15; +; unsigned int lenght:14; +; uint64_t total_bytes:16; +; uint64_t segs : 6; +; } s; +; } +; +; unsigned long long foo(volatile struct cvmx_buf_ptr bufptr) { +; bufptr.s.addr = 123; +; bufptr.s.segs = 4; +; bufptr.s.lenght = 5; +; bufptr.s.total_bytes = bufptr.s.lenght; +; return bufptr.s.addr; +; } + + +define i64 @f123(i64 inreg %bufptr.coerce0, i64 inreg %bufptr.coerce1) local_unnamed_addr #0 { +entry: + %bufptr.sroa.0 = alloca i64, align 8 + %bufptr.sroa.4 = alloca i64, align 8 + store i64 %bufptr.coerce0, i64* %bufptr.sroa.0, align 8 + store i64 %bufptr.coerce1, i64* %bufptr.sroa.4, align 8 + %bufptr.sroa.0.0.bufptr.sroa.0.0.bufptr.sroa.0.0.bf.load = load volatile i64, i64* %bufptr.sroa.0, align 8 + %bf.clear = and i64 %bufptr.sroa.0.0.bufptr.sroa.0.0.bufptr.sroa.0.0.bf.load, 134217727 + %bf.set = or i64 %bf.clear, 16508780544 + store volatile i64 %bf.set, i64* %bufptr.sroa.0, align 8 + %bufptr.sroa.4.0.bufptr.sroa.4.0.bufptr.sroa.4.8.bf.load2 = load volatile i64, i64* %bufptr.sroa.4, align 8 + %bf.clear3 = and i64 %bufptr.sroa.4.0.bufptr.sroa.4.0.bufptr.sroa.4.8.bf.load2, -16911433729 + %bf.set4 = or i64 %bf.clear3, 1073741824 + store volatile i64 %bf.set4, i64* %bufptr.sroa.4, align 8 + %bufptr.sroa.4.0.bufptr.sroa.4.0.bufptr.sroa.4.8.bf.load6 = load volatile i64, i64* %bufptr.sroa.4, align 8 + %bf.clear7 = and i64 %bufptr.sroa.4.0.bufptr.sroa.4.0.bufptr.sroa.4.8.bf.load6, 1125899906842623 + %bf.set8 = or i64 %bf.clear7, 5629499534213120 + store volatile i64 %bf.set8, i64* %bufptr.sroa.4, align 8 + %bufptr.sroa.4.0.bufptr.sroa.4.0.bufptr.sroa.4.8.bf.load11 = load volatile i64, i64* %bufptr.sroa.4, align 8 + %bf.lshr = lshr i64 %bufptr.sroa.4.0.bufptr.sroa.4.0.bufptr.sroa.4.8.bf.load11, 50 + %bufptr.sroa.4.0.bufptr.sroa.4.0.bufptr.sroa.4.8.bf.load13 = load volatile i64, i64* %bufptr.sroa.4, align 8 + %bf.shl = shl nuw nsw i64 %bf.lshr, 34 + %bf.clear14 = and i64 %bufptr.sroa.4.0.bufptr.sroa.4.0.bufptr.sroa.4.8.bf.load13, -1125882726973441 + %bf.set15 = or i64 %bf.clear14, %bf.shl + store volatile i64 %bf.set15, i64* %bufptr.sroa.4, align 8 + %bufptr.sroa.0.0.bufptr.sroa.0.0.bufptr.sroa.0.0.bf.load17 = load volatile i64, i64* %bufptr.sroa.0, align 8 + %bf.lshr18 = lshr i64 %bufptr.sroa.0.0.bufptr.sroa.0.0.bufptr.sroa.0.0.bf.load17, 27 + ret i64 %bf.lshr18 +} + + +; CHECK: daddiu $[[R0:[0-9]+]], $zero, 123 +; CHECK: dins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 27, 37 +; CHECK: daddiu $[[R0:[0-9]+]], $zero, 5 +; CHECK: daddiu $[[R0:[0-9]+]], $zero, 4 +; CHECK: dins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 28, 6 +; CHECK: dins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 50, 14 +; CHECK: dsrl $[[R0:[0-9]+]], $[[R1:[0-9]+]], 50 +; CHECK: dins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 34, 16 \ No newline at end of file Index: test/CodeGen/Mips/mips64-f128.ll =================================================================== --- test/CodeGen/Mips/mips64-f128.ll +++ test/CodeGen/Mips/mips64-f128.ll @@ -418,18 +418,16 @@ declare fp128 @llvm.powi.f128(fp128, i32) #3 ; ALL-LABEL: libcall2_copysignl: -; ALL-DAG: daddiu $[[R2:[0-9]+]], $zero, 1 -; ALL-DAG: dsll $[[R3:[0-9]+]], $[[R2]], 63 +; NOT-R2R6-DAG: daddiu $[[R2:[0-9]+]], $zero, 1 +; NOT-R2R6-DAG: dsll $[[R3:[0-9]+]], $[[R2]], 63 ; ALL-DAG: ld $[[R0:[0-9]+]], %got_disp(gld1) ; ALL-DAG: ld $[[R1:[0-9]+]], 8($[[R0]]) -; ALL-DAG: and $[[R4:[0-9]+]], $[[R1]], $[[R3]] +; NOT-R2R6-DAG: and $[[R4:[0-9]+]], $[[R1]], $[[R3]] ; ALL-DAG: ld $[[R5:[0-9]+]], %got_disp(gld0) ; ALL-DAG: ld $[[R6:[0-9]+]], 8($[[R5]]) ; NOT-R2R6-DAG: daddiu $[[R7:[0-9]+]], $[[R3]], -1 ; NOT-R2R6-DAG: and $[[R8:[0-9]+]], $[[R6]], $[[R7]] ; NOT-R2R6-DAG: or $4, $[[R8]], $[[R4]] -; R2R6-DAG: dextm $[[R7:[0-9]+]], $[[R6]], 0, 63 -; R2R6-DAG: or $4, $[[R7]], $[[R4]] ; ALL-DAG: ld $2, 0($[[R5]]) define fp128 @libcall2_copysignl() {