Skip to content

Commit 3ffaaf6

Browse files
authored
[Xtensa] Implement Xtensa S32C1I Option and atomics lowering. (#137134)
Implement Xtensa S32C1I Option. Implement atomic_cmp_swap_32 operation using s32c1i instruction. Use atomic_cmp_swap_32 operation and AtomicExpand pass to implement atomics operations.
1 parent a4ff76e commit 3ffaaf6

File tree

14 files changed

+15015
-35
lines changed

14 files changed

+15015
-35
lines changed

llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -145,39 +145,40 @@ struct DecodeRegister {
145145
};
146146

147147
const DecodeRegister SRDecoderTable[] = {
148-
{Xtensa::LBEG, 0}, {Xtensa::LEND, 1},
149-
{Xtensa::LCOUNT, 2}, {Xtensa::SAR, 3},
150-
{Xtensa::BREG, 4}, {Xtensa::LITBASE, 5},
151-
{Xtensa::ACCLO, 16}, {Xtensa::ACCHI, 17},
152-
{Xtensa::M0, 32}, {Xtensa::M1, 33},
153-
{Xtensa::M2, 34}, {Xtensa::M3, 35},
154-
{Xtensa::WINDOWBASE, 72}, {Xtensa::WINDOWSTART, 73},
155-
{Xtensa::IBREAKENABLE, 96}, {Xtensa::MEMCTL, 97},
156-
{Xtensa::DDR, 104}, {Xtensa::IBREAKA0, 128},
157-
{Xtensa::IBREAKA1, 129}, {Xtensa::DBREAKA0, 144},
158-
{Xtensa::DBREAKA1, 145}, {Xtensa::DBREAKC0, 160},
159-
{Xtensa::DBREAKC1, 161}, {Xtensa::CONFIGID0, 176},
160-
{Xtensa::EPC1, 177}, {Xtensa::EPC2, 178},
161-
{Xtensa::EPC3, 179}, {Xtensa::EPC4, 180},
162-
{Xtensa::EPC5, 181}, {Xtensa::EPC6, 182},
163-
{Xtensa::EPC7, 183}, {Xtensa::DEPC, 192},
164-
{Xtensa::EPS2, 194}, {Xtensa::EPS3, 195},
165-
{Xtensa::EPS4, 196}, {Xtensa::EPS5, 197},
166-
{Xtensa::EPS6, 198}, {Xtensa::EPS7, 199},
167-
{Xtensa::CONFIGID1, 208}, {Xtensa::EXCSAVE1, 209},
168-
{Xtensa::EXCSAVE2, 210}, {Xtensa::EXCSAVE3, 211},
169-
{Xtensa::EXCSAVE4, 212}, {Xtensa::EXCSAVE5, 213},
170-
{Xtensa::EXCSAVE6, 214}, {Xtensa::EXCSAVE7, 215},
171-
{Xtensa::CPENABLE, 224}, {Xtensa::INTERRUPT, 226},
172-
{Xtensa::INTCLEAR, 227}, {Xtensa::INTENABLE, 228},
173-
{Xtensa::PS, 230}, {Xtensa::VECBASE, 231},
174-
{Xtensa::EXCCAUSE, 232}, {Xtensa::DEBUGCAUSE, 233},
175-
{Xtensa::CCOUNT, 234}, {Xtensa::PRID, 235},
176-
{Xtensa::ICOUNT, 236}, {Xtensa::ICOUNTLEVEL, 237},
177-
{Xtensa::EXCVADDR, 238}, {Xtensa::CCOMPARE0, 240},
178-
{Xtensa::CCOMPARE1, 241}, {Xtensa::CCOMPARE2, 242},
179-
{Xtensa::MISC0, 244}, {Xtensa::MISC1, 245},
180-
{Xtensa::MISC2, 246}, {Xtensa::MISC3, 247}};
148+
{Xtensa::LBEG, 0}, {Xtensa::LEND, 1},
149+
{Xtensa::LCOUNT, 2}, {Xtensa::SAR, 3},
150+
{Xtensa::BREG, 4}, {Xtensa::LITBASE, 5},
151+
{Xtensa::SCOMPARE1, 12}, {Xtensa::ACCLO, 16},
152+
{Xtensa::ACCHI, 17}, {Xtensa::M0, 32},
153+
{Xtensa::M1, 33}, {Xtensa::M2, 34},
154+
{Xtensa::M3, 35}, {Xtensa::WINDOWBASE, 72},
155+
{Xtensa::WINDOWSTART, 73}, {Xtensa::IBREAKENABLE, 96},
156+
{Xtensa::MEMCTL, 97}, {Xtensa::ATOMCTL, 99},
157+
{Xtensa::DDR, 104}, {Xtensa::IBREAKA0, 128},
158+
{Xtensa::IBREAKA1, 129}, {Xtensa::DBREAKA0, 144},
159+
{Xtensa::DBREAKA1, 145}, {Xtensa::DBREAKC0, 160},
160+
{Xtensa::DBREAKC1, 161}, {Xtensa::CONFIGID0, 176},
161+
{Xtensa::EPC1, 177}, {Xtensa::EPC2, 178},
162+
{Xtensa::EPC3, 179}, {Xtensa::EPC4, 180},
163+
{Xtensa::EPC5, 181}, {Xtensa::EPC6, 182},
164+
{Xtensa::EPC7, 183}, {Xtensa::DEPC, 192},
165+
{Xtensa::EPS2, 194}, {Xtensa::EPS3, 195},
166+
{Xtensa::EPS4, 196}, {Xtensa::EPS5, 197},
167+
{Xtensa::EPS6, 198}, {Xtensa::EPS7, 199},
168+
{Xtensa::CONFIGID1, 208}, {Xtensa::EXCSAVE1, 209},
169+
{Xtensa::EXCSAVE2, 210}, {Xtensa::EXCSAVE3, 211},
170+
{Xtensa::EXCSAVE4, 212}, {Xtensa::EXCSAVE5, 213},
171+
{Xtensa::EXCSAVE6, 214}, {Xtensa::EXCSAVE7, 215},
172+
{Xtensa::CPENABLE, 224}, {Xtensa::INTERRUPT, 226},
173+
{Xtensa::INTCLEAR, 227}, {Xtensa::INTENABLE, 228},
174+
{Xtensa::PS, 230}, {Xtensa::VECBASE, 231},
175+
{Xtensa::EXCCAUSE, 232}, {Xtensa::DEBUGCAUSE, 233},
176+
{Xtensa::CCOUNT, 234}, {Xtensa::PRID, 235},
177+
{Xtensa::ICOUNT, 236}, {Xtensa::ICOUNTLEVEL, 237},
178+
{Xtensa::EXCVADDR, 238}, {Xtensa::CCOMPARE0, 240},
179+
{Xtensa::CCOMPARE1, 241}, {Xtensa::CCOMPARE2, 242},
180+
{Xtensa::MISC0, 244}, {Xtensa::MISC1, 245},
181+
{Xtensa::MISC2, 246}, {Xtensa::MISC3, 247}};
181182

