Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/BuiltinsPPC.def
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,10 @@ TARGET_BUILTIN(__builtin_amo_lwat, "UiUi*UiIi", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_ldat, "ULiULi*ULiIi", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_lwat_s, "SiSi*SiIi", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_ldat_s, "SLiSLi*SLiIi", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_lwat_cond, "UiUi*Ii", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_ldat_cond, "ULiULi*Ii", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_lwat_cond_s, "SiSi*Ii", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_ldat_cond_s, "SLiSLi*Ii", "", "isa-v30-instructions")

// Set the floating point rounding mode
BUILTIN(__builtin_setrnd, "di", "")
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/CodeGen/TargetBuiltins/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1374,5 +1374,17 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_ldat),
{Op0, Op1, Op2});
}
case PPC::BI__builtin_amo_lwat_cond_s: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_lwat_cond),
{Op0, Op1});
}
case PPC::BI__builtin_amo_ldat_cond_s: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_ldat_cond),
{Op0, Op1});
}
}
}
19 changes: 19 additions & 0 deletions clang/lib/Sema/SemaPPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
case PPC::BI__builtin_amo_ldat:
case PPC::BI__builtin_amo_lwat_s:
case PPC::BI__builtin_amo_ldat_s:
case PPC::BI__builtin_amo_lwat_cond:
case PPC::BI__builtin_amo_ldat_cond:
case PPC::BI__builtin_amo_lwat_cond_s:
case PPC::BI__builtin_amo_ldat_cond_s:
return true;
}
return false;
Expand Down Expand Up @@ -281,6 +285,21 @@ bool SemaPPC::CheckPPCBuiltinFunctionCall(const TargetInfo &TI,
<< toString(Result, 10) << (IsUnsigned ? "0-4, 6" : "0, 5, 7") << "8"
<< Arg->getSourceRange();
}
case PPC::BI__builtin_amo_lwat_cond:
case PPC::BI__builtin_amo_ldat_cond:
case PPC::BI__builtin_amo_lwat_cond_s:
case PPC::BI__builtin_amo_ldat_cond_s: {
llvm::APSInt Result;
if (SemaRef.BuiltinConstantArg(TheCall, 1, Result))
return true;
unsigned Val = Result.getZExtValue();
if (llvm::is_contained({24u, 25u, 28u}, Val))
return false;

Expr *Arg = TheCall->getArg(1);
return SemaRef.Diag(Arg->getBeginLoc(), diag::err_argument_invalid_range)
<< toString(Result, 10) << "24, 25" << "28" << Arg->getSourceRange();
}
}
llvm_unreachable("must return from switch");
}
Expand Down
24 changes: 24 additions & 0 deletions clang/test/CodeGen/PowerPC/builtins-amo-err.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,28 @@ void test_amo() {
__builtin_amo_ldat_s(ptr4, value4, 5);
// FC-ERROR: error: argument value 6 is outside the valid range [0, 5, 7, 8]
__builtin_amo_ldat_s(ptr4, value4, 6);

unsigned int *ptr5;
// AIX32-ERROR-COUNT-2: error: this builtin is only available on 64-bit targets
__builtin_amo_lwat_cond(ptr5, 24);
// FC-ERROR: argument value 20 is outside the valid range [24, 25, 28]
__builtin_amo_lwat_cond(ptr5, 20);

unsigned long int *ptr6;
// AIX32-ERROR-COUNT-2: error: this builtin is only available on 64-bit targets
__builtin_amo_ldat_cond(ptr6, 28);
// FC-ERROR: argument value 0 is outside the valid range [24, 25, 28]
__builtin_amo_ldat_cond(ptr6, 0);

signed int *ptr7;
// AIX32-ERROR-COUNT-2: error: this builtin is only available on 64-bit targets
__builtin_amo_lwat_cond_s(ptr7, 24);
// FC-ERROR: argument value 20 is outside the valid range [24, 25, 28]
__builtin_amo_lwat_cond_s(ptr7, 20);

signed long int *ptr8;
// AIX32-ERROR-COUNT-2: error: this builtin is only available on 64-bit targets
__builtin_amo_ldat_cond_s(ptr6, 28);
// FC-ERROR: argument value 0 is outside the valid range [24, 25, 28]
__builtin_amo_ldat_cond_s(ptr6, 0);
}
77 changes: 76 additions & 1 deletion clang/test/CodeGen/PowerPC/builtins-ppc-amo.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ void test_signed_lwat(int *ptr, int value, int * resp) {
*resp = res;
}


