Skip to content

Commit

Permalink
[PowerPC] Implement 32-bit expansion for rldimi (#86783)
Browse files Browse the repository at this point in the history
rldimi is 64-bit instruction, due to backward compatibility, it needs to
be expanded into series of rotate and masking in 32-bit environment. In
the future, we may improve bit permutation selector and remove such
direct codegen.
  • Loading branch information
ecnelises committed Apr 9, 2024
1 parent 9430a4b commit a4558a4
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 11 deletions.
10 changes: 10 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17288,6 +17288,16 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
Value *Op1 = EmitScalarExpr(E->getArg(1));
Value *Op2 = EmitScalarExpr(E->getArg(2));
Value *Op3 = EmitScalarExpr(E->getArg(3));
// rldimi is 64-bit instruction, expand the intrinsic before isel to
// leverage peephole and avoid legalization efforts.
if (BuiltinID == PPC::BI__builtin_ppc_rldimi &&
!getTarget().getTriple().isPPC64()) {
Function *F = CGM.getIntrinsic(Intrinsic::fshl, Op0->getType());
Op2 = Builder.CreateZExt(Op2, Int64Ty);
Value *Shift = Builder.CreateCall(F, {Op0, Op0, Op2});
return Builder.CreateOr(Builder.CreateAnd(Shift, Op3),
Builder.CreateAnd(Op1, Builder.CreateNot(Op3)));
}
return Builder.CreateCall(
CGM.getIntrinsic(BuiltinID == PPC::BI__builtin_ppc_rldimi
? Intrinsic::ppc_rldimi
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5232,7 +5232,6 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
case PPC::BI__builtin_ppc_fetch_and_andlp:
case PPC::BI__builtin_ppc_fetch_and_orlp:
case PPC::BI__builtin_ppc_fetch_and_swaplp:
case PPC::BI__builtin_ppc_rldimi:
return true;
}
return false;
Expand Down
6 changes: 0 additions & 6 deletions clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ void test_trap(void) {
__tw(ia, ib, 0); //expected-error {{argument value 0 is outside the valid range [1, 31]}}
}

#ifdef __PPC64__
void test_builtin_ppc_rldimi() {
unsigned int shift;
unsigned long long mask;
Expand All @@ -33,7 +32,6 @@ void test_builtin_ppc_rldimi() {
res = __builtin_ppc_rldimi(ull, ull, 63, 0xFFFF000000000F00); // expected-error {{argument 3 value should represent a contiguous bit field}}
res = __builtin_ppc_rldimi(ull, ull, 64, 0xFFFF000000000000); // expected-error {{argument value 64 is outside the valid range [0, 63]}}
}
#endif

void test_builtin_ppc_rlwimi() {
unsigned int shift;
Expand Down Expand Up @@ -86,10 +84,6 @@ void testalignx(const void *pointer, unsigned int alignment) {
}

#ifndef __PPC64__
unsigned long long testrldimi32() {
return __rldimi(ull, ui, 3, 0x7ffff8ULL); //expected-error {{this builtin is only available on 64-bit targets}}
}

long long testbpermd(long long bit_selector, long long source) {
return __bpermd(bit_selector, source); //expected-error {{this builtin is only available on 64-bit targets}}
}
Expand Down
7 changes: 3 additions & 4 deletions llvm/include/llvm/IR/IntrinsicsPowerPC.td
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,6 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
def int_ppc_fctuwz
: ClangBuiltin<"__builtin_ppc_fctuwz">,
DefaultAttrsIntrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_rldimi
: ClangBuiltin<"__builtin_ppc_rldimi">,
DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty],
[IntrNoMem, ImmArg<ArgIndex<2>>, ImmArg<ArgIndex<3>>]>;
def int_ppc_rlwimi
: ClangBuiltin<"__builtin_ppc_rlwimi">,
DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
Expand All @@ -194,6 +190,9 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
: ClangBuiltin<"__builtin_ppc_rlwnm">,
DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, ImmArg<ArgIndex<2>>]>;
def int_ppc_rldimi
: DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty],
[IntrNoMem, ImmArg<ArgIndex<2>>, ImmArg<ArgIndex<3>>]>;

// XL compatible select functions
// TODO: Add llvm_f128_ty support.
Expand Down
154 changes: 154 additions & 0 deletions llvm/test/CodeGen/PowerPC/rldimi.ll
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,158 @@ define i64 @rldimi11(i64 %a, i64 %b) {
ret i64 %r
}

define i64 @rldimi12(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi12:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 20
; CHECK-NEXT: rldimi 4, 3, 44, 31
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 0, i64 18446726490113441791)
ret i64 %r
}

define i64 @rldimi13(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi13:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 62
; CHECK-NEXT: rldimi 4, 3, 32, 2
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 30, i64 4611686014132420608)
ret i64 %r
}

define i64 @rldimi14(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi14:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 23
; CHECK-NEXT: rldimi 4, 3, 53, 0
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18437736874454810624) ; mb=0, me=10
ret i64 %r
}

define i64 @rldimi15(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi15:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 36
; CHECK-NEXT: rldimi 4, 3, 40, 10
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18013298997854208) ; mb=10, me=23
ret i64 %r
}

define i64 @rldimi16(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi16:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 57
; CHECK-NEXT: rldimi 4, 3, 19, 10
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18014398508957696) ; mb=10, me=44
ret i64 %r
}

define i64 @rldimi17(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi17:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 43
; CHECK-NEXT: rldimi 4, 3, 33, 25
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 541165879296) ; mb=25, me=30
ret i64 %r
}

define i64 @rldimi18(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi18:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 57
; CHECK-NEXT: rldimi 4, 3, 19, 25
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 549755289600) ; mb=25, me=44
ret i64 %r
}

define i64 @rldimi19(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi19:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 57
; CHECK-NEXT: rldimi 4, 3, 19, 33
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 2146959360) ; mb=33, me=44
ret i64 %r
}

define i64 @rldimi20(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi20:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 23
; CHECK-NEXT: rldimi 4, 3, 53, 15
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18438299824408231935) ; mb=15, me=10
ret i64 %r
}

define i64 @rldimi21(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi21:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 23
; CHECK-NEXT: rldimi 4, 3, 53, 25
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18437737424210624511) ; mb=25, me=10
ret i64 %r
}

define i64 @rldimi22(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi22:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 34
; CHECK-NEXT: rldimi 4, 3, 42, 25
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18446740225418854399) ; mb=25, me=21
ret i64 %r
}

define i64 @rldimi23(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi23:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 23
; CHECK-NEXT: rldimi 4, 3, 53, 44
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18437736874455859199) ; mb=44, me=10
ret i64 %r
}

define i64 @rldimi24(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi24:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 38
; CHECK-NEXT: rldimi 4, 3, 38, 44
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18446743798832693247) ; mb=44, me=25
ret i64 %r
}

define i64 @rldimi25(i64 %a, i64 %b) {
; CHECK-LABEL: rldimi25:
; CHECK: # %bb.0:
; CHECK-NEXT: rotldi 3, 3, 48
; CHECK-NEXT: rldimi 4, 3, 28, 44
; CHECK-NEXT: mr 3, 4
; CHECK-NEXT: blr
%r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 12, i64 18446744073442164735) ; mb=44, me=35
ret i64 %r
}

declare i64 @llvm.ppc.rldimi(i64, i64, i32 immarg, i64 immarg)

0 comments on commit a4558a4

Please sign in to comment.