diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -5158,7 +5158,8 @@ unsigned TOCSaveOffset = Subtarget.getFrameLowering()->getTOCSaveOffset(); unsigned StackOffset = MI.getOperand(1).getImm(); Register StackReg = MI.getOperand(2).getReg(); - if (StackReg == PPC::X1 && StackOffset == TOCSaveOffset) + Register SPReg = Subtarget.isPPC64() ? PPC::X1 : PPC::R1; + if (StackReg == SPReg && StackOffset == TOCSaveOffset) return true; return false; diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp --- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp +++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp @@ -226,28 +226,30 @@ void PPCMIPeephole::UpdateTOCSaves( std::map &TOCSaves, MachineInstr *MI) { assert(TII->isTOCSaveMI(*MI) && "Expecting a TOC save instruction here"); - assert(MF->getSubtarget().isELFv2ABI() && - "TOC-save removal only supported on ELFv2"); - PPCFunctionInfo *FI = MF->getInfo(); - - MachineBasicBlock *Entry = &MF->front(); - uint64_t CurrBlockFreq = MBFI->getBlockFreq(MI->getParent()).getFrequency(); - - // If the block in which the TOC save resides is in a block that - // post-dominates Entry, or a block that is hotter than entry (keep in mind - // that early MachineLICM has already run so the TOC save won't be hoisted) - // we can just do the save in the prologue. - if (CurrBlockFreq > EntryFreq || MPDT->dominates(MI->getParent(), Entry)) - FI->setMustSaveTOC(true); - - // If we are saving the TOC in the prologue, all the TOC saves can be removed - // from the code. - if (FI->mustSaveTOC()) { - for (auto &TOCSave : TOCSaves) - TOCSave.second = false; - // Add new instruction to map. - TOCSaves[MI] = false; - return; + // FIXME: Saving TOC in prologue hasn't been implemented well in AIX ABI part, + // here only support it under ELFv2. + if (MF->getSubtarget().isELFv2ABI()) { + PPCFunctionInfo *FI = MF->getInfo(); + + MachineBasicBlock *Entry = &MF->front(); + uint64_t CurrBlockFreq = MBFI->getBlockFreq(MI->getParent()).getFrequency(); + + // If the block in which the TOC save resides is in a block that + // post-dominates Entry, or a block that is hotter than entry (keep in mind + // that early MachineLICM has already run so the TOC save won't be hoisted) + // we can just do the save in the prologue. + if (CurrBlockFreq > EntryFreq || MPDT->dominates(MI->getParent(), Entry)) + FI->setMustSaveTOC(true); + + // If we are saving the TOC in the prologue, all the TOC saves can be + // removed from the code. + if (FI->mustSaveTOC()) { + for (auto &TOCSave : TOCSaves) + TOCSave.second = false; + // Add new instruction to map. + TOCSaves[MI] = false; + return; + } } bool Keep = true; @@ -476,10 +478,12 @@ } break; } + case PPC::STW: case PPC::STD: { MachineFrameInfo &MFI = MF->getFrameInfo(); if (MFI.hasVarSizedObjects() || - !MF->getSubtarget().isELFv2ABI()) + (!MF->getSubtarget().isELFv2ABI() && + !MF->getSubtarget().isAIXABI())) break; // When encountering a TOC save instruction, call UpdateTOCSaves // to add it to the TOCSaves map and mark any existing TOC saves diff --git a/llvm/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll b/llvm/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll --- a/llvm/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll +++ b/llvm/test/CodeGen/PowerPC/remove-redundant-toc-saves.ll @@ -1,9 +1,20 @@ ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix-xcoff < %s | FileCheck %s --check-prefix=AIX +; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix-xcoff < %s | FileCheck %s --check-prefix=AIX32 + define signext i32 @test1(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) { entry: ; CHECK-LABEL: test1: ; CHECK: std 2, 24(1) ; CHECK-NOT: std 2, 24(1) + +; AIX-LABEL: test1: +; AIX: std 2, 40(1) +; AIX-NOT: std 2, 40(1) + +; AIX32-LABEL: test1: +; AIX32: stw 2, 20(1) +; AIX32-NOT: std 2, 20(1) %call = tail call signext i32 %Func(i32 signext %i) %call1 = tail call signext i32 %Func2(i32 signext %i) %add2 = add nsw i32 %call1, %call @@ -15,6 +26,14 @@ ; CHECK-LABEL: test2: ; CHECK: std 2, 24(1) ; CHECK-NOT: std 2, 24(1) + +; AIX-LABEL: test2: +; AIX: std 2, 40(1) +; AIX-NOT: std 2, 40(1) + +; AIX32-LABEL: test2: +; AIX32: stw 2, 20(1) +; AIX32-NOT: std 2, 20(1) %call = tail call signext i32 %Func(i32 signext %i) %tobool = icmp eq i32 %j, 0 br i1 %tobool, label %if.end, label %if.then @@ -38,6 +57,12 @@ ; CHECK-LABEL: test3: ; CHECK: std 2, 24(1) ; CHECK-NOT: std 2, 24(1) + +; AIX-LABEL: test3: +; AIX-COUNT-3: std 2, 40(1) + +; AIX32-LABEL: test3: +; AIX32-COUNT-3: stw 2, 20(1) entry: %tobool = icmp eq i32 %i, 0 br i1 %tobool, label %if.else, label %if.then @@ -62,6 +87,13 @@ ; CHECK: std 2, 24(1) ; CHECK-NOT: std 2, 24(1) +; AIX-LABEL: test4: +; AIX: std 2, 40(1) +; AIX-NOT: std 2, 40(1) + +; AIX32-LABEL: test4: +; AIX32: stw 2, 20(1) +; AIX32-NOT: std 2, 20(1) entry: %call = tail call signext i32 %Func(i32 signext %i) %tobool = icmp eq i32 %i, 0 @@ -87,6 +119,11 @@ ; CHECK-LABEL: test5: ; CHECK: std 2, 24(1) +; AIX-LABEL: test5: +; AIX: std 2, 40(1) + +; AIX32-LABEL: test5: +; AIX32: stw 2, 20(1) %tobool = icmp eq i32 %i, 0 br i1 %tobool, label %if.end, label %if.then @@ -108,6 +145,13 @@ ; CHECK: std 2, 24(1) ; CHECK: std 2, 24(1) +; AIX-LABEL: test6: +; AIX: std 2, 40(1) +; AIX: std 2, 40(1) + +; AIX32-LABEL: test6: +; AIX32: stw 2, 20(1) +; AIX32: stw 2, 20(1) %conv = sext i32 %i to i64 %0 = alloca i8, i64 %conv, align 16 %1 = bitcast i8* %0 to i32*