// CHECK-LABEL: define dso_local void @test_signed_ldat(
// CHECK-SAME: ptr noundef [[PTR:%.*]], i64 noundef [[VALUE:%.*]], ptr noundef writeonly captures(none) initializes((0, 8)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
Expand All @@ -81,6 +80,82 @@ void test_signed_ldat(long int *ptr, long int value, long int * resp) {
*resp = res;
}

// CHECK-LABEL: define dso_local void @test_unsigned_lwat_cond(
// CHECK-SAME: ptr noundef [[PTR:%.*]], ptr noundef writeonly captures(none) initializes((0, 4)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.amo.lwat.cond(ptr [[PTR]], i32 24)
// CHECK-NEXT: store i32 [[TMP0]], ptr [[RESP]], align 4, !tbaa [[INT_TBAA2]]
// CHECK-NEXT: ret void
//
// AIX-LABEL: define void @test_unsigned_lwat_cond(
// AIX-SAME: ptr noundef [[PTR:%.*]], ptr noundef writeonly captures(none) initializes((0, 4)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// AIX-NEXT: [[ENTRY:.*:]]
// AIX-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.amo.lwat.cond(ptr [[PTR]], i32 24)
// AIX-NEXT: store i32 [[TMP0]], ptr [[RESP]], align 4, !tbaa [[INT_TBAA2]]
// AIX-NEXT: ret void
//
void test_unsigned_lwat_cond(unsigned int *ptr, unsigned int * resp) {
unsigned int res = __builtin_amo_lwat_cond(ptr, 24);
*resp = res;
}

// CHECK-LABEL: define dso_local void @test_unsigned_ldat_cond(
// CHECK-SAME: ptr noundef [[PTR:%.*]], ptr noundef writeonly captures(none) initializes((0, 8)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.amo.ldat.cond(ptr [[PTR]], i32 25)
// CHECK-NEXT: store i64 [[TMP0]], ptr [[RESP]], align 8, !tbaa [[LONG_TBAA6]]
// CHECK-NEXT: ret void
//
// AIX-LABEL: define void @test_unsigned_ldat_cond(
// AIX-SAME: ptr noundef [[PTR:%.*]], ptr noundef writeonly captures(none) initializes((0, 8)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// AIX-NEXT: [[ENTRY:.*:]]
// AIX-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.amo.ldat.cond(ptr [[PTR]], i32 25)
// AIX-NEXT: store i64 [[TMP0]], ptr [[RESP]], align 8, !tbaa [[LONG_TBAA6]]
// AIX-NEXT: ret void
//
void test_unsigned_ldat_cond(unsigned long int *ptr, unsigned long int * resp) {
unsigned long int res = __builtin_amo_ldat_cond(ptr, 25);
*resp = res;
}

// CHECK-LABEL: define dso_local void @test_signed_lwat_cond(
// CHECK-SAME: ptr noundef [[PTR:%.*]], ptr noundef writeonly captures(none) initializes((0, 4)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.amo.lwat.cond(ptr [[PTR]], i32 24)
// CHECK-NEXT: store i32 [[TMP0]], ptr [[RESP]], align 4, !tbaa [[INT_TBAA2]]
// CHECK-NEXT: ret void
//
// AIX-LABEL: define void @test_signed_lwat_cond(
// AIX-SAME: ptr noundef [[PTR:%.*]], ptr noundef writeonly captures(none) initializes((0, 4)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// AIX-NEXT: [[ENTRY:.*:]]
// AIX-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.amo.lwat.cond(ptr [[PTR]], i32 24)
// AIX-NEXT: store i32 [[TMP0]], ptr [[RESP]], align 4, !tbaa [[INT_TBAA2]]
// AIX-NEXT: ret void
//
void test_signed_lwat_cond(int *ptr, int * resp) {
int res = __builtin_amo_lwat_cond_s(ptr, 24);
*resp = res;
}

