summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorTim Northover <t.p.northover@gmail.com>2019-11-07 13:36:03 +0000
committerTim Northover <t.p.northover@gmail.com>2019-11-07 13:36:44 +0000
commit10e0d64337d64ebdb658bf9108bd9bb48fb5390c (patch)
tree1feb4f9038679ad3fd3cef89ab676f2568b4234e /clang/lib/CodeGen
parent0ec6a4882eeb34338b916567f8e63fb71afc84fd (diff)
downloadbcm5719-llvm-10e0d64337d64ebdb658bf9108bd9bb48fb5390c.tar.gz
bcm5719-llvm-10e0d64337d64ebdb658bf9108bd9bb48fb5390c.zip
CodeGen: set correct result for atomic compound expressions
Atomic compound expressions try to use atomicrmw if possible, but this path doesn't set the Result variable, leaving it to crash in later code if anything ever tries to use the result of the expression. This fixes that issue by recalculating the new value based on the old one atomically loaded.
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp29
1 files changed, 20 insertions, 9 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index c1391d46f60..82297664064 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2849,7 +2849,8 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) &&
CGF.getLangOpts().getSignedOverflowBehavior() !=
LangOptions::SOB_Trapping) {
- llvm::AtomicRMWInst::BinOp aop = llvm::AtomicRMWInst::BAD_BINOP;
+ llvm::AtomicRMWInst::BinOp AtomicOp = llvm::AtomicRMWInst::BAD_BINOP;
+ llvm::Instruction::BinaryOps Op;
switch (OpInfo.Opcode) {
// We don't have atomicrmw operands for *, %, /, <<, >>
case BO_MulAssign: case BO_DivAssign:
@@ -2858,30 +2859,40 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
case BO_ShrAssign:
break;
case BO_AddAssign:
- aop = llvm::AtomicRMWInst::Add;
+ AtomicOp = llvm::AtomicRMWInst::Add;
+ Op = llvm::Instruction::Add;
break;
case BO_SubAssign:
- aop = llvm::AtomicRMWInst::Sub;
+ AtomicOp = llvm::AtomicRMWInst::Sub;
+ Op = llvm::Instruction::Sub;
break;
case BO_AndAssign:
- aop = llvm::AtomicRMWInst::And;
+ AtomicOp = llvm::AtomicRMWInst::And;
+ Op = llvm::Instruction::And;
break;
case BO_XorAssign:
- aop = llvm::AtomicRMWInst::Xor;
+ AtomicOp = llvm::AtomicRMWInst::Xor;
+ Op = llvm::Instruction::Xor;
break;
case BO_OrAssign:
- aop = llvm::AtomicRMWInst::Or;
+ AtomicOp = llvm::AtomicRMWInst::Or;
+ Op = llvm::Instruction::Or;
break;
default:
llvm_unreachable("Invalid compound assignment type");
}
- if (aop != llvm::AtomicRMWInst::BAD_BINOP) {
- llvm::Value *amt = CGF.EmitToMemory(
+ if (AtomicOp != llvm::AtomicRMWInst::BAD_BINOP) {
+ llvm::Value *Amt = CGF.EmitToMemory(
EmitScalarConversion(OpInfo.RHS, E->getRHS()->getType(), LHSTy,
E->getExprLoc()),
LHSTy);
- Builder.CreateAtomicRMW(aop, LHSLV.getPointer(), amt,
+ Value *OldVal = Builder.CreateAtomicRMW(
+ AtomicOp, LHSLV.getPointer(), Amt,
llvm::AtomicOrdering::SequentiallyConsistent);
+
+ // Since operation is atomic, the result type is guaranteed to be the
+ // same as the input in LLVM terms.
+ Result = Builder.CreateBinOp(Op, OldVal, Amt);
return LHSLV;
}
}
OpenPOWER on IntegriCloud