diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -2733,23 +2733,21 @@ static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG) { SDLoc dl(Op); - LoadSDNode *LdNode = dyn_cast(Op.getNode()); - assert(LdNode && LdNode->getOffset().isUndef() - && "Unexpected node type"); + LoadSDNode *LdNode = cast(Op.getNode()); + assert(LdNode->getOffset().isUndef() && "Unexpected node type"); - unsigned alignment = LdNode->getAlignment(); - if (alignment > 8) - alignment = 8; + Align Alignment = commonAlignment(LdNode->getOriginalAlign(), 8); SDValue Hi64 = DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LdNode->getBasePtr(), - LdNode->getPointerInfo(), alignment); + LdNode->getPointerInfo(), Alignment); EVT addrVT = LdNode->getBasePtr().getValueType(); SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, LdNode->getBasePtr(), DAG.getConstant(8, dl, addrVT)); SDValue Lo64 = DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LoPtr, - LdNode->getPointerInfo(), alignment); + LdNode->getPointerInfo().getWithOffset(8), + Alignment); SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32); SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32); @@ -2787,9 +2785,9 @@ // Lower a f128 store into two f64 stores. static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) { SDLoc dl(Op); - StoreSDNode *StNode = dyn_cast(Op.getNode()); - assert(StNode && StNode->getOffset().isUndef() - && "Unexpected node type"); + StoreSDNode *StNode = cast(Op.getNode()); + assert(StNode->getOffset().isUndef() && "Unexpected node type"); + SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32); SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32); @@ -2804,20 +2802,20 @@ StNode->getValue(), SubRegOdd); - unsigned alignment = StNode->getAlignment(); - if (alignment > 8) - alignment = 8; + Align Alignment = commonAlignment(StNode->getOriginalAlign(), 8); SDValue OutChains[2]; OutChains[0] = DAG.getStore(StNode->getChain(), dl, SDValue(Hi64, 0), - StNode->getBasePtr(), MachinePointerInfo(), alignment); + StNode->getBasePtr(), StNode->getPointerInfo(), + Alignment); EVT addrVT = StNode->getBasePtr().getValueType(); SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, StNode->getBasePtr(), DAG.getConstant(8, dl, addrVT)); OutChains[1] = DAG.getStore(StNode->getChain(), dl, SDValue(Lo64, 0), LoPtr, - MachinePointerInfo(), alignment); + StNode->getPointerInfo().getWithOffset(8), + Alignment); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); } @@ -2836,7 +2834,8 @@ SDValue Val = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, St->getValue()); SDValue Chain = DAG.getStore( St->getChain(), dl, Val, St->getBasePtr(), St->getPointerInfo(), - St->getAlignment(), St->getMemOperand()->getFlags(), St->getAAInfo()); + St->getOriginalAlign(), St->getMemOperand()->getFlags(), + St->getAAInfo()); return Chain; } @@ -3402,8 +3401,9 @@ SDLoc dl(N); SDValue LoadRes = DAG.getExtLoad( Ld->getExtensionType(), dl, MVT::v2i32, Ld->getChain(), - Ld->getBasePtr(), Ld->getPointerInfo(), MVT::v2i32, Ld->getAlignment(), - Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); + Ld->getBasePtr(), Ld->getPointerInfo(), MVT::v2i32, + Ld->getOriginalAlign(), Ld->getMemOperand()->getFlags(), + Ld->getAAInfo()); SDValue Res = DAG.getNode(ISD::BITCAST, dl, MVT::i64, LoadRes); Results.push_back(Res); diff --git a/llvm/test/CodeGen/SPARC/fp128-split.ll b/llvm/test/CodeGen/SPARC/fp128-split.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPARC/fp128-split.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -mtriple=sparcv9-unknown-linux -verify-machineinstrs -stop-after=finalize-isel < %s | FileCheck %s + +; Check that the fp128 load/store is correctly split. +; The pointer metadata for the upper/lower halves of the load/store should be in +; sync with the OP address. + +define fp128 @testcase(fp128 %0) { + ; CHECK-LABEL: name: testcase + ; CHECK: bb.0.Entry: + ; CHECK: liveins: $q0 + ; CHECK: [[COPY:%[0-9]+]]:qfpregs = COPY $q0 + ; CHECK: [[COPY1:%[0-9]+]]:dfpregs = COPY [[COPY]].sub_odd64 + ; CHECK: [[LEAX_ADDri:%[0-9]+]]:i64regs = LEAX_ADDri %stack.0, 0 + ; CHECK: [[ORXri:%[0-9]+]]:i64regs = ORXri killed [[LEAX_ADDri]], 8 + ; CHECK: STDFrr [[ORXri]], $g0, killed [[COPY1]] :: (store 8 into %stack.0 + 8) + ; CHECK: [[COPY2:%[0-9]+]]:dfpregs = COPY [[COPY]].sub_even64 + ; CHECK: STDFri %stack.0, 0, killed [[COPY2]] :: (store 8 into %stack.0, align 16) + ; CHECK: [[LDXrr:%[0-9]+]]:i64regs = LDXrr [[ORXri]], $g0 :: (load 8 from %stack.0 + 8) + ; CHECK: [[LDXri:%[0-9]+]]:i64regs = LDXri %stack.0, 0 :: (load 8 from %stack.0, align 16) + ; CHECK: [[COPY3:%[0-9]+]]:intregs = COPY [[LDXrr]] + ; CHECK: [[COPY4:%[0-9]+]]:intregs = COPY [[LDXri]] + ; CHECK: [[SRLXri:%[0-9]+]]:i64regs = SRLXri [[LDXrr]], 32 + ; CHECK: [[COPY5:%[0-9]+]]:intregs = COPY [[SRLXri]] + ; CHECK: [[SRLXri1:%[0-9]+]]:i64regs = SRLXri [[LDXri]], 32 + ; CHECK: [[COPY6:%[0-9]+]]:intregs = COPY [[SRLXri1]] + ; CHECK: [[ADDCCri:%[0-9]+]]:intregs = ADDCCri killed [[COPY3]], -1, implicit-def $icc + ; CHECK: [[ADDEri:%[0-9]+]]:intregs = ADDEri killed [[COPY5]], -1, implicit-def $icc, implicit $icc + ; CHECK: [[ADDEri1:%[0-9]+]]:intregs = ADDEri killed [[COPY4]], -1, implicit-def $icc, implicit $icc + ; CHECK: [[ADDEri2:%[0-9]+]]:intregs = ADDEri killed [[COPY6]], -1, implicit-def dead $icc, implicit $icc + ; CHECK: [[SRLri:%[0-9]+]]:i64regs = SRLri killed [[ADDCCri]], 0 + ; CHECK: [[COPY7:%[0-9]+]]:i64regs = COPY [[ADDEri]] + ; CHECK: [[SLLXri:%[0-9]+]]:i64regs = SLLXri killed [[COPY7]], 32 + ; CHECK: [[ORXrr:%[0-9]+]]:i64regs = ORXrr killed [[SLLXri]], killed [[SRLri]] + ; CHECK: [[LEAX_ADDri1:%[0-9]+]]:i64regs = LEAX_ADDri %stack.1, 0 + ; CHECK: [[ORXri1:%[0-9]+]]:i64regs = ORXri killed [[LEAX_ADDri1]], 8 + ; CHECK: STXrr [[ORXri1]], $g0, killed [[ORXrr]] :: (store 8 into %stack.1 + 8, basealign 16) + ; CHECK: [[SRLri1:%[0-9]+]]:i64regs = SRLri killed [[ADDEri1]], 0 + ; CHECK: [[COPY8:%[0-9]+]]:i64regs = COPY [[ADDEri2]] + ; CHECK: [[SLLXri1:%[0-9]+]]:i64regs = SLLXri killed [[COPY8]], 32 + ; CHECK: [[ORXrr1:%[0-9]+]]:i64regs = ORXrr killed [[SLLXri1]], killed [[SRLri1]] + ; CHECK: STXri %stack.1, 0, killed [[ORXrr1]] :: (store 8 into %stack.1, align 16) + ; CHECK: [[LDDFri:%[0-9]+]]:dfpregs = LDDFri %stack.1, 0 :: (load 8 from %stack.1, align 16) + ; CHECK: [[DEF:%[0-9]+]]:qfpregs = IMPLICIT_DEF + ; CHECK: [[INSERT_SUBREG:%[0-9]+]]:qfpregs = INSERT_SUBREG [[DEF]], killed [[LDDFri]], %subreg.sub_even64 + ; CHECK: [[LDDFrr:%[0-9]+]]:dfpregs = LDDFrr [[ORXri1]], $g0 :: (load 8 from %stack.1 + 8) + ; CHECK: [[INSERT_SUBREG1:%[0-9]+]]:qfpregs = INSERT_SUBREG [[INSERT_SUBREG]], killed [[LDDFrr]], %subreg.sub_odd64 + ; CHECK: $q0 = COPY [[INSERT_SUBREG1]] + ; CHECK: RETL 8, implicit $q0 +Entry: + %1 = bitcast fp128 %0 to i128 + %2 = add i128 %1, -1 + %3 = bitcast i128 %2 to fp128 + ret fp128 %3 +}