[llvm-branch-commits] [llvm] f2ce10d - [PowerPC] Handle inline assembly clobber of link regsiter
Tom Stellard via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jun 3 21:17:23 PDT 2021
Author: Stefan Pintilie
Date: 2021-06-03T21:16:41-07:00
New Revision: f2ce10d14b7c07b93b7726615aeb40ad04837a88
URL: https://github.com/llvm/llvm-project/commit/f2ce10d14b7c07b93b7726615aeb40ad04837a88
DIFF: https://github.com/llvm/llvm-project/commit/f2ce10d14b7c07b93b7726615aeb40ad04837a88.diff
LOG: [PowerPC] Handle inline assembly clobber of link regsiter
This patch adds the handling of clobbers of the link register LR for inline
assembly.
This patch is to fix:
https://bugs.llvm.org/show_bug.cgi?id=50147
Reviewed By: nemanjai, #powerpc
Differential Revision: https://reviews.llvm.org/D101657
(cherry picked from commit 15051f0b4a2e0a0af9da7cd5e5cfaabb9f6aaa3d)
Added:
llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll
Modified:
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/lib/Target/PowerPC/PPCISelLowering.h
llvm/lib/Target/PowerPC/PPCRegisterInfo.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 929a72ac687eb..7833bfc1d1b6e 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -167,6 +167,10 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
// Sub-word ATOMIC_CMP_SWAP need to ensure that the input is zero-extended.
setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Custom);
+ // Custom lower inline assembly to check for special registers.
+ setOperationAction(ISD::INLINEASM, MVT::Other, Custom);
+ setOperationAction(ISD::INLINEASM_BR, MVT::Other, Custom);
+
// PowerPC has an i16 but no i8 (or i1) SEXTLOAD.
for (MVT VT : MVT::integer_valuetypes()) {
setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
@@ -3461,6 +3465,57 @@ SDValue PPCTargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
return Op.getOperand(0);
}
+SDValue PPCTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ PPCFunctionInfo &MFI = *MF.getInfo<PPCFunctionInfo>();
+
+ assert((Op.getOpcode() == ISD::INLINEASM ||
+ Op.getOpcode() == ISD::INLINEASM_BR) &&
+ "Expecting Inline ASM node.");
+
+ // If an LR store is already known to be required then there is not point in
+ // checking this ASM as well.
+ if (MFI.isLRStoreRequired())
+ return Op;
+
+ // Inline ASM nodes have an optional last operand that is an incoming Flag of
+ // type MVT::Glue. We want to ignore this last operand if that is the case.
+ unsigned NumOps = Op.getNumOperands();
+ if (Op.getOperand(NumOps - 1).getValueType() == MVT::Glue)
+ --NumOps;
+
+ // Check all operands that may contain the LR.
+ for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
+ unsigned Flags = cast<ConstantSDNode>(Op.getOperand(i))->getZExtValue();
+ unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
+ ++i; // Skip the ID value.
+
+ switch (InlineAsm::getKind(Flags)) {
+ default:
+ llvm_unreachable("Bad flags!");
+ case InlineAsm::Kind_RegUse:
+ case InlineAsm::Kind_Imm:
+ case InlineAsm::Kind_Mem:
+ i += NumVals;
+ break;
+ case InlineAsm::Kind_Clobber:
+ case InlineAsm::Kind_RegDef:
+ case InlineAsm::Kind_RegDefEarlyClobber: {
+ for (; NumVals; --NumVals, ++i) {
+ Register Reg = cast<RegisterSDNode>(Op.getOperand(i))->getReg();
+ if (Reg != PPC::LR && Reg != PPC::LR8)
+ continue;
+ MFI.setLRStoreRequired();
+ return Op;
+ }
+ break;
+ }
+ }
+ }
+
+ return Op;
+}
+
SDValue PPCTargetLowering::LowerINIT_TRAMPOLINE(SDValue Op,
SelectionDAG &DAG) const {
if (Subtarget.isAIXABI())
@@ -10316,6 +10371,8 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG);
+ case ISD::INLINEASM:
+ case ISD::INLINEASM_BR: return LowerINLINEASM(Op, DAG);
// Variable argument lowering.
case ISD::VASTART: return LowerVASTART(Op, DAG);
case ISD::VAARG: return LowerVAARG(Op, DAG);
@@ -15090,6 +15147,11 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
return std::make_pair(0U, &PPC::VSSRCRegClass);
else
return std::make_pair(0U, &PPC::VSFRCRegClass);
+ } else if (Constraint == "lr") {
+ if (VT == MVT::i64)
+ return std::make_pair(0U, &PPC::LR8RCRegClass);
+ else
+ return std::make_pair(0U, &PPC::LRRCRegClass);
}
// If we name a VSX register, we can't defer to the base class because it
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 0dda2c1815722..836c52bdff954 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -1128,6 +1128,7 @@ namespace llvm {
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index e03617aa75fff..45d60369018bf 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -409,6 +409,13 @@ def CTRRC8 : RegisterClass<"PPC", [i64], 64, (add CTR8)> {
let isAllocatable = 0;
}
+def LRRC : RegisterClass<"PPC", [i32], 32, (add LR)> {
+ let isAllocatable = 0;
+}
+def LR8RC : RegisterClass<"PPC", [i64], 64, (add LR8)> {
+ let isAllocatable = 0;
+}
+
def VRSAVERC : RegisterClass<"PPC", [i32], 32, (add VRSAVE)>;
def CARRYRC : RegisterClass<"PPC", [i32], 32, (add CARRY, XER)> {
let CopyCost = -1;
diff --git a/llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll b/llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll
new file mode 100644
index 0000000000000..3d66683c4c752
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/ppc64-inlineasm-clobber.ll
@@ -0,0 +1,264 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=powerpc64le-unknown-linux-unknown -verify-machineinstrs %s \
+; RUN: -ppc-asm-full-reg-names -o - | FileCheck %s --check-prefix=PPC64LE
+; RUN: llc -mtriple=powerpc64-unknown-linux-unknown -verify-machineinstrs %s \
+; RUN: -ppc-asm-full-reg-names -o - | FileCheck %s --check-prefix=PPC64BE
+
+define dso_local void @ClobberLR() local_unnamed_addr #0 {
+; PPC64LE-LABEL: ClobberLR:
+; PPC64LE: # %bb.0: # %entry
+; PPC64LE-NEXT: mflr r0
+; PPC64LE-NEXT: std r0, 16(r1)
+; PPC64LE-NEXT: stdu r1, -32(r1)
+; PPC64LE-NEXT: #APP
+; PPC64LE-NEXT: #NO_APP
+; PPC64LE-NEXT: addi r1, r1, 32
+; PPC64LE-NEXT: ld r0, 16(r1)
+; PPC64LE-NEXT: mtlr r0
+; PPC64LE-NEXT: blr
+;
+; PPC64BE-LABEL: ClobberLR:
+; PPC64BE: # %bb.0: # %entry
+; PPC64BE-NEXT: mflr r0
+; PPC64BE-NEXT: std r0, 16(r1)
+; PPC64BE-NEXT: stdu r1, -48(r1)
+; PPC64BE-NEXT: #APP
+; PPC64BE-NEXT: #NO_APP
+; PPC64BE-NEXT: addi r1, r1, 48
+; PPC64BE-NEXT: ld r0, 16(r1)
+; PPC64BE-NEXT: mtlr r0
+; PPC64BE-NEXT: blr
+entry:
+ tail call void asm sideeffect "", "~{lr}"()
+ ret void
+}
+
+define dso_local void @ClobberR5() local_unnamed_addr #0 {
+; PPC64LE-LABEL: ClobberR5:
+; PPC64LE: # %bb.0: # %entry
+; PPC64LE-NEXT: #APP
+; PPC64LE-NEXT: #NO_APP
+; PPC64LE-NEXT: blr
+;
+; PPC64BE-LABEL: ClobberR5:
+; PPC64BE: # %bb.0: # %entry
+; PPC64BE-NEXT: #APP
+; PPC64BE-NEXT: #NO_APP
+; PPC64BE-NEXT: blr
+entry:
+ tail call void asm sideeffect "", "~{r5}"()
+ ret void
+}
+
+define dso_local void @ClobberR15() local_unnamed_addr #0 {
+; PPC64LE-LABEL: ClobberR15:
+; PPC64LE: # %bb.0: # %entry
+; PPC64LE-NEXT: std r15, -136(r1) # 8-byte Folded Spill
+; PPC64LE-NEXT: #APP
+; PPC64LE-NEXT: #NO_APP
+; PPC64LE-NEXT: ld r15, -136(r1) # 8-byte Folded Reload
+; PPC64LE-NEXT: blr
+;
+; PPC64BE-LABEL: ClobberR15:
+; PPC64BE: # %bb.0: # %entry
+; PPC64BE-NEXT: std r15, -136(r1) # 8-byte Folded Spill
+; PPC64BE-NEXT: #APP
+; PPC64BE-NEXT: #NO_APP
+; PPC64BE-NEXT: ld r15, -136(r1) # 8-byte Folded Reload
+; PPC64BE-NEXT: blr
+entry:
+ tail call void asm sideeffect "", "~{r15}"()
+ ret void
+}
+
+;; Test for INLINEASM_BR
+define dso_local signext i32 @ClobberLR_BR(i32 signext %in) #0 {
+; PPC64LE-LABEL: ClobberLR_BR:
+; PPC64LE: # %bb.0: # %entry
+; PPC64LE-NEXT: #APP
+; PPC64LE-NEXT: nop
+; PPC64LE-NEXT: #NO_APP
+; PPC64LE-NEXT: # %bb.1: # %return
+; PPC64LE-NEXT: extsw r3, r3
+; PPC64LE-NEXT: blr
+; PPC64LE-NEXT: .Ltmp0: # Block address taken
+; PPC64LE-NEXT: .LBB3_2: # %return_early
+; PPC64LE-NEXT: mflr r0
+; PPC64LE-NEXT: std r0, 16(r1)
+; PPC64LE-NEXT: stdu r1, -32(r1)
+; PPC64LE-NEXT: li r3, 0
+; PPC64LE-NEXT: addi r1, r1, 32
+; PPC64LE-NEXT: ld r0, 16(r1)
+; PPC64LE-NEXT: mtlr r0
+; PPC64LE-NEXT: extsw r3, r3
+; PPC64LE-NEXT: blr
+;
+; PPC64BE-LABEL: ClobberLR_BR:
+; PPC64BE: # %bb.0: # %entry
+; PPC64BE-NEXT: #APP
+; PPC64BE-NEXT: nop
+; PPC64BE-NEXT: #NO_APP
+; PPC64BE-NEXT: # %bb.1: # %return
+; PPC64BE-NEXT: extsw r3, r3
+; PPC64BE-NEXT: blr
+; PPC64BE-NEXT: .Ltmp0: # Block address taken
+; PPC64BE-NEXT: .LBB3_2: # %return_early
+; PPC64BE-NEXT: mflr r0
+; PPC64BE-NEXT: std r0, 16(r1)
+; PPC64BE-NEXT: stdu r1, -48(r1)
+; PPC64BE-NEXT: li r3, 0
+; PPC64BE-NEXT: addi r1, r1, 48
+; PPC64BE-NEXT: ld r0, 16(r1)
+; PPC64BE-NEXT: mtlr r0
+; PPC64BE-NEXT: extsw r3, r3
+; PPC64BE-NEXT: blr
+entry:
+ callbr void asm sideeffect "nop", "X,~{lr}"(i8* blockaddress(@ClobberLR_BR, %return_early))
+ to label %return [label %return_early]
+
+return_early:
+ br label %return
+
+return:
+ %retval.0 = phi i32 [ 0, %return_early ], [ %in, %entry ]
+ ret i32 %retval.0
+}
+
+define dso_local signext i32 @ClobberR5_BR(i32 signext %in) #0 {
+; PPC64LE-LABEL: ClobberR5_BR:
+; PPC64LE: # %bb.0: # %entry
+; PPC64LE-NEXT: #APP
+; PPC64LE-NEXT: nop
+; PPC64LE-NEXT: #NO_APP
+; PPC64LE-NEXT: # %bb.1: # %return
+; PPC64LE-NEXT: extsw r3, r3
+; PPC64LE-NEXT: blr
+; PPC64LE-NEXT: .Ltmp1: # Block address taken
+; PPC64LE-NEXT: .LBB4_2: # %return_early
+; PPC64LE-NEXT: li r3, 0
+; PPC64LE-NEXT: extsw r3, r3
+; PPC64LE-NEXT: blr
+;
+; PPC64BE-LABEL: ClobberR5_BR:
+; PPC64BE: # %bb.0: # %entry
+; PPC64BE-NEXT: #APP
+; PPC64BE-NEXT: nop
+; PPC64BE-NEXT: #NO_APP
+; PPC64BE-NEXT: # %bb.1: # %return
+; PPC64BE-NEXT: extsw r3, r3
+; PPC64BE-NEXT: blr
+; PPC64BE-NEXT: .Ltmp1: # Block address taken
+; PPC64BE-NEXT: .LBB4_2: # %return_early
+; PPC64BE-NEXT: li r3, 0
+; PPC64BE-NEXT: extsw r3, r3
+; PPC64BE-NEXT: blr
+entry:
+ callbr void asm sideeffect "nop", "X,~{r5}"(i8* blockaddress(@ClobberR5_BR, %return_early))
+ to label %return [label %return_early]
+
+return_early:
+ br label %return
+
+return:
+ %retval.0 = phi i32 [ 0, %return_early ], [ %in, %entry ]
+ ret i32 %retval.0
+}
+
+
+
+define dso_local void @DefLR() local_unnamed_addr #0 {
+; PPC64LE-LABEL: DefLR:
+; PPC64LE: # %bb.0: # %entry
+; PPC64LE-NEXT: mflr r0
+; PPC64LE-NEXT: std r0, 16(r1)
+; PPC64LE-NEXT: stdu r1, -32(r1)
+; PPC64LE-NEXT: #APP
+; PPC64LE-NEXT: #NO_APP
+; PPC64LE-NEXT: addi r1, r1, 32
+; PPC64LE-NEXT: ld r0, 16(r1)
+; PPC64LE-NEXT: mtlr r0
+; PPC64LE-NEXT: blr
+;
+; PPC64BE-LABEL: DefLR:
+; PPC64BE: # %bb.0: # %entry
+; PPC64BE-NEXT: mflr r0
+; PPC64BE-NEXT: std r0, 16(r1)
+; PPC64BE-NEXT: stdu r1, -48(r1)
+; PPC64BE-NEXT: #APP
+; PPC64BE-NEXT: #NO_APP
+; PPC64BE-NEXT: addi r1, r1, 48
+; PPC64BE-NEXT: ld r0, 16(r1)
+; PPC64BE-NEXT: mtlr r0
+; PPC64BE-NEXT: blr
+entry:
+ tail call i64 asm sideeffect "", "={lr}"()
+ ret void
+}
+
+define dso_local void @EarlyClobberLR() local_unnamed_addr #0 {
+; PPC64LE-LABEL: EarlyClobberLR:
+; PPC64LE: # %bb.0: # %entry
+; PPC64LE-NEXT: mflr r0
+; PPC64LE-NEXT: std r0, 16(r1)
+; PPC64LE-NEXT: stdu r1, -32(r1)
+; PPC64LE-NEXT: #APP
+; PPC64LE-NEXT: #NO_APP
+; PPC64LE-NEXT: addi r1, r1, 32
+; PPC64LE-NEXT: ld r0, 16(r1)
+; PPC64LE-NEXT: mtlr r0
+; PPC64LE-NEXT: blr
+;
+; PPC64BE-LABEL: EarlyClobberLR:
+; PPC64BE: # %bb.0: # %entry
+; PPC64BE-NEXT: mflr r0
+; PPC64BE-NEXT: std r0, 16(r1)
+; PPC64BE-NEXT: stdu r1, -48(r1)
+; PPC64BE-NEXT: #APP
+; PPC64BE-NEXT: #NO_APP
+; PPC64BE-NEXT: addi r1, r1, 48
+; PPC64BE-NEXT: ld r0, 16(r1)
+; PPC64BE-NEXT: mtlr r0
+; PPC64BE-NEXT: blr
+entry:
+ tail call i64 asm sideeffect "", "=&{lr}"()
+ ret void
+}
+
+define dso_local void @ClobberMulti() local_unnamed_addr #0 {
+; PPC64LE-LABEL: ClobberMulti:
+; PPC64LE: # %bb.0: # %entry
+; PPC64LE-NEXT: mflr r0
+; PPC64LE-NEXT: std r15, -136(r1) # 8-byte Folded Spill
+; PPC64LE-NEXT: std r16, -128(r1) # 8-byte Folded Spill
+; PPC64LE-NEXT: std r0, 16(r1)
+; PPC64LE-NEXT: stdu r1, -176(r1)
+; PPC64LE-NEXT: #APP
+; PPC64LE-NEXT: #NO_APP
+; PPC64LE-NEXT: addi r1, r1, 176
+; PPC64LE-NEXT: ld r0, 16(r1)
+; PPC64LE-NEXT: ld r16, -128(r1) # 8-byte Folded Reload
+; PPC64LE-NEXT: ld r15, -136(r1) # 8-byte Folded Reload
+; PPC64LE-NEXT: mtlr r0
+; PPC64LE-NEXT: blr
+;
+; PPC64BE-LABEL: ClobberMulti:
+; PPC64BE: # %bb.0: # %entry
+; PPC64BE-NEXT: mflr r0
+; PPC64BE-NEXT: std r0, 16(r1)
+; PPC64BE-NEXT: stdu r1, -192(r1)
+; PPC64BE-NEXT: std r15, 56(r1) # 8-byte Folded Spill
+; PPC64BE-NEXT: std r16, 64(r1) # 8-byte Folded Spill
+; PPC64BE-NEXT: #APP
+; PPC64BE-NEXT: #NO_APP
+; PPC64BE-NEXT: ld r16, 64(r1) # 8-byte Folded Reload
+; PPC64BE-NEXT: ld r15, 56(r1) # 8-byte Folded Reload
+; PPC64BE-NEXT: addi r1, r1, 192
+; PPC64BE-NEXT: ld r0, 16(r1)
+; PPC64BE-NEXT: mtlr r0
+; PPC64BE-NEXT: blr
+entry:
+ tail call void asm sideeffect "", "~{lr},~{r15},~{r16}"()
+ ret void
+}
+
+attributes #0 = { nounwind }
More information about the llvm-branch-commits
mailing list