182183
static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
183184
uint64_t Address,

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
200200
case Xtensa::WINDOWBASE:
201201
case Xtensa::WINDOWSTART:
202202
return FeatureBits[Xtensa::FeatureWindowed];
203+
case Xtensa::ATOMCTL:
204+
case Xtensa::SCOMPARE1:
205+
return FeatureBits[Xtensa::FeatureWindowed];
203206
case Xtensa::NoRegister:
204207
return false;
205208
}

llvm/lib/Target/Xtensa/XtensaFeatures.td

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ def FeatureDiv32 : SubtargetFeature<"div32", "HasDiv32", "true",
7373
def HasDiv32 : Predicate<"Subtarget->hasDiv32()">,
7474
AssemblerPredicate<(all_of FeatureDiv32)>;
7575

76+
def FeatureS32C1I : SubtargetFeature<"s32c1i", "HasS32C1I", "true",
77+
"Enable Xtensa S32C1I option">;
78+
def HasS32C1I : Predicate<"Subtarget->hasS32C1I()">,
79+
AssemblerPredicate<(all_of FeatureS32C1I)>;
80+
81+
// Assume that lock-free native-width atomics are available, even if the target
82+
// and operating system combination would not usually provide them. The user
83+
// is responsible for providing any necessary __sync implementations. Code
84+
// built with this feature is not ABI-compatible with code built without this
85+
// feature, if atomic variables are exposed across the ABI boundary.
86+
def FeatureForcedAtomics : SubtargetFeature<"forced-atomics", "HasForcedAtomics", "true",
87+
"Assume that lock-free native-width atomics are available">;
88+
def HasForcedAtomics : Predicate<"Subtarget->hasForcedAtomics()">,
89+
AssemblerPredicate<(all_of FeatureForcedAtomics)>;
90+
def HasAtomicLdSt : Predicate<"Subtarget->hasS32C1I() || Subtarget->hasForcedAtomics()">;
91+
7692
def FeatureRegionProtection : SubtargetFeature<"regprotect", "HasRegionProtection", "true",
7793
"Enable Xtensa Region Protection option">;
7894
def HasRegionProtection : Predicate<"Subtarget->hasRegionProtection()">,

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,15 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
250250
// Floating-point truncation and stores need to be done separately.
251251
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
252252

