Skip to content

Commit 01673ae

Browse files
committed
[RISCV] Custom lower llvm.clear_cache on glibc targets
Typically __clear_cache is used but on these targets __riscv_flush_icache is used instead. Because it also has a different signature we need custom lowering.
1 parent 58df646 commit 01673ae

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,11 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
662662

663663
setBooleanContents(ZeroOrOneBooleanContent);
664664

665+
if (Subtarget.getTargetTriple().isOSGlibc()) {
666+
// Custom lowering of llvm.clear_cache.
667+
setOperationAction(ISD::CLEAR_CACHE, MVT::Other, Custom);
668+
}
669+
665670
if (Subtarget.hasVInstructions()) {
666671
setBooleanVectorContents(ZeroOrOneBooleanContent);
667672

@@ -7152,7 +7157,48 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
71527157
return lowerVPSpliceExperimental(Op, DAG);
71537158
case ISD::EXPERIMENTAL_VP_REVERSE:
71547159
return lowerVPReverseExperimental(Op, DAG);
7160+
case ISD::CLEAR_CACHE: {
7161+
assert(Subtarget.getTargetTriple().isOSGlibc() &&
7162+
"llvm.clear_cache only needs custom lower on glibc targets");
7163+
SDLoc DL(Op);
7164+
SDValue Flags = DAG.getConstant(0, DL, Subtarget.getXLenVT());
7165+
return emitFlushICache(DAG, Op.getOperand(0), Op.getOperand(1),
7166+
Op.getOperand(2), Flags, DL);
71557167
}
7168+
}
7169+
}
7170+
7171+
SDValue RISCVTargetLowering::emitFlushICache(SelectionDAG &DAG, SDValue InChain,
7172+
SDValue Start, SDValue End,
7173+
SDValue Flags, SDLoc DL) const {
7174+
TargetLowering::ArgListTy Args;
7175+
TargetLowering::ArgListEntry Entry;
7176+
7177+
// start
7178+
Entry.Node = Start;
7179+
Entry.Ty = PointerType::getUnqual(*DAG.getContext());
7180+
Args.push_back(Entry);
7181+
7182+
// end
7183+
Entry.Node = End;
7184+
Entry.Ty = PointerType::getUnqual(*DAG.getContext());
7185+
Args.push_back(Entry);
7186+
7187+
// flags
7188+
Entry.Node = Flags;
7189+
Entry.Ty = Type::getIntNTy(*DAG.getContext(), Subtarget.getXLen());
7190+
Args.push_back(Entry);
7191+
7192+
TargetLowering::CallLoweringInfo CLI(DAG);
7193+
EVT Ty = getPointerTy(DAG.getDataLayout());
7194+
CLI.setDebugLoc(DL).setChain(InChain).setLibCallee(
7195+
CallingConv::C, Type::getVoidTy(*DAG.getContext()),
7196+
DAG.getExternalSymbol("__riscv_flush_icache", Ty), std::move(Args));
7197+
7198+
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
7199+
7200+
// This function returns void so only the out chain matters.
7201+
return CallResult.second;
71567202
}
71577203

71587204
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty,

llvm/lib/Target/RISCV/RISCVISelLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,9 @@ class RISCVTargetLowering : public TargetLowering {
10371037
const APInt &AndMask) const override;
10381038

10391039
unsigned getMinimumJumpTableEntries() const override;
1040+
1041+
SDValue emitFlushICache(SelectionDAG &DAG, SDValue InChain, SDValue Start,
1042+
SDValue End, SDValue Flags, SDLoc DL) const;
10401043
};
10411044

10421045
/// As per the spec, the rules for passing vector arguments are as follows:
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=riscv32 < %s | FileCheck --check-prefix=RV32 %s
3+
; RUN: llc -mtriple=riscv64 < %s | FileCheck --check-prefix=RV64 %s
4+
; RUN: llc -mtriple=riscv32-unknown-linux-gnu < %s | FileCheck --check-prefix=RV32-GLIBC %s
5+
; RUN: llc -mtriple=riscv64-unknown-linux-gnu < %s | FileCheck --check-prefix=RV64-GLIBC %s
6+
7+
declare void @llvm.clear_cache(ptr, ptr)
8+
9+
define void @foo(ptr %a, ptr %b) nounwind {
10+
; RV32-LABEL: foo:
11+
; RV32: # %bb.0:
12+
; RV32-NEXT: addi sp, sp, -16
13+
; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
14+
; RV32-NEXT: call __clear_cache
15+
; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
16+
; RV32-NEXT: addi sp, sp, 16
17+
; RV32-NEXT: ret
18+
;
19+
; RV64-LABEL: foo:
20+
; RV64: # %bb.0:
21+
; RV64-NEXT: addi sp, sp, -16
22+
; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
23+
; RV64-NEXT: call __clear_cache
24+
; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
25+
; RV64-NEXT: addi sp, sp, 16
26+
; RV64-NEXT: ret
27+
;
28+
; RV32-GLIBC-LABEL: foo:
29+
; RV32-GLIBC: # %bb.0:
30+
; RV32-GLIBC-NEXT: addi sp, sp, -16
31+
; RV32-GLIBC-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
32+
; RV32-GLIBC-NEXT: li a2, 0
33+
; RV32-GLIBC-NEXT: call __riscv_flush_icache
34+
; RV32-GLIBC-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
35+
; RV32-GLIBC-NEXT: addi sp, sp, 16
36+
; RV32-GLIBC-NEXT: ret
37+
;
38+
; RV64-GLIBC-LABEL: foo:
39+
; RV64-GLIBC: # %bb.0:
40+
; RV64-GLIBC-NEXT: addi sp, sp, -16
41+
; RV64-GLIBC-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
42+
; RV64-GLIBC-NEXT: li a2, 0
43+
; RV64-GLIBC-NEXT: call __riscv_flush_icache
44+
; RV64-GLIBC-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
45+
; RV64-GLIBC-NEXT: addi sp, sp, 16
46+
; RV64-GLIBC-NEXT: ret
47+
call void @llvm.clear_cache(ptr %a, ptr %b)
48+
ret void
49+
}

0 commit comments

Comments
 (0)