mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[SelectionDAG] Handle non-power-of-2 bitwidths in expandROT
Differential Revision: https://reviews.llvm.org/D86449
This commit is contained in:
parent
0e778b809f
commit
92aef7a9e9
@ -6247,12 +6247,9 @@ bool TargetLowering::expandROT(SDNode *Node, SDValue &Result,
|
||||
EVT ShVT = Op1.getValueType();
|
||||
SDValue Zero = DAG.getConstant(0, DL, ShVT);
|
||||
|
||||
assert(isPowerOf2_32(EltSizeInBits) && EltSizeInBits > 1 &&
|
||||
"Expecting the type bitwidth to be a power of 2");
|
||||
|
||||
// If a rotate in the other direction is supported, use it.
|
||||
unsigned RevRot = IsLeft ? ISD::ROTR : ISD::ROTL;
|
||||
if (isOperationLegalOrCustom(RevRot, VT)) {
|
||||
if (isOperationLegalOrCustom(RevRot, VT) && isPowerOf2_32(EltSizeInBits)) {
|
||||
SDValue Sub = DAG.getNode(ISD::SUB, DL, ShVT, Zero, Op1);
|
||||
Result = DAG.getNode(RevRot, DL, VT, Op0, Sub);
|
||||
return true;
|
||||
@ -6265,18 +6262,31 @@ bool TargetLowering::expandROT(SDNode *Node, SDValue &Result,
|
||||
!isOperationLegalOrCustomOrPromote(ISD::AND, VT)))
|
||||
return false;
|
||||
|
||||
// Otherwise,
|
||||
// (rotl x, c) -> (or (shl x, (and c, w-1)), (srl x, (and -c, w-1)))
|
||||
// (rotr x, c) -> (or (srl x, (and c, w-1)), (shl x, (and -c, w-1)))
|
||||
//
|
||||
unsigned ShOpc = IsLeft ? ISD::SHL : ISD::SRL;
|
||||
unsigned HsOpc = IsLeft ? ISD::SRL : ISD::SHL;
|
||||
SDValue BitWidthMinusOneC = DAG.getConstant(EltSizeInBits - 1, DL, ShVT);
|
||||
SDValue NegOp1 = DAG.getNode(ISD::SUB, DL, ShVT, Zero, Op1);
|
||||
SDValue And0 = DAG.getNode(ISD::AND, DL, ShVT, Op1, BitWidthMinusOneC);
|
||||
SDValue And1 = DAG.getNode(ISD::AND, DL, ShVT, NegOp1, BitWidthMinusOneC);
|
||||
Result = DAG.getNode(ISD::OR, DL, VT, DAG.getNode(ShOpc, DL, VT, Op0, And0),
|
||||
DAG.getNode(HsOpc, DL, VT, Op0, And1));
|
||||
SDValue ShVal;
|
||||
SDValue HsVal;
|
||||
if (isPowerOf2_32(EltSizeInBits)) {
|
||||
// (rotl x, c) -> x << (c & (w - 1)) | x >> (-c & (w - 1))
|
||||
// (rotr x, c) -> x >> (c & (w - 1)) | x << (-c & (w - 1))
|
||||
SDValue NegOp1 = DAG.getNode(ISD::SUB, DL, ShVT, Zero, Op1);
|
||||
SDValue ShAmt = DAG.getNode(ISD::AND, DL, ShVT, Op1, BitWidthMinusOneC);
|
||||
ShVal = DAG.getNode(ShOpc, DL, VT, Op0, ShAmt);
|
||||
SDValue HsAmt = DAG.getNode(ISD::AND, DL, ShVT, NegOp1, BitWidthMinusOneC);
|
||||
HsVal = DAG.getNode(HsOpc, DL, VT, Op0, HsAmt);
|
||||
} else {
|
||||
// (rotl x, c) -> x << (c % w) | x >> 1 >> (w - 1 - (c % w))
|
||||
// (rotr x, c) -> x >> (c % w) | x << 1 << (w - 1 - (c % w))
|
||||
SDValue BitWidthC = DAG.getConstant(EltSizeInBits, DL, ShVT);
|
||||
SDValue ShAmt = DAG.getNode(ISD::UREM, DL, ShVT, Op1, BitWidthC);
|
||||
ShVal = DAG.getNode(ShOpc, DL, VT, Op0, ShAmt);
|
||||
SDValue HsAmt = DAG.getNode(ISD::SUB, DL, ShVT, BitWidthMinusOneC, ShAmt);
|
||||
SDValue One = DAG.getConstant(1, DL, ShVT);
|
||||
HsVal =
|
||||
DAG.getNode(HsOpc, DL, VT, DAG.getNode(HsOpc, DL, VT, Op0, One), HsAmt);
|
||||
}
|
||||
Result = DAG.getNode(ISD::OR, DL, VT, ShVal, HsVal);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
22
test/CodeGen/WebAssembly/fshl.ll
Normal file
22
test/CodeGen/WebAssembly/fshl.ll
Normal file
@ -0,0 +1,22 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s | FileCheck %s
|
||||
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
; From https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25150
|
||||
define i33 @fshr_multi_use(i33 %a) {
|
||||
; CHECK-LABEL: fshr_multi_use:
|
||||
; CHECK: .functype fshr_multi_use (i64) -> (i64)
|
||||
; CHECK-NEXT: # %bb.0:
|
||||
; CHECK-NEXT: local.get 0
|
||||
; CHECK-NEXT: i64.const 1
|
||||
; CHECK-NEXT: i64.shr_u
|
||||
; CHECK-NEXT: i64.const 31
|
||||
; CHECK-NEXT: i64.and
|
||||
; CHECK-NEXT: # fallthrough-return
|
||||
%b = tail call i33 @llvm.fshr.i33(i33 %a, i33 %a, i33 1)
|
||||
%e = and i33 %b, 31
|
||||
ret i33 %e
|
||||
}
|
||||
|
||||
declare i33 @llvm.fshr.i33(i33, i33, i33)
|
Loading…
x
Reference in New Issue
Block a user