253+
if (Subtarget.hasS32C1I()) {
254+
setMaxAtomicSizeInBitsSupported(32);
255+
setMinCmpXchgSizeInBits(32);
256+
} else if (Subtarget.hasForcedAtomics()) {
257+
setMaxAtomicSizeInBitsSupported(32);
258+
} else {
259+
setMaxAtomicSizeInBitsSupported(0);
260+
}
261+
253262
// Compute derived properties from the register classes
254263
computeRegisterProperties(STI.getRegisterInfo());
255264
}
@@ -1548,6 +1557,11 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
15481557
return nullptr;
15491558
}
15501559

1560+
TargetLowering::AtomicExpansionKind
1561+
XtensaTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
1562+
return AtomicExpansionKind::CmpXChg;
1563+
}
1564+
15511565
//===----------------------------------------------------------------------===//
15521566
// Custom insertion
15531567
//===----------------------------------------------------------------------===//
@@ -1696,6 +1710,23 @@ MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
16961710

16971711
return MBB;
16981712
}
1713+
case Xtensa::ATOMIC_CMP_SWAP_32_P: {
1714+
MachineOperand &R = MI.getOperand(0);
1715+
MachineOperand &Addr = MI.getOperand(1);
1716+
MachineOperand &Cmp = MI.getOperand(2);
1717+
MachineOperand &Swap = MI.getOperand(3);
1718+
1719+
BuildMI(*MBB, MI, DL, TII.get(Xtensa::WSR), Xtensa::SCOMPARE1)
1720+
.addReg(Cmp.getReg());
1721+
1722+
BuildMI(*MBB, MI, DL, TII.get(Xtensa::S32C1I), R.getReg())
1723+
.addReg(Swap.getReg())
1724+
.addReg(Addr.getReg())
1725+
.addImm(0);
1726+
1727+
MI.eraseFromParent();
1728+
return MBB;
1729+
}
16991730
default:
17001731
llvm_unreachable("Unexpected instr type to insert");
17011732
}

llvm/lib/Target/Xtensa/XtensaISelLowering.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ class XtensaTargetLowering : public TargetLowering {
145145
const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
146146
SelectionDAG &DAG) const override;
147147

148+
bool shouldInsertFencesForAtomic(const Instruction *I) const override {
149+
return true;
150+
}
151+
152+
AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *) const override;
153+
148154
bool decomposeMulByConstant(LLVMContext &Context, EVT VT,
149155
SDValue C) const override;
150156

llvm/lib/Target/Xtensa/XtensaInstrInfo.td

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,8 @@ def EXTW : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
496496
let hasSideEffects = 1;
497497
}
498498

499+
def : Pat<(atomic_fence timm, timm), (MEMW)>;
500+
499501
//===----------------------------------------------------------------------===//
500502
// Illegal instructions
501503
//===----------------------------------------------------------------------===//
@@ -1498,6 +1500,46 @@ def RFI : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins uimm4:$imm),
14981500
let t = 0x1;
14991501
}
15001502

1503+
//===----------------------------------------------------------------------===//
1504+
// S32C1I
1505+
//===----------------------------------------------------------------------===//
1506+
1507+
let mayStore = 1, mayLoad = 1, Predicates = [HasS32C1I] in {
1508+
def S32C1I : RRI8_Inst<0x02, (outs AR:$a), (ins AR:$t, mem32:$addr),
1509+
"s32c1i\t$t, $addr", []> {
1510+
bits<12> addr;
1511+
1512+
let r = 0x0e;
1513+
let Uses = [SCOMPARE1];
1514+
let Constraints = "$a = $t";
1515+
let imm8{7-0} = addr{11-4};
1516+
let s{3-0} = addr{3-0};
1517+
}
1518+
}
1519+
1520+
//===----------------------------------------------------------------------===//
1521+
// Atomic patterns
1522+
//===----------------------------------------------------------------------===//
1523+
1524+
// Atomic load/store are available under both +s32c1i and +force-atomics.
1525+
// Fences will be inserted for atomic load/stores according to the logic in
1526+
// XtensaTargetLowering.
1527+
let Predicates = [HasAtomicLdSt] in {
1528+
def : Pat<(i32 (atomic_load_8 addr_ish1:$addr)), (L8UI addr_ish1:$addr)>;
1529+
def : Pat<(i32 (atomic_load_16 addr_ish2:$addr)), (L16UI addr_ish2:$addr)>;
1530+
def : Pat<(i32 (atomic_load_32 addr_ish4:$addr)), (L32I addr_ish4:$addr)>;
1531+
1532+
def : Pat<(atomic_store_8 AR:$t, addr_ish1:$addr), (S8I AR:$t, addr_ish1:$addr)>;
1533+
def : Pat<(atomic_store_16 AR:$t, addr_ish2:$addr), (S16I AR:$t, addr_ish2:$addr)>;
1534+
def : Pat<(atomic_store_32 AR:$t, addr_ish4:$addr), (S32I AR:$t, addr_ish4:$addr)>;
1535+
}
1536+
1537+
let usesCustomInserter = 1, Predicates = [HasS32C1I] in {
1538+
def ATOMIC_CMP_SWAP_32_P : Pseudo<(outs AR:$dst), (ins AR:$ptr, AR:$cmp, AR:$swap),
1539+
"!atomic_cmp_swap_32_p, $dst, $ptr, $cmp, $swap",
1540+
[(set AR:$dst, (atomic_cmp_swap_i32 AR:$ptr, AR:$cmp, AR:$swap))]>;
1541+
}
1542+
15011543
//===----------------------------------------------------------------------===//
15021544
// DSP Instructions
15031545
//===----------------------------------------------------------------------===//