// CHECK-LABEL: define dso_local void @test_signed_ldat_cond(
// CHECK-SAME: ptr noundef [[PTR:%.*]], ptr noundef writeonly captures(none) initializes((0, 8)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.amo.ldat.cond(ptr [[PTR]], i32 25)
// CHECK-NEXT: store i64 [[TMP0]], ptr [[RESP]], align 8, !tbaa [[LONG_TBAA6]]
// CHECK-NEXT: ret void
//
// AIX-LABEL: define void @test_signed_ldat_cond(
// AIX-SAME: ptr noundef [[PTR:%.*]], ptr noundef writeonly captures(none) initializes((0, 8)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// AIX-NEXT: [[ENTRY:.*:]]
// AIX-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.amo.ldat.cond(ptr [[PTR]], i32 25)
// AIX-NEXT: store i64 [[TMP0]], ptr [[RESP]], align 8, !tbaa [[LONG_TBAA6]]
// AIX-NEXT: ret void
//
void test_signed_ldat_cond(long int *ptr, long int * resp) {
long int res = __builtin_amo_ldat_cond_s(ptr, 25);
*resp = res;
}

//.
// CHECK: [[INT_TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
// CHECK: [[META3]] = !{!"int", [[META4:![0-9]+]], i64 0}
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsPowerPC.td
Original file line number Diff line number Diff line change
Expand Up @@ -2150,4 +2150,12 @@ let TargetPrefix = "ppc" in {
DefaultAttrsIntrinsic<[llvm_i64_ty],[llvm_ptr_ty,
llvm_i64_ty, llvm_i32_ty],
[IntrArgMemOnly, ImmArg<ArgIndex<2>>]>;
def int_ppc_amo_lwat_cond : ClangBuiltin<"__builtin_amo_lwat_cond">,
DefaultAttrsIntrinsic<[llvm_i32_ty],[llvm_ptr_ty,
llvm_i32_ty],
[IntrArgMemOnly, ImmArg<ArgIndex<1>>]>;
def int_ppc_amo_ldat_cond : ClangBuiltin<"__builtin_amo_ldat_cond">,
DefaultAttrsIntrinsic<[llvm_i64_ty],[llvm_ptr_ty,
llvm_i32_ty],
[IntrArgMemOnly, ImmArg<ArgIndex<1>>]>;
}
43 changes: 42 additions & 1 deletion llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11641,7 +11641,7 @@ SDValue PPCTargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
SDLoc dl(Op);
switch (IntrinsicID) {
case Intrinsic::ppc_amo_lwat:
case Intrinsic::ppc_amo_ldat:
case Intrinsic::ppc_amo_ldat: {
SDValue Ptr = Op.getOperand(2);
SDValue Val1 = Op.getOperand(3);
SDValue FC = Op.getOperand(4);
Expand All @@ -11654,6 +11654,21 @@ SDValue PPCTargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
SDValue OutChain = SDValue(MNode, 1);
return DAG.getMergeValues({Result, OutChain}, dl);
}
case Intrinsic::ppc_amo_lwat_cond:
case Intrinsic::ppc_amo_ldat_cond: {
SDValue Ptr = Op.getOperand(2);
SDValue FC = Op.getOperand(3);
SDValue Ops[] = {Ptr, FC};
bool IsLwat_cond = IntrinsicID == Intrinsic::ppc_amo_lwat_cond;
unsigned Opcode =
IsLwat_cond ? PPC::LWAT_COND_PSEUDO : PPC::LDAT_COND_PSEUDO;
MachineSDNode *MNode = DAG.getMachineNode(
Opcode, dl, {IsLwat_cond ? MVT::i32 : MVT::i64, MVT::Other}, Ops);
SDValue Result = SDValue(MNode, 0);
SDValue OutChain = SDValue(MNode, 1);
return DAG.getMergeValues({Result, OutChain}, dl);
}
}
return SDValue();
}

