[llvm] r340027 - [AtomicExpandPass] Widen partword atomicrmw or/xor/and before tryExpandAtomicRMW
Alex Bradbury via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 17 07:03:37 PDT 2018
Author: asb
Date: Fri Aug 17 07:03:37 2018
New Revision: 340027
URL: http://llvm.org/viewvc/llvm-project?rev=340027&view=rev
Log:
[AtomicExpandPass] Widen partword atomicrmw or/xor/and before tryExpandAtomicRMW
This patch performs a widening transformation of bitwise atomicrmw
{or,xor,and} and applies it prior to tryExpandAtomicRMW. This operates
similarly to convertCmpXchgToIntegerType. For these operations, the i8/i16
atomicrmw can be implemented in terms of the 32-bit atomicrmw by appropriately
manipulating the operands. There is no functional change for the handling of
partword or/xor, but the transformation for partword 'and' is new.
The advantage of performing this transformation early is that the same
code-path can be used regardless of the approach used to expand the atomicrmw
(AtomicExpansionKind). i.e. the same logic is used for
AtomicExpansionKind::CmpXchg and can also be used by the intrinsic-based
expansion in D47882.
Differential Revision: https://reviews.llvm.org/D48129
Modified:
llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp
llvm/trunk/test/Transforms/AtomicExpand/SPARC/partword.ll
Modified: llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp?rev=340027&r1=340026&r2=340027&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp (original)
+++ llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp Fri Aug 17 07:03:37 2018
@@ -88,6 +88,7 @@ namespace {
void expandPartwordAtomicRMW(
AtomicRMWInst *I,
TargetLoweringBase::AtomicExpansionKind ExpansionKind);
+ AtomicRMWInst *widenPartwordAtomicRMW(AtomicRMWInst *AI);
void expandPartwordCmpXchg(AtomicCmpXchgInst *I);
AtomicCmpXchgInst *convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI);
@@ -306,6 +307,16 @@ bool AtomicExpand::runOnFunction(Functio
if (isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) {
MadeChange = true;
} else {
+ unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
+ unsigned ValueSize = getAtomicOpSize(RMWI);
+ AtomicRMWInst::BinOp Op = RMWI->getOperation();
+ if (ValueSize < MinCASSize &&
+ (Op == AtomicRMWInst::Or || Op == AtomicRMWInst::Xor ||
+ Op == AtomicRMWInst::And)) {
+ RMWI = widenPartwordAtomicRMW(RMWI);
+ MadeChange = true;
+ }
+
MadeChange |= tryExpandAtomicRMW(RMWI);
}
} else if (CASI) {
@@ -659,12 +670,10 @@ static Value *performMaskedAtomicOp(Atom
}
case AtomicRMWInst::Or:
case AtomicRMWInst::Xor:
- // Or/Xor won't affect any other bits, so can just be done
- // directly.
- return performAtomicOp(Op, Builder, Loaded, Shifted_Inc);
+ case AtomicRMWInst::And:
+ llvm_unreachable("Or/Xor/And handled by widenPartwordAtomicRMW");
case AtomicRMWInst::Add:
case AtomicRMWInst::Sub:
- case AtomicRMWInst::And:
case AtomicRMWInst::Nand: {
// The other arithmetic ops need to be masked into place.
Value *NewVal = performAtomicOp(Op, Builder, Loaded, Shifted_Inc);
@@ -733,6 +742,41 @@ void AtomicExpand::expandPartwordAtomicR
AI->eraseFromParent();
}
+// Widen the bitwise atomicrmw (or/xor/and) to the minimum supported width.
+AtomicRMWInst *AtomicExpand::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
+ IRBuilder<> Builder(AI);
+ AtomicRMWInst::BinOp Op = AI->getOperation();
+
+ assert((Op == AtomicRMWInst::Or || Op == AtomicRMWInst::Xor ||
+ Op == AtomicRMWInst::And) &&
+ "Unable to widen operation");
+
+ PartwordMaskValues PMV =
+ createMaskInstrs(Builder, AI, AI->getType(), AI->getPointerOperand(),
+ TLI->getMinCmpXchgSizeInBits() / 8);
+
+ Value *ValOperand_Shifted =
+ Builder.CreateShl(Builder.CreateZExt(AI->getValOperand(), PMV.WordType),
+ PMV.ShiftAmt, "ValOperand_Shifted");
+
+ Value *NewOperand;
+
+ if (Op == AtomicRMWInst::And)
+ NewOperand =
+ Builder.CreateOr(PMV.Inv_Mask, ValOperand_Shifted, "AndOperand");
+ else
+ NewOperand = ValOperand_Shifted;
+
+ AtomicRMWInst *NewAI = Builder.CreateAtomicRMW(Op, PMV.AlignedAddr,
+ NewOperand, AI->getOrdering());
+
+ Value *FinalOldResult = Builder.CreateTrunc(
+ Builder.CreateLShr(NewAI, PMV.ShiftAmt), PMV.ValueType);
+ AI->replaceAllUsesWith(FinalOldResult);
+ AI->eraseFromParent();
+ return NewAI;
+}
+
void AtomicExpand::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
// The basic idea here is that we're expanding a cmpxchg of a
// smaller memory size up to a word-sized cmpxchg. To do this, we
Modified: llvm/trunk/test/Transforms/AtomicExpand/SPARC/partword.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/SPARC/partword.ll?rev=340027&r1=340026&r2=340027&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/AtomicExpand/SPARC/partword.ll (original)
+++ llvm/trunk/test/Transforms/AtomicExpand/SPARC/partword.ll Fri Aug 17 07:03:37 2018
@@ -147,6 +147,31 @@ entry:
ret i16 %ret
}
+; CHECK-LABEL: @test_or_i16(
+; (I'm going to just assert on the bits that differ from add, above.)
+; CHECK:atomicrmw.start:
+; CHECK: %new = or i32 %loaded, %ValOperand_Shifted
+; CHECK: %6 = cmpxchg i32* %AlignedAddr, i32 %loaded, i32 %new monotonic monotonic
+; CHECK:atomicrmw.end:
+define i16 @test_or_i16(i16* %arg, i16 %val) {
+entry:
+ %ret = atomicrmw or i16* %arg, i16 %val seq_cst
+ ret i16 %ret
+}
+
+; CHECK-LABEL: @test_and_i16(
+; (I'm going to just assert on the bits that differ from add, above.)
+; CHECK: %AndOperand = or i32 %Inv_Mask, %ValOperand_Shifted
+; CHECK:atomicrmw.start:
+; CHECK: %new = and i32 %loaded, %AndOperand
+; CHECK: %6 = cmpxchg i32* %AlignedAddr, i32 %loaded, i32 %new monotonic monotonic
+; CHECK:atomicrmw.end:
+define i16 @test_and_i16(i16* %arg, i16 %val) {
+entry:
+ %ret = atomicrmw and i16* %arg, i16 %val seq_cst
+ ret i16 %ret
+}
+
; CHECK-LABEL: @test_min_i16(
; CHECK:atomicrmw.start:
; CHECK: %6 = lshr i32 %loaded, %ShiftAmt
More information about the llvm-commits
mailing list