llvm/lib/Target/Xtensa/XtensaRegisterInfo.td

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ def SAR : SRReg<3, "sar", ["SAR","3"]>;
8484
// Boolean Register
8585
def BREG : SRReg<4, "br", ["BR","4"]>;
8686

87+
// Expected data value for S32C1I operation
88+
def SCOMPARE1 : SRReg<12, "scompare1", ["SCOMPARE1", "12"]>;
89+
8790
// Literal base
8891
def LITBASE : SRReg<5, "litbase", ["LITBASE", "5"]>;
8992

@@ -97,6 +100,9 @@ def IBREAKENABLE : SRReg<96, "ibreakenable", ["IBREAKENABLE", "96"]>;
97100
// Memory Control Register
98101
def MEMCTL : SRReg<97, "memctl", ["MEMCTL", "97"]>;
99102

103+
// Atomic Operation Control
104+
def ATOMCTL : SRReg<99, "atomctl", ["ATOMCTL", "99"]>;
105+
100106
def DDR : SRReg<104, "ddr", ["DDR", "104"]>;
101107

102108
// Instuction break address register 0
@@ -218,8 +224,8 @@ def MR23 : RegisterClass<"Xtensa", [i32], 32, (add M2, M3)>;
218224
def MR : RegisterClass<"Xtensa", [i32], 32, (add MR01, MR23)>;
219225

220226
def SR : RegisterClass<"Xtensa", [i32], 32, (add
221-
LBEG, LEND, LCOUNT, SAR, BREG, LITBASE, ACCLO, ACCHI, MR,
222-
WINDOWBASE, WINDOWSTART, IBREAKENABLE, MEMCTL, DDR, IBREAKA0, IBREAKA1,
227+
LBEG, LEND, LCOUNT, SAR, BREG, SCOMPARE1, LITBASE, ACCLO, ACCHI, MR,
228+
WINDOWBASE, WINDOWSTART, IBREAKENABLE, MEMCTL, ATOMCTL, DDR, IBREAKA0, IBREAKA1,
223229
DBREAKA0, DBREAKA1, DBREAKC0, DBREAKC1, CONFIGID0, EPC1, EPC2, EPC3, EPC4, EPC5,
224230
EPC6, EPC7, DEPC, EPS2, EPS3, EPS4, EPS5, EPS6, EPS7, CONFIGID1, EXCSAVE1, EXCSAVE2,
225231
EXCSAVE3, EXCSAVE4, EXCSAVE5, EXCSAVE6, EXCSAVE7, CPENABLE, INTERRUPT, INTSET, INTCLEAR, INTENABLE,

llvm/lib/Target/Xtensa/XtensaSubtarget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
7777
bool hasMul32() const { return HasMul32; }
7878
bool hasMul32High() const { return HasMul32High; }
7979
bool hasDiv32() const { return HasDiv32; }
80+
bool hasS32C1I() const { return HasS32C1I; }
81+
bool hasForcedAtomics() const { return HasForcedAtomics; }
8082
bool hasSingleFloat() const { return HasSingleFloat; }
8183
bool hasRegionProtection() const { return HasRegionProtection; }
8284
bool hasRelocatableVector() const { return HasRelocatableVector; }

llvm/lib/Target/Xtensa/XtensaTargetMachine.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class XtensaPassConfig : public TargetPassConfig {
107107
}
108108

109109
bool addInstSelector() override;
110+
void addIRPasses() override;
110111
void addPreEmitPass() override;
111112
};
112113
} // end anonymous namespace
@@ -116,6 +117,11 @@ bool XtensaPassConfig::addInstSelector() {
116117
return false;
117118
}
118119

120+
void XtensaPassConfig::addIRPasses() {
121+
addPass(createAtomicExpandLegacyPass());
122+
TargetPassConfig::addIRPasses();
123+
}
124+
119125
void XtensaPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); }
120126

121127
TargetPassConfig *XtensaTargetMachine::createPassConfig(PassManagerBase &PM) {

0 commit comments

Comments
 (0)