Expand Down Expand Up @@ -14777,6 +14792,32 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
else
BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), DstReg)
.addReg(Result64);
} else if (MI.getOpcode() == PPC::LWAT_COND_PSEUDO ||
MI.getOpcode() == PPC::LDAT_COND_PSEUDO) {
DebugLoc DL = MI.getDebugLoc();
Register DstReg = MI.getOperand(0).getReg();
Register PtrReg = MI.getOperand(1).getReg();
unsigned FC = MI.getOperand(2).getImm();
bool IsLwat_Cond = MI.getOpcode() == PPC::LWAT_COND_PSEUDO;

Register Pair = MRI.createVirtualRegister(&PPC::G8pRCRegClass);
BuildMI(*BB, MI, DL, TII->get(TargetOpcode::IMPLICIT_DEF), Pair);

Register PairResult = MRI.createVirtualRegister(&PPC::G8pRCRegClass);
BuildMI(*BB, MI, DL, TII->get(IsLwat_Cond ? PPC::LWAT : PPC::LDAT),
PairResult)
.addReg(Pair)
.addReg(PtrReg)
.addImm(FC);
Register Result64 = MRI.createVirtualRegister(&PPC::G8RCRegClass);
BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), Result64)
.addReg(PairResult, 0, PPC::sub_gp8_x0);
if (IsLwat_Cond)
BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), DstReg)
.addReg(Result64, 0, PPC::sub_32);
else
BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), DstReg)
.addReg(Result64);
} else {
llvm_unreachable("Unexpected instr type to insert");
}
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/PowerPC/PPCInstr64Bit.td
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,12 @@ def LDAT_PSEUDO : PPCCustomInserterPseudo<
"#LDAT_PSEUDO",
[]>;

def LDAT_COND_PSEUDO : PPCCustomInserterPseudo <
(outs g8rc:$dst),
(ins ptr_rc_nor0:$ptr, u5imm:$fc),
"#LDAT_COND_PSEUDO",
[]>;

let Defs = [CR0], mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
def STDCX : XForm_1_memOp<31, 214, (outs), (ins g8rc:$RST, (memrr $RA, $RB):$addr),
"stdcx. $RST, $addr", IIC_LdStSTDCX, []>, isRecordForm;
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/PowerPC/PPCInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,12 @@ def LWAT_PSEUDO : PPCCustomInserterPseudo<
"#LWAT_PSEUDO",
[]>;

def LWAT_COND_PSEUDO : PPCCustomInserterPseudo <
(outs gprc:$dst),
(ins ptr_rc_nor0:$ptr, u5imm:$fc),
"#LWAT_COND_PSEUDO",
[]>;

let Defs = [CR0], mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
def STBCX : XForm_1_memOp<31, 694, (outs), (ins gprc:$RST, (memrr $RA, $RB):$addr),
"stbcx. $RST, $addr", IIC_LdStSTWCX, []>,
Expand Down
38 changes: 38 additions & 0 deletions llvm/test/CodeGen/PowerPC/amo-enable.ll
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,43 @@ entry:
ret void
}

define void @test_lwat_cond(ptr noundef %ptr, ptr nocapture %resp) {
; CHECK-LABEL: test_lwat_cond:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: lwat r6, r3, 24
; CHECK-NEXT: stw r6, 0(r4)
; CHECK-NEXT: blr
;
; CHECK-BE-LABEL: test_lwat_cond:
; CHECK-BE: # %bb.0: # %entry
; CHECK-BE-NEXT: lwat r6, r3, 24
; CHECK-BE-NEXT: stw r6, 0(r4)
; CHECK-BE-NEXT: blr
entry:
%0 = tail call i32 @llvm.ppc.amo.lwat.cond(ptr %ptr, i32 24)
store i32 %0, ptr %resp, align 4
ret void
}

define void @test_ldat_cond(ptr noundef %ptr, ptr nocapture %resp) {
; CHECK-LABEL: test_ldat_cond:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: ldat r6, r3, 24
; CHECK-NEXT: std r6, 0(r4)
; CHECK-NEXT: blr
;
; CHECK-BE-LABEL: test_ldat_cond:
; CHECK-BE: # %bb.0: # %entry
; CHECK-BE-NEXT: ldat r6, r3, 24
; CHECK-BE-NEXT: std r6, 0(r4)
; CHECK-BE-NEXT: blr
entry:
%0 = tail call i64 @llvm.ppc.amo.ldat.cond(ptr %ptr, i32 24)
store i64 %0, ptr %resp, align 8
ret void
}

declare i64 @llvm.ppc.amo.ldat(ptr, i64, i32 immarg)
declare i32 @llvm.ppc.amo.lwat(ptr, i32, i32 immarg)
declare i64 @llvm.ppc.amo.ldat.cond(ptr, i32 immarg)
declare i32 @llvm.ppc.amo.lwat.cond(ptr, i32 immarg)
Loading